summaryrefslogtreecommitdiff
path: root/data/extensions/https-everywhere@eff.org/components
diff options
context:
space:
mode:
authorRuben Rodriguez <ruben@gnu.org>2015-07-13 22:53:00 -0500
committerRuben Rodriguez <ruben@gnu.org>2015-07-13 22:53:00 -0500
commit23103d7773e24fdf15b79ed69c67089b593fb31a (patch)
treeee1b744a80dd192e62fefc72ff1f0bf978d0d24c /data/extensions/https-everywhere@eff.org/components
parent9cb91f8a48f9467e448f88984c20b3429e8a2510 (diff)
HTTPS-Everywhere updated to 5.0.5
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/components')
-rw-r--r--data/extensions/https-everywhere@eff.org/components/https-everywhere.js487
-rw-r--r--data/extensions/https-everywhere@eff.org/components/ssl-observatory.js101
2 files changed, 329 insertions, 259 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
index c248139..81f6ad6 100644
--- a/data/extensions/https-everywhere@eff.org/components/https-everywhere.js
+++ b/data/extensions/https-everywhere@eff.org/components/https-everywhere.js
@@ -1,42 +1,31 @@
-// LOG LEVELS ---
-
-VERB=1;
-DBUG=2;
-INFO=3;
-NOTE=4;
-WARN=5;
+// 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;
-//---------------
-
-https_domains = {}; // maps domain patterns (with at most one
- // wildcard) to RuleSets
-
-https_everywhere_blacklist = {}; // URLs we've given up on rewriting because
- // of redirection loops
-
-https_blacklist_domains = {}; // domains for which there is at least one
- // blacklisted URL
+// 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 CU = Components.utils;
-const CR = Components.results;
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
-const Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
-const CP_SHOULDPROCESS = 4;
-
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";
@@ -136,43 +125,18 @@ INCLUDE('ChannelReplacement', 'IOUtil', 'HTTPSRules', 'HTTPS', 'Thread', 'Applic
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-// This is black magic for storing Expando data w/ an nsIDOMWindow
-// See http://pastebin.com/qY28Jwbv ,
-// https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIControllers
-
-StorageController.prototype = {
- QueryInterface: XPCOMUtils.generateQI(
- [ Components.interfaces.nsISupports,
- Components.interfaces.nsIController ]),
- wrappedJSObject: null, // Initialized by constructor
- supportsCommand: function (cmd) {return (cmd == this.command);},
- isCommandEnabled: function (cmd) {return (cmd == this.command);},
- onEvent: function(eventName) {return true;},
- doCommand: function() {return true;}
-};
-
-function StorageController(command) {
- this.command = command;
- this.data = {};
- this.wrappedJSObject = this;
-};
-
-/*var Controller = Class("Controller", XPCOM(CI.nsIController), {
- init: function (command, data) {
- this.command = command;
- this.data = data;
- },
- supportsCommand: function (cmd) cmd === this.command
-});*/
-
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
@@ -218,12 +182,14 @@ function HTTPSEverywhere() {
}
-
/*
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()
@@ -243,8 +209,7 @@ In recent versions of Firefox and HTTPS Everywhere, the call stack for performin
In addition, the following other important tasks happen along the way:
-HTTPSEverywhere.observe() aborts if there is a redirect loop
- finds a reference to the ApplicableList or alist that represents the toolbar context menu
+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)
@@ -292,8 +257,6 @@ HTTPSEverywhere.prototype = {
[ Components.interfaces.nsIObserver,
Components.interfaces.nsISupports,
Components.interfaces.nsISupportsWeakReference,
- Components.interfaces.nsIWebProgressListener,
- Components.interfaces.nsIWebProgressListener2,
Components.interfaces.nsIChannelEventSink ]),
wrappedJSObject: null, // Initialized by constructor
@@ -303,134 +266,229 @@ HTTPSEverywhere.prototype = {
},
// An "expando" is an attribute glued onto something. From NoScript.
- getExpando: function(domWin, key) {
- var c = domWin.controllers.getControllerForCommand("https-everywhere-storage");
- try {
- if (c) {
- c = c.wrappedJSObject;
- //this.log(DBUG, "Found a controller, returning data");
- return c.data[key];
- } else {
- this.log(INFO, "No controller attached to " + domWin);
- return null;
- }
- } catch(e) {
- // Firefox 3.5
- this.log(WARN,"exception in getExpando");
- this.getExpando = this.getExpando_old;
- this.setExpando = this.setExpando_old;
- return this.getExpando_old(domWin, key, null);
- }
- },
- setExpando: function(domWin, key, value) {
- var c = domWin.controllers.getControllerForCommand("https-everywhere-storage");
- try {
- if (!c) {
- this.log(DBUG, "Appending new StorageController for " + domWin);
- c = new StorageController("https-everywhere-storage");
- domWin.controllers.appendController(c);
- } else {
- c = c.wrappedJSObject;
+ getExpando: function(browser, key) {
+ let obj = this.expandoMap.get(browser);
+ if (!obj) {
+ if (browser.currentURI) {
+ this.log(NOTE, "No expando for " + browser.currentURI.spec);
}
- c.data[key] = value;
- } catch(e) {
- this.log(WARN,"exception in setExpando");
- this.getExpando = this.getExpando_old;
- this.setExpando = this.setExpando_old;
- this.setExpando_old(domWin, key, value);
+ return null;
}
+ return obj[key];
},
- // This method is straight out of NoScript... we fall back to it in FF 3.*?
- getExpando_old: function(domWin, key, defValue) {
- var domObject = domWin.document;
- return domObject && domObject.__httpsEStorage && domObject.__httpsEStorage[key] ||
- (defValue ? this.setExpando(domObject, key, defValue) : null);
- },
- setExpando_old: function(domWin, key, value) {
- var domObject = domWin.document;
- if (!domObject) return null;
- if (!domObject.__httpsEStorage) domObject.__httpsEStorage = {};
- if (domObject.__httpsEStorage) domObject.__httpsEStorage[key] = value;
- else this.log(WARN, "Warning: cannot set expando " + key + " to value " + value);
- return value;
+ 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 onLocationChange to make a fresh list of rulesets that could have
+ // 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.
- onLocationChange: function(wp, req, uri) {
- if (wp instanceof CI.nsIWebProgress) {
- if (!this.newApplicableListForDOMWin(wp.DOMWindow))
- this.log(WARN,"Something went wrong in onLocationChange");
- } else {
- this.log(WARN,"onLocationChange: no nsIWebProgress");
+ resetApplicableList: function(browser) {
+ if (!this.prefs.getBoolPref("globalEnabled")) {
+ return;
+ }
+ try {
+ this.newApplicableListForBrowser(browser);
+ } catch (e) {
+ this.log(WARN, "Couldn't make applicable list"+e);
}
},
- getWindowForChannel: function(channel) {
- // Obtain an nsIDOMWindow from a channel
- let loadContext;
+ // 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);
+ loadContext = channel.loadGroup.notificationCallbacks
+ .getInterface(CI.nsILoadContext);
} catch(e) {
- this.log(NOTE, "No loadContext for " + channel.URI.spec);
+ // 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) { 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) {
+ }
+ }
- let domWin = loadContext.associatedWindow;
- if (!domWin) {
- this.log(NOTE, "failed to get DOMWin for " + channel.URI.spec);
+ // 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;
}
-
- domWin = domWin.top;
- return domWin;
},
// 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 domWin = this.getWindowForChannel(channel);
- return this.getApplicableListForDOMWin(domWin, "on-modify-request w " + domWin);
+ var browser = this.getBrowserForChannel(channel);
+ return this.getApplicableListForBrowser(browser);
},
- newApplicableListForDOMWin: function(domWin) {
- if (!domWin || !(domWin instanceof CI.nsIDOMWindow)) {
- this.log(WARN, "Get alist without domWin");
+ newApplicableListForBrowser: function(browser) {
+ if (!browser) {
+ this.log(WARN, "Get alist without browser");
return null;
}
- var dw = domWin.top;
- var alist = new ApplicableList(this.log,dw.document,dw);
- this.setExpando(dw,"applicable_rules",alist);
+ var alist = new ApplicableList(this.log, browser.currentURI);
+ this.setExpando(browser,"applicable_rules",alist);
return alist;
},
- getApplicableListForDOMWin: function(domWin, where) {
- if (!domWin || !(domWin instanceof CI.nsIDOMWindow)) {
- //this.log(WARN, "Get alist without domWin");
+ getApplicableListForBrowser: function(browser) {
+ if (!browser) {
+ //this.log(WARN, "Get alist without browser");
return null;
}
- var dw = domWin.top;
- var alist= this.getExpando(dw,"applicable_rules");
+ var alist= this.getExpando(browser,"applicable_rules");
if (alist) {
- //this.log(DBUG,"get AL success in " + where);
return alist;
} else {
- //this.log(DBUG, "Making new AL in getApplicableListForDOMWin in " + where);
- alist = new ApplicableList(this.log,dw.document,dw);
- this.setExpando(dw,"applicable_rules",alist);
+ 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;
@@ -438,15 +496,11 @@ HTTPSEverywhere.prototype = {
if (topic == "http-on-modify-request") {
if (!(channel instanceof CI.nsIHttpChannel)) return;
-
+
this.log(DBUG,"Got http-on-modify-request: "+channel.URI.spec);
- var lst = this.getApplicableListForChannel(channel); // null if no window is associated (ex: xhr)
- if (channel.URI.spec in https_everywhere_blacklist) {
- this.log(DBUG, "Avoiding blacklisted " + channel.URI.spec);
- if (lst) lst.breaking_rule(https_everywhere_blacklist[channel.URI.spec]);
- else this.log(NOTE,"Failed to indicate breakage in content menu");
- return;
- }
+ // 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 : '') );
@@ -483,16 +537,13 @@ HTTPSEverywhere.prototype = {
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);
-
- var dls = CC['@mozilla.org/docloaderservice;1']
- .getService(CI.nsIWebProgress);
- dls.addProgressListener(this, CI.nsIWebProgress.NOTIFY_LOCATION);
+
this.log(INFO,"ChannelReplacement.supported = "+ChannelReplacement.supported);
HTTPSRules.init();
@@ -615,26 +666,26 @@ HTTPSEverywhere.prototype = {
return;
}
var alist = this.juggleApplicableListsDuringRedirection(oldChannel, newChannel);
- HTTPS.replaceChannel(alist,newChannel, this.httpNowhereEnabled);
+ 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 domWin = this.getWindowForChannel(oldChannel);
+ var browser = this.getBrowserForChannel(oldChannel);
var old_alist = null;
- if (domWin)
- old_alist = this.getExpando(domWin,"applicable_rules");
- domWin = this.getWindowForChannel(newChannel);
- if (!domWin) return null;
- var new_alist = this.getExpando(domWin,"applicable_rules");
+ 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(domWin,"applicable_rules",new_alist);
+ this.setExpando(browser,"applicable_rules",new_alist);
} else if (!new_alist) {
- new_alist = new ApplicableList(this.log, domWin.document, domWin);
- this.setExpando(domWin,"applicable_rules",new_alist);
+ new_alist = new ApplicableList(this.log, browser.currentURI);
+ this.setExpando(browser,"applicable_rules",new_alist);
}
return new_alist;
},
@@ -720,62 +771,53 @@ HTTPSEverywhere.prototype = {
},
toggleEnabledState: function() {
- if(this.prefs.getBoolPref("globalEnabled")){
- try{
- // toggling some of these after startup may be inconsequential...
- // this.obsService.removeObserver(this, "sessionstore-windows-restored");
- this.obsService.removeObserver(this, "profile-before-change");
- this.obsService.removeObserver(this, "profile-after-change");
- 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 = Components.classes["@mozilla.org/categorymanager;1"]
- .getService(Components.interfaces.nsICategoryManager);
- catman.deleteCategoryEntry("net-channel-event-sinks", SERVICE_CTRID, true);
-
- var dls = CC['@mozilla.org/docloaderservice;1']
- .getService(CI.nsIWebProgress);
- dls.removeProgressListener(this);
-
- 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);
-
- var dls = CC['@mozilla.org/docloaderservice;1']
- .getService(CI.nsIWebProgress);
- dls.addProgressListener(this, CI.nsIWebProgress.NOTIFY_LOCATION);
-
- this.log(INFO,"ChannelReplacement.supported = "+ChannelReplacement.supported);
+ 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);
- if(!Thread.hostRunning)
- 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);
-
- HTTPSRules.init();
- this.prefs.setBoolPref("globalEnabled", true);
- }
- catch(e){
- this.log(WARN, "Couldn't add observers: " + e);
+ 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);
+ }
}
},
@@ -829,8 +871,15 @@ function https_everywhereLog(level, str) {
threshold = WARN;
}
if (level >= threshold) {
- dump("HTTPS Everywhere: "+str+"\n");
- econsole.logStringMessage("HTTPS Everywhere: " +str);
+ 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);
}
}
diff --git a/data/extensions/https-everywhere@eff.org/components/ssl-observatory.js b/data/extensions/https-everywhere@eff.org/components/ssl-observatory.js
index a783a72..abcb175 100644
--- a/data/extensions/https-everywhere@eff.org/components/ssl-observatory.js
+++ b/data/extensions/https-everywhere@eff.org/components/ssl-observatory.js
@@ -7,23 +7,23 @@ const CC = Components.classes;
const CR = Components.results;
// Log levels
-VERB=1;
-DBUG=2;
-INFO=3;
-NOTE=4;
-WARN=5;
+let VERB=1;
+let DBUG=2;
+let INFO=3;
+let NOTE=4;
+let WARN=5;
-BASE_REQ_SIZE=4096;
-TIMEOUT = 60000;
-MAX_OUTSTANDING = 20; // Max # submission XHRs in progress
-MAX_DELAYED = 32; // Max # XHRs are waiting around to be sent or retried
+let BASE_REQ_SIZE=4096;
+let TIMEOUT = 60000;
+let MAX_OUTSTANDING = 20; // Max # submission XHRs in progress
+let MAX_DELAYED = 32; // Max # XHRs are waiting around to be sent or retried
-ASN_PRIVATE = -1; // Do not record the ASN this cert was seen on
-ASN_IMPLICIT = -2 // ASN can be learned from connecting IP
-ASN_UNKNOWABLE = -3; // Cert was seen in the absence of [trustworthy] Internet access
+let ASN_PRIVATE = -1; // Do not record the ASN this cert was seen on
+let ASN_IMPLICIT = -2; // ASN can be learned from connecting IP
+let ASN_UNKNOWABLE = -3; // Cert was seen in the absence of [trustworthy] Internet access
// XXX: We should make the _observatory tree relative.
-LLVAR="extensions.https_everywhere.LogLevel";
+let LLVAR="extensions.https_everywhere.LogLevel";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/ctypes.jsm");
@@ -64,13 +64,20 @@ function SSLObservatory() {
try {
// Check for torbutton
- this.tor_logger = CC["@torproject.org/torbutton-logger;1"]
- .getService(CI.nsISupports).wrappedJSObject;
- this.torbutton_installed = true;
+ var tor_logger_component = CC["@torproject.org/torbutton-logger;1"];
+ if (tor_logger_component) {
+ this.tor_logger =
+ tor_logger_component.getService(CI.nsISupports).wrappedJSObject;
+ this.torbutton_installed = true;
+ }
} catch(e) {
this.torbutton_installed = false;
}
+ this.HTTPSEverywhere = CC["@eff.org/https-everywhere;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+
/* The proxy test result starts out null until the test is attempted.
* This is for UI notification purposes */
this.proxy_test_successful = null;
@@ -344,10 +351,10 @@ SSLObservatory.prototype = {
var host_ip = "-1";
var httpchannelinternal = subject.QueryInterface(Ci.nsIHttpChannelInternal);
- try {
+ try {
host_ip = httpchannelinternal.remoteAddress;
} catch(e) {
- this.log(INFO, "Could not get server IP address.");
+ this.log(INFO, "Could not get server IP address.");
}
subject.QueryInterface(Ci.nsIHttpChannel);
var certchain = this.getSSLCert(subject);
@@ -378,16 +385,16 @@ SSLObservatory.prototype = {
}
if (subject.URI.port == -1) {
- this.submitChain(chainArray, fps, new String(subject.URI.host), subject, host_ip, false);
+ this.submitChain(chainArray, fps, new String(subject.URI.host), subject, host_ip, false);
} else {
- this.submitChain(chainArray, fps, subject.URI.host+":"+subject.URI.port, subject, host_ip, false);
+ this.submitChain(chainArray, fps, subject.URI.host+":"+subject.URI.port, subject, host_ip, false);
}
}
}
},
observatoryActive: function() {
-
+
if (!this.myGetBoolPref("enabled"))
return false;
@@ -416,7 +423,7 @@ SSLObservatory.prototype = {
var pbs = CC["@mozilla.org/privatebrowsing;1"].getService(CI.nsIPrivateBrowsingService);
if (pbs.privateBrowsingEnabled) return false;
} catch (e) { /* seamonkey or old firefox */ }
-
+
return true;
}
@@ -475,7 +482,7 @@ SSLObservatory.prototype = {
if (!convergence || !convergence.enabled) return null;
this.log(INFO, "Convergence uses its own internal root certs; not submitting those");
-
+
//this.log(WARN, convergence.certificateStatus.getVerificiationStatus(chain.certArray[0]));
try {
var certInfo = this.extractRealLeafFromConveregenceLeaf(chain.certArray[0]);
@@ -633,7 +640,13 @@ SSLObservatory.prototype = {
var HTTPSEverywhere = CC["@eff.org/https-everywhere;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
- var win = channel ? HTTPSEverywhere.getWindowForChannel(channel) : null;
+ var win = null;
+ if (channel) {
+ var browser = this.HTTPSEverywhere.getBrowserForChannel(channel);
+ if (browser) {
+ var win = browser.contentWindow;
+ }
+ }
var req = this.buildRequest(params);
req.timeout = TIMEOUT;
@@ -645,10 +658,11 @@ SSLObservatory.prototype = {
if (req.status == 200) {
that.log(INFO, "Successful cert submission");
- if (!that.prefs.getBoolPref("extensions.https_everywhere._observatory.cache_submitted"))
- if (c.fps[0] in that.already_submitted)
- delete that.already_submitted[c.fps[0]];
-
+ if (!that.prefs.getBoolPref("extensions.https_everywhere._observatory.cache_submitted") &&
+ c.fps[0] in that.already_submitted) {
+ delete that.already_submitted[c.fps[0]];
+ }
+
// Retry up to two previously failed submissions
let n = 0;
for (let fp in that.delayed_submissions) {
@@ -668,8 +682,9 @@ SSLObservatory.prototype = {
}
} else {
// Submission failed
- if (c.fps[0] in that.already_submitted)
+ if (c.fps[0] in that.already_submitted) {
delete that.already_submitted[c.fps[0]];
+ }
try {
that.log(WARN, "Cert submission failure "+req.status+": "+req.responseText);
} catch(e) {
@@ -677,13 +692,12 @@ SSLObservatory.prototype = {
}
// If we don't have too many delayed submissions, and this isn't
// (somehow?) one of them, then plan to retry this submission later
- if (Object.keys(that.delayed_submissions).length < MAX_DELAYED)
- if (!(c.fps[0] in that.delayed_submissions)) {
- that.log(WARN, "Planning to retry submission...");
- let retry = function() { that.submitChain(certArray, fps, domain, channel, host_ip, true); };
- that.delayed_submissions[c.fps[0]] = retry;
- }
-
+ if (Object.keys(that.delayed_submissions).length < MAX_DELAYED &&
+ c.fps[0] in that.delayed_submissions) {
+ that.log(WARN, "Planning to retry submission...");
+ let retry = function() { that.submitChain(certArray, fps, domain, channel, host_ip, true); };
+ that.delayed_submissions[c.fps[0]] = retry;
+ }
}
}
};
@@ -707,7 +721,7 @@ SSLObservatory.prototype = {
// Send the proper header information along with the request
// Do not set gzip header.. It will ruin the padding
- req.setRequestHeader("X-Privacy-Info", "EFF SSL Observatory: https://eff.org/r.22c");
+ req.setRequestHeader("X-Privacy-Info", "EFF SSL Observatory: https://www.eff.org/r.22c");
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", params.length);
req.setRequestHeader("Connection", "close");
@@ -895,7 +909,7 @@ SSLObservatory.prototype = {
encString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
encStringS: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
-
+
log: function(level, str) {
var econsole = CC["@mozilla.org/consoleservice;1"]
.getService(CI.nsIConsoleService);
@@ -906,8 +920,15 @@ SSLObservatory.prototype = {
threshold = WARN;
}
if (level >= threshold) {
- dump("SSL Observatory: "+str+"\n");
- econsole.logStringMessage("SSL Observatory: " +str);
+ var levelName = ["", "VERB", "DBUG", "INFO", "NOTE", "WARN"][level];
+ var prefix = "SSL Observatory " + 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 (this.prefs.getBoolPref("extensions.https_everywhere.log_to_stdout")) {
+ dump(prefix + str + "\n");
+ }
+ econsole.logStringMessage(prefix + str);
}
}
};