Skip to content

Commit 0ebce4a

Browse files
committed
Use NoScript's get/setExpando for data storage
1 parent 9b55744 commit 0ebce4a

File tree

5 files changed

+111
-31
lines changed

5 files changed

+111
-31
lines changed

src/chrome/content/code/ApplicableList.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,47 @@
22
// were applied, and which ones weren't but might have been, to the contents
33
// of a given page (top level nsIDOMWindow)
44

5-
function ApplicableList(logger) {
5+
serial_number = 0
6+
7+
function ApplicableList(logger, home) {
8+
this.home = home.baseURIObject.spec; // what doc we're housekeeping for
69
this.log = logger;
710
this.active = {};
811
this.inactive = {};
912
this.moot={}; // rulesets that might be applicable but uris are already https
13+
serial_number += 1;
14+
this.serial = serial_number;
15+
this.log(WARN,"Alist serial #" + this.serial);
1016
};
1117

1218
ApplicableList.prototype = {
1319

1420
active_rule: function(ruleset) {
15-
this.log(WARN,"active rule " + ruleset);
21+
this.log(WARN,"active rule " + ruleset.name +" in "+ this.home);
1622
this.active[ruleset.name] = ruleset;
1723
},
1824

1925
inactive_rule: function(ruleset) {
20-
this.log(WARN,"inactive rule " + ruleset);
26+
this.log(WARN,"inactive rule " + ruleset.name +" in "+ this.home);
2127
this.inactive[ruleset.name] = ruleset;
2228
},
2329

2430
moot_rule: function(ruleset) {
25-
this.log(WARN,"moot rule " + ruleset.name);
31+
this.log(WARN,"moot rule " + ruleset.name +" in "+ this.home);
2632
this.moot[ruleset.name] = ruleset;
2733
},
2834

35+
dom_handler: function(operation,key,data,src,dst) {
36+
// See https://developer.mozilla.org/En/DOM/UserDataHandler
37+
if (src && dst)
38+
dst.setUserData(key, data, this.dom_handler);
39+
},
2940

3041
populate_menu: function(doc, xul_popupmenu) {
3142
// called from the XUL when the context popup is about to be displayed;
3243
// fill out the UI showing which rules are active and inactive in this
3344
// page
45+
this.log(WARN, "populating using alist #" + this.serial);
3446
while (xul_popupmenu.firstChild) {
3547
// delete whatever was in the menu previously
3648
//this.log(WARN,"removing " + xul_popupmenu.firstChild.label +" from menu");
@@ -53,6 +65,7 @@ ApplicableList.prototype = {
5365
// rules that are active for some uris are not really moot
5466
var item = doc.createElement("menuitem");
5567
item.setAttribute("label","moot " + this.moot[x].name);
68+
xul_popupmenu.appendChild(item);
5669
} else {
5770
this.log(WARN,"Moot rule invisible " + this.moot[x].name);
5871
}
@@ -62,11 +75,15 @@ ApplicableList.prototype = {
6275
},
6376

6477
show_applicable: function() {
78+
this.log(WARN, "Applicable list number " + this.serial);
6579
for (var x in this.active)
6680
this.log(WARN,"Active: " + this.active[x].name);
6781

6882
for (x in this.inactive)
69-
this.log(WARN,"Inctive: " + this.inactive[x].name);
83+
this.log(WARN,"Inactive: " + this.inactive[x].name);
84+
85+
for (x in this.moot)
86+
this.log(WARN,"Moot: " + this.moot[x].name);
7087

7188
}
7289
};

src/chrome/content/code/HTTPS.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,15 @@ const HTTPS = {
8989
}
9090
if (ctx instanceof CI.nsIDOMWindow) {
9191
domWin = ctx.QueryInterface(CI.nsIDOMWindow);
92+
doc = domWin.document;
9293
} else if (ctx instanceof CI.nsIDOMNode) {
93-
domWin = ctx.QueryInterface(CI.nsIDOMNode).ownerDocument;
94-
if (! domWin) {
94+
var doc = ctx.QueryInterface(CI.nsIDOMNode).ownerDocument;
95+
if (! doc) {
9596
this.log(WARN, "No Document for request " + uri.spec);
9697
return null;
9798
}
98-
domWin = domWin.defaultView;
99+
domWin = doc.defaultView;
100+
this.log(WARN,"Coerced nsIDOMWin from Node");
99101
} else {
100102
this.log(WARN, "Context for " + uri.spec +
101103
"is some bizarre unexpected thing: " + ctx);
@@ -106,19 +108,22 @@ const HTTPS = {
106108
this.log(WARN, "that isn't a domWindow");
107109
}
108110
domWin = domWin.top; // jump out of iframes
109-
alist = domWin.getUserData("https_everywhere_applicable_rules");
111+
doc = doc.documentElement;
112+
alist = HTTPSEverywhere.instance.getExpando(doc,"applicable_rules", null);
110113
if (alist) {
111114
this.log(DBUG,"Found existing applicable list");
112115
//alist.show_applicable();
113116
} else {
114117
// Usually onLocationChange should have put this in here for us, in some
115118
// cases perhaps we have to make it here...
116-
alist = new ApplicableList(this.log);
117-
domWin.setPropertyAsInterface("https_everywhere_applicable_rules", alist);
119+
alist = new ApplicableList(this.log,doc);
120+
this.log(WARN, "Sanity should be, " + alist);
121+
HTTPSEverywhere.instance.setExpando(doc,"applicable_rules", alist);
118122
this.log(WARN, "had to generate applicable list in forceURI for " +
119-
uri.spec + ", " + alist);
123+
uri.spec + " in " + doc.baseURIObject.spec);
124+
alist = HTTPSEverywhere.instance.getExpando(doc,"applicable_rules", null);
125+
this.log(WARN, "Sanity check: " + alist);
120126
}
121-
this.log(VERB, "Successfully returning " + alist);
122127
return alist;
123128
},
124129

src/chrome/content/code/HTTPSRules.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,21 +329,21 @@ const HTTPSRules = {
329329
if (applicable_list) {
330330
this.log("Adding active rule: " + rs[i].name);
331331
applicable_list.active_rule(rs[i]);
332-
applicable_list.show_applicable();
332+
//applicable_list.show_applicable();
333333
}
334334
return newuri;
335335
} else if (0 == newuri) {
336336
// the ruleset is inactive
337337
if (applicable_list) {
338338
this.log("Adding inactive rule: " + rs[i].name);
339339
applicable_list.inactive_rule(rs[i]);
340-
applicable_list.show_applicable();
340+
//applicable_list.show_applicable();
341341
}
342342
} else if (uri.scheme == "https" && applicable_list && rs[i].active) {
343343
// we didn't rewrite but the rule applies to this domain and the
344344
// requests are going over https
345345
applicable_list.moot_rule(rs[i]);
346-
applicable_list.show_applicable();
346+
//applicable_list.show_applicable();
347347
}
348348
}
349349
return null;

src/chrome/content/toolbar_button.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
window.addEventListener("load", https_everywhere_load, true);
22

33
const CI = Components.interfaces;
4+
const CC = Components.classes;
5+
6+
47

58
function https_everywhere_load() {
69
try {
@@ -33,11 +36,19 @@ function show_applicable_list(doc) {
3336
alert(domWin + " is not an nsICDOMWindow");
3437
return null;
3538
}
36-
var alist = domWin.document.getUserData("https_everywhere_applicable_rules");
39+
40+
HTTPSEverywhere = CC["@eff.org/https-everywhere;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
41+
var alist = HTTPSEverywhere.getExpando(domWin.document,"applicable_rules", null);
42+
3743
if (alist) {
44+
alist.log(5,"Success wherein domWin is " + domWin);
45+
alist.show_applicable();
3846
alist.populate_menu(doc,menu_popup);
3947
} else {
40-
alert("Missing applicable rules");
48+
HTTPSEverywhere.log(5,"Failure wherein domWin is " + domWin);
49+
var str = "Missing applicable rules for " + domWin.document.baseURIObject.spec;
50+
str += "\ndomWin is " + domWin;
51+
alert(str);
4152
return null;
4253
}
4354
}

src/components/https-everywhere.js

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ HTTPSEverywhere.prototype = {
198198
return Components.utils.getWeakReference(this);
199199
},
200200

201+
// An "expando" is an attribute glued onto something. From NoScript.
202+
getExpando: function(domObject, key, defValue) {
203+
return domObject && domObject.__httpsEStorage && domObject.__httpsEStorage[key] ||
204+
(defValue ? this.setExpando(domObject, key, defValue) : null);
205+
},
206+
207+
setExpando: function(domObject, key, value) {
208+
if (!domObject) return null;
209+
if (!domObject.__httpsEStorage) domObject.__httpsEStorage = {};
210+
if (domObject.__httpsEStorage) domObject.__httpsEStorage[key] = value;
211+
else this.log(WARN, "Warning: cannot set expando " + key + " to value " + value);
212+
return value;
213+
},
214+
215+
201216
// This function is registered solely to detect favicon loads by virtue
202217
// of their failure to pass through this function.
203218
onStateChange: function(wp, req, stateFlags, status) {
@@ -219,9 +234,14 @@ HTTPSEverywhere.prototype = {
219234
var x = wp.DOMWindow;
220235
var top_window;
221236
if (x instanceof CI.nsIDOMWindow) {
222-
var top_window = x.top; // climb out of iframes
223-
top_window.document.setUserData("https_everywhere_applicable_rules", new ApplicableList(this.log), null);
224-
this.log(WARN,"onLocationChange, made new alist for " +uri.spec);
237+
top_window = x.top; // climb out of iframes
238+
if (top_window.document) {
239+
var alist = new ApplicableList(this.log,top_window.document);
240+
this.setExpando(top_window, "applicable rules", alist);
241+
this.log(WARN,"onLocationChange, made new alist for " +uri.spec);
242+
} else {
243+
this.log(WARN,"onLocationChange, document is null");
244+
}
225245
} else {
226246
this.log(WARN,"onLocationChange: no nsIDOMWindow");
227247
}
@@ -230,9 +250,8 @@ HTTPSEverywhere.prototype = {
230250
}
231251
},
232252

233-
// the lists get made when the urlbar is loading something new, but they
234-
// need to be appended to with reference only to the channel
235-
getApplicableListForChannel: function(channel) {
253+
getWindowForChannel: function(channel) {
254+
// Obtain an nsIDOMWindow from a channel
236255
var nc = channel.notificationCallbacks ? channel.notificationCallbacks : channel.loadGroup.notificationCallbacks;
237256
if (!nc) {
238257
this.log(WARN, "no window for " + channel.URI.spec);
@@ -244,16 +263,26 @@ HTTPSEverywhere.prototype = {
244263
return null;
245264
}
246265
domWin = domWin.top;
247-
if ("https_everywhere_applicable_rules" in domWin) {
248-
//domWin.https_everywhere_applicable_rules.show_applicable();
249-
return domWin.https_everywhere_applicable_rules;
266+
return domWin
267+
},
268+
269+
// the lists get made when the urlbar is loading something new, but they
270+
// need to be appended to with reference only to the channel
271+
getApplicableListForChannel: function(channel) {
272+
var domWin = this.getWindowForChannel(channel);
273+
var alist= this.getExpando(domWin.document,"applicable_rules",null);
274+
if (alist) {
275+
this.log(WARN,"get AL success");
276+
return alist;
250277
} else {
251278
this.log(DBUG, "Making new AL in getApplicableListForChannel");
252-
domWin.document.setUserData("https_everywhere_applicable_rules", new ApplicableList(this.log), null);
279+
alist = new ApplicableList(this.log,domWin.document);
280+
this.setExpando(domWin.document,"applicable_rules",alist);
253281
}
254-
return domWin.https_everywhere_applicable_rules;
282+
return alist;
255283
},
256284

285+
257286
observe: function(subject, topic, data) {
258287
// Top level glue for the nsIObserver API
259288
var channel = subject;
@@ -323,9 +352,26 @@ HTTPSEverywhere.prototype = {
323352
this.log(DBUG, newChannel + " is not an instance of nsIHttpChannel");
324353
return;
325354
}
355+
var alist = this.juggleApplicableListsDuringRedirection(oldChannel, newChannel);
356+
HTTPS.replaceChannel(alist,newChannel);
357+
},
326358

327-
var lst = this.getApplicableListForChannel(channel);
328-
HTTPS.replaceChannel(lst,newChannel);
359+
juggleApplicableListsDuringRedirection: function(oldChannel, newChannel) {
360+
// If the new channel doesn't yet have a list of applicable rulesets, start
361+
// with the old one because that's probably a better representation of how
362+
// secure the load process was for this page
363+
var domWin = this.getWindowForChannel(oldChannel);
364+
var old_alist = this.getExpando(domWin,"applicable_rules", null);
365+
domWin = this.getWindowForChannel(newChannel);
366+
var new_alist = this.getExpando(domWin,"applicable_rules", null);
367+
if (old_alist && !new_alist) {
368+
new_alist = old_alist;
369+
this.setExpando(domWin,"applicable_rules",new_alist);
370+
} else if (!new_alist) {
371+
new_alist = new ApplicableList(this.log, domWin.document);
372+
this.setExpando(domWin,"applicable_rules",new_alist);
373+
}
374+
return new_alist;
329375
},
330376

331377
asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
@@ -347,6 +393,7 @@ HTTPSEverywhere.prototype = {
347393
var unwrappedLocation = IOUtil.unwrapURL(aContentLocation);
348394
var scheme = unwrappedLocation.scheme;
349395
var isHTTP = /^https?$/.test(scheme); // s? -> either http or https
396+
this.log(VERB,"shoulLoad for " + aContentLocation.spec);
350397
if (isHTTP)
351398
HTTPS.forceURI(aContentLocation, null, aContext);
352399
return true;

0 commit comments

Comments
 (0)