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/background.js | |
parent | c3b304c51a3386ea09527a479a883253ea35243a (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.js | 647 |
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); |