aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja
diff options
context:
space:
mode:
Diffstat (limited to 'src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja')
-rw-r--r--src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja173
1 files changed, 172 insertions, 1 deletions
diff --git a/src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja b/src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja
index 653b7df..593673b 100644
--- a/src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja
+++ b/src/hydrilla/proxy/policies/injectable_scripts/popup.js.jinja
@@ -45,6 +45,177 @@ code in a proprietary program, I am not going to enforce this in court.
#}
(function(){
- console.log('TODO: make Haketilo able to actually display a popup')
document.currentScript.remove();
+
+ /*
+ * To slightly decrease the chance of accidental popup breakage we snapshot
+ * methods that other code might redefine.
+ */
+ function get_setter(obj, name) {
+ return Object.getOwnPropertyDescriptor(obj, name).set;
+ }
+
+ const ElementPrototype = [0, 0, 0]
+ .reduce(n => Object.getPrototypeOf(n), document.documentElement);
+
+ const prepend_fun = ElementPrototype.prepend;
+ const setattr_fun = ElementPrototype.setAttribute;
+ const remove_fun = ElementPrototype.remove;
+ const setinner_fun = get_setter(ElementPrototype, "innerHTML");
+ const open_fun = window.open;
+
+ const shortcut = "HKT";
+ const nonce = atob("{{nonce_b64}}");
+ const popup_style = "{{popup_style}}";
+ const popup_html = atob("{{popup_page_b64}}");
+ const popup_container = document.createElement("div");
+ const popup_frame = document.createElement("iframe");
+
+ function make_style(styles_obj) {
+ return Object.entries(styles_obj)
+ .map(([key, val]) => `${key}: ${val} !important`)
+ .join(';');
+ }
+
+ const frame_style = make_style({
+ "position": "absolute",
+ "left": "50%",
+ "top": "50%",
+ "transform": "translate(-50%, -50%)",
+ "display": "block",
+ "visibility": "visible",
+ "min-width": "initial",
+ "width": "600px",
+ "max-width": "calc(100vw - 20px)",
+ "min-height": "initial",
+ "height": "700px",
+ "max-height": "calc(100vh - 20px)",
+ "background-color": "#fff",
+ "opacity": "100%",
+ "margin": 0,
+ "padding": 0,
+ "border": "none",
+ "border-radius": "5px"
+ });
+
+ const container_style = make_style({
+ "position": "fixed",
+ "left": "0",
+ "top": "0",
+ "transform": "initial",
+ "z-index": 2147483647,
+ "display": "block",
+ "visibility": "visible",
+ "min-width": "100vw",
+ "max-width": "100vw",
+ "min-height": "100vh",
+ "max-height": "100vh",
+ "background-color": "#0008",
+ "opacity": "100%",
+ "margin": 0,
+ "padding": 0,
+ "border": "none",
+ "border-radius": 0
+ });
+
+ const popup_blob_opts = {type: "text/html;charset=UTF-8"};
+ const popup_blob = new Blob([popup_html], popup_blob_opts);
+ const popup_url = URL.createObjectURL(popup_blob);
+
+ function show_popup_dialog() {
+ setattr_fun.call(popup_frame, "srcdoc", popup_html);
+ setattr_fun.call(popup_frame, "nonce", nonce);
+ setattr_fun.call(popup_frame, "style", frame_style);
+
+ setattr_fun.call(popup_container, "style", container_style);
+ setinner_fun.call(popup_container, "");
+ prepend_fun.call(popup_container, popup_frame);
+
+ prepend_fun.call(document.body, popup_container);
+ }
+
+ let popup_newtab_wanted = false;
+
+ function show_popup_newtab() {
+ /*
+ * We cannot open popup directly here because browsers block window
+ * creation attempts from "keypress" event handlers. Instead, we set a
+ * flag to have "click" event handler open the popup.
+ */
+ popup_newtab_wanted = true;
+ console.info(`You typed "${shortcut}". Please click anywhere on the page to show Haketilo page information.`);
+ }
+
+ function show_popup() {
+ if (popup_style === "T") {
+ show_popup_newtab();
+ } else {
+ /* popup_syle === "D" */
+ show_popup_dialog();
+ }
+ }
+
+ function hide_popup_dialog() {
+ remove_fun.call(popup_container);
+ }
+
+ let letters_matched = 0;
+
+ function matches_previous(letter) {
+ return letters_matched > 0 && letter === shortcut[letters_matched - 1];
+ }
+
+ function match_letter(letter) {
+ if (letter !== shortcut[letters_matched] && !matches_previous(letter))
+ letters_matched = 0;
+
+ if (letter === shortcut[letters_matched]) {
+ if (++letters_matched === shortcut.length) {
+ letters_matched = 0;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function consume_keypress(event) {
+ if (!event.isTrusted)
+ return;
+
+ if (match_letter(event.key))
+ show_popup();
+ }
+
+ function cancel_event(event) {
+ event.stopImmediatePropagation();
+ event.stopPropagation();
+ event.preventDefault();
+ }
+
+ function consume_click(event) {
+ if (!event.isTrusted)
+ return;
+
+ if (popup_style === "T") {
+ if (popup_newtab_wanted) {
+ popup_newtab_wanted = false;
+ cancel_event(event);
+ window.open(
+ popup_url,
+ "_blank",
+ "popup,width=600px,height=700px"
+ );
+ }
+ } else {
+ /* popup_syle === "D" */
+ if (event.target === popup_container) {
+ hide_popup_dialog();
+ cancel_event(event);
+ }
+ }
+ }
+
+ document.addEventListener("keypress", consume_keypress, {capture: true});
+ document.addEventListener("click", consume_click, {capture: true});
})();