summaryrefslogtreecommitdiff
path: root/data/extensions/https-everywhere@eff.org/components/https-everywhere.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/components/https-everywhere.js')
-rw-r--r--data/extensions/https-everywhere@eff.org/components/https-everywhere.js895
1 files changed, 0 insertions, 895 deletions
diff --git a/data/extensions/https-everywhere@eff.org/components/https-everywhere.js b/data/extensions/https-everywhere@eff.org/components/https-everywhere.js
deleted file mode 100644
index 81f6ad6..0000000
--- a/data/extensions/https-everywhere@eff.org/components/https-everywhere.js
+++ /dev/null
@@ -1,895 +0,0 @@
-// LOG LEVELS
-let VERB=1;
-let DBUG=2;
-let INFO=3;
-let NOTE=4;
-let WARN=5;
-
-// PREFERENCE BRANCHES
-let PREFBRANCH_ROOT=0;
-let PREFBRANCH_RULE_TOGGLE=1;
-let PREFBRANCH_NONE=2;
-
-// maps domain patterns (with at most one wildcard) to RuleSets
-let https_domains = {};
-// URLs we've given up on rewriting because of redirection loops
-let https_everywhere_blacklist = {};
-// domains for which there is at least one blacklisted URL
-let https_blacklist_domains = {};
-
-const CI = Components.interfaces;
-const CC = Components.classes;
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
-
-const SERVICE_CTRID = "@eff.org/https-everywhere;1";
-const SERVICE_ID=Components.ID("{32c165b4-fe5e-4964-9250-603c410631b4}");
-const SERVICE_NAME = "Encrypts your communications with a number of major websites";
-
-const LLVAR = "LogLevel";
-
-const IOS = CC["@mozilla.org/network/io-service;1"].getService(CI.nsIIOService);
-const OS = CC['@mozilla.org/observer-service;1'].getService(CI.nsIObserverService);
-const LOADER = CC["@mozilla.org/moz/jssubscript-loader;1"].getService(CI.mozIJSSubScriptLoader);
-const _INCLUDED = {};
-
-// NoScript uses this blob to include js constructs that stored in the chrome/
-// directory, but are not attached to the Firefox UI (normally, js located
-// there is attached to an Overlay and therefore is part of the UI).
-
-// Reasons for this: things in components/ directory cannot be split into
-// separate files; things in chrome/ can be
-
-const INCLUDE = function(name) {
- if (arguments.length > 1)
- for (var j = 0, len = arguments.length; j < len; j++)
- INCLUDE(arguments[j]);
- else if (!_INCLUDED[name]) {
- // we used to try/catch here, but that was less useful because it didn't
- // produce line numbers for syntax errors
- LOADER.loadSubScript("chrome://https-everywhere/content/code/"
- + name + ".js");
- _INCLUDED[name] = true;
- }
-};
-
-const WP_STATE_START = CI.nsIWebProgressListener.STATE_START;
-const WP_STATE_STOP = CI.nsIWebProgressListener.STATE_STOP;
-const WP_STATE_DOC = CI.nsIWebProgressListener.STATE_IS_DOCUMENT;
-const WP_STATE_START_DOC = WP_STATE_START | WP_STATE_DOC;
-const WP_STATE_RESTORING = CI.nsIWebProgressListener.STATE_RESTORING;
-
-const LF_VALIDATE_ALWAYS = CI.nsIRequest.VALIDATE_ALWAYS;
-const LF_LOAD_BYPASS_ALL_CACHES = CI.nsIRequest.LOAD_BYPASS_CACHE | CI.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE;
-
-const NS_OK = 0;
-const NS_BINDING_ABORTED = 0x804b0002;
-const NS_BINDING_REDIRECTED = 0x804b0003;
-const NS_ERROR_UNKNOWN_HOST = 0x804b001e;
-const NS_ERROR_REDIRECT_LOOP = 0x804b001f;
-const NS_ERROR_CONNECTION_REFUSED = 0x804b000e;
-const NS_ERROR_NOT_AVAILABLE = 0x804b0111;
-
-const LOG_CONTENT_BLOCK = 1;
-const LOG_CONTENT_CALL = 2;
-const LOG_CONTENT_INTERCEPT = 4;
-const LOG_CHROME_WIN = 8;
-const LOG_XSS_FILTER = 16;
-const LOG_INJECTION_CHECK = 32;
-const LOG_DOM = 64;
-const LOG_JS = 128;
-const LOG_LEAKS = 1024;
-const LOG_SNIFF = 2048;
-const LOG_CLEARCLICK = 4096;
-const LOG_ABE = 8192;
-
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-
-const WHERE_UNTRUSTED = 1;
-const WHERE_TRUSTED = 2;
-const ANYWHERE = 3;
-
-const N_COHORTS = 1000;
-
-const DUMMY_OBJ = {};
-DUMMY_OBJ.wrappedJSObject = DUMMY_OBJ;
-const DUMMY_FUNC = function() {};
-const DUMMY_ARRAY = [];
-
-const EARLY_VERSION_CHECK = !("nsISessionStore" in CI && typeof(/ /) === "object");
-
-// This is probably obsolete since the switch to the channel.redirectTo API
-const OBSERVER_TOPIC_URI_REWRITE = "https-everywhere-uri-rewrite";
-
-// XXX: Better plan for this?
-// We need it to exist to make our updates of ChannelReplacement.js easier.
-var ABE = {
- consoleDump: false,
- log: function(str) {
- https_everywhereLog(WARN, str);
- }
-};
-
-function xpcom_checkInterfaces(iid,iids,ex) {
- for (var j = iids.length; j-- >0;) {
- if (iid.equals(iids[j])) return true;
- }
- throw ex;
-}
-
-INCLUDE('ChannelReplacement', 'IOUtil', 'HTTPSRules', 'HTTPS', 'Thread', 'ApplicableList');
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function HTTPSEverywhere() {
-
- // Set up logging in each component:
- HTTPS.log = HTTPSRules.log = RuleWriter.log = this.log = https_everywhereLog;
-
- this.expandoMap = new WeakMap();
-
- this.log = https_everywhereLog;
- this.wrappedJSObject = this;
- this.https_rules = HTTPSRules;
- this.rw = RuleWriter; // currently used for some file IO helpers, though that
- // should probably be refactored
- this.INCLUDE=INCLUDE;
- this.ApplicableList = ApplicableList;
- this.browser_initialised = false; // the browser is completely loaded
-
-
- this.prefs = this.get_prefs();
- this.rule_toggle_prefs = this.get_prefs(PREFBRANCH_RULE_TOGGLE);
-
- this.httpNowhereEnabled = this.prefs.getBoolPref("http_nowhere.enabled");
- this.isMobile = this.doMobileCheck();
-
- // We need to use observers instead of categories for FF3.0 for these:
- // https://developer.mozilla.org/en/Observer_Notifications
- // https://developer.mozilla.org/en/nsIObserverService.
- // https://developer.mozilla.org/en/nsIObserver
- // We also use the observer service to let other extensions know about URIs
- // we rewrite.
- this.obsService = CC["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
-
- if (this.prefs.getBoolPref("globalEnabled")) {
- this.obsService.addObserver(this, "profile-before-change", false);
- this.obsService.addObserver(this, "profile-after-change", false);
- this.obsService.addObserver(this, "sessionstore-windows-restored", false);
- this.obsService.addObserver(this, "browser:purge-session-history", false);
- } else {
- // Need this to initialize FF for Android UI even when HTTPS-E is off
- if (this.isMobile) {
- this.obsService.addObserver(this, "sessionstore-windows-restored", false);
- }
- }
-
- var pref_service = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranchInternal);
- var branch = pref_service.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
-
- branch.addObserver("extensions.https_everywhere.enable_mixed_rulesets",
- this, false);
- branch.addObserver("security.mixed_content.block_active_content",
- this, false);
-
- return;
-}
-
-
-/*
-In recent versions of Firefox and HTTPS Everywhere, the call stack for performing an HTTP -> HTTPS rewrite looks like this:
-
-1. HTTPSEverywhere.observe() gets a callback with the "http-on-modify-request" topic, and the channel as a subject
-
-1. HTTPSEverywhere.shouldIgnoreURI() checks for very quick reasons to ignore a
-request, such as redirection loops, non-HTTP[S] URIs, and OCSP
-
- 2. HTTPS.replaceChannel()
-
- 3. HTTPSRules.rewrittenURI()
-
- 4. HTTPSRules.potentiallyApplicableRulesets uses <target host=""> elements to identify relevant rulesets
-
- foreach RuleSet:
-
- 4. RuleSet.transformURI()
-
- 5. RuleSet.apply() does the tests and rewrites with RegExps, returning a string
-
- 4. RuleSet.transformURI() makes a new uri object for the destination string, if required
-
- 2. HTTPS.replaceChannel() calls channel.redirectTo() if a redirect is needed
-
-
-In addition, the following other important tasks happen along the way:
-
-HTTPSEverywhere.observe() finds a reference to the ApplicableList or alist that represents the toolbar context menu
-
-HTTPS.replaceChannel() notices redirect loops (and used to do much more complex XPCOM API work in the NoScript-based past)
-
-HTTPSRules.rewrittenURI() works around weird URI types like about: and http://user:pass@example.com/
- and notifies the alist of what it should display for each ruleset
-
-*/
-
-// This defines for Mozilla what stuff HTTPSEverywhere will implement.
-
-// ChannelEventSink used to be necessary in order to handle redirects (eg
-// HTTP redirects) correctly. It may now be obsolete? XXX
-
-HTTPSEverywhere.prototype = {
- prefs: null,
- // properties required for XPCOM registration:
- classDescription: SERVICE_NAME,
- classID: SERVICE_ID,
- contractID: SERVICE_CTRID,
-
- _xpcom_factory: {
- createInstance: function (outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- if (!HTTPSEverywhere.instance)
- HTTPSEverywhere.instance = new HTTPSEverywhere();
- return HTTPSEverywhere.instance.QueryInterface(iid);
- },
-
- QueryInterface: XPCOMUtils.generateQI(
- [ Components.interfaces.nsISupports,
- Components.interfaces.nsIModule,
- Components.interfaces.nsIFactory ])
- },
-
- // [optional] an array of categories to register this component in.
- _xpcom_categories: [
- {
- category: "app-startup",
- }
- ],
-
- // QueryInterface implementation, e.g. using the generateQI helper
- QueryInterface: XPCOMUtils.generateQI(
- [ Components.interfaces.nsIObserver,
- Components.interfaces.nsISupports,
- Components.interfaces.nsISupportsWeakReference,
- Components.interfaces.nsIChannelEventSink ]),
-
- wrappedJSObject: null, // Initialized by constructor
-
- getWeakReference: function () {
- return Components.utils.getWeakReference(this);
- },
-
- // An "expando" is an attribute glued onto something. From NoScript.
- getExpando: function(browser, key) {
- let obj = this.expandoMap.get(browser);
- if (!obj) {
- if (browser.currentURI) {
- this.log(NOTE, "No expando for " + browser.currentURI.spec);
- }
- return null;
- }
- return obj[key];
- },
-
- setExpando: function(browser, key, value) {
- if (!this.expandoMap.has(browser)) {
- this.expandoMap.set(browser, {});
- }
- let obj = this.expandoMap.get(browser);
- obj[key] = value;
- },
-
- // We use resetApplicableList to make a fresh list of rulesets that could have
- // applied to the content in the current page (the "applicable list" is used
- // for the context menu in the UI). This will be appended to as various
- // content is embedded / requested by JavaScript.
- resetApplicableList: function(browser) {
- if (!this.prefs.getBoolPref("globalEnabled")) {
- return;
- }
- try {
- this.newApplicableListForBrowser(browser);
- } catch (e) {
- this.log(WARN, "Couldn't make applicable list"+e);
- }
- },
-
- // Given an nsIChannel (essentially, a container for an HTTP or similar
- // resource request), try to find the relevant tab if there is one.
- // Specifically, find the XUL <browser> element for that tab. Note
- // there are multiple meanings for the word 'browser' in Firefox, described at:
- // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Tabbed_browser
- // We're looking for this one:
- // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
- // Also note some requests, like Safe Browsing requests, will have no
- // associated tab.
- getBrowserForChannel: function(channel) {
- let loadContext, topFrameElement, associatedWindow;
- let spec = channel.URI.spec;
- try {
- loadContext = channel.notificationCallbacks.getInterface(CI.nsILoadContext);
- } catch(e) {
- }
-
- if (!loadContext) {
- try {
- loadContext = channel.loadGroup.notificationCallbacks
- .getInterface(CI.nsILoadContext);
- } catch(e) {
- // Lots of requests have no notificationCallbacks, mostly background
- // ones like OCSP checks or smart browsing fetches.
- this.log(DBUG, "getBrowserForChannel: no loadContext for " + spec);
- return null;
- }
- }
-
- if (loadContext) {
- topFrameElement = loadContext.topFrameElement;
- try {
- // If loadContext is an nsDocShell, associatedWindow is present.
- // Otherwise, if it's just a LoadContext, accessing it will throw
- // NS_ERROR_UNEXPECTED.
- associatedWindow = loadContext.associatedWindow;
- } catch (e) {
- }
- }
-
- // On e10s (multiprocess, aka electrolysis) Firefox,
- // loadContext.topFrameElement gives us a reference to the XUL <browser>
- // element we need. However, on non-e10s Firefox, topFrameElement is null.
- if (topFrameElement) {
- return topFrameElement;
- } else if (associatedWindow) {
- // For non-e10s Firefox, get the XUL <browser> element using this rather
- // magical / opaque code cribbed from
- // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Tabbed_browser#Getting_the_browser_that_fires_the_http-on-modify-request_notification_(example_code_updated_for_loadContext)
-
- // this is the HTML DOM window of the page that just loaded
- var contentWindow = loadContext.associatedWindow;
- // aDOMWindow this is the firefox window holding the tab
- var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow);
- // this is the gBrowser object of the firefox window this tab is in
- var gBrowser = aDOMWindow.gBrowser;
- if (gBrowser && gBrowser._getTabForContentWindow) {
- var aTab = gBrowser._getTabForContentWindow(contentWindow.top);
- // this is the clickable tab xul element, the one found in the tab strip
- // of the firefox window, aTab.linkedBrowser is same as browser var above
- // this is the browser within the tab
- if (aTab) {
- return aTab.linkedBrowser;
- } else {
- this.log(NOTE, "getBrowserForChannel: aTab was null for " + spec);
- return null;
- }
- } else if (aDOMWindow.BrowserApp) {
- // gBrowser is unavailable in Firefox for Android, and in some desktop
- // contexts, like the fetches for new tab tiles (which have an
- // associatedWindow, but no gBrowser)?
- // If available, try using the BrowserApp API:
- // https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/BrowserApp
- // TODO: We don't get the toolbar icon on android. Probably need to fix
- // the gBrowser reference in toolbar_button.js.
- // Also TODO: Where are these log messages going? They don't show up in
- // remote debug console.
- var mTab = aDOMWindow.BrowserApp.getTabForWindow(contentWindow.top);
- if (mTab) {
- return mTab.browser;
- } else {
- this.log(WARN, "getBrowserForChannel: mTab was null for " + spec);
- return null;
- }
- } else {
- this.log(INFO, "getBrowserForChannel: No gBrowser and no BrowserApp for " + spec);
- return null;
- }
- } else {
- this.log(NOTE, "getBrowserForChannel: No loadContext for " + spec);
- return null;
- }
- },
-
- // the lists get made when the urlbar is loading something new, but they
- // need to be appended to with reference only to the channel
- getApplicableListForChannel: function(channel) {
- var browser = this.getBrowserForChannel(channel);
- return this.getApplicableListForBrowser(browser);
- },
-
- newApplicableListForBrowser: function(browser) {
- if (!browser) {
- this.log(WARN, "Get alist without browser");
- return null;
- }
- var alist = new ApplicableList(this.log, browser.currentURI);
- this.setExpando(browser,"applicable_rules",alist);
- return alist;
- },
-
- getApplicableListForBrowser: function(browser) {
- if (!browser) {
- //this.log(WARN, "Get alist without browser");
- return null;
- }
- var alist= this.getExpando(browser,"applicable_rules");
- if (alist) {
- return alist;
- } else {
- alist = new ApplicableList(this.log, browser.currentURI);
- this.setExpando(browser,"applicable_rules",alist);
- }
- return alist;
- },
-
- // These are the highest level heuristics for figuring out whether
- // we should consider rewriting a URI. Everything here should be simple
- // and avoid dependence on the ruleset library
- shouldIgnoreURI: function(channel, alist) {
- var uri = channel.URI;
- // Ignore all non-http(s) requests?
- if (!(uri.schemeIs("http") || uri.schemeIs("https"))) { return true; }
-
- // If HTTP Nowhere is enabled, skip the rest of the shouldIgnoreURI checks
- if (this.httpNowhereEnabled) {
- return false;
- }
-
- // These are URIs we've seen redirecting back in loops after we redirect them
- if (uri.spec in https_everywhere_blacklist) {
- this.log(DBUG, "Avoiding blacklisted " + uri.spec);
- if (alist) {
- alist.breaking_rule(https_everywhere_blacklist[uri.spec]);
- } else {
- this.log(NOTE,"Failed to indicate breakage in content menu");
- }
- return true;
- }
-
- // OCSP (currently) needs to be HTTP to avoid cert validation loops
- // though someone should rev the spec to allow opportunistic encryption
- if ("allowSTS" in channel) {
- // Firefox 32+ lets us infer whether this is an OCSP request
- if (!channel.allowSTS) {
- this.log(INFO, "Channel with HTTPS rewrites forbidden, deeming OCSP, for " + channel.URI.spec);
- return true;
- }
- } else {
- // Firefox <32 requires a more hacky estimate
- // load the list opportunistically to speed startup & FF 32+
- if (this.ocspList == undefined) { this.loadOCSPList(); }
- if (this.ocspList.indexOf(uri.spec.replace(/\/$/,'')) !== -1) {
- this.log(INFO, "Known ocsp request "+uri.spec);
- return true;
- }
- }
-
- return false;
- },
-
- loadOCSPList: function() {
- try {
- var loc = "chrome://https-everywhere/content/code/commonOCSP.json";
- var file = CC["@mozilla.org/file/local;1"].createInstance(CI.nsILocalFile);
- file.initWithPath(this.rw.chromeToPath(loc));
- var data = this.rw.read(file);
- this.ocspList = JSON.parse(data);
- } catch(e) {
- this.log(WARN, "Failed to load OCSP list: " + e);
- this.ocspList = [];
- }
- },
-
- observe: function(subject, topic, data) {
- // Top level glue for the nsIObserver API
- var channel = subject;
- //this.log(VERB,"Got observer topic: "+topic);
-
- if (topic == "http-on-modify-request") {
- if (!(channel instanceof CI.nsIHttpChannel)) return;
-
- this.log(DBUG,"Got http-on-modify-request: "+channel.URI.spec);
- // lst is null if no window is associated (ex: some XHR)
- var lst = this.getApplicableListForChannel(channel);
- if (this.shouldIgnoreURI(channel, lst)) return;
- HTTPS.replaceChannel(lst, channel, this.httpNowhereEnabled);
- } else if (topic == "http-on-examine-response") {
- this.log(DBUG, "Got http-on-examine-response @ "+ (channel.URI ? channel.URI.spec : '') );
- HTTPS.handleSecureCookies(channel);
- } else if (topic == "http-on-examine-merged-response") {
- this.log(DBUG, "Got http-on-examine-merged-response ");
- HTTPS.handleSecureCookies(channel);
- } else if (topic == "cookie-changed") {
- // Javascript can add cookies via document.cookie that are insecure.
- if (data == "added" || data == "changed") {
- // subject can also be an nsIArray! bleh.
- try {
- subject.QueryInterface(CI.nsIArray);
- var elems = subject.enumerate();
- while (elems.hasMoreElements()) {
- var cookie = elems.getNext()
- .QueryInterface(CI.nsICookie2);
- if (!cookie.isSecure) {
- HTTPS.handleInsecureCookie(cookie);
- }
- }
- } catch(e) {
- subject.QueryInterface(CI.nsICookie2);
- if(!subject.isSecure) {
- HTTPS.handleInsecureCookie(subject);
- }
- }
- }
- } else if (topic == "profile-before-change") {
- this.log(INFO, "Got profile-before-change");
- var catman = Components.classes["@mozilla.org/categorymanager;1"]
- .getService(Components.interfaces.nsICategoryManager);
- catman.deleteCategoryEntry("net-channel-event-sinks", SERVICE_CTRID, true);
- Thread.hostRunning = false;
- } else if (topic == "profile-after-change") {
- this.log(DBUG, "Got profile-after-change");
-
- if(this.prefs.getBoolPref("globalEnabled")){
- OS.addObserver(this, "cookie-changed", false);
- OS.addObserver(this, "http-on-modify-request", false);
- OS.addObserver(this, "http-on-examine-merged-response", false);
- OS.addObserver(this, "http-on-examine-response", false);
-
- this.log(INFO,"ChannelReplacement.supported = "+ChannelReplacement.supported);
-
- HTTPSRules.init();
-
- Thread.hostRunning = true;
- var catman = Components.classes["@mozilla.org/categorymanager;1"]
- .getService(Components.interfaces.nsICategoryManager);
- // hook on redirections (non persistent, otherwise crashes on 1.8.x)
- catman.addCategoryEntry("net-channel-event-sinks", SERVICE_CTRID,
- SERVICE_CTRID, false, true);
- }
- } else if (topic == "sessionstore-windows-restored") {
- this.log(DBUG,"Got sessionstore-windows-restored");
- if (!this.isMobile) {
- this.maybeShowObservatoryPopup();
- } else {
- this.log(WARN, "Initializing Firefox for Android UI");
- Cu.import("chrome://https-everywhere/content/code/AndroidUI.jsm");
- AndroidUI.init();
- }
- this.browser_initialised = true;
- } else if (topic == "nsPref:changed") {
- // If the user toggles the Mixed Content Blocker settings, reload the rulesets
- // to enable/disable the mixedcontent ones
-
- // this pref gets set to false and then true during FF 26 startup!
- // so do nothing if we're being notified during startup
- if (!this.browser_initialised)
- return;
- switch (data) {
- case "security.mixed_content.block_active_content":
- case "extensions.https_everywhere.enable_mixed_rulesets":
- var p = CC["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefBranch);
- var val = p.getBoolPref("security.mixed_content.block_active_content");
- this.log(INFO,"nsPref:changed for "+data + " to " + val);
- HTTPSRules.init();
- break;
- }
- } else if (topic == "browser:purge-session-history") {
- // The list of rulesets that have been loaded from the sqlite DB
- // constitutes a parallel history store, so we have to clear it.
- this.log(DBUG, "History cleared, reloading HTTPSRules to avoid information leak.");
- HTTPSRules.init();
- }
- return;
- },
-
- maybeShowObservatoryPopup: function() {
- // Show the popup at most once. Users who enabled the Observatory before
- // a version that would have shown it to them, don't need to see it
- // again.
- var ssl_observatory = CC["@eff.org/ssl-observatory;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
- var shown = ssl_observatory.myGetBoolPref("popup_shown");
- var enabled = ssl_observatory.myGetBoolPref("enabled");
- var that = this;
- var obs_popup_callback = function(result) {
- if (result) that.log(INFO, "Got positive proxy test.");
- else that.log(INFO, "Got negative proxy text.");
- // We are now ready to show the popup in its most informative state
- that.chrome_opener("chrome://https-everywhere/content/observatory-popup.xul");
- };
- if (!shown && !enabled)
- ssl_observatory.registerProxyTestNotification(obs_popup_callback);
-
- if (shown && enabled)
- this.maybeCleanupObservatoryPrefs(ssl_observatory);
- },
-
- maybeCleanupObservatoryPrefs: function(ssl_observatory) {
- // Recover from a past UI processing bug that would leave the Obsevatory
- // accidentally disabled for some users
- // https://trac.torproject.org/projects/tor/ticket/10728
- var clean = ssl_observatory.myGetBoolPref("clean_config");
- if (clean) return;
-
- // unchanged: returns true if a pref has not been modified
- var unchanged = function(p){return !ssl_observatory.prefs.prefHasUserValue("extensions.https_everywhere._observatory."+p)};
- var cleanup_obsprefs_callback = function(tor_avail) {
- // we only run this once
- ssl_observatory.prefs.setBoolPref("extensions.https_everywhere._observatory.clean_config", true);
- if (!tor_avail) {
- // use_custom_proxy is the variable that is often false when it should be true;
- if (!ssl_observatory.myGetBoolPref("use_custom_proxy")) {
- // however don't do anything if any of the prefs have been set by the user
- if (unchanged("alt_roots") && unchanged("self_signed") && unchanged ("send_asn") && unchanged("priv_dns")) {
- ssl_observatory.prefs.setBoolPref("extensions.https_everywhere._observatory.use_custom_proxy", true);
- }
- }
- }
- }
- ssl_observatory.registerProxyTestNotification(cleanup_obsprefs_callback);
- },
-
-
- getExperimentalFeatureCohort: function() {
- // This variable is used for gradually turning on features for testing and
- // scalability purposes. It is a random integer [0,N_COHORTS) generated
- // once and stored thereafter.
- //
- // This is not currently used/called in the development branch
- var cohort;
- try {
- cohort = this.prefs.getIntPref("experimental_feature_cohort");
- } catch(e) {
- cohort = Math.round(Math.random() * N_COHORTS);
- this.prefs.setIntPref("experimental_feature_cohort", cohort);
- }
- return cohort;
- },
-
- // nsIChannelEventSink implementation
- // XXX This was here for rewrites in the past. Do we still need it?
- onChannelRedirect: function(oldChannel, newChannel, flags) {
- const uri = newChannel.URI;
- this.log(DBUG,"Got onChannelRedirect to "+uri.spec);
- if (!(newChannel instanceof CI.nsIHttpChannel)) {
- this.log(DBUG, newChannel + " is not an instance of nsIHttpChannel");
- return;
- }
- var alist = this.juggleApplicableListsDuringRedirection(oldChannel, newChannel);
- HTTPS.replaceChannel(alist, newChannel, this.httpNowhereEnabled);
- },
-
- juggleApplicableListsDuringRedirection: function(oldChannel, newChannel) {
- // If the new channel doesn't yet have a list of applicable rulesets, start
- // with the old one because that's probably a better representation of how
- // secure the load process was for this page
- var browser = this.getBrowserForChannel(oldChannel);
- var old_alist = null;
- if (browser)
- old_alist = this.getExpando(browser,"applicable_rules");
- browser = this.getBrowserForChannel(newChannel);
- if (!browser) return null;
- var new_alist = this.getExpando(browser,"applicable_rules");
- if (old_alist && !new_alist) {
- new_alist = old_alist;
- this.setExpando(browser,"applicable_rules",new_alist);
- } else if (!new_alist) {
- new_alist = new ApplicableList(this.log, browser.currentURI);
- this.setExpando(browser,"applicable_rules",new_alist);
- }
- return new_alist;
- },
-
- asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
- this.onChannelRedirect(oldChannel, newChannel, flags);
- callback.onRedirectVerifyCallback(0);
- },
-
- get_prefs: function(prefBranch) {
- if(!prefBranch) prefBranch = PREFBRANCH_ROOT;
-
- // get our preferences branch object
- // FIXME: Ugly hack stolen from https
- var branch_name;
- if(prefBranch === PREFBRANCH_RULE_TOGGLE)
- branch_name = "extensions.https_everywhere.rule_toggle.";
- else if (prefBranch === PREFBRANCH_NONE)
- branch_name = "";
- else
- branch_name = "extensions.https_everywhere.";
- var o_prefs = false;
- var o_branch = false;
- // this function needs to be called from inside https_everywhereLog, so
- // it needs to do its own logging...
- var econsole = Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService);
-
- o_prefs = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
-
- if (!o_prefs)
- {
- econsole.logStringMessage("HTTPS Everywhere: Failed to get preferences-service!");
- return false;
- }
-
- o_branch = o_prefs.getBranch(branch_name);
- if (!o_branch)
- {
- econsole.logStringMessage("HTTPS Everywhere: Failed to get prefs branch!");
- return false;
- }
-
- if(prefBranch == PREFBRANCH_ROOT) {
- // make sure there's an entry for our log level
- try {
- o_branch.getIntPref(LLVAR);
- } catch (e) {
- econsole.logStringMessage("Creating new about:config https_everywhere.LogLevel variable");
- o_branch.setIntPref(LLVAR, WARN);
- }
- }
-
- return o_branch;
- },
-
- // Are we on Firefox for Android?
- doMobileCheck: function() {
- let appInfo = CC["@mozilla.org/xre/app-info;1"].getService(CI.nsIXULAppInfo);
- let ANDROID_ID = "{aa3c5121-dab2-40e2-81ca-7ea25febc110}";
- return (appInfo.ID === ANDROID_ID);
- },
-
- chrome_opener: function(uri, args) {
- // we don't use window.open, because we need to work around TorButton's
- // state control
- args = args || 'chrome,centerscreen';
- return CC['@mozilla.org/appshell/window-mediator;1']
- .getService(CI.nsIWindowMediator)
- .getMostRecentWindow('navigator:browser')
- .open(uri,'', args );
- },
-
- tab_opener: function(uri) {
- var gb = CC['@mozilla.org/appshell/window-mediator;1']
- .getService(CI.nsIWindowMediator)
- .getMostRecentWindow('navigator:browser')
- .gBrowser;
- var tab = gb.addTab(uri);
- gb.selectedTab = tab;
- return tab;
- },
-
- toggleEnabledState: function() {
- if (this.prefs.getBoolPref("globalEnabled")) {
- try {
- this.obsService.removeObserver(this, "profile-before-change");
- this.obsService.removeObserver(this, "profile-after-change");
- this.obsService.removeObserver(this, "sessionstore-windows-restored");
- OS.removeObserver(this, "cookie-changed");
- OS.removeObserver(this, "http-on-modify-request");
- OS.removeObserver(this, "http-on-examine-merged-response");
- OS.removeObserver(this, "http-on-examine-response");
-
- var catman = CC["@mozilla.org/categorymanager;1"]
- .getService(CI.nsICategoryManager);
- catman.deleteCategoryEntry("net-channel-event-sinks",
- SERVICE_CTRID, true);
-
- this.prefs.setBoolPref("globalEnabled", false);
- } catch(e) {
- this.log(WARN, "Couldn't remove observers: " + e);
- }
- } else {
- try {
- this.obsService.addObserver(this, "profile-before-change", false);
- this.obsService.addObserver(this, "profile-after-change", false);
- this.obsService.addObserver(this, "sessionstore-windows-restored", false);
- OS.addObserver(this, "cookie-changed", false);
- OS.addObserver(this, "http-on-modify-request", false);
- OS.addObserver(this, "http-on-examine-merged-response", false);
- OS.addObserver(this, "http-on-examine-response", false);
-
- this.log(INFO,
- "ChannelReplacement.supported = "+ChannelReplacement.supported);
-
- if (!Thread.hostRunning) {
- Thread.hostRunning = true;
- }
-
- var catman = CC["@mozilla.org/categorymanager;1"]
- .getService(CI.nsICategoryManager);
- // hook on redirections (non persistent, otherwise crashes on 1.8.x)
- catman.addCategoryEntry("net-channel-event-sinks", SERVICE_CTRID,
- SERVICE_CTRID, false, true);
-
- HTTPSRules.init();
- this.prefs.setBoolPref("globalEnabled", true);
- } catch(e) {
- this.log(WARN, "Couldn't add observers: " + e);
- }
- }
- },
-
- toggleHttpNowhere: function() {
- let prefService = Services.prefs;
- let thisBranch =
- prefService.getBranch("extensions.https_everywhere.http_nowhere.");
- let securityBranch = prefService.getBranch("security.");
-
- // Whether cert is treated as invalid when OCSP connection fails
- let OCSP_REQUIRED = "OCSP.require";
-
- // Branch to save original settings
- let ORIG_OCSP_REQUIRED = "orig.ocsp.required";
-
-
- if (thisBranch.getBoolPref("enabled")) {
- // Restore original OCSP settings. TODO: What if user manually edits
- // these while HTTP Nowhere is enabled?
- let origOcspRequired = thisBranch.getBoolPref(ORIG_OCSP_REQUIRED);
- securityBranch.setBoolPref(OCSP_REQUIRED, origOcspRequired);
-
- thisBranch.setBoolPref("enabled", false);
- this.httpNowhereEnabled = false;
- } else {
- // Save original OCSP settings in HTTP Nowhere preferences branch.
- let origOcspRequired = securityBranch.getBoolPref(OCSP_REQUIRED);
- thisBranch.setBoolPref(ORIG_OCSP_REQUIRED, origOcspRequired);
-
- // Disable OCSP enforcement
- securityBranch.setBoolPref(OCSP_REQUIRED, false);
-
- thisBranch.setBoolPref("enabled", true);
- this.httpNowhereEnabled = true;
- }
- }
-};
-
-var prefs = 0;
-var econsole = 0;
-function https_everywhereLog(level, str) {
- if (prefs == 0) {
- prefs = HTTPSEverywhere.instance.get_prefs();
- econsole = Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService);
- }
- try {
- var threshold = prefs.getIntPref(LLVAR);
- } catch (e) {
- econsole.logStringMessage( "HTTPS Everywhere: Failed to read about:config LogLevel");
- threshold = WARN;
- }
- if (level >= threshold) {
- var levelName = ["", "VERB", "DBUG", "INFO", "NOTE", "WARN"][level];
- var prefix = "HTTPS Everywhere " + levelName + ": ";
- // dump() prints to browser stdout. That's sometimes undesireable,
- // so only do it when a pref is set (running from test.sh enables
- // this pref).
- if (prefs.getBoolPref("log_to_stdout")) {
- dump(prefix + str + "\n");
- }
- econsole.logStringMessage(prefix + str);
- }
-}
-
-/**
-* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
-* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
-*/
-if (XPCOMUtils.generateNSGetFactory)
- var NSGetFactory = XPCOMUtils.generateNSGetFactory([HTTPSEverywhere]);
-else
- var NSGetModule = XPCOMUtils.generateNSGetModule([HTTPSEverywhere]);
-
-/* vim: set tabstop=4 expandtab: */