summaryrefslogtreecommitdiff
path: root/html
diff options
context:
space:
mode:
Diffstat (limited to 'html')
-rw-r--r--html/display-panel.html85
-rw-r--r--html/display-panel.js226
-rw-r--r--html/options_main.js6
3 files changed, 309 insertions, 8 deletions
diff --git a/html/display-panel.html b/html/display-panel.html
index 5e5580e..9b6d619 100644
--- a/html/display-panel.html
+++ b/html/display-panel.html
@@ -6,9 +6,90 @@
<html>
<head>
<meta charset="utf-8"/>
- <title>Myext popup</title>
+ <title>Hachette - page settings</title>
+ <style>
+ input[type="radio"], input[type="checkbox"] {
+ display: none;
+ }
+
+ body {
+ width: 300px;
+ height: 300px;
+ }
+
+ .show_next:not(:checked)+* {
+ display: none;
+ }
+
+ .hide {
+ display: none;
+ }
+
+ #possible_patterns_chbx:not(:checked)+label span#triangle:first-child+span,
+ #possible_patterns_chbx:not(:checked)+label+*,
+ #possible_patterns_chbx:checked+label span#triangle:first-child {
+ display: none;
+ }
+
+ #container_for_injected>#none_injected:not(:last-child) {
+ display: none;
+ }
+
+ input#connected_chbx:checked+div+h3 {
+ display: none;
+ }
+ </style>
</head>
<body>
- <button id="settings_but" type="button">Settings</button>_POPUPSCRIPTS_
+ <!-- The invisible div below is for elements that will be cloned. -->
+ <div class="hide">
+ <li id="pattern_li_template">
+ <span></span>
+ <button>View in settings</button>
+ </li>
+ </div>
+
+ <h2 id="page_url_heading"></h2>
+
+ <input id="show_privileged_notice_chbx" type="checkbox" class="show_next"></input>
+ <h3>Privileged page</h3>
+
+ <input id="show_page_state_chbx" type="checkbox" class="show_next"></input>
+ <div>
+ <input id="possible_patterns_chbx" type="checkbox"></input>
+ <label for="possible_patterns_chbx">
+ <h3>
+ <span id="triangle">&#x23F5;</span><span>&#x23F7;</span>
+ Possible patterns
+ </h3>
+ </label>
+ <ul id="possible_patterns"></ul>
+
+ <input id="connected_chbx" type="checkbox" class="show_next"></input>
+ <div>
+ <h3>
+ Matched pattern: <span id="pattern">...</span>
+ <button id="view_pattern" class="hide">
+ View in settings
+ </button>
+ </h3>
+ <h3>
+ Blocked: <span id="blocked">...</span>
+ </h3>
+ <h3>
+ Payload: <span id="payload">...</span>
+ <button id="view_payload" class="hide">
+ View in settings
+ </button>
+ </h3>
+ <h3>Injected</h3>
+ <div id="container_for_injected">
+ <span id="none_injected">None</span>
+ </div>
+ </div>
+ <h3>Trying to connect..<input id="loading_chbx" type="checkbox" class="show_next"></input><span>.</span></h3>
+ </div>
+
+ <button id="settings_but" type="button" style="margin-top: 20px;">Settings</button>_POPUPSCRIPTS_
</body>
</html>
diff --git a/html/display-panel.js b/html/display-panel.js
index 4a4cdcd..9ae35fd 100644
--- a/html/display-panel.js
+++ b/html/display-panel.js
@@ -8,8 +8,232 @@
/*
* IMPORTS_START
* IMPORT browser
+ * IMPORT is_chrome
+ * IMPORT is_mozilla
+ * IMPORT CONNECTION_TYPE
+ * IMPORT url_item
+ * IMPORT is_privileged_url
+ * IMPORT TYPE_PREFIX
+ * IMPORT nice_name
+ * IMPORT open_in_settings
+ * IMPORT for_each_possible_pattern
* IMPORTS_END
*/
-document.getElementById("settings_but")
+function by_id(id)
+{
+ return document.getElementById(id);
+}
+
+const tab_query = {currentWindow: true, active: true};
+
+async function get_current_tab()
+{
+ /* Fix for fact that Chrome does not use promises here */
+ const promise = is_chrome ?
+ new Promise((resolve, reject) =>
+ browser.tabs.query(tab_query, tab => resolve(tab))) :
+ browser.tabs.query(tab_query);
+
+ try {
+ return (await promise)[0];
+ } catch(e) {
+ console.log(e);
+ }
+}
+
+const page_url_heading = by_id("page_url_heading");
+const show_privileged_notice_chbx = by_id("show_privileged_notice_chbx");
+const show_page_state_chbx = by_id("show_page_state_chbx");
+
+async function show_page_activity_info()
+{
+ const tab = await get_current_tab();
+
+ if (tab === undefined) {
+ page_url_heading.textContent = "unknown page";
+ return;
+ }
+
+ const url = url_item(tab.url);
+ page_url_heading.textContent = url;
+ if (is_privileged_url(url)) {
+ show_privileged_notice_chbx.checked = true;
+ return;
+ }
+
+ populate_possible_patterns_list(url);
+ show_page_state_chbx.checked = true;
+
+ try_to_connect(tab.id);
+}
+
+function populate_possible_patterns_list(url)
+{
+ for_each_possible_pattern(url, add_pattern_to_list);
+
+ const port = browser.runtime.connect({name: CONNECTION_TYPE.PAGE_INFO});
+ port.onMessage.addListener(handle_page_info);
+ port.postMessage(["subscribe", url]);
+}
+
+const possible_patterns_ul = by_id("possible_patterns");
+const pattern_li_template = by_id("pattern_li_template");
+pattern_li_template.removeAttribute("id");
+const known_patterns = new Map();
+
+function add_pattern_to_list(pattern)
+{
+ const li = pattern_li_template.cloneNode(true);
+ li.id = `pattern_li_${known_patterns.size}`;
+ known_patterns.set(pattern, li.id);
+
+ const span = li.firstElementChild;
+ span.textContent = pattern;
+
+ const button = span.nextElementSibling;
+ const settings_opener = () => open_in_settings(TYPE_PREFIX.PAGE, pattern);
+ button.addEventListener("click", settings_opener);
+
+ possible_patterns_ul.appendChild(li)
+
+ return li.id;
+}
+
+function ensure_pattern_exists(pattern)
+{
+ let id = known_patterns.get(pattern);
+ /*
+ * As long as pattern computation works well, we should never get into this
+ * conditional block. This is just a safety measure. To be removed as part
+ * of a bigger rework when we start taking iframes into account.
+ */
+ if (id === undefined) {
+ console.log(`unknown pattern: ${pattern}`);
+ id = add_pattern_to_list(pattern);
+ }
+
+ return id;
+}
+
+function set_pattern_li_button_text(li_id, text)
+{
+ by_id(li_id).firstElementChild.nextElementSibling.textContent = text;
+}
+
+function handle_page_info(message)
+{
+ const [type, data] = message;
+
+ if (type === "change") {
+ const li_id = ensure_pattern_exists(data.item);
+ if (data.old_val === undefined)
+ set_pattern_li_button_text(li_id, "Edit in settings");
+ if (data.new_val === undefined)
+ set_pattern_li_button_text(li_id, "Add setting");
+ }
+
+ if (type === "new_url") {
+ for (const li_id of known_patterns.values())
+ set_pattern_li_button_text(li_id, "Add setting");
+ for (const [pattern, settings] of data) {
+ set_pattern_li_button_text(ensure_pattern_exists(pattern),
+ "Edit in settings")
+ }
+ }
+}
+
+const connected_chbx = by_id("connected_chbx");
+
+function try_to_connect(tab_id)
+{
+ /* This won't connect to iframes. We'll add support for them later */
+ const connect_info = {name: CONNECTION_TYPE.ACTIVITY_INFO, frameId: 0};
+ const port = browser.tabs.connect(tab_id, connect_info);
+
+ port.onDisconnect.addListener(port => handle_disconnect(tab_id));
+ port.onMessage.addListener(handle_activity_report);
+
+ if (is_mozilla)
+ setTimeout(() => monitor_connecting(port, tab_id), 1000);
+}
+
+const loading_chbx = by_id("loading_chbx");
+
+function handle_disconnect(tab_id)
+{
+ if (is_chrome && !browser.runtime.lastError)
+ return;
+
+ /* return if there was no connection initialization failure */
+ if (connected_chbx.checked)
+ return;
+
+ loading_chbx.checked = !loading_chbx.checked;
+ setTimeout(() => try_to_connect(tab_id), 1000);
+}
+
+function monitor_connecting(port, tab_id)
+{
+ if (connected_chbx.checked)
+ return;
+
+ port.disconnect();
+ loading_chbx.checked = !loading_chbx.checked;
+ try_to_connect(tab_id);
+}
+
+const pattern_span = by_id("pattern");
+const view_pattern_but = by_id("view_pattern");
+const blocked_span = by_id("blocked");
+const payload_span = by_id("payload");
+const view_payload_but = by_id("view_payload");
+const container_for_injected = by_id("container_for_injected");
+
+function handle_activity_report(message)
+{
+ connected_chbx.checked = true;
+
+ const [type, data] = message;
+
+ if (type === "settings") {
+ let [pattern, settings] = data;
+
+ settings = settings || {};
+ blocked_span.textContent = settings.allow ? "no" : "yes";
+
+ if (pattern) {
+ pattern_span.textContent = pattern;
+ const settings_opener =
+ () => open_in_settings(TYPE_PREFIX.PAGE, pattern);
+ view_pattern_but.classList.remove("hide");
+ view_pattern_but.addEventListener("click", settings_opener);
+ } else {
+ pattern_span.textContent = "none";
+ }
+
+ const components = settings.components;
+ if (components) {
+ payload_span.textContent = nice_name(...components);
+ const settings_opener = () => open_in_settings(...components);
+ view_payload_but.classList.remove("hide");
+ view_payload_but.addEventListener("click", settings_opener);
+ } else {
+ payload_span.textContent = "none";
+ }
+ }
+ if (type === "script") {
+ const h4 = document.createElement("h4");
+ const pre = document.createElement("pre");
+ h4.textContent = "script";
+ pre.textContent = data;
+
+ container_for_injected.appendChild(h4);
+ container_for_injected.appendChild(pre);
+ }
+}
+
+by_id("settings_but")
.addEventListener("click", (e) => browser.runtime.openOptionsPage());
+
+show_page_activity_info();
diff --git a/html/options_main.js b/html/options_main.js
index 9c66a27..f7adf39 100644
--- a/html/options_main.js
+++ b/html/options_main.js
@@ -12,6 +12,7 @@
* IMPORT TYPE_NAME
* IMPORT list_prefixes
* IMPORT url_extract_target
+ * IMPORT nice_name
* IMPORTS_END
*/
@@ -21,11 +22,6 @@ function by_id(id)
return document.getElementById(id);
}
-function nice_name(prefix, name)
-{
- return `${name} (${TYPE_NAME[prefix]})`;
-}
-
const item_li_template = by_id("item_li_template");
const bag_component_li_template = by_id("bag_component_li_template");
const chbx_component_li_template = by_id("chbx_component_li_template");