diff options
author | Ruben Rodriguez <ruben@gnu.org> | 2018-09-13 20:39:48 -0400 |
---|---|---|
committer | Ruben Rodriguez <ruben@gnu.org> | 2018-09-13 21:02:13 -0400 |
commit | d26b319fd6f98517cc3421f10bf18698b953e4d2 (patch) | |
tree | bc70c4e472a2eaf514d411dba5067d530e5bbea9 /data/extensions/https-everywhere@eff.org/pages | |
parent | c3b304c51a3386ea09527a479a883253ea35243a (diff) |
Updated extensions list for v60
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/pages')
20 files changed, 1428 insertions, 0 deletions
diff --git a/data/extensions/https-everywhere@eff.org/pages/cancel/index.html b/data/extensions/https-everywhere@eff.org/pages/cancel/index.html new file mode 100644 index 0000000..94a4799 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/cancel/index.html @@ -0,0 +1,16 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta http-equiv="Content-Style-Type" content="text/css" /> + <title>⚠ HTTPS Everywhere ⚠</title> + <style type="text/css">code{white-space: pre;}</style> + <link rel="stylesheet" href="style.css" type="text/css" /> + </head> + <body> + <h1 id="https-everywhere"><img src="../../images/banner-red.png" alt="HTTPS Everywhere" /></h1> + <p data-i18n="cancel_he_blocking_explainer"></p> + <script src="../translation.js"></script> + <script src="ux.js"></script> + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/cancel/style.css b/data/extensions/https-everywhere@eff.org/pages/cancel/style.css new file mode 100644 index 0000000..80ec5b3 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/cancel/style.css @@ -0,0 +1,20 @@ +body{ + margin-top: 6em; + left: 50%; + position: relative; + overflow: hidden; +} + +h1 img{ + position: relative; + left: -289px; +} + +p{ + width: 600px; + position: relative; + left: -300px; + font-size: 12pt; + font-family: sans-serif; + line-height: 150%; +} diff --git a/data/extensions/https-everywhere@eff.org/pages/cancel/ux.js b/data/extensions/https-everywhere@eff.org/pages/cancel/ux.js new file mode 100644 index 0000000..d7475dd --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/cancel/ux.js @@ -0,0 +1,21 @@ +"use strict"; + +let observer; +document.addEventListener("DOMContentLoaded", () => { + const explainer = document.querySelector("[data-i18n=cancel_he_blocking_explainer]"); + observer = new MutationObserver(() => {replaceLink(explainer)}); + if (explainer.innerText.length > 0) { + replaceLink(explainer); + } else { + observer.observe(explainer, {childList: true}); + } +}); + +function replaceLink(explainer){ + observer.disconnect(); + const linkText = chrome.i18n.getMessage("cancel_he_blocking_network"); + const link = document.createElement("a"); + link.href = "https://en.wikipedia.org/wiki/Downgrade_attack"; + link.innerText = linkText; + explainer.innerHTML = explainer.innerHTML.replace(linkText, link.outerHTML); +} diff --git a/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/index.html b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/index.html new file mode 100644 index 0000000..bd6f743 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/index.html @@ -0,0 +1,25 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title></title> + <link href="style.css" rel="stylesheet"> + <script src="/external/codemirror/codemirror-5.31.0.min.js"></script> + <link href="/external/codemirror/codemirror-5.31.0.min.css" rel="stylesheet"> + <script src="/external/codemirror/codemirror-5.31.0.xml.min.js"></script> + </head> + <body> + <div class="section-header"><span class="section-header-span">Debugging Rulesets</span></div> + <div class="section-explainer"> + Enter ruleset XML below and click save when ready. These rulesets will be immediately activated upon saving, and will persist across restarts.<br> + <i>Warning</i>: This should only be used for debugging rulesets. This feature is not guaranteed to work reliably for regular usage.<br> + <i>Note</i>: Due to a bug in Chromium, it may be necessary to close the options ui before saving. + </div> + <div id="unsaved-text">There are unsaved changes! Be sure to save them for them to take effect.</div> + <textarea id="codemirror-textarea"></textarea> + <button type="button" id="save-button">Save</button> + <div id="saved-text">Saved!</div> + <script src="../send-message.js"></script> + <script src="ux.js"></script> + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/style.css b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/style.css new file mode 100644 index 0000000..e424c70 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/style.css @@ -0,0 +1,40 @@ +.cm-s-main{ + width: 100%; + height: 500px; +} + +.cm-s-saved{ + border: 1px solid black; +} + +.cm-s-unsaved{ + border: 1px solid red; +} + +.section-explainer{ + margin-bottom: 5px; +} + +.section-header{ + margin-bottom: 10px; +} + +.section-header-span{ + border-bottom: 1px solid #ccc; + font-size: 15px; +} + +#saved-text{ + display: none; + color: green; + font-weight: bold; + margin: 30px; +} + +#unsaved-text{ + font-weight: bold; + margin: 10px 0px; + color: red; + visibility: hidden; + text-align: center; +} diff --git a/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/ux.js b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/ux.js new file mode 100644 index 0000000..be6c8b5 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/debugging-rulesets/ux.js @@ -0,0 +1,44 @@ +/* global sendMessage, CodeMirror */ + +"use strict"; + +const savedTextElement = document.getElementById("saved-text"); +const unsavedTextElement = document.getElementById("unsaved-text"); +const savedTitle = "Debugging Rulesets"; +const unsavedTitle = "* Debugging Rulesets"; + +document.title = savedTitle; + +const cm = CodeMirror.fromTextArea( + document.getElementById("codemirror-textarea"), + { + mode: "xml", + theme: "default main saved" + } +); + +let valueHasChanged = false; +sendMessage("get_option", { debugging_rulesets: "" }, item => { + cm.setValue(item.debugging_rulesets); + cm.on("change", cm => { + if (!(valueHasChanged)) { + valueHasChanged = true; + document.title = unsavedTitle; + cm.setOption("theme", "default main unsaved"); + unsavedTextElement.style.visibility = "visible"; + } + }); +}); + +document.getElementById("save-button").addEventListener("click", e => { + e.preventDefault(); + sendMessage("set_option", { debugging_rulesets: cm.getValue() }, () => { + savedTextElement.style.display = "block"; + setTimeout(() => { savedTextElement.style.display = "none" }, 1000); + + valueHasChanged = false; + document.title = savedTitle; + cm.setOption("theme", "default main saved"); + unsavedTextElement.style.visibility = "hidden"; + }); +}); diff --git a/data/extensions/https-everywhere@eff.org/pages/devtools/index.html b/data/extensions/https-everywhere@eff.org/pages/devtools/index.html new file mode 100644 index 0000000..02711dc --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/devtools/index.html @@ -0,0 +1,10 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title></title> + <script src="../send-message.js"></script> + <script src="ux.js"></script> + </head> + <body></body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/devtools/panel-ux.js b/data/extensions/https-everywhere@eff.org/pages/devtools/panel-ux.js new file mode 100644 index 0000000..2cd6a56 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/devtools/panel-ux.js @@ -0,0 +1,131 @@ +"use strict"; + +function e(id) { + return document.getElementById(id); +} + +/** + * Send message to main extension for HTML to display + * @param type: enable/disable + */ +function sendMessage(type) { + chrome.runtime.sendMessage({ + type: type, + tabId: chrome.devtools.inspectedWindow.tabId, + }); +} + +/** + * Turn on the Switch Planner recording mode, and hide the long description. + */ +function enableSwitchPlanner() { + sendMessage("enable"); + e("SwitchPlannerDescription").style.display = "none"; + e("SwitchPlannerDetails").style.display = "block"; + // Hack: Fetch and display summary information from background page + // once per second. + setInterval(display, 1000); + chrome.devtools.inspectedWindow.reload(); +} + +/** + * Disable the switch planner and reload, so any state is forgotten and + * the long description is restored. + */ +function disableSwitchPlanner() { + sendMessage("disable"); + document.location.reload(); +} + +/** + * Fetch summary HTML of the planner results from the background page for + * display in the devtools panel. + */ +function display() { + chrome.runtime.sendMessage({ + type: "getHosts", + tabId: chrome.devtools.inspectedWindow.tabId, + }, function(response) { + var switch_planner_details = e("SwitchPlannerDetails"); + while (switch_planner_details.firstChild) { + switch_planner_details.removeChild(switch_planner_details.firstChild); + } + + var nrw_text_div = document.createElement("div"); + nrw_text_div.innerText = "Unrewritten HTTP resources loaded from this tab (enable HTTPS on these domains and add them to HTTPS Everywhere):" + var nrw_div = switchPlannerSmallHtmlSection(response.nrw); + var rw_text_div = document.createElement("div"); + rw_text_div.style.marginTop = "20px"; + rw_text_div.innerText = "Resources rewritten successfully from this tab (update these in your source code):" + var rw_div = switchPlannerSmallHtmlSection(response.rw); + + switch_planner_details.appendChild(nrw_text_div); + switch_planner_details.appendChild(nrw_div); + switch_planner_details.appendChild(rw_text_div); + switch_planner_details.appendChild(rw_div); + + e("SwitchPlannerResults").style.display = "block"; + }); +} + +/** +* Format the switch planner output for presentation to a user. +* */ +function switchPlannerSmallHtmlSection(asset_host_list) { + var wrapper_div = document.createElement("div"); + if (asset_host_list.length == 0) { + wrapper_div.style.fontWeight = "bold"; + wrapper_div.innerText = "none"; + return wrapper_div; + } + + for (var i = asset_host_list.length - 1; i >= 0; i--) { + var host = asset_host_list[i][3]; + var activeCount = asset_host_list[i][1]; + var passiveCount = asset_host_list[i][2]; + + var div = document.createElement("div"); + var b = document.createElement("b"); + b.innerText = host; + div.appendChild(b); + + var text_arr = []; + if (activeCount > 0) { + text_arr.push(activeCount + " active"); + } + if (passiveCount > 0) { + text_arr.push(passiveCount + " passive"); + } + div.appendChild(document.createTextNode(": " + text_arr.join(', '))); + + wrapper_div.appendChild(div); + } + return wrapper_div; +} + +window.onload = function() { + // Open a connection to the background page. Right now this is only used + // by the background page so it knows when the devtools pane has closed. + // We don't receive messages from the background page currently, though that + // may be a future improvement. Sending messages to the background page doesn't + // require an existing connection. + chrome.runtime.connect({ name: "devtools-page" }); + + var checkbox = e("SwitchPlannerCheckbox"); + checkbox.addEventListener("change", function() { + if (checkbox.checked) { + enableSwitchPlanner(); + } else { + disableSwitchPlanner(); + } + }); + + e("SwitchPlannerDetailsLink").addEventListener("click", function() { + window.open("/pages/switch-planner/index.html?tab=" + chrome.devtools.inspectedWindow.tabId); + }); + // Since this is rendered in a devtools console, we have to make clicks on the + // link open a new window. + e("MixedContentLink").addEventListener("click", function(e) { + window.open(e.target.href); + }); +}; diff --git a/data/extensions/https-everywhere@eff.org/pages/devtools/panel.html b/data/extensions/https-everywhere@eff.org/pages/devtools/panel.html new file mode 100644 index 0000000..f5f6859 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/devtools/panel.html @@ -0,0 +1,38 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title></title> + <style> + html { + background: #fff; + color: #000; + } + </style> + </head> + <body> + <div id="SwitchPlanner"> + <input type="checkbox" id="SwitchPlannerCheckbox"> + <label for="SwitchPlannerCheckbox">Enable HTTPS Switch Planner mode (reloads page).</label> + <br> + <div id="SwitchPlannerDescription"> + <p>Switch Planner mode helps prepare for your site's switch to HTTPS by generating a report of external HTTP + resources that might not yet be available on HTTPS.</p> + <p>After enabling, navigate around your site and try to exercise all functionality in order to get a + comprehensive list of external resources.</p> + <p>For each group of resources listed as "Unrewritten," find out whether they are available on HTTPS. If so: + add a rule to HTTPS Everywhere! If not: try to make them available over HTTPS or use a different resource or + provider. Otherwise your site will generate <a id="MixedContentLink" + href="https://developer.mozilla.org/en-US/docs/Security/MixedContent#Mixed_passive.2Fdisplay_content">Mixed + Content</a> (passive or active) errors when you turn on HTTPS.</p> + <p>For most accurate results, disable ad blockers before using. Closing this panel will deactivate Switch + Planner mode and clear stored data.</p> + </div> + <div id="SwitchPlannerResults" style="display: none"> + <div id="SwitchPlannerDetails"></div> + <a id="SwitchPlannerDetailsLink" href="javascript:void 0">details</a> + </div> + </div> + <script src="panel-ux.js"></script> + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/devtools/ux.js b/data/extensions/https-everywhere@eff.org/pages/devtools/ux.js new file mode 100644 index 0000000..8244cbf --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/devtools/ux.js @@ -0,0 +1,17 @@ +/* global sendMessage */ + +"use strict"; + +const defaultOptions = { + showDevtoolsTab: true +}; + +sendMessage("get_option", defaultOptions, item => { + if (item.showDevtoolsTab) { + chrome.devtools.panels.create("HTTPS Everywhere", + "/images/icons/icon-active-38.png", + "/pages/devtools/panel.html", + function() { } + ); + } +}); diff --git a/data/extensions/https-everywhere@eff.org/pages/options/index.html b/data/extensions/https-everywhere@eff.org/pages/options/index.html new file mode 100644 index 0000000..d72d279 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/options/index.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title></title> + <link href="style.css" rel="stylesheet"> + </head> + <body> + <span class="section-header-span active" data-show="general-settings-wrapper" data-i18n="options_generalSettings"></span> + <span class="section-header-span inactive" data-show="advanced-settings-wrapper" data-i18n="options_advancedSettings"></span> + <span class="section-header-span inactive" data-show="update-channels-wrapper" data-i18n="options_updateChannels"></span> + + <div class="section-wrapper" id="general-settings-wrapper"> + <div id="counter-wrapper" class="settings-wrapper"> + <input type="checkbox" id="showCounter"> + <label for="showCounter" data-i18n="menu_showCounter"></label> + </div> + <div id="update-wrapper" class="settings-wrapper"> + <input type="checkbox" id="autoUpdateRulesets"> + <label for="autoUpdateRulesets" data-i18n="options_autoUpdateRulesets"></label> + </div> + </div> + + <div class="section-wrapper" id="advanced-settings-wrapper"> + <div id="mixed-rulesets-wrapper" class="settings-wrapper"> + <input type="checkbox" id="enableMixedRulesets"> + <label for="enableMixedRulesets" data-i18n="options_enableMixedRulesets"></label> + </div> + <div id="show-devtools-tab-wrapper" class="settings-wrapper"> + <input type="checkbox" id="showDevtoolsTab"> + <label for="showDevtoolsTab" data-i18n="options_showDevtoolsTab"></label> + </div> + </div> + + <div class="section-wrapper" id="update-channels-wrapper"> + <div id="update-channels-error"> + <span id="update-channels-error-text"></span> + <img id="update-channels-error-hide" src="/images/remove.png"> + </div> + <div id="update-channels-warning" data-i18n="options_updateChannelsWarning"></div> + <div id="update-channels-last-checked"></div> + <div class="clearer"></div> + <div id="update-channels-list"></div> + <div id="add-update-channel-wrapper"> + <button id="add-update-channel" data-i18n="options_addUpdateChannel"></button> + <input type="text" id="update-channel-name" /> + </div> + </div> + + <script src="ux.js"></script> + <script src="../translation.js"></script> + <script src="../send-message.js"></script> + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/options/style.css b/data/extensions/https-everywhere@eff.org/pages/options/style.css new file mode 100644 index 0000000..0e7b545 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/options/style.css @@ -0,0 +1,147 @@ +body{ + min-width: 500px; + display: block; +} + +.settings-wrapper{ + margin: 10px 0 0 0; +} + +.settings-wrapper#update-wrapper{ + margin-bottom: 20px; +} + +.settings-wrapper#show-devtools-tab-wrapper{ + margin-bottom: 20px; +} + +.section-header{ + margin-bottom: 10px; +} + +#import{ + margin-bottom: 10px; + float: right; +} + +#import-confirmed{ + display: none; +} + +.section-header-span{ + font-size: 15px; + border: 0px; + border-radius: 13px; + padding: 8px; + margin-right: 10px; + display: inline-block; +} + +.section-header-span.active{ + background-color: #66ccff; +} + +.section-header-span.inactive{ + background-color: #ddd; +} + +.update-channel{ + margin-top: 30px; + margin-bottom: 30px; + border: 1px solid grey; + border-radius: 20px; + width: 498px; +} + +.update-channel-name{ + font-weight: bold; + font-size: 14px; + margin: 10px; +} + +.update-channel-column-left { + width: 89px; + float: left; + font-size: 13px; + text-align: right; + margin-right: 10px; + min-height: 1px; +} + +.update-channel-column-right { + float: left; + width: 380px; +} + +textarea.update-channel-jwk { + width: 380px; + height: 250px; +} + +input.update-channel-path-prefix { + width: 367px; +} + +.update-channel-column-right button { + float: right; + margin: 10px; + border-radius: 7px; +} + +button#add-update-channel{ + float: right; + margin: 0px 10px 10px 10px; + border-radius: 7px; +} + +input#update-channel-name{ + float: right; +} + +.clearer{ + clear: both; +} + +.update-channel-last-updated { + float: right; + font-weight: lighter; + font-size: 10px; +} + +div#update-channels-error, div#update-channels-warning { + margin-top: 20px; + font-weight: bold; + padding: 10px; + border-radius: 10px; +} + +div#update-channels-error { + background-color: #CC3333; + display: none; + color: white; +} + +div#update-channels-warning { + background-color: #FFCC00; + font-color: black; +} + +#update-channels-error-text{ + display: inline-block; + width: 460px; +} + +img#update-channels-error-hide { + float: right; +} + +div#update-channels-last-checked { + margin-top: 10px; + float: right; + font-weight: bold; + font-size: 10px; +} + +#update-channels-wrapper{ + width: 500px; +} diff --git a/data/extensions/https-everywhere@eff.org/pages/options/ux.js b/data/extensions/https-everywhere@eff.org/pages/options/ux.js new file mode 100644 index 0000000..7a4306c --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/options/ux.js @@ -0,0 +1,258 @@ +/* global sendMessage */ + +"use strict"; + +document.addEventListener("DOMContentLoaded", () => { + + const showCounter = document.getElementById("showCounter"); + const autoUpdateRulesets = document.getElementById("autoUpdateRulesets"); + const enableMixedRulesets = document.getElementById("enableMixedRulesets"); + const showDevtoolsTab = document.getElementById("showDevtoolsTab"); + + const defaultOptions = { + showCounter: true, + autoUpdateRulesets: false, + enableMixedRulesets: false, + showDevtoolsTab: true + }; + + sendMessage("get_option", defaultOptions, item => { + showCounter.checked = item.showCounter; + autoUpdateRulesets.checked = item.autoUpdateRulesets; + enableMixedRulesets.checked = item.enableMixedRulesets; + showDevtoolsTab.checked = item.showDevtoolsTab; + + showCounter.addEventListener("change", () => { + sendMessage("set_option", { showCounter: showCounter.checked }); + }); + + autoUpdateRulesets.addEventListener("change", () => { + sendMessage("set_option", { autoUpdateRulesets: autoUpdateRulesets.checked }); + }); + + enableMixedRulesets.addEventListener("change", () => { + sendMessage("set_option", { enableMixedRulesets: enableMixedRulesets.checked }); + }); + + showDevtoolsTab.addEventListener("change", () => { + sendMessage("set_option", { showDevtoolsTab: showDevtoolsTab.checked }); + }); + }); + + function onlyShowSection(sectionId){ + document.querySelectorAll('.section-wrapper').forEach(sw => { + sw.style.display = "none"; + }); + document.getElementById(sectionId).style.display = "block"; + } + onlyShowSection('general-settings-wrapper'); + + document.querySelectorAll('.section-header-span').forEach(shs => { + shs.addEventListener("click", () => { + document.querySelectorAll('.section-header-span').forEach(shs => { + shs.classList.remove("active"); + shs.classList.add("inactive"); + }); + shs.classList.remove("inactive"); + shs.classList.add("active"); + onlyShowSection(shs.dataset.show); + }); + }); + + function create_update_channel_element(update_channel, last_updated, pinned){ + let ruleset_version_string; + + if(last_updated){ + const ruleset_date = new Date(last_updated * 1000); + ruleset_version_string = ruleset_date.getUTCFullYear() + "." + (ruleset_date.getUTCMonth() + 1) + "." + ruleset_date.getUTCDate(); + } else { + ruleset_version_string = "n/a"; + } + + const update_channel_div = document.createElement('div'); + update_channel_div.className = "update-channel"; + + const update_channel_name = document.createElement('div'); + update_channel_name.className = "update-channel-name"; + update_channel_name.innerText = update_channel.name; + update_channel_div.appendChild(update_channel_name); + const update_channel_last_updated = document.createElement('div'); + update_channel_last_updated.className = "update-channel-last-updated"; + update_channel_last_updated.innerText = chrome.i18n.getMessage("options_storedRulesetsVersion") + ruleset_version_string; + update_channel_name.appendChild(update_channel_last_updated); + + const update_channel_row_jwk = document.createElement('div'); + update_channel_row_jwk.className = "update-channel-row-jwk"; + update_channel_div.appendChild(update_channel_row_jwk); + const update_channel_jwk_column_left = document.createElement('div'); + update_channel_jwk_column_left.className = "update-channel-column-left"; + update_channel_jwk_column_left.innerText = "JWK:"; + update_channel_row_jwk.appendChild(update_channel_jwk_column_left); + const update_channel_jwk_column_right = document.createElement('div'); + update_channel_jwk_column_right.className = "update-channel-column-right"; + update_channel_row_jwk.appendChild(update_channel_jwk_column_right); + const update_channel_jwk = document.createElement('textarea'); + update_channel_jwk.className = "update-channel-jwk"; + update_channel_jwk.setAttribute("data-name", update_channel.name); + update_channel_jwk.disabled = pinned; + update_channel_jwk.innerText = JSON.stringify(update_channel.jwk); + update_channel_jwk_column_right.appendChild(update_channel_jwk); + + const update_channel_row_path_prefix = document.createElement('div'); + update_channel_row_path_prefix.className = "update-channel-row-path-prefix"; + update_channel_div.appendChild(update_channel_row_path_prefix); + const update_channel_path_prefix_column_left = document.createElement('div'); + update_channel_path_prefix_column_left.className = "update-channel-column-left"; + update_channel_path_prefix_column_left.innerText = "Path Prefix:"; + update_channel_row_path_prefix.appendChild(update_channel_path_prefix_column_left); + const update_channel_path_prefix_column_right = document.createElement('div'); + update_channel_path_prefix_column_right.className = "update-channel-column-right"; + update_channel_row_path_prefix.appendChild(update_channel_path_prefix_column_right); + const update_channel_path_prefix = document.createElement('input'); + update_channel_path_prefix.setAttribute("type", "text"); + update_channel_path_prefix.className = "update-channel-path-prefix"; + update_channel_path_prefix.setAttribute("data-name", update_channel.name); + update_channel_path_prefix.disabled = pinned; + update_channel_path_prefix.value = update_channel.update_path_prefix; + update_channel_path_prefix_column_right.appendChild(update_channel_path_prefix); + + const update_channel_row_controls = document.createElement('div'); + update_channel_row_controls.className = "update-channel-row-controls"; + update_channel_div.appendChild(update_channel_row_controls); + const update_channel_controls_column_left = document.createElement('div'); + update_channel_controls_column_left.className = "update-channel-column-left"; + update_channel_controls_column_left.innerText = " "; + update_channel_row_controls.appendChild(update_channel_controls_column_left); + const update_channel_controls_column_right = document.createElement('div'); + update_channel_controls_column_right.className = "update-channel-column-right"; + update_channel_row_controls.appendChild(update_channel_controls_column_right); + const update_channel_update = document.createElement('button'); + update_channel_update.className = "update-channel-update"; + update_channel_update.setAttribute("data-name", update_channel.name); + update_channel_update.disabled = pinned; + update_channel_update.innerText = chrome.i18n.getMessage("options_update"); + update_channel_controls_column_right.appendChild(update_channel_update); + const update_channel_delete = document.createElement('button'); + update_channel_delete.className = "update-channel-update"; + update_channel_delete.setAttribute("data-name", update_channel.name); + update_channel_delete.disabled = pinned; + update_channel_delete.innerText = chrome.i18n.getMessage("options_delete"); + update_channel_controls_column_right.appendChild(update_channel_delete); + + const clearer = document.createElement('div'); + clearer.className = "clearer"; + update_channel_div.appendChild(clearer); + + update_channel_delete.addEventListener("click", () => { + sendMessage("delete_update_channel", update_channel.name, () => { + render_update_channels(); + }); + }); + + update_channel_update.addEventListener("click", () => { + sendMessage("update_update_channel", { + name: update_channel.name, + jwk: JSON.parse(update_channel_jwk.value), + update_path_prefix: update_channel_path_prefix.value + }, () => { + render_update_channels(); + }); + }); + + return update_channel_div; + } + + function render_update_channels(){ + const update_channels_list = document.getElementById("update-channels-list"); + while(update_channels_list.firstChild){ + update_channels_list.removeChild(update_channels_list.firstChild); + } + + sendMessage("get_pinned_update_channels", null, item => { + for(const update_channel of item.update_channels){ + update_channels_list.appendChild( + create_update_channel_element( + update_channel, + item.last_updated[update_channel.name], + true + ) + ); + + } + }); + + sendMessage("get_stored_update_channels", null, item => { + for(const update_channel of item.update_channels){ + update_channels_list.appendChild( + create_update_channel_element( + update_channel, + item.last_updated[update_channel.name], + false + ) + ); + } + }); + } + render_update_channels(); + + const add_update_channel = document.getElementById("add-update-channel"); + const update_channel_name_div = document.getElementById("update-channel-name"); + const update_channels_error_text = document.getElementById("update-channels-error-text"); + const update_channels_error = document.getElementById("update-channels-error"); + update_channel_name_div.setAttribute("placeholder", chrome.i18n.getMessage("options_enterUpdateChannelName")); + + function displayError(text){ + update_channels_error_text.innerText = text; + update_channels_error.style.display = "block"; + window.scrollTo(0,0); + } + + add_update_channel.addEventListener("click", () => { + const update_channel_name = update_channel_name_div.value; + if(update_channel_name.trim() == ""){ + displayError("Error: The update channel name is blank. Please enter another name."); + } else { + update_channel_name_div.value = ""; + sendMessage("create_update_channel", update_channel_name, result => { + if(result == true){ + render_update_channels(); + } else { + displayError("Error: There already exists an update channel with this name."); + } + }); + } + }); + + const update_channels_error_hide = document.getElementById("update-channels-error-hide"); + update_channels_error_hide.addEventListener("click", () => { + update_channels_error.style.display = "none"; + }); + + const update_channels_last_checked = document.getElementById("update-channels-last-checked"); + sendMessage("get_last_checked", null, last_checked => { + let last_checked_string; + if(last_checked){ + const last_checked_date = new Date(last_checked * 1000); + const options = { + year: '2-digit', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + timeZoneName: 'short' + }; + const customDateTime = new Intl.DateTimeFormat('default', options).format; + last_checked_string = customDateTime(last_checked_date); + } else { + last_checked_string = chrome.i18n.getMessage("options_updatesLastCheckedNever"); + } + update_channels_last_checked.innerText = chrome.i18n.getMessage("options_updatesLastChecked") + last_checked_string; + }); + + document.onkeydown = function(evt) { + evt = evt || window.event; + if (evt.ctrlKey && evt.keyCode == 90) { + window.open("/pages/debugging-rulesets/index.html"); + } + }; +}); diff --git a/data/extensions/https-everywhere@eff.org/pages/popup/index.html b/data/extensions/https-everywhere@eff.org/pages/popup/index.html new file mode 100644 index 0000000..21dac99 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/popup/index.html @@ -0,0 +1,84 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title data-i18n="about_ext_name"></title> + + <link href="style.css" rel="stylesheet"> + <script src="ux.js"></script> + <script src="../translation.js"></script> + <script src="../send-message.js"></script> + </head> + <body> + <header> + <h1 data-i18n="about_ext_name"></h1> + </header> + + <section id="disableButton" class="options" style="visibility: hidden;"> + <div class="onoffswitch"> + <input id="onoffswitch" type="checkbox" checked><label data-i18n="menu_globalEnable" for="onoffswitch"></label> + </div> + </section> + + <section id="HttpNowhere" class="options" style="visibility: hidden;"> + <input id="http-nowhere-checkbox" type="checkbox"><label data-i18n="menu_blockUnencryptedRequests" for="http-nowhere-checkbox"></label> + </section> + + <div id="RuleManagement"> + <section> + <a href="javascript:void 0" id="add-rule-link" data-i18n="chrome_add_rule"></a> + <div id="add-new-rule-div" style="display: none"> + <h3 data-i18n="about_add_new_rule"></h3> + <p data-i18n="chrome_always_https_for_host"></p> + <label for="new-rule-host" data-i18n="chrome_host"></label><br> + <input size="50" id="new-rule-host" type="text" disabled><br> + <div id="new-rule-regular-text"> + <a href="javascript:void 0" id="new-rule-show-advanced-link" data-i18n="chrome_show_advanced"></a><br> + </div> + <div id="new-rule-advanced" style="display: none"> + <a href="javascript:void 0" id="new-rule-hide-advanced-link" data-i18n="chrome_hide_advanced"></a><br> + <br> + <label for="new-rule-name" data-i18n="chrome_rule_name"></label><br> + <input size="50" id="new-rule-name" type="text"><br> + <label for="new-rule-regex" data-i18n="chrome_regex"></label><br> + <input size="50" id="new-rule-regex" type="text"><br> + <label for="new-rule-redirect" data-i18n="chrome_redirect_to"></label><br> + <input size="50" id="new-rule-redirect" type="text"><br> + </div> + <button id="add-new-rule-button" data-i18n="chrome_add_new_rule"></button><br> + <button id="cancel-new-rule" data-i18n="chrome_status_cancel_button"></button> + </div> + </section> + + <section id="StableRules" class="rules"> + <h3 data-i18n="chrome_stable_rules"></h3> + <p class="description" data-i18n="chrome_stable_rules_description"></p> + </section> + + <section id="UnstableRules" class="rules"> + <h3 data-i18n="chrome_experimental_rules"></h3> + <p class="description" data-i18n="chrome_experimental_rules_description"></p> + </section> + + <section id="resetButton" class="options"> + <a href="javascript:void 0" id="reset-to-defaults" data-i18n="prefs_reset_defaults"></a> + </section> + </div> + + <footer> + <a id="viewAllRules" href="https://www.eff.org/https-everywhere/atlas" target="_blank" data-i18n="menu_viewAllRules"></a><br> + <br> + <a id="aboutTitle" href="https://www.eff.org/https-everywhere" target="_blank" data-i18n="about_title"></a><br> + <br> + <a id="donateEFF" href="https://supporters.eff.org/donate/support-https-everywhere" target="_blank" data-i18n="menu_donate_eff_imperative"></a> + <p> + <small> + <span data-i18n="about_version">Version</span>: <span id="current-version"></span> + <span id="rulesets-versions"> + </span> + </small> + </p> + </footer> + + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/popup/style.css b/data/extensions/https-everywhere@eff.org/pages/popup/style.css new file mode 100644 index 0000000..a1cc358 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/popup/style.css @@ -0,0 +1,128 @@ +html { + background-color: #fff +} + +body { + cursor: default; + margin-left: 1em; + margin-right: 1em; + margin-top: 0; + margin-bottom: 0; + min-width: 20em; + font-family: 'Lucida Grande', 'Segoe UI', Tahoma, 'DejaVu Sans', Arial, sans-serif; + font-size: 75%; + color: #303942; +} + +p { + line-height: 1.8em; +} + +h1, h2, h3 { + user-select: none; + font-weight: normal; + line-height: 1; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.3em; + margin-bottom: 0.4em; +} + +h3 { + color: black; + font-size: 1.2em; + margin-bottom: 0.8em; +} + +a { + color: #15c; + text-decoration: underline; +} + +a:active { + color: #052577; +} + +/* Don't wrap text for important stuff. */ +h1, h2, h3, .rule > label { + white-space: nowrap; +} + +/* Hide rules & options if the extension is off. */ +.disabled #RuleManagement,.disabled #HttpNowhere { + display: none; +} + +/* Initially hide section (until rules get added). */ +section.rules { + display: none; +} + +.rule { + height: 25px; +} + +.rule label { + padding: 0; + max-width: 93%; + overflow: hidden; +} + +/* Underline rules that have notes. */ +.rule[title] span { + border-bottom: 1px dotted; + cursor: help; +} + +input[type='checkbox'] { + vertical-align: middle; +} + +.rule img.remove { + float: right; +} + +header { + border-bottom: 1px solid #eee; +} + +header > h1 { + margin: 0; + padding: 21px 0 13px; +} + +section { + padding-left: 18px; + padding-top: 9px; + padding-bottom: 9px; +} + +section > h3 { + margin-left: -18px; +} + +footer { + border-top: 1px solid #eee; + margin-top: 8px; + padding-top: 8px; + padding-bottom: 8px; +} + +/* By default the "Add a rule" link is hidden. It's shown on HTTPS sites only. */ +#add-rule-link { + display: none; +} + +#rulesets-versions{ + display: block; + clear: both; +} + +.rulesets-version{ + display: block; +} diff --git a/data/extensions/https-everywhere@eff.org/pages/popup/ux.js b/data/extensions/https-everywhere@eff.org/pages/popup/ux.js new file mode 100644 index 0000000..a35c00c --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/popup/ux.js @@ -0,0 +1,281 @@ +/* global sendMessage */ + +"use strict"; + +function e(id) { + return document.getElementById(id); +} + +/** + * Handles rule (de)activation in the popup + */ +function toggleRuleLine(event) { + if (event.target.matches("input[type=checkbox]")) { + getTab(activeTab => { + const set_ruleset = { + active: event.target.checked, + name: event.target.nextSibling.innerText, + tab_id: activeTab.id, + }; + + sendMessage("set_ruleset_active_status", set_ruleset, () => { + // purge the name from the cache so that this unchecking is persistent. + sendMessage("delete_from_ruleset_cache", set_ruleset.name, () => { + // Now reload the selected tab of the current window. + chrome.tabs.reload(set_ruleset.tab_id); + }); + }); + }); + } +} + + +/** + * Creates rule lines (including checkbox and icon) for the popup + * @param rulesets + * @param list_div + * @returns {*} + */ +function appendRulesToListDiv(rulesets, list_div) { + if (rulesets && rulesets.length) { + // template parent block for each ruleset + let templateLine = document.createElement("div"); + templateLine.className = "rule checkbox"; + + // label "container" + let templateLabel = document.createElement("label"); + + // checkbox + let templateCheckbox = document.createElement("input"); + templateCheckbox.type = "checkbox"; + + // label text + let templateLabelText = document.createElement("span"); + + // img "remove" button + let templateRemove = document.createElement("img"); + templateRemove.src = chrome.extension.getURL("images/remove.png"); + templateRemove.className = "remove"; + + templateLabel.appendChild(templateCheckbox); + templateLabel.appendChild(templateLabelText); + templateLine.appendChild(templateLabel); + + for (const ruleset of rulesets) { + let line = templateLine.cloneNode(true); + let checkbox = line.querySelector("input[type=checkbox]"); + let text = line.querySelector("span"); + + checkbox.checked = ruleset.active; + text.innerText = ruleset.name; + + if (ruleset.note && ruleset.note.length) { + line.title = ruleset.note; + + if (ruleset.note === "user rule") { + let remove = templateRemove.cloneNode(true); + line.appendChild(remove); + + remove.addEventListener("click", () => { + sendMessage("remove_rule", ruleset, () => { + list_div.removeChild(line); + }); + }); + } + } + list_div.appendChild(line); + } + show(list_div); + } +} + +function showHttpNowhereUI() { + // Set up checkbox for HTTP nowhere mode + getOption_('httpNowhere', false, function(item) { + if (item.httpNowhere) { + e('http-nowhere-checkbox').checked = true; + } + e('HttpNowhere').style.visibility = "visible"; + }); +}; + +// Change the UI to reflect extension enabled/disabled +function updateEnabledDisabledUI() { + getOption_('globalEnabled', true, function(item) { + e('onoffswitch').checked = item.globalEnabled; + e('disableButton').style.visibility = "visible"; + // Hide or show the rules sections + if (item.globalEnabled) { + document.body.className = "" + showHttpNowhereUI() + } else { + document.body.className = "disabled" + } + }); +} + +// Toggle extension enabled/disabled status +function toggleEnabledDisabled() { + var extension_toggle_effect = function() { + updateEnabledDisabledUI(); + // The extension state changed, so reload this tab. + chrome.tabs.reload(); + window.close(); + } + + getOption_('globalEnabled', true, function(item) { + setOption_('globalEnabled', !item.globalEnabled, extension_toggle_effect); + }); + +} + +/** + * Create the list of rules for a specific tab + * @param activeTab + */ +function gotTab(activeTab) { + sendMessage("get_active_rulesets", activeTab.id, function(rulesets) { + if (rulesets) { + const stableRules = rulesets.filter(ruleset => ruleset.default_state); + const unstableRules = rulesets.filter(ruleset => !ruleset.default_state); + + appendRulesToListDiv(stableRules, e("StableRules")); + appendRulesToListDiv(unstableRules, e("UnstableRules")); + + // Add listener to capture the toggle event + e("RuleManagement").addEventListener("click", toggleRuleLine); + } + + // Only show the "Add a rule" link if we're on an HTTPS page + if (/^https:/.test(activeTab.url)) { + show(e("add-rule-link")); + } + }); +} + +/** + * Fill in content into the popup on load + */ +document.addEventListener("DOMContentLoaded", function () { + getTab(gotTab); + + // Set up the enabled/disabled switch & hide/show rules + updateEnabledDisabledUI(); + e('onoffswitch').addEventListener('click', toggleEnabledDisabled); + e('http-nowhere-checkbox').addEventListener('click', toggleHttpNowhere, false); + e('reset-to-defaults').addEventListener('click', () => { + if (confirm(chrome.i18n.getMessage("prefs_reset_defaults_message"))) { + sendMessage("reset_to_defaults", null, () => { + window.close(); + }); + } + }); + + // Print the extension's current version. + var the_manifest = chrome.runtime.getManifest(); + var version_info = e('current-version'); + version_info.innerText = the_manifest.version; + + let rulesets_versions = e('rulesets-versions'); + sendMessage("get_ruleset_timestamps", null, timestamps => { + for(let [update_channel, timestamp] of timestamps){ + if(timestamp > 0){ + let ruleset_date = new Date(timestamp * 1000); + let ruleset_version_string = ruleset_date.getUTCFullYear() + "." + (ruleset_date.getUTCMonth() + 1) + "." + ruleset_date.getUTCDate(); + + let timestamp_span = document.createElement("span"); + timestamp_span.className = "rulesets-version"; + timestamp_span.innerText = chrome.i18n.getMessage("about_rulesets_version") + " " + update_channel + ": " + ruleset_version_string; + rulesets_versions.appendChild(timestamp_span); + } + } + }); + e("aboutTitle").title = chrome.i18n.getMessage("about_title"); + e("add-rule-link").addEventListener("click", addManualRule); +}); + + +var escapeForRegex = function( value ) { + return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); +}; + +function hide(elem) { + elem.style.display = "none"; +} + +function show(elem) { + elem.style.display = "block"; +} + +/** + * Handles the manual addition of rules + */ +function addManualRule() { + getTab(function(tab) { + hide(e("add-rule-link")); + show(e("add-new-rule-div")); + + const url = new URL(tab.url); + + e("new-rule-host").value = url.host; + + const escapedHost = escapeForRegex(url.host); + + e("new-rule-regex").value = `^http://${escapedHost}/`; + e("new-rule-redirect").value = `https://${url.host}/`; + e("new-rule-name").value = "Manual rule for " + url.host; + + e("add-new-rule-button").addEventListener("click", function() { + const params = { + host : e("new-rule-host").value, + redirectTo : e("new-rule-redirect").value, + urlMatcher : e("new-rule-regex").value + }; + sendMessage("add_new_rule", params, function() { + location.reload(); + }); + }); + + e("cancel-new-rule").addEventListener("click", function() { + show(e("add-rule-link")); + hide(e("add-new-rule-div")); + }); + + e("new-rule-show-advanced-link").addEventListener("click", function() { + show(e("new-rule-advanced")); + hide(e("new-rule-regular-text")); + }); + + e("new-rule-hide-advanced-link").addEventListener("click", function() { + hide(e("new-rule-advanced")); + show(e("new-rule-regular-text")); + }); + }); +} + +function toggleHttpNowhere() { + getOption_('httpNowhere', false, function(item) { + setOption_('httpNowhere', !item.httpNowhere); + }); +} + +function getOption_(opt, defaultOpt, callback) { + var details = {}; + details[opt] = defaultOpt; + sendMessage("get_option", details, callback); +} + +function setOption_(opt, value, callback) { + var details = {}; + details[opt] = value; + sendMessage("set_option", details, callback); +} + +function getTab(callback) { + let url = new URL(window.location.href); + if (url.searchParams.has('tabId')) { + let parentId = Number(url.searchParams.get('tabId')); + return chrome.tabs.get(parentId, callback); + } + chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => callback(tabs[0])); +} diff --git a/data/extensions/https-everywhere@eff.org/pages/send-message.js b/data/extensions/https-everywhere@eff.org/pages/send-message.js new file mode 100644 index 0000000..da8adf5 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/send-message.js @@ -0,0 +1,7 @@ +/* exported sendMessage */ + +"use strict"; + +function sendMessage(type, object, callback) { + chrome.runtime.sendMessage({ type, object }, callback); +} diff --git a/data/extensions/https-everywhere@eff.org/pages/switch-planner/index.html b/data/extensions/https-everywhere@eff.org/pages/switch-planner/index.html new file mode 100644 index 0000000..5150fc2 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/switch-planner/index.html @@ -0,0 +1,11 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title></title> + </head> + <body> + <div id="content"></div> + <script src="ux.js"></script> + </body> +</html> diff --git a/data/extensions/https-everywhere@eff.org/pages/switch-planner/ux.js b/data/extensions/https-everywhere@eff.org/pages/switch-planner/ux.js new file mode 100644 index 0000000..1562f8f --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/switch-planner/ux.js @@ -0,0 +1,88 @@ +"use strict"; + +document.addEventListener("DOMContentLoaded", () => { + const background = chrome.extension.getBackgroundPage().require('./background'); + var tab = document.location.search.match(/tab=([^&]*)/)[1]; + var content = document.getElementById("content"); + + var nrw_text_div = document.createElement("div"); + nrw_text_div.innerText = "Unrewritten HTTP resources loaded from this tab (enable HTTPS on these domains and add them to HTTPS Everywhere):" + var nrw_div = switchPlannerDetailsHtmlSection( + background.sortSwitchPlanner(tab, "nrw"), + background.switchPlannerInfo[tab]["nrw"] + ); + var rw_text_div = document.createElement("div"); + rw_text_div.style.marginTop = "20px"; + rw_text_div.innerText = "Resources rewritten successfully from this tab (update these in your source code):" + var rw_div = switchPlannerDetailsHtmlSection( + background.sortSwitchPlanner(tab, "rw"), + background.switchPlannerInfo[tab]["rw"] + ); + + content.appendChild(nrw_text_div); + content.appendChild(nrw_div); + content.appendChild(rw_text_div); + content.appendChild(rw_div); +}); + +/** + * Generate the detailed html fot the switch planner, by section + * */ +function switchPlannerDetailsHtmlSection(asset_host_list, link_keys) { + var wrapper_div = document.createElement("div"); + if (asset_host_list.length == 0) { + wrapper_div.style.fontWeight = "bold"; + wrapper_div.innerText = "none"; + return wrapper_div; + } + + for (var i = asset_host_list.length - 1; i >= 0; i--) { + var host = asset_host_list[i][3]; + var activeCount = asset_host_list[i][1]; + var passiveCount = asset_host_list[i][2]; + + var div = document.createElement("div"); + div.style.marginTop = "20px"; + var b = document.createElement("b"); + b.innerText = host; + div.appendChild(b); + + if (activeCount > 0) { + var active_div = document.createElement("div"); + active_div.appendChild(document.createTextNode(activeCount + " active")); + for (const link of linksFromKeys(link_keys[host][1])) { + active_div.appendChild(link); + } + div.appendChild(active_div); + } + if (passiveCount > 0) { + var passive_div = document.createElement("div"); + passive_div.appendChild(document.createTextNode(passiveCount + " passive")); + for (const link of linksFromKeys(link_keys[host][0])) { + passive_div.appendChild(link); + } + div.appendChild(passive_div); + } + wrapper_div.appendChild(div); + } + return wrapper_div; +} + +/** + * Generate a HTML link from urls in map + * map: the map containing the urls + * */ +function linksFromKeys(map) { + if (typeof map == 'undefined') return ""; + var links = []; + for (var key in map) { + if (map.hasOwnProperty(key)) { + var link = document.createElement("a"); + link.style.display = "block"; + link.href = key; + link.innerText = key; + links.push(link); + } + } + return links; +} diff --git a/data/extensions/https-everywhere@eff.org/pages/translation.js b/data/extensions/https-everywhere@eff.org/pages/translation.js new file mode 100644 index 0000000..5cdbd99 --- /dev/null +++ b/data/extensions/https-everywhere@eff.org/pages/translation.js @@ -0,0 +1,8 @@ +"use strict"; + +document.addEventListener("DOMContentLoaded", () => { + // Auto-translate all elements with data-i18n attributes + for (const element of document.querySelectorAll("[data-i18n]")) { + element.innerText = chrome.i18n.getMessage(element.getAttribute("data-i18n")); + } +}); |