@@ -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 = / ^ h t t p s ? $ / . 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