summaryrefslogtreecommitdiff
path: root/data/extensions/https-everywhere@eff.org/background.js
diff options
context:
space:
mode:
authorRuben Rodriguez <ruben@gnu.org>2018-09-13 20:39:48 -0400
committerRuben Rodriguez <ruben@gnu.org>2018-09-13 21:02:13 -0400
commitd26b319fd6f98517cc3421f10bf18698b953e4d2 (patch)
treebc70c4e472a2eaf514d411dba5067d530e5bbea9 /data/extensions/https-everywhere@eff.org/background.js
parentc3b304c51a3386ea09527a479a883253ea35243a (diff)
Updated extensions list for v60
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/background.js')
-rw-r--r--data/extensions/https-everywhere@eff.org/background.js647
1 files changed, 0 insertions, 647 deletions
diff --git a/data/extensions/https-everywhere@eff.org/background.js b/data/extensions/https-everywhere@eff.org/background.js
deleted file mode 100644
index 7b77731..0000000
--- a/data/extensions/https-everywhere@eff.org/background.js
+++ /dev/null
@@ -1,647 +0,0 @@
-"use strict";
-
-(function(exports) {
-
-const rules = require('./rules'),
- store = require('./store'),
- incognito = require('./incognito'),
- util = require('./util');
-
-
-let all_rules = new rules.RuleSets();
-
-async function initialize() {
- await store.initialize();
- await store.performMigrations();
- await initializeStoredGlobals();
- await all_rules.loadFromBrowserStorage(store);
- await incognito.onIncognitoDestruction(destroy_caches);
-}
-initialize();
-
-async function initializeAllRules() {
- const r = new rules.RuleSets();
- await r.loadFromBrowserStorage(store);
- Object.assign(all_rules, r);
-}
-
-/**
- * Load preferences. Structure is:
- * {
- * httpNowhere: Boolean,
- * showCounter: Boolean,
- * isExtensionEnabled: Boolean
- * }
- */
-var httpNowhereOn = false;
-var showCounter = true;
-var isExtensionEnabled = true;
-
-function initializeStoredGlobals(){
- return new Promise(resolve => {
- store.get({
- httpNowhere: false,
- showCounter: true,
- globalEnabled: true,
- enableMixedRulesets: false
- }, function(item) {
- httpNowhereOn = item.httpNowhere;
- showCounter = item.showCounter;
- isExtensionEnabled = item.globalEnabled;
- updateState();
-
- rules.settings.enableMixedRulesets = item.enableMixedRulesets;
-
- resolve();
- });
- });
-}
-
-chrome.storage.onChanged.addListener(async function(changes, areaName) {
- if (areaName === 'sync' || areaName === 'local') {
- if ('httpNowhere' in changes) {
- httpNowhereOn = changes.httpNowhere.newValue;
- updateState();
- }
- if ('showCounter' in changes) {
- showCounter = changes.showCounter.newValue;
- updateState();
- }
- if ('globalEnabled' in changes) {
- isExtensionEnabled = changes.globalEnabled.newValue;
- updateState();
- }
- if ('debugging_rulesets' in changes) {
- initializeAllRules();
- }
- }
-});
-
-if (chrome.tabs) {
- chrome.tabs.onActivated.addListener(function() {
- updateState();
- });
-}
-if (chrome.windows) {
- chrome.windows.onFocusChanged.addListener(function() {
- updateState();
- });
-}
-chrome.webNavigation.onCompleted.addListener(function() {
- updateState();
-});
-
-// Records which tabId's are active in the HTTPS Switch Planner (see
-// devtools-panel.js).
-var switchPlannerEnabledFor = {};
-// Detailed information recorded when the HTTPS Switch Planner is active.
-// Structure is:
-// switchPlannerInfo[tabId]["rw"/"nrw"][resource_host][active_content][url];
-// rw / nrw stand for "rewritten" versus "not rewritten"
-var switchPlannerInfo = {};
-
-function getActiveRulesetCount(id) {
- const applied = activeRulesets.getRulesets(id);
-
- if (!applied)
- {
- return 0;
- }
-
- let activeCount = 0;
-
- for (const key in applied) {
- if (applied[key].active) {
- activeCount++;
- }
- }
-
- return activeCount;
-}
-
-/**
- * Set the icon color correctly
- * active: extension is enabled.
- * blocking: extension is in "block all HTTP requests" mode.
- * disabled: extension is disabled from the popup menu.
- */
-
-function updateState () {
- if (!chrome.tabs) return;
-
- let iconState = 'active';
-
- if (!isExtensionEnabled) {
- iconState = 'disabled';
- } else if (httpNowhereOn) {
- iconState = 'blocking';
- }
-
- if ('setIcon' in chrome.browserAction) {
- chrome.browserAction.setIcon({
- path: {
- 38: 'icons/icon-' + iconState + '-38.png'
- }
- });
- }
-
- chrome.browserAction.setTitle({
- title: 'HTTPS Everywhere' + ((iconState === 'active') ? '' : ' (' + iconState + ')')
- });
-
- chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
- if (!tabs || tabs.length === 0) {
- return;
- }
- const tabId = tabs[0].id;
- const activeCount = getActiveRulesetCount(tabId);
-
- if ('setBadgeBackgroundColor' in chrome.browserAction) {
- chrome.browserAction.setBadgeBackgroundColor({ color: '#666666', tabId });
- }
-
- const showBadge = activeCount > 0 && isExtensionEnabled && showCounter;
-
- if ('setBadgeText' in chrome.browserAction) {
- chrome.browserAction.setBadgeText({ text: showBadge ? String(activeCount) : '', tabId });
- }
- });
-}
-
-/**
- * The following allows fennec to interact with the popup ui
- * */
-chrome.browserAction.onClicked.addListener(e => {
- const url = chrome.extension.getURL("popup.html?tabId=" + e.id);
- chrome.tabs.create({
- url
- });
-});
-
-/**
- * Adds a listener for removed tabs
- * */
-function AppliedRulesets() {
- this.active_tab_rules = {};
-
- var that = this;
- if (chrome.tabs) {
- chrome.tabs.onRemoved.addListener(function(tabId) {
- that.removeTab(tabId);
- });
- }
-}
-
-AppliedRulesets.prototype = {
- addRulesetToTab: function(tabId, ruleset) {
- if (tabId in this.active_tab_rules) {
- this.active_tab_rules[tabId][ruleset.name] = ruleset;
- } else {
- this.active_tab_rules[tabId] = {};
- this.active_tab_rules[tabId][ruleset.name] = ruleset;
- }
- },
-
- getRulesets: function(tabId) {
- if (tabId in this.active_tab_rules) {
- return this.active_tab_rules[tabId];
- }
- return null;
- },
-
- removeTab: function(tabId) {
- delete this.active_tab_rules[tabId];
- }
-};
-
-// FIXME: change this name
-var activeRulesets = new AppliedRulesets();
-
-var urlBlacklist = new Set();
-
-// redirect counter workaround
-// TODO: Remove this code if they ever give us a real counter
-var redirectCounter = new Map();
-
-/**
- * Called before a HTTP(s) request. Does the heavy lifting
- * Cancels the request/redirects it to HTTPS. URL modification happens in here.
- * @param details of the handler, see Chrome doc
- * */
-function onBeforeRequest(details) {
- // If HTTPSe has been disabled by the user, return immediately.
- if (!isExtensionEnabled) {
- return;
- }
-
- let uri = new URL(details.url);
-
- // Normalise hosts with tailing dots, e.g. "www.example.com."
- let canonical_host = uri.hostname;
- while (canonical_host.charAt(canonical_host.length - 1) == ".") {
- canonical_host = canonical_host.slice(0, -1);
- uri.hostname = canonical_host;
- }
-
- // Should the request be canceled?
- const shouldCancel = httpNowhereOn &&
- uri.protocol === 'http:' &&
- uri.hostname.slice(-6) !== '.onion' &&
- uri.hostname !== 'localhost' &&
- !/^127(\.[0-9]{1,3}){3}$/.test(canonical_host) &&
- !/^0\.0\.0\.0$/.test(canonical_host) &&
- uri.hostname !== '[::1]';
-
- // If there is a username / password, put them aside during the ruleset
- // analysis process
- let using_credentials_in_url = false;
- let tmp_user;
- let tmp_pass;
- if (uri.password || uri.username) {
- using_credentials_in_url = true;
- tmp_user = uri.username;
- tmp_pass = uri.password;
- uri.username = '';
- uri.password = '';
- }
-
- var canonical_url = uri.href;
- if (details.url != canonical_url && !using_credentials_in_url) {
- util.log(util.INFO, "Original url " + details.url +
- " changed before processing to " + canonical_url);
- }
- if (urlBlacklist.has(canonical_url)) {
- return {cancel: shouldCancel};
- }
-
- if (details.type == "main_frame") {
- activeRulesets.removeTab(details.tabId);
- }
-
- var potentiallyApplicable = all_rules.potentiallyApplicableRulesets(canonical_host);
-
- if (redirectCounter.get(details.requestId) >= 8) {
- util.log(util.NOTE, "Redirect counter hit for " + canonical_url);
- urlBlacklist.add(canonical_url);
- rules.settings.domainBlacklist.add(canonical_host);
- util.log(util.WARN, "Domain blacklisted " + canonical_host);
- return {cancel: shouldCancel};
- }
-
- var newuristr = null;
-
- for (let ruleset of potentiallyApplicable) {
- activeRulesets.addRulesetToTab(details.tabId, ruleset);
- if (ruleset.active && !newuristr) {
- newuristr = ruleset.apply(canonical_url);
- }
- }
-
- // re-insert userpass info which was stripped temporarily
- if (using_credentials_in_url) {
- if (newuristr) {
- const uri_with_credentials = new URL(newuristr);
- uri_with_credentials.username = tmp_user;
- uri_with_credentials.password = tmp_pass;
- newuristr = uri_with_credentials.href;
- } else {
- const canonical_url_with_credentials = new URL(canonical_url);
- canonical_url_with_credentials.username = tmp_user;
- canonical_url_with_credentials.password = tmp_pass;
- canonical_url = canonical_url_with_credentials.href;
- }
- }
-
- // In Switch Planner Mode, record any non-rewriteable
- // HTTP URIs by parent hostname, along with the resource type.
- if (switchPlannerEnabledFor[details.tabId] && uri.protocol !== "https:") {
- writeToSwitchPlanner(details.type,
- details.tabId,
- canonical_host,
- details.url,
- newuristr);
- }
-
- if (httpNowhereOn) {
- // If loading a main frame, try the HTTPS version as an alternative to
- // failing.
- if (shouldCancel) {
- if (!newuristr) {
- return {redirectUrl: canonical_url.replace(/^http:/, "https:")};
- } else {
- return {redirectUrl: newuristr.replace(/^http:/, "https:")};
- }
- }
- if (newuristr && newuristr.substring(0, 5) === "http:") {
- // Abort early if we're about to redirect to HTTP in HTTP Nowhere mode
- return {cancel: true};
- }
- }
-
- if (newuristr) {
- return {redirectUrl: newuristr};
- } else {
- return {cancel: shouldCancel};
- }
-}
-
-
-// Map of which values for the `type' enum denote active vs passive content.
-// https://developer.chrome.com/extensions/webRequest.html#event-onBeforeRequest
-const mixedContentTypes = {
- object: 1, other: 1, script: 1, stylesheet: 1, sub_frame: 1, xmlhttprequest: 1,
- image: 0, main_frame: 0
-};
-
-/**
- * Record a non-HTTPS URL loaded by a given hostname in the Switch Planner, for
- * use in determining which resources need to be ported to HTTPS.
- * (Reminder: Switch planner is the pro-tool enabled by switching into debug-mode)
- *
- * @param type: type of the resource (see activeTypes and passiveTypes arrays)
- * @param tab_id: The id of the tab
- * @param resource_host: The host of the original url
- * @param resource_url: the original url
- * @param rewritten_url: The url rewritten to
- * */
-function writeToSwitchPlanner(type, tab_id, resource_host, resource_url, rewritten_url) {
- let rw = rewritten_url ? "rw" : "nrw";
-
- let active_content = 1;
- if (mixedContentTypes.hasOwnProperty(type)) {
- active_content = mixedContentTypes[type];
- } else {
- util.log(util.WARN, "Unknown type from onBeforeRequest details: `" + type + "', assuming active");
- }
-
- if (!switchPlannerInfo[tab_id]) {
- switchPlannerInfo[tab_id] = {};
- switchPlannerInfo[tab_id]["rw"] = {};
- switchPlannerInfo[tab_id]["nrw"] = {};
- }
- if (!switchPlannerInfo[tab_id][rw][resource_host])
- switchPlannerInfo[tab_id][rw][resource_host] = {};
- if (!switchPlannerInfo[tab_id][rw][resource_host][active_content])
- switchPlannerInfo[tab_id][rw][resource_host][active_content] = {};
-
- switchPlannerInfo[tab_id][rw][resource_host][active_content][resource_url] = 1;
-}
-
-/**
- * Return the number of properties in an object. For associative maps, this is
- * their size.
- * @param obj: object to calc the size for
- * */
-function objSize(obj) {
- if (typeof obj == 'undefined') return 0;
- var size = 0, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) size++;
- }
- return size;
-}
-
-/**
- * Make an array of asset hosts by score so we can sort them,
- * presenting the most important ones first.
- * */
-function sortSwitchPlanner(tab_id, rewritten) {
- var asset_host_list = [];
- if (typeof switchPlannerInfo[tab_id] === 'undefined' ||
- typeof switchPlannerInfo[tab_id][rewritten] === 'undefined') {
- return [];
- }
- var tabInfo = switchPlannerInfo[tab_id][rewritten];
- for (var asset_host in tabInfo) {
- var ah = tabInfo[asset_host];
- var activeCount = objSize(ah[1]);
- var passiveCount = objSize(ah[0]);
- var score = activeCount * 100 + passiveCount;
- asset_host_list.push([score, activeCount, passiveCount, asset_host]);
- }
- asset_host_list.sort(function(a,b){return a[0]-b[0];});
- return asset_host_list;
-}
-
-/**
- * monitor cookie changes. Automatically convert them to secure cookies
- * @param changeInfo Cookie changed info, see Chrome doc
- * */
-function onCookieChanged(changeInfo) {
- if (!changeInfo.removed && !changeInfo.cookie.secure && isExtensionEnabled) {
- if (all_rules.shouldSecureCookie(changeInfo.cookie)) {
- var cookie = {name:changeInfo.cookie.name,
- value:changeInfo.cookie.value,
- path:changeInfo.cookie.path,
- httpOnly:changeInfo.cookie.httpOnly,
- expirationDate:changeInfo.cookie.expirationDate,
- storeId:changeInfo.cookie.storeId,
- secure: true};
-
- // Host-only cookies don't set the domain field.
- if (!changeInfo.cookie.hostOnly) {
- cookie.domain = changeInfo.cookie.domain;
- }
-
- // The cookie API is magical -- we must recreate the URL from the domain and path.
- if (changeInfo.cookie.domain[0] == ".") {
- cookie.url = "https://www" + changeInfo.cookie.domain + cookie.path;
- } else {
- cookie.url = "https://" + changeInfo.cookie.domain + cookie.path;
- }
- // We get repeated events for some cookies because sites change their
- // value repeatedly and remove the "secure" flag.
- util.log(util.DBUG,
- "Securing cookie " + cookie.name + " for " + changeInfo.cookie.domain + ", was secure=" + changeInfo.cookie.secure);
- chrome.cookies.set(cookie);
- }
- }
-}
-
-/**
- * handling redirects, breaking loops
- * @param details details for the redirect (see chrome doc)
- * */
-function onBeforeRedirect(details) {
- // Catch redirect loops (ignoring about:blank, etc. caused by other extensions)
- let prefix = details.redirectUrl.substring(0, 5);
- if (prefix === "http:" || prefix === "https") {
- let count = redirectCounter.get(details.requestId);
- if (count) {
- redirectCounter.set(details.requestId, count + 1);
- util.log(util.DBUG, "Got redirect id "+details.requestId+
- ": "+count);
- } else {
- redirectCounter.set(details.requestId, 1);
- }
- }
-}
-
-/**
- * handle webrequest.onCompleted, cleanup redirectCounter
- * @param details details for the chrome.webRequest (see chrome doc)
- */
-function onCompleted(details) {
- if (redirectCounter.has(details.requestId)) {
- redirectCounter.delete(details.requestId);
- }
-}
-
-/**
- * handle webrequest.onErrorOccurred, cleanup redirectCounter
- * @param details details for the chrome.webRequest (see chrome doc)
- */
-function onErrorOccurred(details) {
- if (redirectCounter.has(details.requestId)) {
- redirectCounter.delete(details.requestId);
- }
-}
-
-// Registers the handler for requests
-// See: https://github.com/EFForg/https-everywhere/issues/10039
-chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["*://*/*"]}, ["blocking"]);
-
-
-// Try to catch redirect loops on URLs we've redirected to HTTPS.
-chrome.webRequest.onBeforeRedirect.addListener(onBeforeRedirect, {urls: ["https://*/*"]});
-
-// Cleanup redirectCounter if neccessary
-chrome.webRequest.onCompleted.addListener(onCompleted, {urls: ["*://*/*"]});
-
-// Cleanup redirectCounter if neccessary
-chrome.webRequest.onErrorOccurred.addListener(onErrorOccurred, {urls: ["*://*/*"]})
-
-// Listen for cookies set/updated and secure them if applicable. This function is async/nonblocking.
-chrome.cookies.onChanged.addListener(onCookieChanged);
-
-/**
- * disable switch Planner
- * @param tabId the Tab to disable for
- */
-function disableSwitchPlannerFor(tabId) {
- delete switchPlannerEnabledFor[tabId];
- // Clear stored URL info.
- delete switchPlannerInfo[tabId];
-}
-
-/**
- * Enable switch planner for specific tab
- * @param tabId the tab to enable it for
- */
-function enableSwitchPlannerFor(tabId) {
- switchPlannerEnabledFor[tabId] = true;
-}
-
-// Listen for connection from the DevTools panel so we can set up communication.
-chrome.runtime.onConnect.addListener(function (port) {
- if (port.name == "devtools-page") {
- chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
- var tabId = message.tabId;
-
- var disableOnCloseCallback = function() {
- util.log(util.DBUG, "Devtools window for tab " + tabId + " closed, clearing data.");
- disableSwitchPlannerFor(tabId);
- };
-
- if (message.type === "enable") {
- enableSwitchPlannerFor(tabId);
- port.onDisconnect.addListener(disableOnCloseCallback);
- } else if (message.type === "disable") {
- disableSwitchPlannerFor(tabId);
- } else if (message.type === "getHosts") {
- sendResponse({
- nrw: sortSwitchPlanner(tabId, "nrw"),
- rw: sortSwitchPlanner(tabId, "rw")
- });
- }
- });
- }
-});
-
-// This is necessary for communication with the popup in Firefox Private
-// Browsing Mode, see https://bugzilla.mozilla.org/show_bug.cgi?id=1329304
-chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
- if (message.type == "get_option") {
- store.get(message.object, sendResponse);
- return true;
- } else if (message.type == "set_option") {
- store.set(message.object, item => {
- if (sendResponse) {
- sendResponse(item);
- }
- });
- } else if (message.type == "delete_from_ruleset_cache") {
- all_rules.ruleCache.delete(message.object);
- } else if (message.type == "get_active_rulesets") {
- sendResponse(activeRulesets.getRulesets(message.object));
- } else if (message.type == "set_ruleset_active_status") {
- var ruleset = activeRulesets.getRulesets(message.object.tab_id)[message.object.name];
- ruleset.active = message.object.active;
- if (ruleset.default_state == message.object.active) {
- message.object.active = undefined;
- }
- all_rules.setRuleActiveState(message.object.name, message.object.active).then(() => {
- sendResponse(true);
- });
- return true;
- } else if (message.type == "add_new_rule") {
- all_rules.addNewRuleAndStore(message.object).then(() => {
- sendResponse(true);
- });
- return true;
- } else if (message.type == "remove_rule") {
- all_rules.removeRuleAndStore(message.object);
- } else if (message.type == "import_settings") {
- // This is used when importing settings from the options ui
- import_settings(message.object).then(() => {
- sendResponse(true);
- });
- }
-});
-
-/**
- * Import extension settings (custom rulesets, ruleset toggles, globals) from an object
- * @param settings the settings object
- */
-async function import_settings(settings) {
- if (settings && settings.changed) {
- let ruleActiveStates = {};
- // Load all the ruleset toggles into memory and store
- for (const ruleset_name in settings.rule_toggle) {
- ruleActiveStates[ruleset_name] = (settings.rule_toggle[ruleset_name] == "true");
- }
-
- // Save settings
- await new Promise(resolve => {
- store.set({
- legacy_custom_rulesets: settings.custom_rulesets,
- httpNowhere: settings.prefs.http_nowhere_enabled,
- showCounter: settings.prefs.show_counter,
- globalEnabled: settings.prefs.global_enabled,
- ruleActiveStates
- }, resolve);
- });
-
- initializeAllRules();
- }
-}
-
-/**
- * Clear any cache/ blacklist we have.
- */
-function destroy_caches() {
- util.log(util.DBUG, "Destroying caches.");
- all_rules.cookieHostCache.clear();
- all_rules.ruleCache.clear();
- rules.settings.domainBlacklist.clear();
- urlBlacklist.clear();
-}
-
-Object.assign(exports, {
- all_rules,
- urlBlacklist,
- sortSwitchPlanner,
- switchPlannerInfo
-});
-
-})(typeof exports == 'undefined' ? require.scopes.background = {} : exports);