[Pkg-mozext-commits] [noscript] 01/06: Imported Upstream version 2.6.9.23~rc1

David Prévot taffit at moszumanska.debian.org
Wed May 20 17:59:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository noscript.

commit 2e33d66dff0612e42fe7cd8a4d6decd66e908990
Author: David Prévot <david at tilapin.org>
Date:   Wed May 20 12:46:10 2015 -0400

    Imported Upstream version 2.6.9.23~rc1
---
 NoScript_License.txt                               |    2 +-
 chrome/noscript.jar!/content/noscript/CSP.js       |    4 +-
 .../content/noscript/ChannelReplacement.js         |  241 ++-
 chrome/noscript.jar!/content/noscript/DNS.js       |  103 +-
 .../noscript.jar!/content/noscript/FrameScript.jsm |    4 +-
 chrome/noscript.jar!/content/noscript/HTTPS.js     |  126 +-
 .../content/noscript/RequestWatchdog.js            |  905 +++++----
 chrome/noscript.jar!/content/noscript/STS.js       |  234 ---
 chrome/noscript.jar!/content/noscript/WinScript.js |   67 +-
 chrome/noscript.jar!/content/noscript/about.xul    |    8 +-
 .../noscript.jar!/content/noscript/childScript.js  |   49 +
 .../noscript.jar!/content/noscript/frameScript.js  |    2 +-
 chrome/noscript.jar!/content/noscript/loader.js    |   44 +
 .../content/noscript/parentProcess.js              |   43 +
 .../locale/bg-BG/noscript/noscript.dtd             |    2 +-
 .../locale/ca-AD/noscript/noscript.dtd             |    2 +-
 .../locale/cs-CZ/noscript/noscript.dtd             |    2 +-
 .../locale/cy-GB/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/da/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/de/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/el/noscript/noscript.dtd  |    2 +-
 .../locale/en-GB/noscript/noscript.dtd             |    2 +-
 .../locale/en-US/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/eo/noscript/noscript.dtd  |    2 +-
 .../locale/es-AR/noscript/noscript.dtd             |    2 +-
 .../locale/es-CL/noscript/noscript.dtd             |    2 +-
 .../locale/es-ES/noscript/noscript.dtd             |    2 +-
 .../locale/et-EE/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/eu/noscript/noscript.dtd  |    2 +-
 .../locale/fa-IR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/fi/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/fr/noscript/noscript.dtd  |    2 +-
 .../locale/gl-ES/noscript/noscript.dtd             |    2 +-
 .../locale/he-IL/noscript/noscript.dtd             |    2 +-
 .../locale/hr-HR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/hsb/noscript/noscript.dtd |    2 +-
 .../locale/hu-HU/noscript/noscript.dtd             |    2 +-
 .../locale/id-ID/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/it/noscript/noscript.dtd  |    2 +-
 .../locale/ja-JP/noscript/noscript.dtd             |    2 +-
 .../locale/kk-KZ/noscript/noscript.dtd             |    2 +-
 .../locale/km-KH/noscript/noscript.dtd             |    2 +-
 .../locale/ko-KR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/lt/noscript/noscript.dtd  |    2 +-
 .../locale/mk-MK/noscript/noscript.dtd             |    2 +-
 .../locale/ms-MY/noscript/noscript.dtd             |    2 +-
 .../locale/nb-NO/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/nl/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/pl/noscript/noscript.dtd  |    2 +-
 .../locale/pt-BR/noscript/noscript.dtd             |    2 +-
 .../locale/pt-PT/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/ro/noscript/noscript.dtd  |    2 +-
 .../locale/ru-RU/noscript/about.properties         |    4 +-
 .../locale/ru-RU/noscript/noscript.dtd             |   54 +-
 .../locale/ru-RU/noscript/noscript.properties      |   12 +-
 .../locale/sk-SK/noscript/noscript.dtd             |    2 +-
 .../locale/sl-SI/noscript/noscript.dtd             |    2 +-
 .../locale/sr-RS/noscript/noscript.dtd             |    2 +-
 .../locale/sv-SE/noscript/noscript.dtd             |    2 +-
 .../locale/te-IN/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/th/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/tr/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/vi/noscript/noscript.dtd  |    2 +-
 .../locale/zh-CN/noscript/noscript.dtd             |    2 +-
 .../locale/zh-TW/noscript/noscript.dtd             |    2 +-
 components/noscriptService.js                      | 2062 ++++++++++----------
 defaults/preferences/noscript.js                   |   11 +-
 install.rdf                                        |    4 +-
 68 files changed, 1996 insertions(+), 2079 deletions(-)

diff --git a/NoScript_License.txt b/NoScript_License.txt
index 00a3b0e..ab6ab8f 100644
--- a/NoScript_License.txt
+++ b/NoScript_License.txt
@@ -14,4 +14,4 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the
 Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\ No newline at end of file
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/chrome/noscript.jar!/content/noscript/CSP.js b/chrome/noscript.jar!/content/noscript/CSP.js
index c4b9c78..6311245 100644
--- a/chrome/noscript.jar!/content/noscript/CSP.js
+++ b/chrome/noscript.jar!/content/noscript/CSP.js
@@ -1,7 +1,7 @@
 var CSP = {
   HEADER_NAME: "Content-Security-Policy",
   HEADER_VALUE: "script-src 'none'",
-  
+
   block: function(window) {
     window._blockedByCSP = true;
     let doc = window.document;
@@ -22,4 +22,4 @@ var CSP = {
   QueryInterface: xpcom_generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference])
 }
 
-OS.addObserver(CSP, "document-element-inserted", true);
\ No newline at end of file
+OS.addObserver(CSP, "document-element-inserted", true);
diff --git a/chrome/noscript.jar!/content/noscript/ChannelReplacement.js b/chrome/noscript.jar!/content/noscript/ChannelReplacement.js
index 72abd67..806241e 100644
--- a/chrome/noscript.jar!/content/noscript/ChannelReplacement.js
+++ b/chrome/noscript.jar!/content/noscript/ChannelReplacement.js
@@ -16,6 +16,46 @@ CtxCapturingListener.prototype = {
   QueryInterface: xpcom_generateQI([Ci.nsIStreamListener])
 }
 
+function RedirectCallback(channelReplacement) {
+  this.channelReplacement = channelReplacement;
+}
+
+RedirectCallback.prototype = {
+  references: 0,
+  async: false,
+  vetoed: false,
+  _autoPending: false,
+  QueryInterface: xpcom_generateQI([Ci.nsIAsyncVerifyRedirectCallback]),
+  notifySink: function(sink) {
+    let { oldChannel: oldChan, channel: newChan, REDIRECT_FLAGS: flags } = this.channelReplacement;
+    this._notifying = true;
+    this.references++;
+    try {
+      sink.asyncOnChannelRedirect(oldChan, newChan, flags, this);
+    } catch (e) {
+      this.vetoed = true;
+    } finally {
+      this._notifying = false;
+      if (this.references > 0) this.async = true;
+      else if (!this._autoPending) {
+        Thread.asap(this._autoCallback, this);
+        this._autoPending = true;
+      }
+    }
+  },
+  onRedirectVerifyCallback: function(result) {
+    if (!Components.isSuccessCode(result)) this.vetoed = true;
+    if (--this.references === 0 && this.async)
+      this._callback();
+  },
+  _autoCallback: function() {
+    if (!this.async) this._callback();
+  },
+  _callback: function() {
+    if (!this.vetoed) this.channelReplacement.openNew();
+  }
+};
+
 function ChannelReplacement(chan, newURI, newMethod) {
   return this._init(chan, newURI, newMethod);
 }
@@ -38,16 +78,20 @@ ChannelReplacement.prototype = {
   channel: null,
   window: null,
   suspended: false,
-  
+  REDIRECT_FLAGS: Ci.nsIChannelEventSink.REDIRECT_INTERNAL,
+
+  _redirectCallback: null,
+  _ctxCapturingListener: null,
+
   get _unsupportedError() {
     return new Error("Can't replace channels without nsITraceableChannel!");
   },
-  
+
   get _classifierClass() {
     delete this.__proto__._classifierClass;
     return this.__proto__._classifierClass = Cc["@mozilla.org/channelclassifier"];
   },
-  
+
   _autoHeadersRx: /^(?:Host|Cookie|Authorization)$|Cache|^If-/,
   visitHeader: function(key, val) {
     try {
@@ -57,38 +101,44 @@ ChannelReplacement.prototype = {
       dump(e + "\n");
     }
   },
-  
+
   _init: function(chan, newURI, newMethod) {
     if (!(chan instanceof Ci.nsITraceableChannel))
       throw this._unsupportedError;
-  
+
+    let self = this;
+
+    if ("nsIAsyncVerifyRedirectCallback" in Ci) {
+      this._redirectCallback = new RedirectCallback(this);
+    }
+
     newURI = newURI || chan.URI;
-    
+
     var newChan = IOS.newChannelFromURI(newURI);
-    
+
     this.oldChannel = chan;
     this.channel = newChan;
-    
+
     // porting of http://lxr.mozilla.org/mozilla-central/source/netwerk/base/src/nsBaseChannel.cpp#69
-    
+
     var loadFlags = chan.loadFlags;
-    
+
     if (chan.URI.schemeIs("https"))
       loadFlags &= ~chan.INHIBIT_PERSISTENT_CACHING;
-    
-    
+
+
     newChan.loadGroup = chan.loadGroup;
     newChan.notificationCallbacks = chan.notificationCallbacks;
     newChan.loadFlags = loadFlags | newChan.LOAD_REPLACE;
-    
+
     if ("nsIPrivateBrowsingService" in Ci &&
          chan instanceof Ci.nsIPrivateBrowsingService && chan.isChannelPrivate &&
          newChan instanceof Ci.nsIPrivateBrowsingService && !newChan.isChannelPrivate)
       newChan.setPrivate(true);
-    
+
     if (!(newChan instanceof Ci.nsIHttpChannel))
       return this;
-    
+
     // copy headers
     chan.visitRequestHeaders(this);
 
@@ -98,7 +148,7 @@ ChannelReplacement.prototype = {
         if (stream instanceof Ci.nsISeekableStream) {
           stream.seek(stream.NS_SEEK_SET, 0);
         }
-        
+
         try {
           let ctype = chan.getRequestHeader("Content-type");
           let clen = chan.getRequestHeader("Content-length");
@@ -113,7 +163,7 @@ ChannelReplacement.prototype = {
     } else {
       newChan.requestMethod = newMethod;
     }
-    
+
     if (chan.referrer) newChan.referrer = chan.referrer;
     newChan.allowPipelining = chan.allowPipelining;
     newChan.redirectionLimit = chan.redirectionLimit - 1;
@@ -128,21 +178,21 @@ ChannelReplacement.prototype = {
       if ("allowSpdy" in newChan)
         newChan.allowSpdy = chan.allowSpdy;
     }
-    
+
     if (chan instanceof Ci.nsIEncodedChannel && newChan instanceof Ci.nsIEncodedChannel) {
       newChan.applyConversion = chan.applyConversion;
     }
-    
+
     // we can't transfer resume information because we can't access mStartPos and mEntityID :(
     // http://mxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/src/nsHttpChannel.cpp#2826
-    
+
     if ("nsIApplicationCacheChannel" in Ci &&
       chan instanceof Ci.nsIApplicationCacheChannel && newChan instanceof Ci.nsIApplicationCacheChannel) {
       newChan.applicationCache = chan.applicationCache;
       newChan.inheritApplicationCache = chan.inheritApplicationCache;
     }
-    
-    if (chan instanceof Ci.nsIPropertyBag && newChan instanceof Ci.nsIWritablePropertyBag) 
+
+    if (chan instanceof Ci.nsIPropertyBag && newChan instanceof Ci.nsIWritablePropertyBag)
       for (var properties = chan.enumerator, p; properties.hasMoreElements();)
         if ((p = properties.getNext()) instanceof Ci.nsIProperty)
           newChan.setProperty(p.name, p.value);
@@ -150,56 +200,59 @@ ChannelReplacement.prototype = {
     if (chan.loadFlags & chan.LOAD_DOCUMENT_URI) {
       this.window = IOUtil.findWindow(chan);
     }
-    
+
     return this;
   },
-  
+
   _onChannelRedirect: function() {
     var oldChan = this.oldChannel;
     var newChan = this.channel;
-    
+
     if (this.realRedirect) {
       if (oldChan.redirectionLimit === 0) {
         oldChan.cancel(NS_ERROR_REDIRECT_LOOP);
         throw NS_ERROR_REDIRECT_LOOP;
       }
     } else newChan.redirectionLimit += 1;
-    
-    
-    
+
+
+
     // nsHttpHandler::OnChannelRedirect()
 
     const CES = Ci.nsIChannelEventSink;
-    const flags = CES.REDIRECT_INTERNAL;
-    this._callSink(
-      Cc["@mozilla.org/netwerk/global-channel-event-sink;1"].getService(CES),
-      oldChan, newChan, flags);
+
+    this._notifySink(Cc["@mozilla.org/netwerk/global-channel-event-sink;1"].getService(CES));
     var sink;
-    
+
     for (let cess = ns.categoryManager.enumerateCategory("net-channel-event-sinks");
           cess.hasMoreElements();
         ) {
       sink = cess.getNext();
       if (sink instanceof CES)
-        this._callSink(sink, oldChan, newChan, flags);
+        this._notifySink(sink);
     }
     sink = IOUtil.queryNotificationCallbacks(oldChan, CES);
-    if (sink) this._callSink(sink, oldChan, newChan, flags);
-    
+    if (sink) this._notifySink(sink);
+
     // ----------------------------------
-    
+
     newChan.originalURI = oldChan.originalURI;
-    
+
     sink = IOUtil.queryNotificationCallbacks(oldChan, Ci.nsIHttpEventSink);
     if (sink) sink.onRedirect(oldChan, newChan);
   },
-  
-  _callSink: function(sink, oldChan, newChan, flags) {
+
+  _notifySink: function(sink, oldChan, newChan) {
+    const flags = this.REDIRECT_FLAGS;
     try {
       sink instanceof Ci.nsISupports;
       if ("onChannelRedirect" in sink) sink.onChannelRedirect(oldChan, newChan, flags);
       else if ("asyncOnChannelRedirect" in sink) {
-        sink.asyncOnChannelRedirect(oldChan, newChan, flags, this._redirectCallback);
+        if (this._redirectCallback) {
+          this._redirectCallback.notifySink(sink);
+        } else {
+          sink.asyncOnChannelRedirect(oldChan, newChan, flags, null);
+        }
       } else {
         ABE.log("Unexpected: asyncOnChannelRedirect not found, instanceof nsIChannelEventSink = " + (sink instanceof Ci.nsIChannelEventSink) + "\n" +
                 sink + "\n" + (new Error().stack));
@@ -209,7 +262,7 @@ ChannelReplacement.prototype = {
         let oldURL = oldChan.URI.spec;
         try {
           oldChan.URI.spec = newChan.URI.spec;
-          this._callSink(sink, oldChan, newChan, flags);
+          this._notifySink(sink, oldChan, newChan, flags);
         } catch(e1) {
           throw e;
         } finally {
@@ -218,15 +271,8 @@ ChannelReplacement.prototype = {
       } else if (e.message.indexOf("(NS_ERROR_NOT_AVAILABLE)") === -1) throw e;
     }
   },
-  
-  _redirectCallback: ("nsIAsyncVerifyRedirectCallback" in Ci)
-    ? {
-        QueryInterface: xpcom_generateQI([Ci.nsIAsyncVerifyRedirectCallback]),
-        onRedirectVerifyCallback: function(result) {}
-      }
-    : null
-  ,
-  
+
+
   replace: function(realRedirect, callback) {
     let self = this;
     let oldChan = this.oldChannel;
@@ -236,35 +282,37 @@ ChannelReplacement.prototype = {
     }
     ChannelReplacement.runWhenPending(oldChan, function() {
       if (oldChan.status) return; // channel's doom had been already defined
-     
-      let ccl = new CtxCapturingListener(oldChan, self);
+
+      self._ctxCapturingListener = new CtxCapturingListener(oldChan, self);
       self.loadGroup = oldChan.loadGroup;
-     
+
       oldChan.loadGroup = null; // prevents the wheel from stopping spinning
-      
-    
+
+
       if (self._redirectCallback) { // Gecko >= 2
         // this calls asyncAbort, which calls onStartRequest on our listener
-        oldChan.cancel(NS_BINDING_REDIRECTED); 
-        self.suspend(); // believe it or not, this will defer asyncAbort() notifications until resume()
-        callback(self);
+        oldChan.cancel(NS_BINDING_REDIRECTED);
+        if (!self._redirectCallback.vetoed) {
+          self.suspend(); // believe it or not, this will defer asyncAbort() notifications until resume()
+          callback(self);
+        }
       } else {
         // legacy (Gecko < 2)
-        self.observeCapture = function(req, ccl) {
-          self.open = function() { self._redirect(ccl) }
+        self.observeCapture = function() {
+          self.open = self._redirect;
           callback(self);
         }
-        oldChan.cancel(NS_BINDING_REDIRECTED); 
+        oldChan.cancel(NS_BINDING_REDIRECTED);
       }
-      
+
 
     });
   },
-  
-  observeCapture: function(req, ccl) {
-    this._redirect(ccl);
+
+  observeCapture: function() {
+    this._redirect();
   },
-  
+
   _defaultCallback: function(replacement) {
     replacement.open();
   },
@@ -272,7 +320,7 @@ ChannelReplacement.prototype = {
   open: function() {
     this.resume(); // this triggers asyncAbort and the listeners in cascade
   },
-  _redirect: function(ccl) {
+  _redirect: function() {
     let oldChan = this.oldChannel,
       newChan = this.channel,
       overlap;
@@ -282,21 +330,14 @@ ChannelReplacement.prototype = {
         if (ABE.consoleDump && this.window) {
           ABE.log("Opening delayed channel: " + oldChan.name + " - (current loading channel for this window " + (overlap && overlap.name) + ")");
         }
-        
+
         oldChan.loadGroup = this.loadGroup;
-    
+
         this._onChannelRedirect();
-        newChan.asyncOpen(ccl.originalListener, ccl.originalCtx);
-        
-        if (this.window && this.window != IOUtil.findWindow(newChan)) { 
-          // late diverted load, unwanted artifact, abort
-          IOUtil.abort(newChan);
-        } else {
-          // safe browsing hook
-          if (this._classifierClass)
-            this._classifierClass.createInstance(Ci.nsIChannelClassifier).start(newChan, true);
+        if (!this._redirectCallback) {
+          this.openNew();
         }
-        
+
       } catch (e) {
         ABE.log(e);
       }
@@ -305,10 +346,38 @@ ChannelReplacement.prototype = {
         ABE.log("Detected double load on the same window: " + oldChan.name + " - " + (overlap && overlap.name));
       }
     }
-    
+
     this.dispose();
   },
-  
+
+
+  openNew: function() {
+    let newChan = this.channel;
+    let ccl = this._ctxCapturingListener;
+
+    newChan.asyncOpen(ccl.originalListener, ccl.originalCtx);
+
+    if ("nsIRedirectResultListener" in Ci) {
+      // Bug 1153256
+      let vetoHook = IOUtil.queryNotificationCallbacks(
+                      this.oldChannel,
+                      Ci.nsIRedirectResultListener);
+      if (vetoHook) vetoHook.onRedirectResult(true);
+    }
+
+    if (this.window && this.window != IOUtil.findWindow(newChan)) {
+      // late diverted load, unwanted artifact, abort
+      IOUtil.abort(newChan);
+    } else {
+      // safe browsing hook
+      if (this._classifierClass)
+        this._classifierClass.createInstance(Ci.nsIChannelClassifier).start(newChan, true);
+    }
+
+
+
+  },
+
   suspend: function() {
     if (!this.suspended) {
       this.oldChannel.suspend();
@@ -323,7 +392,7 @@ ChannelReplacement.prototype = {
       } catch (e) {}
     }
   },
-  
+
   dispose: function() {
     this.resume();
     if (this.loadGroup) {
@@ -344,7 +413,7 @@ function LoadGroupWrapper(channel, callback) {
 }
 LoadGroupWrapper.prototype = {
   QueryInterface: xpcom_generateQI([Ci.nsILoadGroup]),
-  
+
   get activeCount() {
     return this._inner ? this._inner.activeCount : 0;
   },
@@ -369,7 +438,7 @@ LoadGroupWrapper.prototype = {
   get requests() {
     return this._inner ? this._inner.requests : this._emptyEnum;
   },
-  
+
   addRequest: function(r, ctx) {
     this.detach();
     if (this._inner) try {
@@ -386,7 +455,7 @@ LoadGroupWrapper.prototype = {
     this.detach();
     if (this._inner) this._inner.removeRequest(r, ctx, status);
   },
-  
+
   detach: function() {
     if (this._channel.loadGroup) this._channel.loadGroup = this._inner;
   },
diff --git a/chrome/noscript.jar!/content/noscript/DNS.js b/chrome/noscript.jar!/content/noscript/DNS.js
index afb67fc..8048bd0 100644
--- a/chrome/noscript.jar!/content/noscript/DNS.js
+++ b/chrome/noscript.jar!/content/noscript/DNS.js
@@ -6,7 +6,7 @@ function DNSRecord(record) {
       this.canonicalName = record.canonicalName;
     } catch(e) {}
     this.entries = [];
-    
+
     try {
       for (;;) this.entries.push(record.getNextAddrAsString());
     } catch(e) {
@@ -33,8 +33,8 @@ DNSRecord.prototype = {
   expireTime: 0,
   refreshing: false,
   localExtras: null, // AddressMatcher object which can be added to the LOCAL resolution
-  
-  
+
+
   isLocal: function(all) {
     return all
       ? "everyLocal" in this
@@ -48,12 +48,12 @@ DNSRecord.prototype = {
   get expired() {
     return Date.now() > this.expireTime;
   }
-  
+
 }
 
 
 var DNS = {
-  
+
   get logFile() {
     delete this.logFile;
     var logFile = Cc["@mozilla.org/file/directory_service;1"]
@@ -73,7 +73,7 @@ var DNS = {
         const header="*** Log start at "+new Date().toGMTString()+"\n";
         this.logStream.write(header,header.length);
       }
-      
+
       if (msg!=null) {
         msg += "\n";
         this.logStream.write(msg,msg.length);
@@ -83,19 +83,19 @@ var DNS = {
       dump(ex.message+"\noccurred logging this message:\n"+msg);
     }
   },
-  
+
   get _dns() {
     delete this._dns;
     return this._dns = Cc["@mozilla.org/network/dns-service;1"]
                   .getService(Ci.nsIDNSService);
   },
-  
+
   _cache: {
     CAPACITY: 400, // when we purge, we cut this to half
     _map: {__proto__: null},
     _ext: {__proto__: null},
     count: 0,
-    
+
 
     get: function(key) {
       return key in this._map && this._map[key];
@@ -112,7 +112,7 @@ var DNS = {
     evict: function(host) {
       return (host in this._map) && (delete this._map[host]);
     },
-    
+
     purge: function() {
       var max = this.CAPACITY / 2;
       if (this.count < max) return;
@@ -123,25 +123,25 @@ var DNS = {
       }
       this._doPurge(map, l, max);
     },
-    
+
     reset: function() {
       this._map = {__proto__: null};
       this._ext = {__proto__: null},
       this.count = 0;
     },
-    
+
     _oldLast: function(a, b) {
-      return a.t > b.t ? -1 : a.t < b.t ? 1 : 0; 
+      return a.t > b.t ? -1 : a.t < b.t ? 1 : 0;
     },
-    
+
     putExt: function(host) {
       this._ext[host] = true;
     },
     isExt: function(host) {
       return host in this._ext;
     },
-    
-    
+
+
     _doPurge: function(map, l, max) {
       l.sort(this._oldLast);
       for (var j = l.length; j-- > max;) {
@@ -150,13 +150,13 @@ var DNS = {
       this.count -= (l.length - max);
     }
   },
-  
+
   get idn() {
     delete this.idn;
     return this.idn =  Cc["@mozilla.org/network/idn-service;1"]
       .getService(Ci.nsIIDNService);
   },
-  
+
   _invalidRx: /[^\w\-\.]/,
   checkHostName: function(host) {
     if (this._invalidRx.test(host) && !this.isIP(host)) {
@@ -169,15 +169,15 @@ var DNS = {
     }
     return true;
   },
-  
+
   _resolving: {},
-  resolve: function(host, flags, callback) { 
+  resolve: function(host, flags, callback) {
     flags = flags || 0;
 
     var elapsed = 0, t;
     var cache = this._cache;
     var async = IOUtil.asyncNetworking || !!callback;
-    
+
     var dnsRecord = cache.get(host);
     if (dnsRecord) {
       // cache invalidation, if needed
@@ -192,7 +192,7 @@ var DNS = {
         } else {
           flags |= 1;
         }
-        if (flags & 1) {  
+        if (flags & 1) {
           dnsRecord = null;
           cache.evict(host);
         }
@@ -201,27 +201,27 @@ var DNS = {
     if (dnsRecord) {
       if (ABE.consoleDump) ABE.log("Using cached DNS record for " + host);
     } else if (this.checkHostName(host)) {
-      
+
       if (async) {
         var resolving = this._resolving;
-  
+
         if (host in resolving) {
           ABE.log("Already resolving " + host);
-          
+
           if (callback) {
             resolving[host].push(callback);
             return null;
           }
         } else resolving[host] = callback ? [callback] : [];
-        
+
         var ctrl = {
           running: true,
           startTime: Date.now()
         };
-        
+
         var status = Cr.NS_OK;
-        
-        
+
+
         var resolve = function() {
           DNS._dns.asyncResolve(host, flags, new DNSListener(function() {
             if (DNS.logEnabled) DNS.log("Async " + host);
@@ -233,26 +233,26 @@ var DNS = {
               elapsed = Date.now() - t;
               ABE.log("Async DNS query on " + host + " done, " + elapsed + "ms, callbacks: " + (callbacks && callbacks.length));
             }
-            
+
             if (callbacks && callbacks.length)
               for each(var cb in callbacks)
                 cb(dnsRecord);
-            
+
           }), Thread.currentQueue);
           if (ABE.consoleDump) ABE.log("Waiting for DNS query on " + host);
           if (!callback) Thread.spin(ctrl);
         }
-        
+
         if (callback) {
           t = Date.now();
           resolve();
           return null;
         }
-        
+
         resolve();
-        
+
         if (!Components.isSuccessCode(status)) throw status;
-        
+
         elapsed = ctrl.elapsed || 0;
       } else {
         t = Date.now();
@@ -264,9 +264,9 @@ var DNS = {
     } else {
       this._cache.put(host, dnsRecord = new DNSRecord(null)); // invalid host name
     }
-    
+
     if (ABE.consoleDump) ABE.log("DNS query on " + host + " done, " + elapsed + "ms");
-    
+
     if (callback) {
       callback(dnsRecord);
     } else {
@@ -274,14 +274,14 @@ var DNS = {
     }
     return dnsRecord;
   },
-  
-  
-  
+
+
+
   evict: function(host) {
     ABE.log("Removing DNS cache record for " + host);
     return this._cache.evict(host);
   },
-  
+
   invalidate: function(host) {
     var dnsRecord = this._cache.get(host);
     if (!dnsRecord.valid) return false;
@@ -289,16 +289,16 @@ var DNS = {
     dnsRecord.expireTime = 0;
     return true;
   },
-  
+
   getCached: function(host) {
     return this._cache.get(host);
   },
-  
+
   isCached: function(host) {
     var res =  this._cache.get(host);
     return res && (res.valid || !res.expired);
   },
-  
+
   isLocalURI: function(uri, all) {
     var host;
     try {
@@ -309,7 +309,7 @@ var DNS = {
     if (!host) return true; // local file:///
     return this.isLocalHost(host, all);
   },
-  
+
   _localDomainRx: /\.local$/i,
   isLocalHost: function(host, all, dontResolve) {
     if (host === "localhost" || this._localDomainRx.test(host)) return true;
@@ -318,16 +318,16 @@ var DNS = {
     }
 
     if (all && this._cache.isExt(host) || dontResolve) return false;
-  
+
     var res = this.resolve(host, 0).isLocal(all);
 
     if (!res) {
       this._cache.putExt(host);
     }
-    
+
     return res;
   },
-  
+
   _localIP6Rx: /^(?:::1?$|f(?:[cd]|e[c-f])[0-9a-f]*:)/i,
   get _localIPMatcher() new AddressMatcher('0. 127. 10. 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 255.255.255.255'),
   isLocalIP: function(addr) {
@@ -335,7 +335,7 @@ var DNS = {
     // Relevant RFCs linked at http://en.wikipedia.org/wiki/Private_network
     // Note: we omit link-local IPv6 addresses (fe80:/10) on purpose, because they're currently found in the wild as misconfigured
     //       AAAA DNS records. The safest work-around is considering them external to the LAN always.
-    
+
     return this._localIP6Rx.test(addr) ||
       this._localIPMatcher.testIP(addr = this.ip6to4(addr)) ||
       this.localExtras && this.localExtras.testIP(addr) ||
@@ -345,9 +345,9 @@ var DNS = {
   ip6to4: function(addr) {
     let m = addr.match(this._ip6to4Rx);
     return m ? (m[1]
-          ? m.slice(1).map(function(h) parseInt(h, 16)).join(".") 
+          ? m.slice(1).map(function(h) parseInt(h, 16)).join(".")
           : m[0].substring(1)
-       ) 
+       )
       : addr;
   },
   _ipRx: /^(?:0|[1-9]\d{0,2}\.){3}(?:0|[1-9]\d{0,2})$|:.*:/i, // very restrictive, rejects IPv4 hex, octal and int32
@@ -369,4 +369,3 @@ DNSListener.prototype = {
     if (this.callback) this.callback();
   }
 };
-
diff --git a/chrome/noscript.jar!/content/noscript/FrameScript.jsm b/chrome/noscript.jar!/content/noscript/FrameScript.jsm
index 0e943f9..20ee27e 100644
--- a/chrome/noscript.jar!/content/noscript/FrameScript.jsm
+++ b/chrome/noscript.jar!/content/noscript/FrameScript.jsm
@@ -8,5 +8,5 @@ function FrameScript(ctx) {
 }
 
 FrameScript.prototype = {
-  
-}
\ No newline at end of file
+
+}
diff --git a/chrome/noscript.jar!/content/noscript/HTTPS.js b/chrome/noscript.jar!/content/noscript/HTTPS.js
index 91434fd..acdd417 100644
--- a/chrome/noscript.jar!/content/noscript/HTTPS.js
+++ b/chrome/noscript.jar!/content/noscript/HTTPS.js
@@ -2,7 +2,7 @@ LAZY_INCLUDE('Cookie');
 
 const HTTPS = {
   ready: false,
-  
+
   secureCookies: false,
   secureCookiesExceptions: null,
   secureCookiesForced: null,
@@ -17,33 +17,33 @@ const HTTPS = {
       HTTPS.log("redirectTo " + uri.spec);
       channel.redirectTo(uri);
     } catch(e) {
-      HTTPS.log(e);   
+      HTTPS.log(e);
     }
     ChannelReplacement.runWhenPending(channel, function() {
-    
+
       new ChannelReplacement(channel, uri).replace(true);
       HTTPS.log("Forced Channel " + uri.spec);
     });
     return true;
-    
+
   },
-  
+
   forceURI: function(uri, fallback, ctx) {
     if (this.mustForce(uri)) {
       try {
-        
+
         uri.scheme = "https";
-        
+
         this.log("Forced URI " + uri.spec);
         return true;
-        
+
       } catch(e) {
-        
+
         if (ctx && ctx instanceof Ci.nsIDOMHTMLImageElement || ctx instanceof Ci.nsIDOMHTMLInputElement ||
             ctx instanceof Ci.nsIObjectLoadingContent) {
           uri = uri.clone();
           uri.scheme = "https";
-          
+
           var type, attr;
           if (ctx instanceof Ci.nsIObjectLoadingContent) {
             type = "Object";
@@ -53,41 +53,37 @@ const HTTPS = {
             attr = "src";
           }
           Thread.asap(function() { ctx.setAttribute(attr, uri.spec); });
-          
+
           var msg = type + " HTTP->HTTPS redirection to " + uri.spec;
-          this.log(msg);  
+          this.log(msg);
           throw msg;
         }
-        
+
         if (fallback && fallback()) {
            this.log("Channel redirection fallback on " + uri.spec);
            return true;
         }
-        
+
         this.log("Error trying to force https on " + uri.spec + ": " + e);
       }
     }
     return false;
   },
-  
+
   mustForce: function(uri) {
-    return (uri.schemeIs("http") &&
+    return uri.schemeIs("http") &&
         (this.httpsForced && this.httpsForced.test(uri.spec) ||
-         this.httpsForcedBuiltIn && this.httpsForcedBuiltIn.test(uri.spec) ||
-         STS.isSTSURI(uri)) &&
-          !(this.httpsForcedExceptions &&
-            this.httpsForcedExceptions.test(uri.spec)
-        ));
+         this.httpsForcedBuiltIn && this.httpsForcedBuiltIn.test(uri.spec));
   },
-  
+
   log: function(msg) {
     this.log = ns.getPref("https.showInConsole", true)
       ? function(msg) { ns.log("[NoScript HTTPS] " + msg); }
       : function(msg) {}
-      
+
     return this.log(msg);
   },
-  
+
   onCrossSiteRequest: function(channel, origin, browser, rw) {
     try {
       this.handleCrossSiteCookies(channel, origin, browser);
@@ -95,7 +91,7 @@ const HTTPS = {
       this.log(e + " --- " + e.stack);
     }
   },
-  
+
   registered: false,
   handleSecureCookies: function(req) {
   /*
@@ -111,11 +107,11 @@ const HTTPS = {
        ensure compatibility (ref: mail.yahoo.com and hotmail.com unsafe
        behavior on 11 Sep 2008)
   */
-    
+
     if (!this.secureCookies) return;
-    
+
     var uri = req.URI;
-    
+
     if (uri.schemeIs("https") &&
         !(this.secureCookiesExceptions && this.secureCookiesExceptions.test(uri.spec)) &&
         (req instanceof Ci.nsIHttpChannel)) {
@@ -130,14 +126,14 @@ const HTTPS = {
           var forced = this.secureCookiesForced && this.secureCookiesForced.test(uri.spec);
           var secureFound = false;
           var unsafe = null;
-         
+
           const rw = ns.requestWatchdog;
           var browser = rw.findBrowser(req);
-          
+
           if (!browser) {
             if (ns.consoleDump) ns.dump("Browser not found for " + uri.spec);
           }
-          
+
           var unsafeMap = this.getUnsafeCookies(browser) || {};
           var c;
           for each (var cs in cookies.split("\n")) {
@@ -151,8 +147,8 @@ const HTTPS = {
               unsafe.push(c);
             }
           }
-        
-          
+
+
           if (unsafe && !(forced || secureFound)) {
             // this page did not set any secure cookie, let's check if we already have one
             secureFound = Cookie.find(function(c) {
@@ -163,12 +159,12 @@ const HTTPS = {
               this.log("Secure cookie found for this host: " + Cookie.prototype.toString.apply(secureFound));
             }
           }
-          
+
           if (secureFound && !forced) {
             this.cookiesCleanup(secureFound);
             return;
           }
-          
+
           if (!unsafe) return;
 
           var msg;
@@ -179,12 +175,12 @@ const HTTPS = {
           } else {
             msg = "DETECTED INSECURE";
           }
-          
+
           if (!this.registered) {
             this.registered = true;
             rw.addCrossSiteListener(this);
           }
-          
+
           this.setUnsafeCookies(browser, unsafeMap);
           msg += " on https://" + host + ": ";
           for each (c in unsafe) {
@@ -195,42 +191,42 @@ const HTTPS = {
             }
             this.log(msg + c);
           }
-          
+
         }
       } catch(e) {
         if (ns.consoleDump) ns.dump(e);
       }
     }
   },
-  
+
   handleCrossSiteCookies: function(req, origin, browser) {
-     
+
     var unsafeCookies = this.getUnsafeCookies(browser);
     if (!unsafeCookies) return;
-    
+
     var uri = req.URI;
     var dscheme = uri.scheme;
-    
+
     var oparts = origin && origin.match(/^(https?):\/\/([^\/:]+).*?(\/.*)/);
-    if (!(oparts && /https?/.test(dscheme))) return; 
-    
+    if (!(oparts && /https?/.test(dscheme))) return;
+
     var oscheme = oparts[1];
     if (oscheme == dscheme) return; // we want to check only cross-scheme requests
-    
+
     var dsecure = dscheme == "https";
-    
+
     if (dsecure && !ns.getPref("secureCookies.recycle", false)) return;
-   
+
     var dhost = uri.host;
     var dpath = uri.path;
-    
+
     var ohost = oparts[2];
     var opath = oparts[3];
-    
+
     var ocookieCount = 0, totCount = 0;
     var dcookies = [];
     var c;
-    
+
     for (var k in unsafeCookies) {
       c = unsafeCookies[k];
       if (!c.exists()) {
@@ -245,27 +241,27 @@ const HTTPS = {
         }
       }
     }
-    
+
     if (!totCount) {
       this.setUnsafeCookies(browser, null);
       return;
     }
-    
+
     // We want to "desecurify" cookies only if cross-navigation to unsafe
     // destination originates from a site sharing some secured cookies
 
-    if (ocookieCount == 0 && !dsecure || !dcookies.length) return; 
-    
+    if (ocookieCount == 0 && !dsecure || !dcookies.length) return;
+
     if (dsecure) {
       this.log("Detected cross-site navigation with secured cookies: " + origin + " -> " + uri.spec);
-      
+
     } else {
       this.log("Detected unsafe navigation with NoScript-secured cookies: " + origin + " -> " + uri.spec);
       this.log(uri.prePath + " cannot support secure cookies because it does not use HTTPS. Consider forcing HTTPS for " + uri.host + " in NoScript's Advanced HTTPS options panel.")
     }
-    
+
     var cs = Cc['@mozilla.org/cookieService;1'].getService(Ci.nsICookieService).getCookieString(uri, req);
-      
+
     for each (c in dcookies) {
       c.secure = dsecure;
       c.save();
@@ -284,8 +280,8 @@ const HTTPS = {
     this.log("Sending Cookie for " + dhost + ": " + cs);
     req.setRequestHeader("Cookie", cs, false); // "false" because merge syntax breaks Cookie header
   },
-  
-  
+
+
   cookiesCleanup: function(refCookie) {
     var downgraded = [];
 
@@ -314,13 +310,13 @@ const HTTPS = {
       if (!this.cookiesPerTab) break;
     }
   },
-  
+
   get cookiesPerTab() {
     return ns.getPref("secureCookies.perTab", false);
   },
-  
+
   _globalUnsafeCookies: {},
-  getUnsafeCookies: function(browser) { 
+  getUnsafeCookies: function(browser) {
     return this.cookiesPerTab
       ? browser && ns.getExpando(browser, "unsafeCookies")
       : this._globalUnsafeCookies;
@@ -334,7 +330,7 @@ const HTTPS = {
   _getParent: function(req, w) {
     return  w && w.frameElement || DOM.findBrowserForNode(w || IOUtil.findWindow(req));
   }
-  
+
 };
 
 
@@ -353,7 +349,7 @@ const HTTPS = {
 
 ["secureCookies", "secureCookiesExceptions", "secureCookiesForced",
   "httpsForcedBuiltIn", "httpsForced", "httpsForcedExceptions",
-  "STS.enabled"]
+  ]
     .forEach(function(p) {
   try {
     ns.syncPrefs(ns.prefs, p);
@@ -363,4 +359,4 @@ const HTTPS = {
 });
 
 
-HTTPS.ready = true;
\ No newline at end of file
+HTTPS.ready = true;
diff --git a/chrome/noscript.jar!/content/noscript/RequestWatchdog.js b/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
index 812c4f4..edbdd87 100644
--- a/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
+++ b/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
@@ -33,7 +33,7 @@ var RequestGC = {
 }
 
 
-function RequestWatchdog() {  
+function RequestWatchdog() {
   this.injectionChecker = InjectionChecker;
   this.injectionChecker.logEnabled = !!(ns.consoleDump & LOG_INJECTION_CHECK);
   this.init();
@@ -43,53 +43,50 @@ ns.cleanupRequest = function(channel) {
   PolicyState.detach(channel);
   ABERequest.clear(channel);
 };
-  
+
 
 RequestWatchdog.prototype = {
-  
+
   OBSERVED_TOPICS: ["http-on-examine-response", "http-on-examine-merged-response", "http-on-examine-cached-response"],
-  
+
   init: function() {
     for each (var topic in this.OBSERVED_TOPICS) OS.addObserver(this, topic, true);
   },
   dispose: function() {
     for each (var topic in this.OBSERVED_TOPICS) OS.removeObserver(this, topic);
   },
-  
+
   callback: null,
   externalLoad: null,
   noscriptReload: null,
   DOCUMENT_LOAD_FLAGS: Ci.nsIChannel.LOAD_DOCUMENT_URI
     | Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS, // this for OBJECT subdocs
-  
+
   QueryInterface: xpcom_generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
-  
+
   observe: function(channel, topic, data) {
-   
+
     if (!(channel instanceof Ci.nsIHttpChannel)) return;
-    
+
     if(ns.consoleDump & LOG_SNIFF) {
       ns.dump(topic + ": " + channel.URI.spec + ", " + channel.loadFlags);
     }
 
     let cached = true;
-    
+
     switch(topic) {
 
       case "http-on-examine-response":
-        
-        STS.processRequest(channel);
-
       case "http-on-examine-merged-response":
-        
+
         HTTPS.handleSecureCookies(channel);
         cached = false;
-        
+
       case "http-on-examine-cached-response":
-        
+
         if (ns.externalFilters.enabled)
           ns.callExternalFilters(channel, cached);
-        
+
         if (channel.loadFlags & this.DOCUMENT_LOAD_FLAGS) {
           ns.onContentSniffed(channel);
         } else {
@@ -99,16 +96,16 @@ RequestWatchdog.prototype = {
       break;
     }
   },
-  
+
   onHttpStart: function(channel) {
-    
+
     const loadFlags = channel.loadFlags;
     let isDoc = loadFlags & this.DOCUMENT_LOAD_FLAGS;
 
     PolicyState.attach(channel); // this works before bug 797684 fix, see ns.onStateChange for now
     let abeReq = new ABERequest(channel);
     RequestGC.add(channel);
-    
+
     if (HTTPS.forceChannel(channel)) return null;
 
     if (isDoc) {
@@ -129,20 +126,20 @@ RequestWatchdog.prototype = {
         abeReq.external = true;
         this.externalLoad = null;
       }
-      
+
       if (isDoc) {
-        
+
         let url = abeReq.destination;
         if (url.indexOf("#!") > 0 &&
           (url.indexOf("?") === -1 || url.indexOf("?_escaped_fragment_=") > 0) &&
           ns.getPref("ajaxFallback.enabled")) {
           let qs = '?_escaped_fragment_=' + url.match(/#!(.*)/)[1].replace(/[\s&=]/g, encodeURIComponent);
-          
+
           let newURL = "", isReload = false;
           if (ns.isJSEnabled(ns.getSite(url))) {
             if (url.indexOf(qs) > 0 && (isReload = this.noscriptReload === url)) {
               newURL = url.replace(qs, "").replace(/([^#&]+)&/, '$1?');
-            }   
+            }
           } else if (url.indexOf(qs) === -1) {
             newURL = url.replace(/(?:\?_escaped_fragment_=[^&#]*)|(?=#!)/, qs);
           }
@@ -153,9 +150,9 @@ RequestWatchdog.prototype = {
               replacement.open();
             });
             return null;
-          }          
+          }
         }
-        
+
         new DOSChecker(abeReq).run(function() {
           MaxRunTime.increase(40);
           return this.filterXSS(abeReq);
@@ -170,11 +167,11 @@ RequestWatchdog.prototype = {
     }
     return null;
   },
-  
+
   die: function(channel, e) {
     this.abort({ channel: channel, reason: e + " --- " + e.stack, silent: true });
   },
-  
+
   handleABE: function(abeReq, isDoc) {
     if (abeReq && ABE.enabled) {
       try {
@@ -183,7 +180,7 @@ RequestWatchdog.prototype = {
           return ABE.checkRequest(abeReq);
         });
         if (res) {
-          this.notifyABE(res, !(isDoc && res.fatal && ns.getPref("ABE.notify")));  
+          this.notifyABE(res, !(isDoc && res.fatal && ns.getPref("ABE.notify")));
           if (res.fatal) return true;
         }
       } catch(e) {
@@ -193,7 +190,7 @@ RequestWatchdog.prototype = {
     }
     return false;
   },
-  
+
   notifyABE: function(abeRes, silent) {
     var req = abeRes.request;
     var silentLoopback = !ns.getPref("ABE.notify.namedLoopback");
@@ -202,25 +199,25 @@ RequestWatchdog.prototype = {
         var lastRule = rs.lastMatch;
         var lastPredicate = lastRule.lastMatch;
         if (lastPredicate.permissive) return;
-        
+
         var action = lastPredicate.action;
-        
+
         ns.log("[ABE] <" + lastRule.destinations + "> " + lastPredicate + " on " + req
           + "\n" + rs.name + " rule:\n" + lastRule);
-        
+
         if (silent || rs != abeRes.lastRuleset || lastPredicate.inclusion)
           return;
-        
+
         if (lastRule.local && silentLoopback) {
           var host = req.destinationURI.host;
           if (host != "localhost" && host != "127.0.0.1" && req.destinationURI.port <= 0)
-            // this should hugely reduce notifications for users of bogus hosts files, 
+            // this should hugely reduce notifications for users of bogus hosts files,
             // while keeping "interesting" notifications
             var dnsr = DNS.getCached(host);
             if (dnsr && dnsr.entries.indexOf("127.0.0.1") > -1)
               return;
         }
-        
+
         var w = req.window;
         var browser = this.findBrowser(req.channel, w);
         if (browser)
@@ -236,14 +233,14 @@ RequestWatchdog.prototype = {
             });
       }, this);
   },
-  
+
   get dummyPost() {
     const v = Cc["@mozilla.org/io/string-input-stream;1"].createInstance();
     v.setData("", 0);
     this.__defineGetter__("dummyPost", function() { return v; });
     return v;
   },
-  
+
   getUnsafeRequest: function(browser) {
     return ns.getExpando(browser, "unsafeRequest");
   },
@@ -251,14 +248,14 @@ RequestWatchdog.prototype = {
     return ns.setExpando(browser, "unsafeRequest", request);
   },
   attachUnsafeRequest: function(requestInfo) {
-    if (requestInfo.window && 
-        (requestInfo.window == requestInfo.window.top || 
+    if (requestInfo.window &&
+        (requestInfo.window == requestInfo.window.top ||
         requestInfo.window == requestInfo.unsafeRequest.window)
       ) {
       this.setUnsafeRequest(requestInfo.browser, requestInfo.unsafeRequest);
     }
   },
-  
+
   unsafeReload: function(browser, start) {
     ns.setExpando(browser, "unsafeReload", start);
     if (start) {
@@ -275,9 +272,9 @@ RequestWatchdog.prototype = {
           }
           unsafeRequest.window = null;
         }
-       
-        wn.loadURI(unsafeRequest.URI.spec, 
-              wn.LOAD_FLAGS_BYPASS_CACHE | 
+
+        wn.loadURI(unsafeRequest.URI.spec,
+              wn.LOAD_FLAGS_BYPASS_CACHE |
               wn.LOAD_FLAGS_IS_REFRESH,
               unsafeRequest.referrer, unsafeRequest.postData, null);
         unsafeRequest.issued = true;
@@ -291,7 +288,7 @@ RequestWatchdog.prototype = {
   isUnsafeReload: function(browser) {
     return ns.getExpando(browser, "unsafeReload");
   },
-  
+
   resetUntrustedReloadInfo: function(browser, channel) {
     if (!browser) return;
     var window = IOUtil.findWindow(channel);
@@ -306,7 +303,7 @@ RequestWatchdog.prototype = {
   getUntrustedReloadInfo: function(browser) {
     return ns.getExpando(browser, "untrustedReload");
   },
-  
+
   _listeners: [],
   addCrossSiteListener: function(l) {
     if (!this._listeners.indexOf(l) > -1) this._listeners.push(l);
@@ -315,13 +312,13 @@ RequestWatchdog.prototype = {
     var pos = this._listeners.indexOf(l);
     if (pos > -1) this._listeners.splice(pos);
   },
-  
+
   onCrossSiteRequest: function(channel, origin, browser) {
     for each (var l in this._listeners) {
       l.onCrossSiteRequest(channel, origin, browser, this);
     }
   },
-  
+
   isHome: function(url) {
     return url instanceof Ci.nsIURL &&
       this.getHomes().some(function(urlSpec) {
@@ -341,7 +338,7 @@ RequestWatchdog.prototype = {
     }
     return homes ? homes.split("|") : [];
   },
-  
+
   checkWindowName: function (window, url) {
      var originalAttempt = window.name;
      try {
@@ -364,7 +361,7 @@ RequestWatchdog.prototype = {
 
        if (originalAttempt.length > 11) {
          try {
-           if ((originalAttempt.length % 4 === 0)) { 
+           if ((originalAttempt.length % 4 === 0)) {
              var bin = window.atob(window.name);
              if(/[%=\(\\]/.test(bin) && InjectionChecker.checkURL(bin)) {
                window.name = "BASE_64_XSS";
@@ -379,16 +376,16 @@ RequestWatchdog.prototype = {
       }
     }
   },
-  
-  
+
+
   PAYPAL_BUTTON_RX: /^https:\/\/www\.paypal\.com\/(?:[\w\-]+\/)?cgi-bin\/webscr\b/,
-  
+
   filterXSS: function(abeReq) {
-    
+
     const channel = abeReq.channel;
-    
+
     IOUtil.extractFromChannel(channel, "noscript.xssChecked"); // remove redirected info
-    
+
     const url = abeReq.destinationURI;
     const originalSpec = abeReq.destination;
 
@@ -398,17 +395,17 @@ RequestWatchdog.prototype = {
       this.noscriptReload = null;
       try {
         if (ns.consoleDump) {
-          this.dump(channel, "Fast reload, original flags: " + 
+          this.dump(channel, "Fast reload, original flags: " +
             channel.loadFlags + ", " + (channel.loadGroup && channel.loadGroup.loadFlags));
         }
-        channel.loadFlags = (channel.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) | 
+        channel.loadFlags = (channel.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) |
                     Ci.nsIChannel.LOAD_FROM_CACHE | Ci.nsIChannel.VALIDATE_NEVER;
         if (channel.loadGroup) {
-          channel.loadGroup.loadFlags = (channel.loadGroup.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) | 
+          channel.loadGroup.loadFlags = (channel.loadGroup.loadFlags & ~Ci.nsIChannel.VALIDATE_ALWAYS) |
                   Ci.nsIChannel.LOAD_FROM_CACHE | Ci.nsIChannel.VALIDATE_NEVER;
         }
         if (ns.consoleDump) {
-          this.dump(channel, "Fast reload, new flags: " + 
+          this.dump(channel, "Fast reload, new flags: " +
             channel.loadFlags + ", " + (channel.loadGroup && channel.loadGroup.loadFlags));
         }
       } catch(e) {
@@ -416,7 +413,7 @@ RequestWatchdog.prototype = {
         ns.dump(e);
       }
     }
-    
+
     let origin = abeReq.origin,
       originSite = null,
       browser = null,
@@ -462,17 +459,17 @@ RequestWatchdog.prototype = {
         browser = browser || this.findBrowser(channel, window);
         this.resetUntrustedReloadInfo(browser, channel);
         var unsafeRequest = this.getUnsafeRequest(browser);
-        if (unsafeRequest && unsafeRequest.URI.spec != channel.originalURI.spec && 
+        if (unsafeRequest && unsafeRequest.URI.spec != channel.originalURI.spec &&
             (!window || window == window.top || window == unsafeRequest.window)) {
           this.setUnsafeRequest(browser, null);
         }
       } else origin = origin.replace(/^view-source:/, '');
       if (ns.consoleDump) this.dump(channel, "ORIGIN: " + origin);
     }
-    
+
     const su = SiteUtils;
     originSite = originSite || su.getSite(origin) || '';
-    
+
     let host = url.host;
     if (host[host.length - 1] == "." && ns.getPref("canonicalFQDN", true)) {
       try {
@@ -483,7 +480,7 @@ RequestWatchdog.prototype = {
         this.dump(channel, ex);
       }
     }
-    
+
     let targetSite;
     const globalJS = ns.globalJS;
     let trustedTarget = globalJS;
@@ -511,32 +508,32 @@ RequestWatchdog.prototype = {
         }
       }
     }
-    
+
     if (!(origin || (window = abeReq.window))) {
       if (ns.consoleDump) this.dump(channel, "-- This channel doesn't belong to any window/origin: internal browser or extension request, skipping. --");
       return;
     }
-      
+
     if (!targetSite) targetSite = su.getSite(originalSpec);
-    
-    // noscript.injectionCheck about:config option adds first-line 
-    // detection for XSS injections in GET requests originated by 
+
+    // noscript.injectionCheck about:config option adds first-line
+    // detection for XSS injections in GET requests originated by
     // whitelisted sites and landing on top level windows. Value can be:
     // 0 - never check
     // 1 - check cross-site requests from temporary allowed sites
     // 2 - check every cross-site request (default)
     // 3 - check every request
-    
+
     let injectionCheck = ns.injectionCheck;
-    
+
     if (originSite == targetSite) {
       if (injectionCheck < 3) return; // same origin, fast return
     } else {
       this.onCrossSiteRequest(channel, origin, browser = browser || this.findBrowser(channel, abeReq.window));
     }
-    
+
     if (this.callback && this.callback(channel, origin)) return;
-    
+
     if (!trustedTarget) {
       if (InjectionChecker.checkNoscript(InjectionChecker.urlUnescape(originalSpec)) && ns.getPref("injectionCheckHTML", true)) {
         if (ns.consoleDump) this.dump(channel, "JavaScript disabled target positive to HTML injection check!");
@@ -545,17 +542,17 @@ RequestWatchdog.prototype = {
         return;
       }
     }
-    
+
      // fast return if nothing to do here
-    if (!(ns.filterXPost || ns.filterXGet)) return;   
-    
+    if (!(ns.filterXPost || ns.filterXGet)) return;
+
     if (!abeReq.external && this.isUnsafeReload(browser = browser || this.findBrowser(channel, abeReq.window))) {
       if (ns.consoleDump) this.dump(channel, "UNSAFE RELOAD of [" + originalSpec +"] from [" + origin + "], SKIP");
       return;
     }
-  
-    let unescapedSpec = unescape(originalSpec);    
-    
+
+    let unescapedSpec = unescape(originalSpec);
+
     if (ns.filterXExceptions) {
       try {
         if (ns.filterXExceptions.test(unescapedSpec) &&
@@ -565,23 +562,23 @@ RequestWatchdog.prototype = {
           if (ns.consoleDump) this.dump(channel, "Safe target according to filterXExceptions: " + ns.filterXExceptions.toString());
           return;
         }
-  
+
         if (ns.filterXExceptions.test("@" + unescape(origin))) {
           if (ns.consoleDump) this.dump(channel, "Safe origin according to filterXExceptions: " + ns.filterXExceptions.toString());
           return;
         }
       } catch(e) {}
     }
-    
+
     if (abeReq.external && /^https?:\/\/msdn\.microsoft\.com\/query\/[^<]+$/.test(unescapedSpec)) {
-      return; // MSDN from Visual Studio   
+      return; // MSDN from Visual Studio
     }
-    
+
     if (originSite) { // specific exceptions
-      
+
       if (/^about:(?!blank)/.test(originSite))
         return; // any about: URL except about:blank
-      
+
       if (/^https?:\/\/my\.ebay\.(?:\w{2,3}|co\.uk)\/ws\/eBayISAPI\.dll\?[^<'"%]*CurrentPage=MyeBayAllFavorites\b[^<'"%]*$/.test(origin) &&
           /^https?:\/\/www\.ebay\.(?:\w{2,3}|co\.uk)\/sch\/i\.html\?[^<'"]*$/.test(unescapedSpec) &&
           url.scheme === abeReq.originURI.scheme &&
@@ -589,8 +586,8 @@ RequestWatchdog.prototype = {
           ns.getPref("filterXException.ebay")) {
         if (ns.consoleDump) this.dump(channel, "Ebay exception");
         return;
-      }  
-      
+      }
+
       if (/^https?:\/\/(?:[^/]+\.)photobucket.com$/.test(originSite) &&
           /^https?:\/\/(?:[^/]+\.)photobucket.com\/[^<]*$/.test(unescapedSpec) &&
           url.scheme === abeReq.originURI.scheme &&
@@ -599,7 +596,7 @@ RequestWatchdog.prototype = {
         if (ns.consoleDump) this.dump(channel, "Photobucket exception");
         return;
       }
-      
+
       if (originSite === "https://www.youtube.com" &&
           /^https:\/\/(?:plus\.googleapis|apis\.google)\.com\/[\w/]+\/widget\/render\/comments\?/.test(originalSpec) &&
           ns.getPref("filterXExceptions.yt_comments")
@@ -607,58 +604,58 @@ RequestWatchdog.prototype = {
         if (ns.consoleDump) this.dump(channel, "YouTube comments exception");
         return;
       }
-      
+
       if (channel.requestMethod == "POST") {
-        
+
         if (originSite === "https://sso.post.ch" && targetSite === "https://app.swisspost.ch") {
           return;
         }
-        
+
         if (originSite === "https://twitter.com" && /^https:\/\/.*\.twitter.com$/.test(targetSite)) {
           return;
         }
-        
+
         if (/^https?:\/\/csr\.ebay\.(?:\w{2,3}|co\.uk)\/cse\/start\.jsf$/.test(origin) &&
             /^https?:\/\/msa-lfn\.ebay\.(?:\w{2,3}|co\.uk)\/ws\/eBayISAPI\.dll\?[^<'"%]*$/.test(unescapedSpec) &&
             url.scheme === abeReq.originURI.scheme &&
             ns.getPref("filterXException.ebay")) {
           if (ns.consoleDump) this.dump(channel, "Ebay exception");
           return;
-        } 
-        
+        }
+
         if (/^https:\/\/(?:cap\.securecode\.com|www\.securesuite\.net|(?:.*?\.)?firstdata\.(?:l[tv]|com))$/.test(origin) &&
             ns.getPref("filterXException.visa")) {
           if (ns.consoleDump) this.dump(channel, "Verified by Visa exception");
           return;
         }
-        
-        if (/\.verizon\.com$/.test(originSite) && 
+
+        if (/\.verizon\.com$/.test(originSite) &&
             /^https:\/\/signin\.verizon\.com\/sso\/authsso\/forumLogin\.jsp$/.test(originalSpec) &&
             ns.getPref("filterXExceptions.verizon")) {
           if (ns.consoleDump) this.dump(channel, "Verizon login exception");
           return;
         }
-        
+
         if (/^https?:\/\/mail\.lycos\.com\/lycos\/mail\/MailCompose\.lycos$/.test(origin) &&
             /\.lycosmail\.lycos\.com$/.test(targetSite) &&
             ns.getPref("filterXExceptions.lycosmail")) {
           if (ns.consoleDump) this.dump(channel, "Lycos Mail exception");
           return;
         }
-        
+
         if (/\.livejournal\.com$/.test(originSite) &&
             /^https?:\/\/www\.livejournal\.com\/talkpost_do\.bml$/.test(originalSpec) &&
             ns.getPref("filterXExceptions.livejournal")) {
           if (ns.consoleDump) this.dump(channel, "Livejournal comments exception");
           return;
         }
-        
+
         if (originSite == "https://ssl.rapidshare.com" &&
             ns.getBaseDomain(ns.getDomain(targetSite)) == "rapidshare.com") {
           if (ns.consoleDump) this.dump(channel, "Rapidshare upload exception");
           return;
         }
-        
+
         if (originSite == "http://wm.letitbit.net" &&
             /^http:\/\/http\.letitbit\.net:81\/cgi-bin\/multi\/upload\.cgi\?/.test(originalSpec) &&
             ns.getPref("filterXExceptions.letitibit")
@@ -666,7 +663,7 @@ RequestWatchdog.prototype = {
           if (ns.consoleDump) this.dump(channel, "letitbit.net upload exception");
           return;
         }
-        
+
         if (/\.deviantart\.com$/.test(originSite) &&
             /^http:\/\/my\.deviantart\.com\/journal\/update\b/.test(originalSpec) &&
              ns.getPref("filterXExceptions.deviantart")
@@ -674,7 +671,7 @@ RequestWatchdog.prototype = {
           if (ns.consoleDump) this.dump(channel, "deviantart.com journal post exception");
           return;
         }
-        
+
         if (originSite == "https://www.mymedicare.gov" &&
             targetSite == "https://myporal.medicare.gov" &&
             ns.getPref("filterXExceptions.medicare")
@@ -682,7 +679,7 @@ RequestWatchdog.prototype = {
           if (ns.consoleDump) this.dump(channel, "mymedicare.gov exception");
           return;
         }
-        
+
         if (/^https?:\/\/(?:draft|www)\.blogger\.com\/template-editor\.g\?/.test(origin) &&
             /^https?:\/\/[\w\-]+\.blogspot\.com\/b\/preview\?/.test(originalSpec) &&
             ns.getPref("filterXExceptions.blogspot")
@@ -690,7 +687,7 @@ RequestWatchdog.prototype = {
           if (ns.consoleDump) this.dump(channel, "blogspot.com template preview exception");
           return;
         }
-        
+
         if (/^https?:\/\/www\.readability\.com\/articles\/queue$/.test(originalSpec) &&
             ns.getPref("filterXExceptions.readability")) {
           if (ns.consoleDump) this.dump(channel, "Readability exception");
@@ -698,28 +695,28 @@ RequestWatchdog.prototype = {
         }
 
       }
-    
+
     } else { // maybe data or javascript URL?
-      
+
       if (/^(?:javascript|data):/i.test(origin) && ns.getPref("xss.trustData", true)) {
         originSite = ns.getSite(abeReq.traceBack);
-        if (originSite) { 
+        if (originSite) {
           origin = abeReq.breadCrumbs.join(">>>");
         }
       }
-      
+
     }
-    
-   
-    
+
+
+
     let originalAttempt;
     let postInjection = false;
-    
+
     window = window || abeReq.window;
-    
+
     // neutralize window.name-based attack
     if (window && window.name) {
-      
+
       if (ns.compatEvernote && window.frameElement && window.name.indexOf("iframe") > 0
           && /^https?:\/\/(?:[a-z]+\.)*evernote\.com\/clip\.action$/.test(originalSpec)
           && channel.requestMethod == "POST") {
@@ -729,36 +726,36 @@ RequestWatchdog.prototype = {
         return;
       }
     }
-    
+
     IOUtil.attachToChannel(channel, "noscript.checkWindowName", DUMMY_OBJ);
-    
+
     let focusedBrowserWin = DOM.mostRecentBrowserWindow;
     let trustedOrigin = globalJS || ns.isJSEnabled(originSite, focusedBrowserWin && focusedBrowserWin.content) ||
-        !origin // we consider null origin as "trusted" (i.e. we check for injections but 
-                // don't strip POST unconditionally) to make some extensions (e.g. Google Gears) 
+        !origin // we consider null origin as "trusted" (i.e. we check for injections but
+                // don't strip POST unconditionally) to make some extensions (e.g. Google Gears)
                 // work. For dangerous edge cases we should have moz-null-principal: now, anyway.
-                || 
+                ||
         origin.substring(0, 5) == "file:";
-    
+
     if (trustedOrigin) {
 
       if (origin &&
           (
-          /^https?:\/\/(?:[^\/]+.)?facebook\.com\/[\w\.\-\/]+fbml\.php$/.test(originalSpec) && channel.requestMethod == "POST" || 
+          /^https?:\/\/(?:[^\/]+.)?facebook\.com\/[\w\.\-\/]+fbml\.php$/.test(originalSpec) && channel.requestMethod == "POST" ||
           /^https?:\/\/www.facebook.com\/plugins\/serverfbml.php\?/.test(originalSpec) ||
           /^https?:\/\/api\.connect\.facebook\.com$/.test(originSite)
-            
+
           ) &&
             ns.getPref("filterXExceptions.fbconnect")) {
         if (ns.consoleDump) this.dump(channel, 'Facebook connect exception');
         return;
       }
-      
-      
+
+
       this.resetUntrustedReloadInfo(browser = browser || this.findBrowser(channel, window), channel);
-      
+
       // here we exceptionally consider same site also https->http with same domain
-      
+
       if (injectionCheck < 3 && originSite && abeReq.originURI.schemeIs("https")) {
         let originDomain = ns.getDomain(originSite), targetDomain = ns.getDomain(url);
         if (targetDomain == originDomain) {
@@ -766,22 +763,22 @@ RequestWatchdog.prototype = {
           return;
         }
       }
-      
+
     }
-    
-    let stripPost = !trustedOrigin && ns.filterXPost; 
-    
+
+    let stripPost = !trustedOrigin && ns.filterXPost;
+
     // check for injections
-      
+
     let injectionAttempt = injectionCheck && (injectionCheck > 1 || !trustedOrigin || ns.isTemp(originSite)) &&
       (!window || ns.injectionCheckSubframes || window == window.top);
-    
-   
-    
+
+
+
     if (injectionAttempt) {
       let skipArr, skipRx;
       let isPaypal = this.PAYPAL_BUTTON_RX.test(originalSpec);
-      
+
       if (isPaypal) {
         stripPost = false;
         // Paypal buttons encrypted parameter causes a DOS, strip it out
@@ -798,7 +795,7 @@ RequestWatchdog.prototype = {
       } else if (url.ref && trustedOrigin &&
           (/^https?:\/\/api\.facebook\.com\//.test(origin) && ns.getPref("filterXExceptions.fbconnect")
           || /^https:\/\/tbpl\.mozilla\.org\//.test(origin)  // work-around for hg reftest DOS
-          || /^https:\/\/[^\/]+.googleusercontent\.com\/gadgets\/ifr\?/.test(originalSpec) && ns.getPref("filterXExceptions.ggadgets") // Google gadgets 
+          || /^https:\/\/[^\/]+.googleusercontent\.com\/gadgets\/ifr\?/.test(originalSpec) && ns.getPref("filterXExceptions.ggadgets") // Google gadgets
           )) {
         skipRx = /#[^#]+$/; // remove receiver's hash
       } else if (/^https?:\/\/apps\.facebook\.com\//.test(origin) && ns.getPref("filterXExceptions.fbconnect")) {
@@ -818,51 +815,51 @@ RequestWatchdog.prototype = {
       if (skipArr) {
         skipRx = new RegExp("(?:^|[&?])(?:" + skipArr.join('|') + ")=[^&]+", "g");
       }
-      
-      
+
+
       let injectionChecker = ns.injectionChecker;
-      
+
       injectionChecker.reset();
-      
+
       if (!stripPost)
         stripPost = postInjection =
           ns.filterXPost &&
           (!origin || originSite != "chrome:") &&
           channel.requestMethod == "POST" && injectionChecker.checkPost(channel, skipArr);
-      
+
       let protectName = injectionChecker.nameAssignment;
-      
+
       injectionAttempt = ns.filterXGet && injectionChecker.checkURL(
         skipRx ? originalSpec.replace(skipRx, '') : originalSpec);
-      
+
       if ((protectName = (protectName || injectionChecker.nameAssignment)))
         IOUtil.attachToChannel(channel, "noscript.protectName", DUMMY_OBJ); // remove redirected info
-      
-      
-      
+
+
+
       if (ns.consoleDump) {
         if (injectionAttempt) this.dump(channel, "Detected injection attempt at level " + injectionCheck);
         if (postInjection) this.dump(channel, "Detected POST injection attempt at level "  + injectionCheck);
         if (protectName) this.dump(channel, "Name assignment detected, gonna protect window.name");
       }
     }
-    
+
     IOUtil.attachToChannel(channel, "noscript.xssChecked", DUMMY_OBJ); // remove redirected info
-    
+
     if (trustedOrigin && !(injectionAttempt || stripPost))
       return;
-    
+
     if (untrustedReload && browser) {
       this.resetUntrustedReloadInfo(browser, channel);
     }
 
 
     // -- DANGER ZONE --
-    
+
     let requestInfo = new RequestInfo(channel, url, origin, window);
 
     // transform upload requests into no-data GETs
-    if (ns.filterXPost && stripPost && 
+    if (ns.filterXPost && stripPost &&
         (channel instanceof Ci.nsIUploadChannel) && channel.uploadStream
       ) {
       try {
@@ -875,12 +872,12 @@ RequestWatchdog.prototype = {
         originalAttempt: originalSpec + (postInjection ? "###DATA###" + postInjection : ""),
         silent: untrustedReload
       }));
-      
+
       this.attachUnsafeRequest(requestInfo);
     }
-    
+
     if (!(injectionAttempt || postInjection)) return;
-    
+
     if (ns.filterXGet && ns.filterXGetRx) {
       var changes = null;
       var xsan = ns.createXSanitizer();
@@ -900,9 +897,9 @@ RequestWatchdog.prototype = {
         }
         try {
           if (!changes) {
-            changes = { 
-              minor: !channel.referrer.spec || 
-                      unescape(originalAttempt) != unescape(channel.referrer.spec) 
+            changes = {
+              minor: !channel.referrer.spec ||
+                      unescape(originalAttempt) != unescape(channel.referrer.spec)
             };
           }
           if (changes.minor) {
@@ -920,11 +917,11 @@ RequestWatchdog.prototype = {
           channel.referrer = channel.referrer.clone();
         }
       }
-      
+
       originalAttempt = originalSpec;
-      
+
       let newURI = url.clone();
-      
+
       if (injectionAttempt) {
         xsan.brutal = injectionAttempt;
         changes = xsan.sanitizeURL(newURI);
@@ -933,7 +930,7 @@ RequestWatchdog.prototype = {
             reason: "filterXGet",
             originalAttempt: originalAttempt,
             sanitizedURI: newURI,
-            silent: !(changes.major || postInjection) 
+            silent: !(changes.major || postInjection)
           }));
         }
         if (newURI.spec != url.spec) {
@@ -944,39 +941,39 @@ RequestWatchdog.prototype = {
         }
       }
     }
-   
+
     if (requestInfo.xssMaybe) {
       // avoid surprises from history & cache
       if (channel instanceof Ci.nsICachingChannel) {
-        
-        const CACHE_FLAGS = channel.LOAD_FROM_CACHE | 
-                            channel.VALIDATE_NEVER | 
+
+        const CACHE_FLAGS = channel.LOAD_FROM_CACHE |
+                            channel.VALIDATE_NEVER |
                             channel.LOAD_ONLY_FROM_CACHE;
-        
+
         channel.loadFlags = channel.loadFlags & ~CACHE_FLAGS | channel.LOAD_BYPASS_CACHE;
         if (this.consoleDump) this.dump(channel, "SKIPPING CACHE");
       }
-      
+
       this.attachUnsafeRequest(requestInfo);
     }
-    
-    
+
+
   },
-  
-  
-  
+
+
+
   isBadException: function(host) {
     // TLD check for Google search
     let m = host.match(/\bgoogle\.((?:[a-z]{1,3}\.)?[a-z]+)$/i);
     return m && ns.getPublicSuffix(host) != m[1];
   },
-  
-  
-  
+
+
+
   proxyHack: function(channel) {
     // Work-around for channel.URI not being used directly here:
     // http://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpChannel.cpp#504
-    
+
     var proxyInfo = IOUtil.getProxyInfo(channel);
      if (proxyInfo && proxyInfo.type == "http") {
        if (channel.URI.userPass == "") {
@@ -986,104 +983,104 @@ RequestWatchdog.prototype = {
        }
      }
   },
-  
+
   abortChannel: function(channel, reason) {
     let originURI = ABERequest.getOrigin(channel)
     let requestInfo = this.addXssInfo(new RequestInfo(channel), {
       reason: reason || "filterXGet",
       originalAttempt: channel.name,
       origin: originURI && originURI.spec || "",
-      silent: false, 
+      silent: false,
     });
     this.abort(requestInfo);
     this.attachUnsafeRequest(requestInfo);
   },
-  
+
   abort: function(requestInfo) {
     var channel = requestInfo.channel;
-    
+
     if (channel instanceof Ci.nsIRequest)
       IOUtil.abort(channel);
-    
+
     if (requestInfo.browser) {
       requestInfo.browser.stop(requestInfo.browser.STOP_ALL);
     }
     this.dump(channel, "Aborted - " + requestInfo.reason);
- 
+
     this.notify(requestInfo);
   },
-  
+
   mergeDefaults: function(o1, o2) {
     for (let p in o2) {
       if (!(p in o1)) o1[p] = o2[p];
     }
     return o1;
   },
-  
+
   addXssInfo: function(requestInfo, xssInfo) {
     try {
       requestInfo.window = requestInfo.window || IOUtil.findWindow(requestInfo.channel);
-      requestInfo.browser = requestInfo.browser || (requestInfo.window && 
+      requestInfo.browser = requestInfo.browser || (requestInfo.window &&
                             DOM.findBrowserForNode(requestInfo.window));
     } catch(e) {}
     requestInfo.xssMaybe = true;
     return this.mergeDefaults(xssInfo, requestInfo);
   },
-  
+
   notify: function(requestInfo) {
-    var msg = "[NoScript XSS] " + ns.getString("xss.reason." + requestInfo.reason, [ 
+    var msg = "[NoScript XSS] " + ns.getString("xss.reason." + requestInfo.reason, [
         requestInfo.originalAttempt || "N/A",
         requestInfo.unsafeRequest && requestInfo.unsafeRequest.origin || "",
         requestInfo.sanitizedURI && requestInfo.sanitizedURI.spec || ""
       ]);
     this.dump(requestInfo.channel, "Notifying " + msg + "\n\n\n");
     ns.log(msg);
-   
+
     try {
       let sync = requestInfo.channel.status !== 0;
-      if (requestInfo.silent || !requestInfo.window || !ns.getPref("xss.notify", true)) 
+      if (requestInfo.silent || !requestInfo.window || !ns.getPref("xss.notify", true))
         return;
-      if(requestInfo.window != requestInfo.window.top) { 
+      if(requestInfo.window != requestInfo.window.top) {
         // subframe
 
         var cur = this.getUnsafeRequest(requestInfo.browser);
         if(cur && !cur.issued) return;
-        
+
         requestInfo.unsafeRequest.window = requestInfo.window;
         this.observeSubframeXSS(requestInfo.originalAttempt, requestInfo.unsafeRequest);
-        
+
         if(!ns.getPref("xss.notify.subframes", true))
           return;
 
         sync = true;
       }
-      
+
       if (sync) {
         let overlay = ns.findOverlay(requestInfo.browser);
         if(overlay) overlay.notifyXSS(requestInfo);
       }
-      
+
       requestInfo.wrappedJSObject = requestInfo;
       IOUtil.attachToChannel(requestInfo.channel, "noscript.XSS", requestInfo);
     } catch(e) {
       dump(e + "\n");
     }
   },
-  
+
   observeSubframeXSS: function(url, unsafeRequest) {
     unsafeRequest.window.addEventListener("unload", function(ev) {
         var w = ev.currentTarget;
-        if(w.location.href != url) return; 
+        if(w.location.href != url) return;
         w.removeEventListener("unload", arguments.callee, false);
         unsafeRequest.window = null;
      }, false);
   },
-  
-  
+
+
   findBrowser: function(channel, window) {
     return DOM.findBrowserForNode(window || IOUtil.findWindow(channel));
   },
-  
+
   dump: function(channel, msg) {
     if (!(ns.consoleDump & LOG_XSS_FILTER)) return;
     dump("[NoScript] ");
@@ -1095,13 +1092,13 @@ RequestWatchdog.prototype = {
     dump(msg);
     dump("\n");
   }
-  
-  
+
+
 }
 
 
 var Entities = {
-  
+
   get htmlNode() {
     delete this.htmlNode;
     var impl = Cc["@mozilla.org/xul/xul-document;1"].createInstance(Ci.nsIDOMDocument).implementation;
@@ -1109,7 +1106,7 @@ var Entities = {
       ? impl.createHTMLDocument("")
       : impl.createDocument(
         HTML_NS, "html", impl.createDocumentType(
-          "html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"  
+          "html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"
         ))
       ).createElementNS(HTML_NS, "body");
   },
@@ -1153,18 +1150,18 @@ const IC_EVENT_PATTERN = "on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found
 const IC_EVENT_DOS_PATTERN =
       "\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=[\\s\\S]*\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b"
       + "|\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b[\\s\\S]+\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=";
-      
+
 var InjectionChecker = {
   reset: function () {
-    
+
     this.isPost =
       this.base64 =
       this.nameAssignment = false;
-      
+
     this.base64tested = [];
-   
+
   },
-  
+
   fuzzify: fuzzify,
   syntax: new SyntaxChecker(),
   _log: function(msg, t, i) {
@@ -1183,21 +1180,21 @@ var InjectionChecker = {
     }
     this.dump("[NoScript InjectionChecker] " + msg + "\n");
   },
-  
+
   _printable: function (msg) {
     return msg.toString().replace(/[^\u0020-\u007e]/g, function(s) { return "{" + s.charCodeAt(0).toString(16) + "}"; });
   },
-  
+
   dump: dump,
   log: function() {},
   get logEnabled() { return this.log == this._log; },
   set logEnabled(v) { this.log = v ? this._log : function() {}; },
-  
+
   escalate: function(msg) {
     this.log(msg);
     ns.log("[NoScript InjectionChecker] " + msg);
   },
-  
+
   bb: function(brac, s, kets) {
     for(var j = 3; j-- > 0;) {
       s = brac + s + kets;
@@ -1205,13 +1202,13 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   checkJSSyntax: function(s) {
     // bracket balancing for micro injections like "''), e v a l (name,''"
     if (/^(?:''|"")?[^\('"]*\)/.test(s)) return this.bb("x(\n", s, "\n)");
     if (/^(?:''|"")?[^\['"]*\\]/.test(s)) return this.bb("y[\n", s, "\n]");
     if (/^(?:''|"")?[^\{'"]*\}/.test(s)) return this.bb("function z() {\n", s, "\n}");
-    
+
     s += " /* COMMENT_TERMINATOR */\nDUMMY_EXPR";
     if (this.syntax.check(s)) {
       this.log("Valid fragment " + s);
@@ -1219,7 +1216,7 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   get breakStops() {
     var def = "\\/\\?&#;\\s\\x00}<>"; // we stop on URL, JS and HTML delimiters
     var bs = {
@@ -1228,32 +1225,32 @@ var InjectionChecker = {
     Array.forEach("'\"`", // special treatment for quotes
       function(c) { bs[c] = new RegExp("[" + def + c + "]"); }
     );
-    delete this.breakStops;  
+    delete this.breakStops;
     return this.breakStops = bs;
   },
-  
+
   collapseChars: function(s)
       s.replace(/\;+/g, ';').replace(/\/{4,}/g, '////')
         .replace(/\s+/g, function(s) /\n/g.test(s) ? '\n' : ' ')
   ,
-  
+
   _reduceBackslashes: function(bs) bs.length % 2 ? "\\" : "",
-  
+
   reduceQuotes: function(s) {
     if (s[0] == '/') {
       // reduce common leading path fragment resembling a regular expression or a comment
       s = s.replace(/^\/[^\/\n\r]+\//, '_RX_').replace(/^\/\/[^\r\n]*/, '//_COMMENT_');
     }
-    
+
     if (/\/\*/.test(s)) // C-style comments, would make everything really tricky
       return s;
-    
-    
+
+
     if (/['"\/]/.test(s)) {
-    
+
       // drop noisy backslashes
       s = s.replace(/\\{2,}/g, this._reduceBackslashes);
-      
+
       // drop escaped quotes
       s = s.replace(/\\["'\/]/g, " EQ ");
       var expr;
@@ -1264,32 +1261,32 @@ var InjectionChecker = {
          s = expr;
       }
     }
-    
-    // remove c++ style comments    
+
+    // remove c++ style comments
     return s.replace(/^([^'"`\\]*?)\/\/[^\r\n]*/g, "$1//_COMMENT_");
   },
-  
+
   reduceURLs: function(s) {
     // nested URLs with protocol are parsed as C++ style comments, and since
     // they're potentially very expensive, we preemptively remove them if possible
     while (/^[^'"]*?:\/\//.test(s)) {
       s = s.replace(/:\/\/[^*\s]*/, ':');
-    }    
+    }
     s = s.replace(/:\/\/[^'"*\n]*/g, ':');
-    
+
     return (/\bhttps?:$/.test(s) && !/\bh\W*t\W*t\W*p\W*s?.*=/.test(s))
       ? s.replace(/\b(?:[\w.]+=)?https?:$/, '')
       : s;
   },
-  
+
   reduceJSON: function(s) {
     const toStringRx = /^function\s*toString\(\)\s*{\s*\[native code\]\s*\}$/;
     // optimistic case first, one big JSON block
     for (;;) {
-     
+
       let m = s.match(/{[\s\S]+}/);
       if (!m) return s;
-      
+
       let whole = s;
       let expr = m[0];
       let json = ns.json;
@@ -1297,54 +1294,54 @@ var InjectionChecker = {
         try {
           if (!toStringRx.test(json.decode(expr).toString))
             return s;
-          
+
           this.log("Reducing big JSON " + expr);
           return s.replace(expr, '{}');
         } catch(e) {}
       }
-      
+
       // heavier duty, scattered JSON blocks
       while((m = s.match(/\{[^\{\}:]+:[^\{\}]+\}/g))) {
         let prev = s;
-  
+
         for each(expr in m) {
           if (json) try {
             if (!toStringRx.test(json.decode(expr).toString))
               continue;
-            
+
             this.log("Reducing JSON " + expr);
             s = s.replace(expr, '{}');
             continue;
           } catch(e) {}
-          
+
           if (/\btoString\b[\s\S]*:/.test(expr)) continue;
-          
+
           let qred = this.reduceQuotes(expr);
           if (/\{(?:\s*(?:(?:\w+:)+\w+)+;\s*)+\}/.test(qred)) {
              this.log("Reducing pseudo-JSON " + expr);
              s = s.replace(expr, '{}');
-          } else if (!/[\(=\.]|[^:\s]\s*\[|:\s*(?:location|document|eval|open|show\w*Dialog)\b/.test(qred) && 
+          } else if (!/[\(=\.]|[^:\s]\s*\[|:\s*(?:location|document|eval|open|show\w*Dialog)\b/.test(qred) &&
              this.checkJSSyntax("JSON = " + qred) // no-assignment JSON fails with "invalid label"
-          ) { 
+          ) {
             this.log("Reducing slow JSON " + expr);
             s = s.replace(expr, '{}');
           }
         }
-        
+
         if (s == prev) break;
       }
-      
+
       if (s == whole) break;
     }
 
     return s;
   },
-  
+
   reduceXML: function reduceXML(s) {
     var res;
-    
+
     for (let pos = s.indexOf("<"); pos !== -1; pos = s.indexOf("<", 1)) {
-      
+
       let head = s.substring(0, pos);
       let tail = s.substring(pos);
 
@@ -1353,9 +1350,9 @@ var InjectionChecker = {
         if (pos === 0 || head[pos - 1] != '\\') qnum++;
       }
       if (qnum % 2)  break; // odd quotes
-      
+
       let t = tail.replace(/^<(\??\s*\/?[a-zA-Z][\w:-]*)(?:[\s+]+[\w:-]+="[^"]*")*[\s+]*(\/?\??)>/, '<$1$2>');
-     
+
       (res || (res = [])).push(head);
       s = t;
     }
@@ -1363,11 +1360,11 @@ var InjectionChecker = {
       res.push(s);
       s = res.join('');
     }
-    
+
     return s;
   }
 ,
-  
+
   _singleAssignmentRx: new RegExp(
     "(?:\\b" + fuzzify('document') + "\\b[\\s\\S]*\\.|\\s" + fuzzify('setter') + "\\b[\\s\\S]*=)|/.*/[\\s\\S]*(?:\\.(?:" +
      "\\b" + fuzzify("onerror") + "\\b[\\s\\S]*=|" +
@@ -1380,9 +1377,9 @@ var InjectionChecker = {
     "=[\\s\\S]*\\b" + fuzzify('name') + "\\b|" +
     fuzzify("hostname") + "[\\s\\S]*=[\\s\\S]*(?:\\b\\d|[\"'{}~^|<*/+-])"
   ),
-  
+
   _maybeJSRx: new RegExp(
-    // accessor followed by function call or assignment.    
+    // accessor followed by function call or assignment.
     '(?:(?:\\[[\\s\\S]*\\]|\\.\\D)[\\s\\S]*(?:\\([\\s\\S]*\\)|=[\\s\\S]*\\S)' +
     // double function call
     '|\\([\\s\\S]*\\([\\s\\S]*\\)' +
@@ -1401,14 +1398,14 @@ var InjectionChecker = {
     "|(?:[^\\w$]|^)" + IC_EVENT_PATTERN + IC_COMMENT_PATTERN + "="
   )
  ,
-    
+
   _riskyParensRx: new RegExp(
     "(?:^|\\W)(?:(?:" + IC_EVAL_PATTERN + "|on\\w+)\\s*\\(|" +
     fuzzify("with") + "\\b[\\s\\S]*\\(|" +
     fuzzify("for") + "\\b[\\s\\S]*\\([\\s\\S]*[\\w$\\u0080-\\uffff]+[\\s\\S]*\\b(?:" +
     fuzzify ("in|of") + ")\\b)"
   ),
-  
+
   _dotRx: /\./g,
   _removeDotsRx: /^openid\.[\w.-]+(?==)|(?:[?&#\/]|^)[\w.-]+(?=[\/\?&#]|$)|[\w\.]*(?:\b[A-Z]+|\d|[a-z][$_])[\w.-]*|=[a-z.-]+\.(?:com|net|org|biz|info|xxx|[a-z]{2})(?:[;&/]|$)/g,
   _removeDots: function(p) p.replace(InjectionChecker._dotRx, '|'),
@@ -1420,13 +1417,13 @@ var InjectionChecker = {
   _neutralDotsRx: /(?:^|[\/;&#])[\w-]+\.[\w-]+[\?;\&#]/g,
   _openIdRx: /^scope=(?:\w+\+)\w/, // OpenID authentication scope parameter, see http://forums.informaction.com/viewtopic.php?p=69851#p69851
   _gmxRx: /\$\(clientName\)-\$\(dataCenter\)\.(\w+\.)+\w+/, // GMX webmail, see http://forums.informaction.com/viewtopic.php?p=69700#p69700
-  
+
   maybeJS: function(expr) {
-   
+
     if (/`[\s\S]*`/.test(expr) ||  // ES6 templates, extremely insidious!!!
         this._riskyOperatorsRx.test(expr) // this must be checked before removing dots...
         ) return true;
-    
+
     expr = // dotted URL components can lead to false positives, let's remove them
       expr.replace(this._removeDotsRx, this._removeDots)
         .replace(this._arrayAccessRx, '_ARRAY_ACCESS_')
@@ -1436,27 +1433,27 @@ var InjectionChecker = {
         .replace(this._openIdRx, '_OPENID_SCOPE_=XYZ')
         .replace(this._gmxRx, '_GMX_-_GMX_')
         ;
-        
+
     if (expr.indexOf(")") !== -1) expr += ")"; // account for externally balanced parens
     if(this._assignmentRx.test(expr) && !this._badRightHandRx.test(expr)) // commonest case, single assignment or simple chained assignments, no break
        return this._singleAssignmentRx.test(expr) || this._riskyAssignmentRx.test(expr) && this._nameRx.test(expr);
-     
+
     return this._riskyParensRx.test(expr) ||
       this._maybeJSRx.test(expr.replace(this._neutralDotsRx, '')) &&
-        !this._wikiParensRx.test(expr); 
-   
+        !this._wikiParensRx.test(expr);
+
   },
-  
+
   checkNonTrivialJSSyntax: function(expr) {
     return this.maybeJS(this.reduceQuotes(expr)) && this.checkJSSyntax(expr);
   },
-  
-  
+
+
   wantsExpression: function(s) /(?:^[+-]|[!%&(,*/:;<=>?\[^|]|[^-]-|[^+]\+)\s*$/.test(s),
-  
+
   stripLiteralsAndComments: function(s) {
     "use strict";
-       
+
     const MODE_NORMAL = 0;
     const MODE_REGEX = 1;
     const MODE_SINGLEQUOTE = 2;
@@ -1464,7 +1461,7 @@ var InjectionChecker = {
     const MODE_BLOCKCOMMENT = 4;
     const MODE_LINECOMMENT = 6;
     const MODE_INTERPOLATION = 7;
-    
+
     let mode = MODE_NORMAL;
     let escape = false;
     let res = [];
@@ -1479,7 +1476,7 @@ var InjectionChecker = {
         }
     }
     for (let j = 0, l = s.length; j < l; j++) {
-        
+
         switch(mode) {
           case MODE_REGEX:
             handleQuotes(s[j], '/', "_REGEXP_");
@@ -1529,18 +1526,18 @@ var InjectionChecker = {
                       let r = res.join('');
                       res = [r];
                       if (this.wantsExpression(r)) mode = MODE_REGEX;
-                      else res.push('/'); // after a self-contained expression: division operator 
+                      else res.push('/'); // after a self-contained expression: division operator
                 }
                 break;
              default:
                 res.push(s[j]);
           }
-            
+
        }
     }
     return res.join('');
   },
-  
+
   checkLastFunction: function() {
     var fn = this.syntax.lastFunction;
     if (!fn) return false;
@@ -1550,10 +1547,10 @@ var InjectionChecker = {
     return /=[\s\S]*cookie|\b(?:setter|document|location|(?:inn|out)erHTML|\.\W*src)[\s\S]*=|[\w$\u0080-\uffff\)\]]\s*[\[\(]/.test(expr) ||
             this.maybeJS(expr);
   },
-  
+
   _createInvalidRanges: function() {
     function x(n) { return '\\u' + ("0000" + n.toString(16)).slice(-4); }
-    
+
     var ret = "";
     var first = -1;
     var last = -1;
@@ -1572,7 +1569,7 @@ var InjectionChecker = {
           last = cur;
           continue;
         }
-  
+
         if(last != first) ret += "-" + x(last);
         ret+= x(cur);
         last = first = cur;
@@ -1580,33 +1577,33 @@ var InjectionChecker = {
     }
     return ret;
   },
-  
+
   get invalidCharsRx() {
     delete this.invalidCharsRx;
     return this.invalidCharsRx = new RegExp("^[^\"'/]*[" + this._createInvalidRanges() + "]");
   },
-  
+
   checkJSBreak: function InjectionChecker_checkJSBreak(s) {
     // Direct script injection breaking JS string literals or comments
-    
-    
+
+
     // cleanup most urlencoded noise and reduce JSON/XML
     s = ';' + this.reduceXML(this.reduceJSON(this.collapseChars(
         s.replace(/\%\d+[a-z\(]\w*/gi, '§')
           .replace(/[\r\n\u2028\u2029]+/g, "\n")
           .replace(/[\x01-\x09\x0b-\x20]+/g, ' ')
         )));
-    
+
     if (s.indexOf("*/") > 0 && /\*\/[\s\S]+\/\*/.test(s)) { // possible scrambled multi-point with comment balancing
       s += ';' + s.match(/\*\/[\s\S]+/);
     }
-    
+
     if (!this.maybeJS(s)) return false;
 
     const MAX_TIME = 8000, MAX_LOOPS = 1200;
-    
+
     const logEnabled = this.logEnabled;
-    
+
     const
       invalidCharsRx = /[\u007f-\uffff]/.test(s) && this.invalidCharsRx,
       dangerRx = /\(|(?:^|[+-]{2}|[+*/<>~-]+\\s*=)|`[\s\S]*`|\[[^\]]+\]|(?:setter|location|(?:inn|out)erHTML|cookie|on\w{3,}|\.\D)[^&]*=[\s\S]*?(?:\/\/|[\w$\u0080-\uFFFF.[\]})'"-]+)/,
@@ -1616,15 +1613,15 @@ var InjectionChecker = {
       headRx = /^(?:[^'"\/\[\(]*[\]\)]|[^"'\/]*(?:§|[^&]&[\w\.]+=[^=]))/
         // irrepairable syntax error, such as closed parens in the beginning
     ;
-    
+
     const injectionFinderRx = /(['"`#;>:{}]|[/?=](?![?&=])|&(?![\w-.[\]&!-]*=)|\*\/)(?!\1)/g;
-    injectionFinderRx.lastIndex = 0;    
-    
+    injectionFinderRx.lastIndex = 0;
+
     const t = Date.now();
     var iterations = 0;
-    
+
     for (let dangerPos = 0, m; (m = injectionFinderRx.exec(s));) {
-    
+
       let startPos = injectionFinderRx.lastIndex;
       let subj = s.substring(startPos);
       if (startPos > dangerPos) {
@@ -1635,17 +1632,17 @@ var InjectionChecker = {
         }
         dangerPos = dangerRx.lastIndex;
       }
-       
+
       let breakSeq = m[1];
       let quote = breakSeq in this.breakStops ? breakSeq : '';
-      
+
       if (!this.maybeJS(quote ? quote + subj : subj)) {
          this.log("Fast escape on " + subj, t, iterations);
          return false;
       }
 
       let script = this.reduceURLs(subj);
-    
+
       if (script.length < subj.length) {
         if (!this.maybeJS(script)) {
           this.log("Skipping to first nested URL in " + subj, t, iterations);
@@ -1657,7 +1654,7 @@ var InjectionChecker = {
       } else {
         script = subj.substring(0, dangerPos - startPos);
       }
- 
+
       let expr = subj.match(exprMatchRx);
 
       if (expr) {
@@ -1671,24 +1668,24 @@ var InjectionChecker = {
 
       // quickly skip (mis)leading innocuous CGI patterns
       if ((m = subj.match(safeCgiRx))) {
-       
+
         this.log("Skipping CGI pattern in " + subj);
 
         injectionFinderRx.lastIndex += m[0].length - 1;
         continue;
       }
 
-      let bs = this.breakStops[quote || 'nq']  
-   
+      let bs = this.breakStops[quote || 'nq']
+
       for (let len = expr.length, moved = false, hunt = !!expr, lastExpr = ''; hunt;) {
-        
+
         if (Date.now() - t > MAX_TIME) {
           this.log("Too long execution time! Assuming DOS... " + (Date.now() - t), t, iterations);
           return true;
         }
-     
+
         hunt = expr.length < subj.length;
-             
+
         if (moved) {
           moved = false;
         } else if (hunt) {
@@ -1709,21 +1706,21 @@ var InjectionChecker = {
             if (pos === 0) len++;
           }
         }
-        
+
         if(lastExpr === expr) {
           lastExpr = '';
           continue;
         }
-        
+
         lastExpr = expr;
-           
+
         if(invalidCharsRx && invalidCharsRx.test(expr)) {
           this.log("Quick skipping invalid chars");
           break;
         }
-        
-        
-        
+
+
+
         if (quote) {
           if (this.checkNonTrivialJSSyntax(expr)) {
             this.log("Non-trivial JS inside quoted string detected", t, iterations);
@@ -1743,7 +1740,7 @@ var InjectionChecker = {
         } else {
           script = expr;
         }
-        
+
         if (headRx.test(script.split("//")[0])) {
           let balanced = script.replace(/^[^"'{}(]*\)/, 'P ');
           if (balanced !== script && balanced.indexOf('(') > -1) {
@@ -1751,9 +1748,9 @@ var InjectionChecker = {
           } else {
             this.log("SKIP (head syntax) " + script, t, iterations);
             break; // unrepairable syntax error in the head, move left cursor forward
-          } 
+          }
         }
-        
+
         if (this.maybeJS(this.reduceQuotes(script))) {
 
           if (this.checkJSSyntax(script) && this.checkLastFunction()) {
@@ -1792,7 +1789,7 @@ var InjectionChecker = {
                 }
               }
             } else if (errmsg.indexOf("left-hand") !== -1) break;
-            
+
             if (/invalid .*\bflag\b|missing ; before statement|invalid label|illegal character|identifier starts immediately/.test(errmsg)) {
               if (errmsg.indexOf("illegal character") === -1 && /#\d*\s*$/.test(script)) { // sharp vars exceptional behavior
                 if (!quote) break;
@@ -1831,31 +1828,31 @@ var InjectionChecker = {
     this.log(s, t, iterations);
     return false;
   },
-  
-  
+
+
   checkJS: function(s, unescapedUni) {
     this.log(s);
-    
+
     if (/\?name\b[\s\S]*:|[^&?]\bname\b/.test(s)) {
       this.nameAssignment = true;
     }
-    
+
     var hasUnicodeEscapes = !unescapedUni && /\\u[0-9a-f]{4}/i.test(s);
     if (hasUnicodeEscapes && /\\u00[0-7][0-9a-f]/i.test(s)) {
       this.escalate("Unicode-escaped lower ASCII");
       return true;
     }
-    
+
     if (/\\x[0-9a-f]{2}[\s\S]*['"]/i.test(s)) {
       this.escalate("Obfuscated string literal");
       return true;
     }
-    
+
     if (/`[\s\S]*\$\{[\s\S]+[=(][\s\S]+\}[\s\S]*`/.test(s)) {
       this.escalate("ES6 string interpolation");
       return true;
     }
-    
+
     this.syntax.lastFunction = null;
     let ret = this.checkAttributes(s) ||
       (/[\\\(]|=[^=]/.test(s) || this._riskyOperatorsRx.test(s)) &&  this.checkJSBreak(s) || // MAIN
@@ -1869,7 +1866,7 @@ var InjectionChecker = {
     }
     return ret;
   },
-  
+
   unescapeJS: function(s) {
     return s.replace(/\\u([0-9a-f]{4})/gi, function(s, c) {
       return String.fromCharCode(parseInt(c, 16));
@@ -1880,7 +1877,7 @@ var InjectionChecker = {
       return String.fromCharCode(parseInt(c, 16));
     });
   },
-  
+
   unescapeCSS: function(s) {
     // see http://www.w3.org/TR/CSS21/syndata.html#characters
     return s.replace(/\\([\da-f]{0,6})\s?/gi, function($0, $1) {
@@ -1891,16 +1888,16 @@ var InjectionChecker = {
       }
     });
   },
-  
+
   reduceDashPlus: function(s) {
     // http://forums.mozillazine.org/viewtopic.php?p=5592865#p5592865
     return s.replace(/\-+/g, "-")
         .replace(/\++/g, "+")
         .replace(/\s+/g, ' ')
         .replace(/(?: \-)+/g, ' -')
-        .replace(/(?:\+\-)+/g, '+-'); 
+        .replace(/(?:\+\-)+/g, '+-');
   },
-  
+
   _rxCheck: function(checker, s) {
     var rx = this[checker + "Checker"];
     var ret = rx.exec(s);
@@ -1910,13 +1907,13 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   AttributesChecker: new RegExp(
     "(?:\\W|^)(?:javascript:(?:[\\s\\S]+[=\\\\\\(\\[\\.<]|[\\s\\S]*(?:\\bname\\b|\\\\[ux]\\d))|" +
     "data:(?:(?:[a-z]\\w+/\\w[\\w+-]+\\w)?[;,]|[\\s\\S]*;[\\s\\S]*\\b(?:base64|charset=)|[\\s\\S]*,[\\s\\S]*<[\\s\\S]*\\w[\\s\\S]*>))|@" +
-    ("import\\W*(?:\\/\\*[\\s\\S]*)?(?:[\"']|url[\\s\\S]*\\()" + 
+    ("import\\W*(?:\\/\\*[\\s\\S]*)?(?:[\"']|url[\\s\\S]*\\()" +
       "|-moz-binding[\\s\\S]*:[\\s\\S]*url[\\s\\S]*\\(")
-      .replace(/[a-rt-z\-]/g, "\\W*$&"), 
+      .replace(/[a-rt-z\-]/g, "\\W*$&"),
     "i"),
   checkAttributes: function(s) {
     s = this.reduceDashPlus(s);
@@ -1929,12 +1926,12 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   HTMLChecker: new RegExp("<[^\\w<>]*(?:[^<>\"'\\s]*:)?[^\\w<>]*(?:" + // take in account quirks and namespaces
-   fuzzify("script|form|style|svg|marquee|(?:link|object|embed|applet|param|i?frame|base|body|meta|ima?ge?|video|audio|bindings|set|isindex|animate") + 
+   fuzzify("script|form|style|svg|marquee|(?:link|object|embed|applet|param|i?frame|base|body|meta|ima?ge?|video|audio|bindings|set|isindex|animate") +
     ")[^>\\w])|['\"\\s\\0/](?:formaction|style|background|src|lowsrc|ping|" + IC_EVENT_PATTERN +
      ")[\\s\\0]*=", "i"),
-  
+
   checkHTML: function(s) {
      let links = s.match(/\b(?:href|src|(?:form)?action)[\s\0]*=[\s\0]*(?:(["'])[\s\S]*?\1|[^'"<>][^>\s]*)/ig);
      if (links) {
@@ -1946,38 +1943,38 @@ var InjectionChecker = {
     }
     return this._rxCheck("HTML", s);
   },
-  
+
   checkNoscript: function(s) {
     this.log(s);
     return s.indexOf("\x1b(J") !== -1 && this.checkNoscript(s.replace(/\x1b\(J/g, '')) || // ignored in iso-2022-jp
      s.indexOf("\x7e\x0a") !== -1 && this.checkNoscript(s.replace(/\x7e\x0a/g, '')) || // ignored in hz-gb-2312
       this.checkHTML(s) || this.checkSQLI(s) || this.checkHeaders(s);
   },
-  
+
   HeadersChecker: /[\r\n]\s*(?:content-(?:type|encoding))\s*:/i,
   checkHeaders: function(s) this._rxCheck("Headers", s),
   SQLIChecker: /(?:(?:(?:\b|[^a-z])union[^a-z]|\()[\w\W]*(?:\b|[^a-z])select[^a-z]|(?:updatexml|extractvalue)(?:\b|[^a-z])[\w\W]*\()[\w\W]+(?:(?:0x|x')[0-9a-f]{16}|(?:0b|b')[01]{64}|\(|\|\||\+)/i
   ,
   checkSQLI: function(s) this._rxCheck("SQLI", s),
-  
+
   base64: false,
   base64tested: [],
   get base64Decoder() { return Base64 }, // exposed here just for debugging purposes
-  
-  
+
+
   checkBase64: function(url) {
     this.base64 = false;
-    
+
     const MAX_TIME = 8000;
     const DOS_MSG = "Too long execution time, assuming DOS in Base64 checks";
-    
+
     this.log(url);
-   
-    
+
+
     var parts = url.split("#"); // check hash
     if (parts.length > 1 && this.checkBase64FragEx(unescape(parts[1])))
       return true;
-    
+
     parts = parts[0].split(/[&;]/); // check query string
     if (parts.length > 0 && parts.some(function(p) {
         var pos = p.indexOf("=");
@@ -1985,15 +1982,15 @@ var InjectionChecker = {
         return this.checkBase64FragEx(unescape(p));
       }, this))
       return true;
-    
+
     url = parts[0];
     parts = Base64.purify(url).split("/");
     if (parts.length > 255) {
       this.log("More than 255 base64 slash chunks, assuming DOS");
       return true;
     }
-    
-    
+
+
     var t = Date.now();
     if (parts.some(function(p) {
         if (Date.now() - t > MAX_TIME) {
@@ -2003,10 +2000,10 @@ var InjectionChecker = {
         return this.checkBase64Frag(Base64.purify(Base64.alt(p)));
       }, this))
       return true;
-    
-    
+
+
     var uparts = Base64.purify(unescape(url)).split("/");
-    
+
     t = Date.now();
     while(parts.length) {
       if (Date.now() - t > MAX_TIME) {
@@ -2016,15 +2013,15 @@ var InjectionChecker = {
       if (this.checkBase64Frag(parts.join("/")) ||
           this.checkBase64Frag(uparts.join("/")))
         return true;
-      
+
       parts.shift();
       uparts.shift();
     }
 
     return false;
   },
-  
-  
+
+
   checkBase64Frag: function(f) {
     if (this.base64tested.indexOf(f) < 0) {
       this.base64tested.push(f);
@@ -2042,12 +2039,12 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   checkBase64FragEx: function(f) {
     return this.checkBase64Frag(Base64.purify(f)) || this.checkBase64Frag(Base64.purify(Base64.alt(f)));
   },
-  
-  
+
+
   checkURL: function(url) {
     return this.checkRecursive(url
       // assume protocol and host are safe, but keep the leading double slash to keep comments in account
@@ -2056,20 +2053,20 @@ var InjectionChecker = {
       .replace(/\/\((S\(\w{24}\))\)\//, '/$1/')
     );
   },
-  
+
   checkRecursive: function(s, depth, isPost) {
     if (typeof(depth) != "number")
       depth = 3;
-    
+
     this.reset();
     this.isPost = isPost || false;
-    
+
     if (ASPIdiocy.affects(s)) {
       if (this.checkRecursive(ASPIdiocy.process(s), depth, isPost))
         return true;
     } else if (ASPIdiocy.hasBadPercents(s) && this.checkRecursive(ASPIdiocy.removeBadPercents(s), depth, isPost))
       return true;
-    
+
     if (FlashIdiocy.affects(s)) {
       let purged = FlashIdiocy.purgeBadEncodings(s);
       if (purged !== s && this.checkRecursive(purged, depth, isPost))
@@ -2078,22 +2075,22 @@ var InjectionChecker = {
       if (decoded !== purged && this.checkRecursive(decoded, depth, isPost))
         return true;
     }
-    
+
     if (s.indexOf("coalesced:") !== 0) {
       let coalesced = ASPIdiocy.coalesceQuery(s);
       if (coalesced !== s && this.checkRecursive("coalesced:" + coalesced, depth, isPost))
         return true;
     }
-    
+
     if (isPost) {
       s = this.formUnescape(s);
       if (this.checkBase64Frag(Base64.purify(s))) return true;
-      
+
       if (s.indexOf("<") > -1) {
         // remove XML-embedded Base64 binary data
         s = s.replace(/<((?:\w+:)?\w+)>[0-9a-zA-Z+\/]+=*<\/\1>/g, '');
       }
-      
+
       s = "#" + s;
     } else {
       if (this.checkBase64(s.replace(/^\/{1,3}/, ''))) return true;
@@ -2102,29 +2099,29 @@ var InjectionChecker = {
     if (isPost) s = "#" + s; // allows the string to be JS-checked as a whole
     return this._checkRecursive(s, depth);
   },
-  
+
   _checkRecursive: function(s, depth) {
 
     if (this.checkHTML(s) || this.checkJS(s) || this.checkSQLI(s) || this.checkHeaders(s))
       return true;
-    
+
     if (s.indexOf("&") !== -1) {
       let unent = Entities.convertAll(s);
       if (unent !== s && this._checkRecursive(unent, depth)) return true;
     }
-    
+
     if (--depth <= 0)
       return false;
-    
+
     if (s.indexOf('+') !== -1 && this._checkRecursive(this.formUnescape(s), depth))
       return true;
-    
+
     var unescaped = this.urlUnescape(s);
     let badUTF8 = this.utf8EscapeError;
-    
+
     if (this._checkOverDecoding(s, unescaped))
       return true;
-    
+
     if (/[\n\r\t]|&#/.test(unescaped)) {
       let unent = Entities.convertAll(unescaped).replace(/[\n\r\t]/g, '');
       if (unescaped != unent && this._checkRecursive(unent, depth)) {
@@ -2132,17 +2129,17 @@ var InjectionChecker = {
         return true;
       }
     }
-    
+
     if (/\\x[0-9a-f]/i.test(unescaped)) {
       let literal = this.unescapeJSLiteral(unescaped);
       if (unescaped !== literal && this._checkRecursive(literal, depth)) {
-        this.log("Escaped literal match!"); 
+        this.log("Escaped literal match!");
         return true;
-      } 
+      }
     }
-    
+
     if (unescaped.indexOf("\x1b(J") !== -1 && this._checkRecursive(unescaped.replace(/\x1b\(J/g, ''), depth) || // ignored in iso-2022-jp
-        unescaped.indexOf("\x7e\x0a") !== -1 && this._checkRecursive(unescaped.replace(/\x7e\x0a/g, '')) // ignored in hz-gb-2312       
+        unescaped.indexOf("\x7e\x0a") !== -1 && this._checkRecursive(unescaped.replace(/\x7e\x0a/g, '')) // ignored in hz-gb-2312
       )
       return true;
 
@@ -2156,14 +2153,14 @@ var InjectionChecker = {
       }
       if (this._checkRecursive(unescaped, depth)) return true;
     }
-    
+
     s = this.ebayUnescape(unescaped);
     if (s != unescaped && this._checkRecursive(s, depth))
       return true;
-    
+
     return false;
   },
-  
+
   _checkOverDecoding: function(s, unescaped) {
     if (/%[8-9a-f]/i.test(s)) {
       const rx = /[<'"]/g;
@@ -2179,7 +2176,7 @@ var InjectionChecker = {
     }
     return false;
   },
-  
+
   utf8OverDecode: function(url, strict) {
     return url.replace(strict
       ? /%(?:f0%80%80|e0%80|c0)%[8-b][0-f]/gi
@@ -2207,7 +2204,7 @@ var InjectionChecker = {
       }
     );
   },
-  
+
   toUnicode: function(s, charset) {
     let sis = Cc["@mozilla.org/io/string-input-stream;1"]
           .createInstance(Ci.nsIStringInputStream);
@@ -2223,7 +2220,7 @@ var InjectionChecker = {
     }
     return ret.join('');
   },
-  
+
   utf8EscapeError: true,
   urlUnescape: function(url, brutal) {
     var od = this.utf8OverDecode(url, !brutal);
@@ -2232,41 +2229,41 @@ var InjectionChecker = {
       return decodeURIComponent(od);
     } catch(warn) {
       this.utf8EscapeError = true;
-      if (url != od) url += " (" + od + ")";  
+      if (url != od) url += " (" + od + ")";
       this.log("Problem decoding " + url + ", maybe not an UTF-8 encoding? " + warn.message);
       return unescape(brutal ? ASPIdiocy.filter(od) : od);
     }
   },
-  
+
   formUnescape: function(s, brutal) {
     return this.urlUnescape(s.replace(/\+/g, ' '), brutal);
   },
-  
+
   aspUnescape: function(s) {
     return unescape(ASPIdiocy.filter(s).replace(/\+/g, ' '));
   },
-  
+
   ebayUnescape: function(url) {
     return url.replace(/Q([\da-fA-F]{2})/g, function(s, c) {
       return String.fromCharCode(parseInt(c, 16));
     });
   },
-  
+
   checkPost: function(channel, skip) {
     if (!((channel instanceof Ci.nsIUploadChannel)
           && channel.uploadStream && (channel.uploadStream instanceof Ci.nsISeekableStream)))
       return false;
-    
+
     var clen = -1;
     try {
       clen = chan.getRequestHeader("Content-length");
     } catch(e) {}
     MaxRunTime.increase(clen < 0 || clen > 300000 ? 60 : Math.ceil(20 * clen / 100000));
-    
+
     this.log("Extracting post data...");
     return this.checkPostStream(channel.URI.spec, channel.uploadStream, skip);
   },
-  
+
   checkPostStream: function(url, stream, skip) {
      var ic = this;
      var pc = new PostChecker(url, stream, skip);
@@ -2277,14 +2274,14 @@ var InjectionChecker = {
       }
     );
   },
-  
+
   testCheckPost: function(url, strData) {
     var stream = Cc["@mozilla.org/io/string-input-stream;1"].
             createInstance(Ci.nsIStringInputStream);
     stream.setData(strData, strData.length);
     return this.checkPostStream(url, stream);
   }
-  
+
 };
 
 function PostChecker(url, uploadStream, skip) {
@@ -2306,12 +2303,12 @@ PostChecker.prototype = {
       us.seek(0, 0);
       const sis = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
       sis.setInputStream(us);
-      
+
       // reset status
       delete this.boundary;
       delete this.isFile;
       delete this.postData;
-     
+
       if ((available = sis.available())) do {
         size = this.postData.length;
         if (size >= MAX_FIELD_SIZE) return size + " bytes or more in one non-file field, assuming memory DOS attempt!";
@@ -2326,7 +2323,7 @@ PostChecker.prototype = {
         }
         available = sis.available();
         chunks = this.parse(!available);
-      
+
         for (var j = 0, len = chunks.length; j < len; j++) {
           ret = callback(chunks[j]);
           if (ret) return ret;
@@ -2340,13 +2337,13 @@ PostChecker.prototype = {
           us.seek(0, 0); // rewind
         } catch(e) {}
     }
-    return false; 
+    return false;
   },
-  
+
   parse: function(eof) {
     var postData = this.postData;
     var m;
-    
+
     if (typeof(this.boundary) != "string") {
       m = postData.match(/^Content-type: multipart\/form-data;\s*boundary=(\S*)/i);
       this.boundary = m && m[1] || '';
@@ -2357,19 +2354,19 @@ PostChecker.prototype = {
     this.postData = '';
 
     var boundary = this.boundary;
-   
+
     var chunks = [];
     var j, len, name;
-    
+
     var skip = this.skip;
-    
-    if (boundary) { // multipart/form-data, see http://www.faqs.org/ftp/rfc/rfc2388.txt  
+
+    if (boundary) { // multipart/form-data, see http://www.faqs.org/ftp/rfc/rfc2388.txt
       if(postData.indexOf(boundary) < 0) {
         // skip big file chunks
         return chunks;
       }
       var parts = postData.split(boundary);
-      
+
       var part, last;
       for(j = 0, len = parts.length; j < len;) {
         part = parts[j];
@@ -2380,7 +2377,7 @@ PostChecker.prototype = {
           continue;
         }
         m = part.match(/^\s*Content-Disposition: form-data; name="(.*?)"(?:;\s*filename="(.*)"|[^;])\r?\n(Content-Type: \w)?.*\r?\n/i);
-        
+
         if (m) {
           // name and filename are backslash-quoted according to RFC822
           name = m[1];
@@ -2392,11 +2389,11 @@ PostChecker.prototype = {
             if (m[3]) {
               // Content-type: skip, it's a file
               this.isFile = true;
-              
-              if (last && !eof) 
+
+              if (last && !eof)
                 this.postData = part.substring(part.length - boundary.length);
 
-              continue; 
+              continue;
             }
           }
           if (eof || !last) {
@@ -2417,7 +2414,7 @@ PostChecker.prototype = {
       }
     } else {
       this.isFile = false;
-      
+
       parts = postData.replace(/^\s+/, '').split("&");
       if (!eof) this.postData = parts.pop();
 
@@ -2446,19 +2443,19 @@ XSanitizer.prototype = {
     var original = url.clone();
     this.brutal = this.brutal || this.injectionChecker.checkURL(url.spec);
     this.base64 = this.injectionChecker.base64;
-    
+
     const changes = { minor: false, major: false, qs: false };
     // sanitize credentials
     if (url.username) url.username = this.sanitizeEnc(url.username);
     if (url.password) url.password = this.sanitizeEnc(url.password);
     url.host = this.sanitizeEnc(url.host);
-    
+
     if (url instanceof Ci.nsIURL) {
       // sanitize path
-     
+
       if (url.param) {
         url.path = this.sanitizeURIComponent(url.path); // param is the URL part after filePath and a semicolon ?!
-      } else if(url.filePath) { 
+      } else if(url.filePath) {
         url.filePath = this.sanitizeURIComponent(url.filePath); // true == lenient == allow ()=
       }
       // sanitize query
@@ -2481,22 +2478,22 @@ XSanitizer.prototype = {
       // fallback for non-URL URIs, we should never get here anyway
       if (url.path) url.path = this.sanitizeURIComponent(url.path);
     }
-    
+
     var urlSpec = url.spec;
     var neutralized = Entities.neutralizeAll(urlSpec, /[^\\'"\x00-\x07\x09\x0B\x0C\x0E-\x1F\x7F<>]/);
     if (urlSpec != neutralized) url.spec = neutralized;
-    
+
     if (this.base64 ||
         FlashIdiocy.affects(urlSpec) ||
         FlashIdiocy.affects(unescape(urlSpec))
       ) {
       url.spec = url.prePath; // drastic, but with base64 / FlashIdiocy we cannot take the risk!
     }
-    
+
     if (url.getRelativeSpec(original) && unescape(url.spec) != unescape(original.spec)) { // ok, this seems overkill but take my word, the double check is needed
       changes.minor = true;
-      changes.major = changes.major || changes.qs || 
-                      unescape(original.spec.replace(/\?.*/g, "")) 
+      changes.major = changes.major || changes.qs ||
+                      unescape(original.spec.replace(/\?.*/g, ""))
                         != unescape(url.spec.replace(/\?.*/g, ""));
       url.spec = url.spec.replace(/'/g, "%27")
       if (changes.major) {
@@ -2508,7 +2505,7 @@ XSanitizer.prototype = {
     }
     return changes;
   },
-  
+
   sanitizeWholeQuery: function(query, changes) {
     var original = query;
     query = Entities.convertAll(query);
@@ -2519,27 +2516,27 @@ XSanitizer.prototype = {
     if(changes) changes.qs = true;
     return escape(query);
   },
-  
+
   _queryRecursionLevel: 0,
   sanitizeQuery: function(query, changes, sep) {
     const MAX_RECUR = 2;
-    
+
     var canRecur = this._queryRecursionLevel++ < MAX_RECUR;
     // replace every character matching noscript.filterXGetRx with a single ASCII space (0x20)
     changes = changes || {};
     if (!sep) {
-      sep = query.indexOf("&") > -1 || this.brutal ? "&" : ";" 
+      sep = query.indexOf("&") > -1 || this.brutal ? "&" : ";"
     }
     const parms = query.split(sep);
-    
+
     for (let j = parms.length; j-- > 0;) {
       let pieces = parms[j].split("=");
 
       try {
         for (let k = pieces.length; k-- > 0;) {
-          
+
           let encodedPz =  InjectionChecker.utf8OverDecode(pieces[k]);
-          
+
           let pz = null, encodeURL = null;
           if (encodedPz.indexOf("+") < 0) {
             try {
@@ -2551,13 +2548,13 @@ XSanitizer.prototype = {
             pz = unescape(ASPIdiocy.filter(encodedPz));
             encodeURL = escape;
           }
-          
+
           let origPz = pz;
-          
+
           // recursion for nested (partial?) URIs
 
           let nestedURI = null;
-          
+
           if (canRecur && /^https?:\/\//i.test(pz)) {
             // try to sanitize as a nested URL
             try {
@@ -2568,37 +2565,37 @@ XSanitizer.prototype = {
               nestedURI = null;
             }
           }
-          
+
           if (!nestedURI) {
             let qpos;
             if (canRecur &&
                  (qpos = pz.indexOf("?")) > - 1 &&
-                 (spos = pz.search(/[&;]/) > qpos)) { 
+                 (spos = pz.search(/[&;]/) > qpos)) {
               // recursive query string?
               // split, sanitize and rejoin
-              pz = [ this.sanitize(pz.substring(0, qpos)), 
+              pz = [ this.sanitize(pz.substring(0, qpos)),
                     this.sanitizeQuery(pz.substring(qpos + 1), changes)
                    ].join("?")
-              
+
             } else {
               pz = this.sanitize(pz);
             }
             if (origPz != pz) changes.qs = true;
           }
-          
-          if (origPz != pz) pieces[k] = encodeURL(pz);  
-         
+
+          if (origPz != pz) pieces[k] = encodeURL(pz);
+
         }
         parms[j] = pieces.join("=");
-      } catch(e) { 
+      } catch(e) {
         // decoding exception, skip this param
         parms.splice(j, 1);
-      } 
+      }
     }
     this._queryRecursionLevel--;
     return parms.join(sep);
   },
-  
+
   sanitizeURIComponent: function(s) {
     try {
       var unescaped = InjectionChecker.urlUnescape(s, this.brutal);
@@ -2622,22 +2619,22 @@ XSanitizer.prototype = {
     if (s.indexOf('"') > -1 && !this.brutal) {
       // try to play nice on search engine queries with grouped quoted elements
       // by allowing double quotes but stripping even more aggressively other chars
-      
+
       // Google preserves "$" and recognizes ~, + and ".." as operators
       // All the other non alphanumeric chars (aside double quotes) are ignored.
       // We will preserve the site: modifier as well
       // Ref.: http://www.google.com/help/refinesearch.html
-      s = s.replace(/[^\w\$\+\.\~"&;\- :\u0080-\uffff]/g, 
+      s = s.replace(/[^\w\$\+\.\~"&;\- :\u0080-\uffff]/g,
           " " // strip everything but alphnum and operators
-          ).replace(":", 
+          ).replace(":",
           function(k, pos, s) { // strip colons as well, unless it's the site: operator
-            return (s.substring(0, pos) == "site" || s.substring(pos - 5) == " site") ? ":" : " " 
+            return (s.substring(0, pos) == "site" || s.substring(pos - 5) == " site") ? ":" : " "
           }
         );
       if (s.replace(/[^"]/g, "").length % 2) s += '"'; // close unpaired quotes
       return s;
     }
-    
+
     if (this.brutal) {
       s = s.replace(/\x1bJ\(/g, '').replace(/\x7e\x0a/g, ''); // ignored in some encodings
     }
@@ -2647,9 +2644,9 @@ XSanitizer.prototype = {
                 function(m) { return m.replace(/(.*?)(\w)/, "$1#no$2"); });
 
     if (this.extraBlacklist) { // additional user-defined blacklist for emergencies
-      s = s.replace(this.extraBlacklist, " "); 
+      s = s.replace(this.extraBlacklist, " ");
     }
-    
+
     if (this.brutal) { // injection checks were positive
       s = InjectionChecker.reduceDashPlus(s)
         .replace(/\bdata:/ig, "nodata:")
@@ -2659,15 +2656,15 @@ XSanitizer.prototype = {
         .replace(/Q[\da-fA-Fa]{2}/g, "Q20") // Ebay-style escaping
         .replace(/%[\n\r\t]*[0-9a-f][\n\r\t]*[0-9a-f]/gi, " ")
         // .replace(/percnt/, 'percent')
-        ; 
+        ;
     }
-    
+
     return s == orig ? unsanitized : s;
   },
-  
+
   _regularReplRx: new RegExp(
     fuzzify('(?:javascript|data)') + '\\W*:+|' +
-      fuzzify('-moz-binding|@import'), 
+      fuzzify('-moz-binding|@import'),
     "ig"
   ),
   _brutalReplRx: new RegExp(
@@ -2675,28 +2672,28 @@ XSanitizer.prototype = {
     IC_EVAL_PATTERN + '|' + IC_EVENT_PATTERN + ')',
     "g"
   )
-  
+
 };
 
 // we need this because of https://bugzilla.mozilla.org/show_bug.cgi?id=439276
 
 const Base64 = {
-  
+
   purify: function(input) {
     return input.replace(/[^A-Za-z0-9\+\/=]+/g, '');
   },
-  
+
   alt: function(s) {
     // URL base64 variant, see http://en.wikipedia.org/wiki/Base64#URL_applications
     return s.replace(/-/g, '+').replace(/_/g, '/')
   },
-  
-  decode: function (input, strict) {  
+
+  decode: function (input, strict) {
     var output = '';
     var chr1, chr2, chr3;
     var enc1, enc2, enc3, enc4;
     var i = 0;
-    
+
     // if (/[^A-Za-z0-9\+\/\=]/.test(input)) return ""; // we don't need this, caller checks for us
 
     const k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
@@ -2747,7 +2744,7 @@ function RequestInfo(channel, url, origin, window) {
   }
 }
 RequestInfo.prototype = {
-  xssMaybe: false 
+  xssMaybe: false
 }
 
 
@@ -2778,7 +2775,7 @@ DOSChecker.prototype = {
   },
   check: function() {
     MaxRunTime.restore();
-    
+
     if (!(this.done || this.canSpin && Thread.activeLoops))
       DOSChecker.abort(this.request, (this.lastClosure && this.lastClosure.toSource()));
   }
@@ -2819,7 +2816,7 @@ var ASPIdiocy = {
   _replaceRx: /%u([0-9a-fA-F]{4})/g,
   _affectsRx: /%u[0-9a-fA-F]{4}/,
   _badPercentRx: /%(?!u[0-9a-fA-F]{4}|[0-9a-fA-F]{2})|%(?:00|u0000)[^&=]*/g,
-  
+
   hasBadPercents: function(s) this._badPercentRx.test(s),
   removeBadPercents: function(s) s.replace(this._badPercentRx, ''),
   affects: function(s) this._affectsRx.test(s),
@@ -2828,17 +2825,17 @@ var ASPIdiocy = {
     return /[\uff5f-\uffff]/.test(s) ? s + '&' + s.replace(/[\uff5f-\uffff]/g, '?') : s;
   },
   filter: function(s) this.removeBadPercents(s).replace(this._replaceRx, this._replace),
-    
+
   coalesceQuery: function(s) { // HPP protection, see https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
     let qm = s.indexOf("?");
     if (qm < 0) return s;
     let p = s.substring(0, qm);
     let q = s.substring(qm + 1);
     if (!q) return s;
-    
+
     let unchanged = true;
     let emptyParams = false;
-    
+
     let pairs = (function rearrange(joinNames) {
       let pairs = q.split("&");
       let accumulator = { __proto__: null };
@@ -2866,12 +2863,12 @@ var ASPIdiocy = {
         ? pairs.concat(rearrange(true).filter(function(p) pairs.indexOf(p) === -1))
         : pairs;
     })();
-    
+
     if (unchanged) return s;
     for (let j = pairs.length; j-- > 0;) if (!pairs[j]) pairs.splice(j, 1);
     return p + pairs.join("&");
   },
-  
+
   _replace: function(match, hex) {
      // lazy init
      INCLUDE("ASPIdiocy");
@@ -2882,7 +2879,7 @@ var ASPIdiocy = {
 var FlashIdiocy = {
   _affectsRx: /%(?:[8-9a-f]|[0-7]?[^0-9a-f])/i, // high (non-ASCII) percent encoding or invalid second digit
   affects: function(s) this._affectsRx.test(s),
-  
+
   purgeBadEncodings: function(s) {
     INCLUDE("FlashIdiocy");
     return this.purgeBadEncodings(s);
diff --git a/chrome/noscript.jar!/content/noscript/STS.js b/chrome/noscript.jar!/content/noscript/STS.js
deleted file mode 100644
index 138a8b7..0000000
--- a/chrome/noscript.jar!/content/noscript/STS.js
+++ /dev/null
@@ -1,234 +0,0 @@
-// http://lists.w3.org/Archives/Public/www-archive/2009Sep/att-0051/draft-hodges-strict-transport-sec-05.plain.html
-
-const STS = {
-  
-  enabled: false,
-  
-  get db() {
-    delete this.db;
-    return this.initPersistentDB();
-  },
-  
-  initPersistentDB: function() {
-    return this.db = new STSDB(STSPersistence);
-  },
-  
-  processRequest: function(chan) {
-    if (this.enabled) {
-      var uri = chan.URI;
-      if (uri.schemeIs("https")) {
-        try {
-          this.db.processHeader(uri.asciiHost, chan.getResponseHeader("Strict-Transport-Security"));
-        } catch (e) {}
-      }
-    }
-  },
-  
-  isSTSURI: function(uri) {
-    return this.enabled && this.db.matches(uri.asciiHost);
-  },
-  
-  enterPrivateBrowsing: function() {
-    try {
-      this.db.save();
-    } catch(e) {}
-    
-    this.db = new STSDB(this.db);
-  },
-  
-  exitPrivateBrowsing: function() {
-    this.initPersistentDB();
-  },
-  
-  eraseDB: function() {
-    this.db.reset();
-    STSPersistence.save(this.db);
-  },
-  
-  patchErrorPage: function(docShell, errorURI) {
-     // see #errors-in-secure-transport-establishment
-    if (!this.enabled) return;
-
-    let m = errorURI.spec.match(/^about:certerror\?.*?\bu=([^&]+)/);
-    if (!m) return;
-    
-    let u = decodeURIComponent(m[1]);
-    m = errorURI.spec.match(/&c=([^&]+)/);
-    let charset = m ? decodeURIComponent(m[1]) : null;    
-    try {
-      let uri = IOS.newURI(u, charset, null);
-      if (STS.isSTSURI(uri))
-      Thread.delay(function() {
-        docShell.document.getElementById("expertContent").style.display = "none";
-      }, 100);
-    } catch(e) {}
-  },
-  
-  dispose: function() {
-    this.db.save();
-  }
-};
-
-function STSDB(source) {
-  this._entries = {};
-  if (source && source._entries) { // clone
-    var entries = source._entries;
-    for (var p in entries) {
-      this._entries[p] = entries[p];
-    }
-  } else {
-    if (source && source.load) {
-      this._persistence = source;
-      this.load();
-    }
-  } 
-}
-
-STSDB.prototype = {
-  _persistence: null,
-  _dirty: false,
-  _saveTimer: null,
-  
-  processHeader: function(host, header) {
-    if (DNS.isIP(host)) return;
-    
-    var m = header.match(/^\s*max-age\s*=\s*(\d+)\s*(;\s*includeSubDomains)?/i);
-    if (!m) return;
-    var maxAge = parseInt(m[1]);
-    var includeSubDomains = !!m[2];
-    var expiration = Math.round(Date.now() / 1000) + maxAge; 
-    if (host in this._entries) {
-      var e = this._entries[host];
-      if (e.expiration == expiration && e.includeSubDomains == includeSubDomains)
-        return;
-      
-      e.expiration = expiration;
-      e.includeSubDomains = includeSubDomains;
-    } else {
-      this.add(new STSEntry(host, expiration, includeSubDomains));
-    }
-    this.saveDeferred();
-  },
-  
-  add: function(entry) {
-    this._entries[entry.host] = entry;
-  },
-  
-  matches: function(host, asSuperDomain) {
-    if (host in this._entries) {
-      var e = this._entries[host];
-      
-      if (e.expiration >= Date.now() / 1000) {
-        if ((!asSuperDomain || e.includeSubDomains))
-          return true;
-      } else {
-        delete this._entries[host];
-      }
-    }
-    
-    var dotPos = host.indexOf(".");
-    var lastDotPos = host.lastIndexOf(".");
-    
-    if (dotPos == lastDotPos)
-      return false;
-    
-    return this.matches(host.substring(dotPos + 1), true);
-  },
-  
-  serialize: function() {
-    var lines = [], ee = this._entries;
-    var e;
-    for (var h in ee) {
-      e = ee[h];
-      lines.push([e.host, e.expiration, e.includeSubDomains ? "*" : ""].join(";"));
-    }
-    return lines.join("\n");
-  },
-  restore: function(s) {
-    s.split(/\s+/).forEach(function(line) {
-      if (line) {
-        var args = line.split(";");
-        if (args.length > 1)
-          this.add(new STSEntry(args[0], parseInt(args[1]), !!args[2]));
-      }
-    }, this);
-  },
-  
-  load: function() {
-    if (this._persistence) {
-      this._persistence.load(this);
-      this.purgeExpired();
-    }
-  },
-  
-  save: function() {
-    if (this._dirty && this._persistence) {
-      this.purgeExpired();
-      this._persistence.save(this);
-      this._dirty = false;
-    }
-  },
-  
-  saveDeferred: function() {
-    if (this._dirty || !this._persistence) return;
-    this._dirty = true;
-    if (!this._timer) this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    this._timer.initWithCallback(this, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
-  },
-  notify: function(timer) {
-    this.save();
-  },
-  
-  purgeExpired: function() {
-    var now = Math.round(Date.now() / 1000);
-    for (var h in this._entries) {
-      if (this._entries[h].expiration < now) delete this._entries[h];
-    }
-  },
-  
-  reset: function() {
-    this._entries = {};
-    this._dirty = false;
-  }
-};
-
-function STSEntry(host, expiration, includeSubDomains) {
-  this.host = host;
-  this.expiration = expiration;
-  if (includeSubDomains) this.includeSubDomains = includeSubDomains;
-}
-
-STSEntry.prototype = {
-  includeSubDomains: false
-};
-
-
-const STSPersistence = {
-  get _file() {
-    delete this._file;
-    var f =  Cc["@mozilla.org/file/directory_service;1"].getService(
-        Ci.nsIProperties).get("ProfD", Ci.nsIFile);
-    f.append("NoScriptSTS.db");
-    return this._file = f;
-  },
-  load: function(db) {
-    var f = this._file;
-    try {
-      if (f.exists()) db.restore(IO.readFile(f));
-    } catch (e) {
-      dump("STS: Error loading db from " + f.path + "!" + e + "\n");
-      return false;
-    }
-    return true;
-  },
-  save: function(db) {
-    var f = this._file;
-    try {
-      IO.safeWriteFile(f, db.serialize());
-    } catch(e) {
-      dump("STS: Error saving db to " + f.path + "!" + e + "\n");
-      return false;
-    }
-    return true;
-  }
-};
diff --git a/chrome/noscript.jar!/content/noscript/WinScript.js b/chrome/noscript.jar!/content/noscript/WinScript.js
index fddc96a..4b0b1e6 100644
--- a/chrome/noscript.jar!/content/noscript/WinScript.js
+++ b/chrome/noscript.jar!/content/noscript/WinScript.js
@@ -1,35 +1,70 @@
-var WinScript = ("blockScriptForGlobal" in Cu)
-?
+var WinScript = ("blockScriptForGlobal" in Cu) ?
 {
   supported: true,
   block: function(window) {
     if (window._blockScriptForGlobal) return;
-    Cu.blockScriptForGlobal(window);
+    try {
+      Cu.blockScriptForGlobal(window);
+      if (!("blockScriptForGlobal" in window)) {
+        this.patchStyle(window.document);
+      }
+    } catch (e) {
+      if (!this._childDo("unblock", window)) throw e;
+    }
     window._blockScriptForGlobal = true;
   },
   unblock: function(window) {
     if (!window._blockScriptForGlobal) return;
-    Cu.unblockScriptForGlobal(window);
+    try {
+      Cu.unblockScriptForGlobal(window);
+    } catch (e) {
+       if (this._childDo("block", window)) throw e;
+    }
     window._blockScriptForGlobal = false;
   },
   isBlocked: function(window) {
     return window._blockScriptForGlobal;
   },
-
+  isDecided: function(window) {
+    return "_blockScriptForGlobal" in window;
+  },
+  get _childDo() {
+    delete this._childDo;
+    return (this._childDo = IPC.parent && IPC.parent.mm && ("isCrossProcessWrapper" in Cu) ?
+      function(verb, window) {
+        if (Cu.isCrossProcessWrapper(window)) {
+          IPC.parent.mm.broadcastAsyncMessage("NoScript:WinScript", verb, { window: window });
+          return true;
+        }
+        return false;
+      }
+    : function() { return false; }
+    );
+  }
 }
 :
 {
   supported: false,
   __noSuchMethod__: function() {},
-  block: function(window) {
-    let ds = DOM.getDocShellForWindow(window)
-  },
-  unblock: function(window) {
-    if (!window._blockScriptForGlobal) return;
-    Cu.unblockScriptForGlobal(window);
-    window._blockScriptForGlobal = false;
-  },
-  isBlocked: function(window) {
-    return window._blockScriptForGlobal;
-  },
+};
+
+WinScript._domUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
+WinScript.patchStyle = function(doc) {
+  let ss = this._domUtils.getAllStyleSheets(doc);
+  // reverse loop because the preference stylesheet is almost always the last one
+  for (let j = ss.length; j-- > 0;) {
+    let s = ss[j];
+    if(s.href === "about:PreferenceStyleSheet") {
+        let rules = s.cssRules;
+        // skip 1st & 2nd, as they are HTML & SVG namespaces
+        for (let j = 2, len = rules.length; j < len; j++) {
+            let r = rules[j];
+            if (r.cssText === "noscript { display: none ! important; }") {
+                s.deleteRule(j);
+                break;
+            }
+        }
+        break;
+    }
+  }
 };
diff --git a/chrome/noscript.jar!/content/noscript/about.xul b/chrome/noscript.jar!/content/noscript/about.xul
index 71da74a..f559ac0 100644
--- a/chrome/noscript.jar!/content/noscript/about.xul
+++ b/chrome/noscript.jar!/content/noscript/about.xul
@@ -48,7 +48,7 @@ function about_onload() {
   
   var str = getString("aboutTitle",["NoScript"]);
   if(str) document.title = str;
-  str = getString("version", ["2.6.9.22"]);
+  str = getString("version", ["2.6.9.23rc1"]);
   if(str) document.getElementById("extensionVersion").setAttribute("value", str);
   
   setString("extensionDescription",null,"extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description");
@@ -86,7 +86,7 @@ function about_open(url, features) {
 <hbox id="headBox" align="end">
 <vbox flex="1">
 <label value="NoScript" id="extensionName" crop="right"/>
-<label value="Version 2.6.9.22" id="extensionVersion" crop="right"/>
+<label value="Version 2.6.9.23rc1" id="extensionVersion" crop="right"/>
 </vbox>
 <vbox flex="1" align="end">
 <hbox align="end">
@@ -114,7 +114,7 @@ function about_open(url, features) {
 <description class="contributor">Algimantas Margevičius (Lithuanian translation)</description>
 <description class="contributor">Asaf Bartov & baryoni (Hebrew translation)</description>
 <description class="contributor">Alf and Liesbeth (Dutch translation)</description>
-<description class="contributor">Alexander Sokolov and Sergei Smirnov (Russian translation)</description>
+<description class="contributor">Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</description>
 <description class="contributor">Batuhan Çetin and eveterinary (Turkish translation)</description>
 <description class="contributor">Baurzhan Muftakhidinov (Kazakh translation)</description>
 <description class="contributor">Beerboy & Haebaru (Japanese translation)</description>
@@ -164,7 +164,7 @@ function about_open(url, features) {
 <hbox>
 <label id="license" class="text-link" tooltiptext="Read end-user license" onclick="about_open('chrome://noscript/content/NoScript_License.txt')">License</label>
 <spacer flex="1"/>
-<label id="changelog" class="text-link" align="center" tooltiptext="See Changelog" onclick="about_open('https://noscript.net/changelog#2.6.9.22')">Changelog</label>
+<label id="changelog" class="text-link" align="center" tooltiptext="See Changelog" onclick="about_open('https://noscript.net/changelog#2.6.9.23rc1')">Changelog</label>
 <spacer flex="1"/>
 <label id="extensionHomepage" class="text-link" tooltiptext="Visit Extension Home Page" onclick="about_open('https://noscript.net')">https://noscript.net</label>
 </hbox>
diff --git a/chrome/noscript.jar!/content/noscript/childScript.js b/chrome/noscript.jar!/content/noscript/childScript.js
new file mode 100644
index 0000000..069247c
--- /dev/null
+++ b/chrome/noscript.jar!/content/noscript/childScript.js
@@ -0,0 +1,49 @@
+
+const { interfaces: Ci, classes: Cc, utils: Cu } = Components;
+const ns = {};
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+var OS = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
+
+const LOADER = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
+//LOADER.loadSubScript("chrome://noscript/content/loader.js");
+// What's going on? Why do I need all this dance to export globals in subscripts?
+this.Cu = Cu;
+this.Cc = Cc;
+this.Ci = Ci;
+this.ns = ns;
+LOADER.loadSubScript("chrome://noscript/content/WinScript.js", this);
+
+var IPC = {};
+IPC.child = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
+  mm: Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender).QueryInterface(Ci.nsIMessageListenerManager),
+  init: function() {
+    OS.addObserver(this, "content-document-global-created", true);
+
+  },
+
+  observe: function(subject, topic, data) {
+    switch (topic) {
+      case "content-document-global-created":
+
+        let window = subject;
+        dump(topic + " - " + data + ", " + window.document.URL);
+        let blockIt = this.mm.sendSyncMessage("NoScript:mustBlockJS", { site: data }, { window: window })[0];
+
+        dump("BlockIt: " + blockIt);
+        if (blockIt) {
+          WinScript.block(window);
+        } else {
+          WinScript.unblock(window);
+        }
+      break;
+    }
+  }
+};
+
+dump("ChildScript loaded\n");
+
+//INCLUDE("WinScript");
+IPC.child.init();
diff --git a/chrome/noscript.jar!/content/noscript/frameScript.js b/chrome/noscript.jar!/content/noscript/frameScript.js
index c826fe4..14bf138 100644
--- a/chrome/noscript.jar!/content/noscript/frameScript.js
+++ b/chrome/noscript.jar!/content/noscript/frameScript.js
@@ -1,2 +1,2 @@
 Components.utils.import("chrome://noscript/content/FrameScript.jsm");
-new FrameScript(this);
\ No newline at end of file
+new FrameScript(this);
diff --git a/chrome/noscript.jar!/content/noscript/loader.js b/chrome/noscript.jar!/content/noscript/loader.js
new file mode 100644
index 0000000..86b20fe
--- /dev/null
+++ b/chrome/noscript.jar!/content/noscript/loader.js
@@ -0,0 +1,44 @@
+const _INCLUDED = {};
+function IS_INCLUDED(name) name in _INCLUDED;
+
+if (!("LOADER" in this)) {
+  var { interfaces: Ci, classes: Cc, utils: Cu } = Components;
+  var LOADER = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
+  var ns = {};
+}
+
+
+
+
+
+function INCLUDE(name) {
+  if (arguments.length > 1)
+    for (var j = 0, len = arguments.length; j < len; j++)
+      INCLUDE(arguments[j]);
+  else if (!(name in _INCLUDED)) {
+    try {
+      _INCLUDED[name] = true;
+      let t = Date.now();
+      LOADER.loadSubScript("chrome://noscript/content/" + name + ".js");
+      // dump((t - TIME0) + " - loaded " + name + " in " + (Date.now() - t) + "\n")
+    } catch(e) {
+      let msg = "INCLUDE " + name + ": " + e + "\n" + e.stack;
+      Components.utils.reportError(msg);
+      dump(msg + "\n");
+    }
+  }
+}
+
+function LAZY_INCLUDE(name) {
+  if (arguments.length > 1)
+    for (var j = 0, len = arguments.length; j < len; j++)
+      arguments.callee(arguments[j]);
+  else if (!(name in this)) {
+    __defineGetter__(name, function() {
+      delete this[name];
+      if (ns.consoleDump) ns.dump(name + " kickstarted at " + (new Error().stack));
+      INCLUDE(name);
+      return this[name];
+    });
+  }
+}
diff --git a/chrome/noscript.jar!/content/noscript/parentProcess.js b/chrome/noscript.jar!/content/noscript/parentProcess.js
new file mode 100644
index 0000000..f4cd6cd
--- /dev/null
+++ b/chrome/noscript.jar!/content/noscript/parentProcess.js
@@ -0,0 +1,43 @@
+var IPC = {};
+IPC.parent = {
+  QueryInterface: xpcom_generateQI([Ci.nsIMessageListener, Ci.nsISupportsWeakReference]),
+  globalMM: null,
+  mm: null,
+  init: function() {
+    if (! ("@mozilla.org/globalmessagemanager;1" in Cc)) return;
+    let globalMM = this.globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+        .getService(Ci.nsIMessageListenerManager)
+        .QueryInterface(Ci.nsIMessageBroadcaster)
+        .QueryInterface(Ci.nsIFrameScriptLoader);
+    globalMM.loadFrameScript("chrome://noscript/content/frameScript.js", true);
+
+    if ("nsIProcessScriptLoader" in Ci) {
+      let mm = this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+        .getService(Ci.nsIMessageListenerManager)
+        .QueryInterface(Ci.nsIMessageBroadcaster)
+        .QueryInterface(Ci.nsIProcessScriptLoader);
+      mm.loadProcessScript("chrome://noscript/content/childScript.js", true);
+      mm.addWeakMessageListener("NoScript:mustBlockJS", this);
+    }
+  },
+  dispose: function() {
+    let globalMM = this.globalMM;
+    if (globalMM) {
+      globalMM.removeDelayedFrameScript("chrome://noscript/content/frameScript.js");
+      let mm = this.mm;
+      if (mm) {
+        mm.removeWeakMessageListener("NoScript:mustBlockJS");
+        mm.removeDelayedProcessScript("chrome://noscript/content/childScript.js");
+      }
+    }
+  },
+
+  receiveMessage: function(m) {
+    switch(m.name) {
+      case "NoScript:mustBlockJS":
+        return ns.mustBlockJS(m.objects.window, m.data.site);
+    }
+  },
+};
+
+IPC.parent.init();
diff --git a/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd b/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
index 17d1a9f..2b353fc 100644
--- a/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Настройки…">
 <!ENTITY noscriptOptions.accesskey "Н">
 <!ENTITY noscriptOptionsLong "Настройки на NoScript">
-<!ENTITY noscriptAbout "За NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "За NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Можете да зададете в кои уеб-сайтове е позволено да се използват скриптовете. Напишете адреса или домейна (например "http://www.site.com" или "site.com") на сайта, който искате да разрешите и натиснете Разреши.">
 <!ENTITY noscriptWebAddress "Адрес на уеб-сайта:">
 <!ENTITY noscriptAllow "Разреши">
diff --git a/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
index 059d751..63fc483 100644
--- a/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcions...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcions de NoScript">
-<!ENTITY noscriptAbout "Quant a NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Quant a NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Podeu especificar quins llocs web poden executar seqüències. El tipus d'adreça o el domini (p.ex. "http://www.site.com" o "site.com") del lloc al qual voleu donar permissos i feu clic a Permet.">
 <!ENTITY noscriptWebAddress "Adreça del lloc web:">
 <!ENTITY noscriptAllow "Permet">
diff --git a/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd b/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
index d5c1c53..9868360 100644
--- a/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Nastavení...">
 <!ENTITY noscriptOptions.accesskey "N">
 <!ENTITY noscriptOptionsLong "Nastavení NoScript">
-<!ENTITY noscriptAbout "O rozšíření NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "O rozšíření NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Můžete si zvolit, které webové stránky mají povoleno spouštět skripty. Zadejte adresu (např. http://www.site.com nebo site.com) na které se nachází stránka, pro kterou chcete skripty povolit a klepněte na Povolit.">
 <!ENTITY noscriptWebAddress "Adresa webové stránky:">
 <!ENTITY noscriptAllow "Povolit">
diff --git a/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd b/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
index ddc001c..ab1dfef 100644
--- a/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opsiynau">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opsiynau NoScript">
-<!ENTITY noscriptAbout "Yngylch NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Yngylch NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Cewch enwi pa wefannau sy'n cael rhedeg sgriptiau. Teipiwch gyfeiriad neu barth (e.e. "http://www.site.com" neu "site.com") y safle rydych eisiau ei ganiatau ac wedyn cliciwch Caniatau.">
 <!ENTITY noscriptWebAddress "Cyfeiriad wefan">
 <!ENTITY noscriptAllow "Caniatau">
diff --git a/chrome/noscript.jar!/locale/da/noscript/noscript.dtd b/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
index 54a3e6b..0581516 100644
--- a/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Indstillinger…">
 <!ENTITY noscriptOptions.accesskey "I">
 <!ENTITY noscriptOptionsLong "NoScript Indstillinger">
-<!ENTITY noscriptAbout "Om NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Om NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Du kan angive hvilke websteder der må udføre scripts. Indtast adresse eller domæne (f.eks. "http://www.site.com" eller "site.com") på det websted du ønsker at tillade og klik på Tillad.">
 <!ENTITY noscriptWebAddress "Webstedets adresse:">
 <!ENTITY noscriptAllow "Tillad">
diff --git a/chrome/noscript.jar!/locale/de/noscript/noscript.dtd b/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
index dddd500..4e83bb5 100644
--- a/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Einstellungen…">
 <!ENTITY noscriptOptions.accesskey "E">
 <!ENTITY noscriptOptionsLong "NoScript - Einstellungen">
-<!ENTITY noscriptAbout "Über NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Über NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Sie können festlegen, welchen Websites Sie das Ausführen von Skripten erlauben möchten. Geben Sie bitte die exakte Adresse oder die Domain der Website ein (z.B. "http://www.site.com" oder "site.com"), für die Sie dies zulassen möchten, und klicken Sie dann auf "Erlauben".">
 <!ENTITY noscriptWebAddress "Adresse der Website:">
 <!ENTITY noscriptAllow "Erlauben">
diff --git a/chrome/noscript.jar!/locale/el/noscript/noscript.dtd b/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
index 837d833..36bc54d 100644
--- a/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Επιλογές">
 <!ENTITY noscriptOptions.accesskey "Ε">
 <!ENTITY noscriptOptionsLong "Επιλογές NoScript">
-<!ENTITY noscriptAbout "Περί NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Περί NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Μπορείτε να καθορίσετε για ποιους ιστότοπους θα επιτρέπεται η εκτέλεση σεναρίων εντολών. Πληκτρολογήστε τη διεύθυνση τομέα (πχ. "http://www.site.com" or "site.com") του ιστότοπου που θέλετε και μετά κάντε κλικ στο «Να επιτρέπεται»">
 <!ENTITY noscriptWebAddress "Διεύθυνση ιστότοπου">
 <!ENTITY noscriptAllow "Να επιτρέπεται">
diff --git a/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd b/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
index a9bdd37..fb1dd01 100644
--- a/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "About NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd b/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
index 17d2791..952ae4f 100644
--- a/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "About NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd b/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
index 2f3ea22..5cb033a 100644
--- a/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcioj…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcioj de NoScript">
-<!ENTITY noscriptAbout "Pri NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Pri NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Vi povas specifi, kiuj ttt-ejoj rajtu plenumigi skriptojn. Entajpu la adreson aŭ la domajnonomon (ekz. “http://www.retejo.org” aŭ “retejo.org”) de la ttt-ejo, kiun vi volas rajtigi, kaj poste alklaku “Rajtigi”.">
 <!ENTITY noscriptWebAddress "Adreso de retpaĝaro:">
 <!ENTITY noscriptAllow "Rajtigi">
diff --git a/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
index 9678d58..1db8bde 100644
--- a/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opciones…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opciones de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Puede especificar a cuáles sitios web le permitirá ejecutar scripts. Escriba la dirección o el dominio (por ejemplo, "http://www.sitio.com" o "sitio.com") del sitio y luego haga clic en Permitir.">
 <!ENTITY noscriptWebAddress "Dirección del sitio web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
index 29ee11c..82b99de 100644
--- a/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opciones de NoScript">
-<!ENTITY noscriptAbout "About NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "About NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
index 3c2c86a..53ae74c 100644
--- a/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opciones…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Configuración de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Aquí puede especificar las páginas web a las que va a permitir ejecutar código JavaScript. Escriba la dirección de la web que quiera incluir (ej. "http://www.paginaweb.com" o "paginaweb.com") y después pulse "Permitir".">
 <!ENTITY noscriptWebAddress "Dirección de la página web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd b/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
index d8dcecf..c3e87b3 100644
--- a/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Sätted…">
 <!ENTITY noscriptOptions.accesskey "S">
 <!ENTITY noscriptOptionsLong "NoScripti sätted">
-<!ENTITY noscriptAbout "Täpsemalt lisast NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Täpsemalt lisast NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Sa saad määrata, millistel veebilehtedel lubatakse skripte käivitada. Kirjuta veebilehe aadress või domeeni, mida soovid lubada (nt "http://www.site.com" või "site.com") ja klõpsa Luba nuppu">
 <!ENTITY noscriptWebAddress "Veebilehe aadress:">
 <!ENTITY noscriptAllow "Luba">
diff --git a/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd b/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
index 431b48b..681607a 100644
--- a/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Aukerak:">
 <!ENTITY noscriptOptions.accesskey "A">
 <!ENTITY noscriptOptionsLong "NoScript aukerak">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22-eri buruz:">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1-eri buruz:">
 <!ENTITY noscriptPermissionsText "Zein webgunek script-ak exekuta ditzakeen zehaztu dezakezu. Idatzi script-ak erabiltzea onartzea nahi duzun domeinuaren izena (adib. "http://www.gunea.org" or "gunea.org") eta Onartu sakatu.">
 <!ENTITY noscriptWebAddress "Webgunearen helbidea:">
 <!ENTITY noscriptAllow "Onartu">
diff --git a/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
index a3a8480..0d75357 100644
--- a/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "تنظیمات...">
 <!ENTITY noscriptOptions.accesskey "ت">
 <!ENTITY noscriptOptionsLong "تنظیمات NoScript">
-<!ENTITY noscriptAbout "درباره NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "درباره NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "شما می توانید سایت هایی را که اجازه اجرای اسکریپت دارند را مشخص کنید.آدرس سایت یا نام دامنه را وارد کنید.(به عنوان مثال "http://www.site.com" یا "site.com")">
 <!ENTITY noscriptWebAddress "آدرس وب سایت :">
 <!ENTITY noscriptAllow "اجازه دادن">
diff --git a/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
index 5525d9f..432096d 100644
--- a/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Asetukset…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript asetukset">
-<!ENTITY noscriptAbout "Tietoja NoScript 2.6.9.22istä…">
+<!ENTITY noscriptAbout "Tietoja NoScript 2.6.9.23rc1istä…">
 <!ENTITY noscriptPermissionsText "Voit määrittää verkkosivut joiden sallitaan suorittaa scriptejä. Kirjoita verkko-osoite tai verkkonimi (esim. "http://www.site.com" tai "site.com") jonka haluat sallia ja paina Salli.">
 <!ENTITY noscriptWebAddress "Verkkosivun osoite:">
 <!ENTITY noscriptAllow "Salli">
diff --git a/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
index 3245b42..3b6107b 100644
--- a/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Options de NoScript">
-<!ENTITY noscriptAbout "À propos de NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "À propos de NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Il est possible de spécifier quels sites Web sont autorisés à exécuter des scripts. Saisissez l'adresse exacte du site que vous désirez autoriser puis cliquez sur Autoriser.">
 <!ENTITY noscriptWebAddress "Adresse du site Web :">
 <!ENTITY noscriptAllow "Autoriser">
diff --git a/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd b/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
index 81b335b..89e02a8 100644
--- a/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcións...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcións de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Acerca de NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Podes especificar que páxinas web poden executar scripts. Teclea o enderezo ou o dominio (por exemplo "http://www.paxina.com" ou "paxina.com") do sitio que queres autorizar e despois preme en "Permitir".">
 <!ENTITY noscriptWebAddress "Enderezo web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd b/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
index 64adc4b..a033c17 100644
--- a/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "הגדרות...">
 <!ENTITY noscriptOptions.accesskey "">
 <!ENTITY noscriptOptionsLong "NoScript הגדרות של">
-<!ENTITY noscriptAbout "אודות NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "אודות NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "ציין אילו אתרים יכולים לקבל היתר להפעלת קבצי Script. הקלד את כתובת האתר או את שם התחום (כגון: "http://www.site.com" או "site.com") ולאחר מכן לחץ על התר.">
 <!ENTITY noscriptWebAddress "כתובת/תחום:">
 <!ENTITY noscriptAllow "התר">
diff --git a/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
index 0554106..df97261 100644
--- a/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcije...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Opcije">
-<!ENTITY noscriptAbout "O NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "O NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Možete odrediti koje web stranice imaju dopuštenje za izvođenje skripti. Upišite adresu ili domenu (npr. "http://www.stranica.hr" ili "stranica.hr") stranice kojoj želite dopustiti i kliknite na Dopusti.">
 <!ENTITY noscriptWebAddress "Adresa web stranice:">
 <!ENTITY noscriptAllow "Dopusti">
diff --git a/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
index d395759..34c51f9 100644
--- a/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcije…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcije NoScript">
-<!ENTITY noscriptAbout "Wo NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Wo NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Móžeće podać, kotre websydła smědźa skripty wuwjesć. Zapisajće adresu abo domenu  (na př. "http://www.site.com" abo "site.com") websydła, kotremuž chceće to dowolić a klikńće potom na "Dowolić".">
 <!ENTITY noscriptWebAddress "Adresa websydła:">
 <!ENTITY noscriptAllow "Dowolić">
diff --git a/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
index 1988fbf..b3265ee 100644
--- a/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Beállítások…">
 <!ENTITY noscriptOptions.accesskey "B">
 <!ENTITY noscriptOptionsLong "A NoScript beállításai">
-<!ENTITY noscriptAbout "A NoScript 2.6.9.22 névjegye">
+<!ENTITY noscriptAbout "A NoScript 2.6.9.23rc1 névjegye">
 <!ENTITY noscriptPermissionsText "Megadhatja, hogy mely webhelyek számára engedélyezi a parancsfájlok futtatását. Írja be az engedélyezni kívánt webhely címét vagy tartomány nevét (pl. "http://www.webhely.hu" vagy "webhely.hu"), majd kattintson az Engedélyezés gombra.">
 <!ENTITY noscriptWebAddress "A webhely címe:">
 <!ENTITY noscriptAllow "Engedélyezés">
diff --git a/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd b/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
index bdf4310..ae552b8 100644
--- a/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Pilihan...">
 <!ENTITY noscriptOptions.accesskey "P">
 <!ENTITY noscriptOptionsLong "Pilihan NoScript">
-<!ENTITY noscriptAbout "Tentang NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Tentang NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Anda dapat menentukan situs web mana yang diijinkan menjalankan naskah. Masukkan alamat atau domain (contoh: "http://www.site.com" atau "site.com") yang akan diberi ijin kemudian klik Ijinkan.">
 <!ENTITY noscriptWebAddress "Alamat situs web:">
 <!ENTITY noscriptAllow "Ijinkan">
diff --git a/chrome/noscript.jar!/locale/it/noscript/noscript.dtd b/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
index 026a994..e84d168 100644
--- a/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opzioni…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opzioni NoScript">
-<!ENTITY noscriptAbout "Informazioni su NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Informazioni su NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Qui si possono indicare i siti per i quali l'esecuzione degli script è consentita. Digitare l'indirizzo o il dominio (es. "http://www.sito.com" oppure "sito.com")  e fare clic su Permetti.">
 <!ENTITY noscriptWebAddress "Indirizzo del sito:">
 <!ENTITY noscriptAllow "Permetti">
diff --git a/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
index 1a0c882..f56b2df 100644
--- a/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "オプション...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript オプション">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22について...">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1について...">
 <!ENTITY noscriptPermissionsText "JavaScriptを許可するサイトを指定する事ができます。許可したいサイトのアドレスかドメインを入力して、ボタンを押してください。(例: "http://www.site.com" または "site.com")">
 <!ENTITY noscriptWebAddress "ウェブサイトのアドレス:">
 <!ENTITY noscriptAllow "許可する">
diff --git a/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd b/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
index 01cadbd..277a7a2 100644
--- a/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Баптаулары">
 <!ENTITY noscriptOptions.accesskey "Б">
 <!ENTITY noscriptOptionsLong "NoScript баптаулары">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22 туралы...">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1 туралы...">
 <!ENTITY noscriptPermissionsText "Қай сайттарға JavaScript орындауға рұқсат екенін көрсете аласыз. Рұқсат етілетін сайттың домен адресін енгізіңіз (мысалы, "http://www.site.com" немесе "site.com"), содан кейін Рұқсат ету басыңыз.">
 <!ENTITY noscriptWebAddress "Веб-сайт адресі:">
 <!ENTITY noscriptAllow "Рұқсат ету">
diff --git a/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd b/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
index 17319c8..2530f18 100644
--- a/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "About NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
index 43a4deb..771cbef 100644
--- a/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "옵션...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 옵션">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22 정보...">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1 정보...">
 <!ENTITY noscriptPermissionsText "스크립트 실행을 허용할 웹 사이트를 지정할 수 있습니다. 스크립트를 허용할 사이트의 주소나 도메인 (예를 들면, "http://www.site.com" 또는 "site.com")을 입력한 후 [허용] 버튼을 클릭합니다.">
 <!ENTITY noscriptWebAddress "웹 사이트 주소">
 <!ENTITY noscriptAllow "허용">
diff --git a/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd b/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
index 7934349..adfe523 100644
--- a/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Nuostatos...">
 <!ENTITY noscriptOptions.accesskey "N">
 <!ENTITY noscriptOptionsLong "NoScript nuostatos">
-<!ENTITY noscriptAbout "Apie NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Apie NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Jūs galite nurodyti, kurioms interneto svetainėms suteikiamas leidimas vykdyti programinius kodus. Įveskite adresą arba domeną (pvz., "http://www.svetaine.lt" arba "svetaine.lt") svetainės, kuriai norite suteikti leidimą ir spauskite Leisti.">
 <!ENTITY noscriptWebAddress "Interneto svetainės adresas:">
 <!ENTITY noscriptAllow "Leisti">
diff --git a/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd b/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
index dc4674e..a7dcca4 100644
--- a/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Опции...">
 <!ENTITY noscriptOptions.accesskey "О">
 <!ENTITY noscriptOptionsLong "NoScript Опции">
-<!ENTITY noscriptAbout "За NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "За NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Можете да ги назначите страните, на кои што скриптите ќе бидат дозволени. Напишете ја дозволената адреса (на пример http://www.site.com или site.com) и кликнете „Дозволи“">
 <!ENTITY noscriptWebAddress "Адреса на дозволената веб страна:">
 <!ENTITY noscriptAllow "Дозволи">
diff --git a/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
index 22e1bca..148e601 100644
--- a/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Tetapan...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Tetapan NoScript">
-<!ENTITY noscriptAbout "Tentang NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Tentang NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Anda boleh menentukan laman web yang anda benarkan skripnya diproses. Taipkan alamat atau domain(contoh:"http://www.tapak.com" atau "tapak.com") laman web yang diingini dan klik Benarkan">
 <!ENTITY noscriptWebAddress "Alamat laman web:">
 <!ENTITY noscriptAllow "Benarkan">
diff --git a/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd b/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
index d162e81..7053d05 100644
--- a/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Innstillinger">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Innstillinger">
-<!ENTITY noscriptAbout "Om NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Om NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Du kan spesifisere hvilke websider som har tillatelse til å kjøre scritper. Skriv inn adresse, eller domene (F.eks: "http://www.side.no", eller &quotside.no") du ønsker å gi tillatelse til, og klikk Tillat.">
 <!ENTITY noscriptWebAddress "Webadresse:">
 <!ENTITY noscriptAllow "Tillat">
diff --git a/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd b/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
index 71c54db..48d11d8 100644
--- a/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opties...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript opties">
-<!ENTITY noscriptAbout "Over NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Over NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Webadressen in deze lijst hebben toestemming om JavaScript te gebruiken. Type het adres of domein in (bijv. "http://www.site.com" of "site.com") van de door u toegestane site; klik daarna op Toestaan.">
 <!ENTITY noscriptWebAddress "Webadres:">
 <!ENTITY noscriptAllow "Toestaan">
diff --git a/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
index 76879cc..3326a4e 100644
--- a/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Ustawienia">
 <!ENTITY noscriptOptions.accesskey "U">
 <!ENTITY noscriptOptionsLong "NoScript – ustawienia">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22 – informacje">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1 – informacje">
 <!ENTITY noscriptPermissionsText "Tutaj można określić witryny internetowe, które będą mogły uruchamiać skrypty. Proszę wprowadzić adres lub domenę witryny (np: „http://www.witryna.pl” lub „witryna.pl”) i nacisnąć przycisk Pozwól.">
 <!ENTITY noscriptWebAddress "Adres witryny:">
 <!ENTITY noscriptAllow "Pozwól">
diff --git a/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
index a3ee3d9..1462c36 100644
--- a/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opções">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opções do NoScript">
-<!ENTITY noscriptAbout "Sobre o NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "Sobre o NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "Você pode especificar os sites que podem executar JavaScripts. Escreva o endereço ou o domínio (ex "http://www.site.com" ou "site.com") do site que deseja permitir e depois clique em Permitir.">
 <!ENTITY noscriptWebAddress "Endereço:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
index e59a03a..86674a9 100644
--- a/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opções">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opções do NoScript">
-<!ENTITY noscriptAbout "Sobre o NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Sobre o NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Pode especificar os sítios que podem executar scripts. Escreva o endereço ou o domínio (ex: "http://www.sitio.com" ou "sitio.com") do sítio que deseja permitir e depois pressione em Permitir.">
 <!ENTITY noscriptWebAddress "Endereço:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
index 04704a5..e8211f2 100644
--- a/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opțiuni...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opțiuni NoScript">
-<!ENTITY noscriptAbout "Despre NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Despre NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Puteți specifica saiturile cărora li se permite să execute scripturi. Scrieți adresa sau domeniul paginii (exemplu: „http://www.sait.ro“ sau „sait.ro“), apoi apăsați pe butonul „Permite“.">
 <!ENTITY noscriptWebAddress "Adresă sait:">
 <!ENTITY noscriptAllow "Permite">
diff --git a/chrome/noscript.jar!/locale/ru-RU/noscript/about.properties b/chrome/noscript.jar!/locale/ru-RU/noscript/about.properties
index ad0c2c9..b1ca739 100644
--- a/chrome/noscript.jar!/locale/ru-RU/noscript/about.properties
+++ b/chrome/noscript.jar!/locale/ru-RU/noscript/about.properties
@@ -1,7 +1,7 @@
-extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Экстра защита для Firefox: С помощью NoScript вы сможете разрешать исполнение JavaScript, Java (и других плагинов) только для доменов, установленных вами (например, ваш веб-сайт). Белый список, базирующийся на принципе упреждающего блокирования, позволяет предотвратить использование уязвимостей (известных и ещё не известных!) без потери функциональности… Эксперты соглашаются: Firefox действительно безопаснее с NoScript :-)
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Дополнительная защита для Firefox: С помощью NoScript вы сможете разрешать исполнение JavaScript, Java (и других плагинов) только для доменов, установленных вами (например, ваш веб-сайт). Белый список, базирующийся на принципе упреждающего блокирования, позволяет предотвратить использование уязвимостей (известных и ещё не известных!) без потери функциональности… Эксперты соглашаются: Firefox действительно безопаснее с NoScript :-)
 aboutTitle=О расширении %S
 extensionContributors=Участники:
-extensionContributors.tip=Люди которые помогали улучшать расширение
+extensionContributors.tip=Люди, которые помогали улучшать расширение
 extensionCreatorLabel=Автор:
 changelog=История версий
 changelog.tip=Просмотреть историю версий NoScript
diff --git a/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.dtd
index ef857c8..042658e 100644
--- a/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.dtd
@@ -2,7 +2,7 @@
 <!ENTITY noscriptOptions.accesskey "а">
 <!ENTITY noscriptOptionsLong "Настройки NoScript">
 <!ENTITY noscriptAbout "О расширении">
-<!ENTITY noscriptPermissionsText "Вы можете устанавливать каким веб-сайтам будет разрешено выполнять код JavaScript. Введите адрес или домен (например «http://www.site.com» или «site.com») сайта которому вы желаете разрешить исполнение JavaScript в текстовом поле ниже, а затем нажмите «Разрешить».">
+<!ENTITY noscriptPermissionsText "Вы можете устанавливать каким веб-сайтам будет разрешено выполнять код JavaScript. Введите адрес или домен (например «http://www.site.com» или «site.com») сайта, которому вы желаете разрешить исполнение JavaScript в текстовом поле ниже, а затем нажмите «Разрешить».">
 <!ENTITY noscriptWebAddress "Адрес веб-сайта:">
 <!ENTITY noscriptAllow "Разрешить">
 <!ENTITY noscriptAllow.accesskey "е">
@@ -30,7 +30,7 @@
 <!ENTITY noscriptExport "Экспорт">
 <!ENTITY noscriptExport.accesskey "к">
 <!ENTITY noscriptNotify "Отображать сообщения о заблокированных скриптах">
-<!ENTITY noscriptNotify.bottom "Располагать сообщения снизу экрана">
+<!ENTITY noscriptNotify.bottom "Располагать сообщения внизу экрана">
 <!ENTITY noscriptSound.choose "Обзор">
 <!ENTITY noscriptSound.choose.accesskey "о">
 <!ENTITY noscriptSound.play "Прослушать">
@@ -38,7 +38,7 @@
 <!ENTITY noscriptSound.reset "Сброс">
 <!ENTITY noscriptSound.reset.accesskey "б">
 <!ENTITY noscriptAdvanced "Дополнительно">
-<!ENTITY noscriptAdditionalPermissions "Дополнительные возможности для доверяемых сайтов">
+<!ENTITY noscriptAdditionalPermissions "Дополнительные возможности для доверенных сайтов">
 <!ENTITY noscriptAllowClipboard "Расширенные копирование/вставка из внешнего буфера обмена">
 <!ENTITY noscriptAdditionalRestrictions "Дополнительные ограничения для ненадёжных сайтов">
 <!ENTITY noscriptPlugins "Плагины">
@@ -47,7 +47,7 @@
 <!ENTITY noscriptForbidXSLT "Запретить отображение элементов XSLT">
 <!ENTITY noscriptForbidSilverlight "Запретить отображение элементов Microsoft® Silverlight™">
 <!ENTITY noscriptForbidIFrames "Запретить отображение элементов <IFRAME>">
-<!ENTITY noscriptForbidFrames "Запретить отображение элементов <FRAMES>">
+<!ENTITY noscriptForbidFrames "Запретить отображение элементов <FRAME>">
 <!ENTITY noscriptForbidFonts "Запретить @font-face">
 <!ENTITY noscriptForbidWebGL "Запретить WebGL">
 <!ENTITY noscriptForbidMedia "Запретить <AUDIO> / <VIDEO>">
@@ -60,12 +60,12 @@
 <!ENTITY noscriptShowPlaceholder "Выделять заблокированные элементы значком с рамкой">
 <!ENTITY noscriptTruncateTitle "Отсекать слишком длинные заголовки веб-сайтов">
 <!ENTITY noscriptFixLinks "Применять алгоритм исправления JavaScript-ссылок">
-<!ENTITY noscriptAllowBookmarks "Разрешать выполнение JavaScript всем веб-сайтам из закладок">
-<!ENTITY noscriptAllowViaBookmarks "Разрешать выполнение JavaScript всем веб-сайтам из закладок">
+<!ENTITY noscriptAllowBookmarks "Разрешать JavaScript документам верхнего уровня сайтов, открываемых через закладки">
+<!ENTITY noscriptAllowViaBookmarks "Разрешать JavaScript документам верхнего уровня сайтов, открываемых через закладки">
 <!ENTITY noscriptAllowPing "Разрешить веб-сайту использовать параметр <A PING…>">
 <!ENTITY noscriptAllowLocalLinks "Разрешить локальные ссылки">
 <!ENTITY noscriptForbidPing "Запретить веб-сайту использовать параметр  <A PING…>">
-<!ENTITY noscriptForbidMetaRefresh "Запретить META перенаправления внутри элементов <noscript>">
+<!ENTITY noscriptForbidMetaRefresh "Запретить META перенаправления внутри элементов <NOSCRIPT>">
 <!ENTITY noscriptForbidMetaRefresh.accesskey "а">
 <!ENTITY noscriptNotifyMeta "Показывать сообщения о заблокированных META перенаправлениях">
 <!ENTITY noscriptNotifyMeta.accesskey "ы">
@@ -85,10 +85,10 @@
 <!ENTITY noscriptPolicies "Политики">
 <!ENTITY noscriptDefaultPolicies "Политики по умолчанию">
 <!ENTITY noscriptSitePolicies "Специальные политики для сайтов">
-<!ENTITY noscriptNselNever "Скрывать элементы <noscript>">
-<!ENTITY noscriptNselForce "Показывать элемент <noscript> который следует за заблокированным <SCRIPT>">
-<!ENTITY noscriptAutoAllowTopLevel "Временно разрешать базовым доменам 2-го уровня по умолчанию">
-<!ENTITY noscriptDescription "Экстра защита для Firefox: NoScript позволяет разрешать исполнение JavaScript, Java (и других плагинов) только доменам, которым доверяете (например, ваш веб-сайт). Белый список, основанный на принципе упреждающего блокирования, позволяет предотвратить использование уязвимостей (известных и ещё неизвестных!) без потери функциональности… Эксперты соглашаются: Firefox действительно безопаснее с NoScript :-)">
+<!ENTITY noscriptNselNever "Скрывать элементы <NOSCRIPT>">
+<!ENTITY noscriptNselForce "Показывать элемент <NOSCRIPT> который следует за заблокированным <SCRIPT>">
+<!ENTITY noscriptAutoAllowTopLevel "Временно разрешать документам верхнего уровня по умолчанию">
+<!ENTITY noscriptDescription "Дополнительная защита для Firefox: NoScript позволяет разрешать исполнение JavaScript, Java (и других плагинов) только доменам, которым доверяете (например, ваш веб-сайт). Белый список, основанный на принципе упреждающего блокирования, позволяет предотвратить использование уязвимостей (известных и ещё не известных!) без потери функциональности… Эксперты соглашаются: Firefox действительно безопаснее с NoScript :-)">
 <!ENTITY noscriptOptBlockCssScanners "Блокировать CSS-сканеры">
 <!ENTITY noscriptOptFilterXGet "Фильтровать запросы, подозреваемые в XSS">
 <!ENTITY noscriptOptFilterXPost "Заменять XSS POST-запросы на GET-запросы без данных">
@@ -101,7 +101,7 @@
 <!ENTITY noscriptUnsafeReload "Небезопасное обновление">
 <!ENTITY noscriptUnsafeReload.accesskey "е">
 <!ENTITY noscriptXssExceptions "Исключения анти-XSS защиты">
-<!ENTITY noscriptXssExceptions.description "Объекты, которые соответствуют этим маскам, НЕ будет защищаться против XSS.">
+<!ENTITY noscriptXssExceptions.description "Объекты, которые соответствуют этим маскам, НЕ будут защищаться против XSS.">
 <!ENTITY noscriptMatchSample "Пример шаблона:">
 <!ENTITY noscriptReset "Сброс">
 <!ENTITY noscriptReset.accesskey "о">
@@ -115,9 +115,9 @@
 <!ENTITY noscriptExceptions "Исключения…">
 <!ENTITY noscriptBlockedObjects "Заблокированные объекты">
 <!ENTITY noscriptAlwaysBlockUntrustedContent "Блокировать любой объект с недоверенных сайтов">
-<!ENTITY noscriptTempAllowPage "Временно разрешить на этой странице">
+<!ENTITY noscriptTempAllowPage "Временно разрешить все скрипты на этой странице">
 <!ENTITY noscriptTempAllowPage.accesskey "о">
-<!ENTITY noscriptAllowPage "Разрешить всё на этой странице">
+<!ENTITY noscriptAllowPage "Разрешить все скрипты на этой странице">
 <!ENTITY noscriptAllowPage.accesskey "а">
 <!ENTITY noscriptTempToPerm "Сохранить установленные разрешения">
 <!ENTITY noscriptTempToPerm.accesskey "о">
@@ -126,15 +126,15 @@
 <!ENTITY noscriptHttpsFaq.accesskey "а">
 <!ENTITY noscriptHttps.behavior "Поведение">
 <!ENTITY noscriptHttps.cookies "Cookies">
-<!ENTITY noscriptHttps.description "Запрещать активное веб-содержимое за исключением защищённых (HTTPS) соединений:">
+<!ENTITY noscriptHttps.description "Запрещать активное веб-содержимое, за исключением защищённых (HTTPS) соединений:">
 <!ENTITY noscriptHttps.never "Никогда">
 <!ENTITY noscriptHttps.proxy "При использовании прокси (рекомендуется Tor)">
 <!ENTITY noscriptHttps.always "Всегда">
-<!ENTITY noscriptHttpsForced "Заставлять указанным сайтам использовать защищённое (HTTPS) соединение:">
+<!ENTITY noscriptHttpsForced "Заставлять указанные сайты использовать защищённое (HTTPS) соединение:">
 <!ENTITY noscriptHttpsForcedExceptions "Не принуждать использовать защищённое (HTTPS) соединение для сайтов:">
 <!ENTITY noscriptSecureCookies "Автоматическая система управления безопасностью cookies">
-<!ENTITY noscriptSecureCookiesForced "Использовать шифрование для всех cookies устанавливаемых через HTTPS со следующих сайтов:">
-<!ENTITY noscriptSecureCookiesExceptions "Игнорировать небезопасные cookies устанавливаемые через HTTPS со следующих сайтов:">
+<!ENTITY noscriptSecureCookiesForced "Использовать шифрование для всех cookies, устанавливаемых через HTTPS со следующих сайтов:">
+<!ENTITY noscriptSecureCookiesExceptions "Игнорировать небезопасные cookies, устанавливаемые через HTTPS со следующих сайтов:">
 <!ENTITY noscriptClearClickTitle "Предупреждения ClearClick">
 <!ENTITY noscriptClearClickHeader "Возможно Clickjacking / Попытка изменения UI">
 <!ENTITY noscriptClearClickDescription "NoScript пресёк выполнение операции с частично скрытым элементом. Нажмите на изображения чтобы увидеть разницу.">
@@ -148,8 +148,8 @@
 <!ENTITY noscriptEmbeddings "Встроенные объекты">
 <!ENTITY noscriptPrev "Предыдущий">
 <!ENTITY noscriptNext "Следующий">
-<!ENTITY noscriptFrameOptErr.title "Это содержимое не может быть отображено в фрейме">
-<!ENTITY noscriptFrameOptErr.desc "Для защиты вашей безопасности, владелец этого содержимого не разрешил отображение во фрейме">
+<!ENTITY noscriptFrameOptErr.title "Это содержимое не может быть отображено во фрейме">
+<!ENTITY noscriptFrameOptErr.desc "Для вашей безопасности владелец этого содержимого не разрешил отображение во фрейме">
 <!ENTITY noscriptFrameOptErr.link "Щёлкните для открытия содержимого в новом окне">
 <!ENTITY noscriptBookmarkSync "Создать резервную копию настроек в закладках для лёгкой синхронизации">
 <!ENTITY noscriptShowReleaseNotes "Показывать примечания к релизу при обновлениях">
@@ -173,7 +173,7 @@
 <!ENTITY noscriptEF.add "Новый фильтр…">
 <!ENTITY noscriptEF.executable "Исполняемый файл:">
 <!ENTITY noscriptEF.browse "Обзор…">
-<!ENTITY noscriptEF.contentType "Content type (MIME) подлежащий фильтрации (точное совпадение или регулярное выражение):">
+<!ENTITY noscriptEF.contentType "Content type (MIME), подлежащий фильтрации (точное совпадение или регулярное выражение):">
 <!ENTITY noscriptEF.exceptions "Не фильтровать объекты с этих сайтов:">
 <!ENTITY noscriptEF.remove "Удалить">
 <!ENTITY noscriptPreset "Уровень защиты">
@@ -181,11 +181,11 @@
 <!ENTITY noscriptPreset.low "Легкое начало (чёрный список + веб-защита)">
 <!ENTITY noscriptPreset.medium "Стандартный (белый список + веб-защита)">
 <!ENTITY noscriptPreset.high "Осадный (на полную катушку)">
-<!ENTITY noscript.hoverUI "Открывать меню разрешению при наведении мыши на значок">
+<!ENTITY noscript.hoverUI "Открывать меню разрешений при наведении мыши на значок">
 <!ENTITY noscriptDonate "Пожертвовать">
 <!ENTITY noscriptDonate.accesskey "в">
-<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
-<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
-<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
-<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
-<!ENTITY noscriptPermanentInPrivate "Permanent "Allow" commands in private windows">
+<!ENTITY noscriptAutoReload.currentTab "Обновлять только активную вкладку">
+<!ENTITY noscriptCascadePermissions "Каскадное разрешение скриптов третьей стороны">
+<!ENTITY noscriptRestrictSubdocScripting "Запретить скрипты из белого списка в субдокументах не из белого списка">
+<!ENTITY noscriptGlobalHttpsWhitelist "Разрешить все HTTPS скрипты в HTTPS документах">
+<!ENTITY noscriptPermanentInPrivate ""Разрешить [...]" (постоянно) в приватном режиме">
diff --git a/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.properties b/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.properties
index 16af2bd..3ad15d5 100644
--- a/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.properties
+++ b/chrome/noscript.jar!/locale/ru-RU/noscript/noscript.properties
@@ -1,5 +1,5 @@
 allowGlobal=Разрешить JavaScript полностью (опасно)
-forbidGlobal=Запретить JavaScript полностью (рекомендуется)
+forbidGlobal=Отменить полное разрешение (рекомендуется)
 allowLocal=Разрешить %S
 allowTemp=Временно разрешить %S
 forbidLocal=Запретить %S
@@ -15,7 +15,7 @@ alwaysAsk=Всегда спрашивать подтверждение
 notifyHide=Скрывать сообщения после %S секунд
 trust=Доверять %S
 distrust=Не доверять %S
-untrustedOrigin=как источник недоверия
+untrustedOrigin=как недоверенный источник
 xss.notify.generic=NoScript отфильтровал потенциальную XSS-атаку (попытку межсайтового скриптинга) с адреса %S. Технические подробности занесены в консоль.
 xss.notify.showConsole=Открыть консоль…
 xss.notify.showConsole.accessKey=о
@@ -23,7 +23,7 @@ xss.reason.filterXGet=Отфильтрован подозрительный за
 xss.reason.filterXGetRef=Отфильтрован подозрительный источник запроса («referer»): URL: [%1$S] со страницы [%2$S]. Отфильтрованный адрес: [%3$S]
 xss.reason.filterXPost=Отфильтрована подозрительная загрузка с [%2$S] к [%1$S]: запрос преобразован в GET-запрос для скачивания.
 unsafeReload.warning=Небезопасная подозрительная перезагрузка\n\n%1$S [%2$S]\n\nОт [%3$S]\n\nNoScript НЕ сможет защитить данный запрос!\n
-metaRefresh.notify=NoScript заблокировал <META>-перенаправление внутри элемента <NOSCRIPT>: %S за %S сек.
+metaRefresh.notify=NoScript заблокировал <META> перенаправление внутри элемента <NOSCRIPT>: %S за %S сек.
 metaRefresh.notify.follow=Выполнить перенаправление
 metaRefresh.notify.follow.accessKey=о
 notify.options=Настройки
@@ -39,7 +39,7 @@ ABE.syntaxError=Синтаксическая ошибка в наборе пра
 ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
 allowFrom=Разрешать всё с %S
 allowTempFrom=Временно разрешить все с %S
-siteInfo.confirm=Вы собираетесь узнать информацию о сайте «%1$S»\nотправив запрос к %2$S.\nПродолжить?
+siteInfo.confirm=Вы собираетесь узнать информацию о сайте «%1$S»,\nотправив запрос к %2$S.\nПродолжить?
 siteInfo.tooltip=Middle-click или shift+click для информации о сайте...
 ef.activate=Фильтр %S
 ef.options=%S настройки...
@@ -47,9 +47,9 @@ ef.newName=Введите название нового фильтра:
 ef.locateExe=Выберите исполняемый файл для фильтра %S
 disable=Отключить %S
 disable.accessKey=ь
-allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
+allowed.glb-emb=Все скрипты разрешены, но некоторые встроенные объекты заблокированы
 removal.title=Security Downgrade Warning
-removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
+removal.message=Отключая или удаляя NoScript, вы отказываетесь от всех мер защиты, предоставляемых NoScript.\n\nЕсли вы просто устали от обработки разрешений скриптов для каждого сайта, то есть безопасный вариант.\n\nNoScript может прекратить блокировать скрипты, за исключением помеченных вами как ненадежные, в то же время применяя самые передовые контрмеры против XSS, CSRF, Clickjacking и других веб-угроз.\n\nВы действительно хотите удалить всю защиту NoScript?\n
 removal.no=No, just stop blocking scripts
 removal.yes=Yes, remove ALL protections
 incompatibleOptions.title=Incompatible Options Warning
diff --git a/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
index b6c6506..ddfcddc 100644
--- a/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Možnosti...">
 <!ENTITY noscriptOptions.accesskey "M">
 <!ENTITY noscriptOptionsLong "NoScript – Možnosti">
-<!ENTITY noscriptAbout "O rozšírení NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "O rozšírení NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Môžete určiť, ktoré webové stránky majú povolené spúšťať JavaScript. Zadajte adresu alebo doménu (napríklad "http://www.site.com" alebo "site.com") stránky, ktorú chcete povoliť, a potom kliknite na tlačidlo Povoliť.">
 <!ENTITY noscriptWebAddress "Adresa webovej stránky:">
 <!ENTITY noscriptAllow "Povoliť">
diff --git a/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
index 4250d7f..63b557f 100644
--- a/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Možnosti...">
 <!ENTITY noscriptOptions.accesskey "M">
 <!ENTITY noscriptOptionsLong "NoScript Možnosti">
-<!ENTITY noscriptAbout "O NoScript 2.6.9.22 programu...">
+<!ENTITY noscriptAbout "O NoScript 2.6.9.23rc1 programu...">
 <!ENTITY noscriptPermissionsText "Določite lahko na katerih straneh bo izvajanje skript dovoljeno. Vnesite naslov ali domeno (pr. "http://www.domena.com" or "domena.com") strani, na kateri želite omogočiti izvajanje skript in kliknite Dovoli.">
 <!ENTITY noscriptWebAddress "Naslov strani:">
 <!ENTITY noscriptAllow "Dovoli">
diff --git a/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
index cd0b28a..13fffb0 100644
--- a/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Подешавања...">
 <!ENTITY noscriptOptions.accesskey "П">
 <!ENTITY noscriptOptionsLong "NoScript подешавања">
-<!ENTITY noscriptAbout "О NoScript 2.6.9.22-у">
+<!ENTITY noscriptAbout "О NoScript 2.6.9.23rc1-у">
 <!ENTITY noscriptPermissionsText "Можете да наведете којим веб странама је дозвољено да извршавају скриптове. Унесите адресу или домен (нпр. "http://www.site.com" или "site.com") стране којој желите да дате дозволу и онда кликните Дозволи.">
 <!ENTITY noscriptWebAddress "Адреса веб стране:">
 <!ENTITY noscriptAllow "Дозволи">
diff --git a/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
index 69981c1..145c506 100644
--- a/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Alternativ...">
 <!ENTITY noscriptOptions.accesskey "A">
 <!ENTITY noscriptOptionsLong "NoScript-alternativ">
-<!ENTITY noscriptAbout "Om NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Om NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Ange vilka webbplatser som får köra skript. Skriv webbadressen eller domänen (t ex. "http://www.webbplats.se" eller "webbplats.se") för den webbplats där skript ska tillåtas. Klicka sedan på "Tillåt".">
 <!ENTITY noscriptWebAddress "Sidans adress:">
 <!ENTITY noscriptAllow "Tillåt">
diff --git a/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd b/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
index c7f8d20..1553e12 100644
--- a/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.6.9.22…">
+<!ENTITY noscriptAbout "About NoScript 2.6.9.23rc1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/th/noscript/noscript.dtd b/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
index 12632c4..452b64a 100644
--- a/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "ตัวเลือก...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "ตัวเลือก NoScript">
-<!ENTITY noscriptAbout "เกี่ยวกับ NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "เกี่ยวกับ NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "คุณสามารถกำหนดเว็บไซต์ที่จะอนุญาตดำเนินการสคริปต์ พิมพ์ที่อยู่หรือโดเมน (เช่น "http://www.site.com" หรือ "site.com") ของไซต์ที่คุณต้องการอนุญาตและคลิกอนุญาต">
 <!ENTITY noscriptWebAddress "ที่อยู่เว็บไซต์:">
 <!ENTITY noscriptAllow "อนุญาต">
diff --git a/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd b/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
index 9ccabd1..c9b7e1a 100644
--- a/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Seçenekler">
 <!ENTITY noscriptOptions.accesskey "S">
 <!ENTITY noscriptOptionsLong "NoScript Seçenekleri">
-<!ENTITY noscriptAbout "NoScript 2.6.9.22 Hakkında">
+<!ENTITY noscriptAbout "NoScript 2.6.9.23rc1 Hakkında">
 <!ENTITY noscriptPermissionsText "Hangi web sayfalarında JavaScript'e izni vereceğinizi kolayca seçebilirsiniz. Lütfen adresi tam olarak girin ve 'İzin ver' düğmesine tıklayarak sayfanın JavaScript kullanmasına izin verin.">
 <!ENTITY noscriptWebAddress "Site adresi:">
 <!ENTITY noscriptAllow "İzin ver">
diff --git a/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd b/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
index e2a7d7e..74bf194 100644
--- a/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Tùy chọn">
 <!ENTITY noscriptOptions.accesskey "y">
 <!ENTITY noscriptOptionsLong "Tùy chọn cho NoScript">
-<!ENTITY noscriptAbout "Thông tin về NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "Thông tin về NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "Bạn có thể chỉ định trang web nào được phép chạy script. Gõ địa chỉ hay tên miền (v.d. "http://www.nhaccodien.com" hay "nhaccodien.com") của trang mà bạn muốn cho phép, rồi nhấn Cho phép.">
 <!ENTITY noscriptWebAddress "Địa chỉ của trang web:">
 <!ENTITY noscriptAllow "Cho phép">
diff --git a/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd b/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
index 68c3526..1427dd2 100644
--- a/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "选项...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 选项">
-<!ENTITY noscriptAbout "关于 NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "关于 NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "您可以指定允许执行脚本的网站。请输入您想要允许的网站地址或域名(例如: “http://www.site.com”或者“site.com”)然后单击“允许”。">
 <!ENTITY noscriptWebAddress "网站地址:">
 <!ENTITY noscriptAllow "允许">
diff --git a/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd b/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
index b26f35e..f461f93 100644
--- a/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "選項…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 選項">
-<!ENTITY noscriptAbout "關於 NoScript 2.6.9.22">
+<!ENTITY noscriptAbout "關於 NoScript 2.6.9.23rc1">
 <!ENTITY noscriptPermissionsText "您可以指定允許執行 JavaScript 的網站。輸入您要允許的網址或網域(例如 "http://www.site.com" 或 "site.com"),然後按下允許.">
 <!ENTITY noscriptWebAddress "網址:">
 <!ENTITY noscriptAllow "允許">
diff --git a/components/noscriptService.js b/components/noscriptService.js
index a90dc7d..3ffd45c 100644
--- a/components/noscriptService.js
+++ b/components/noscriptService.js
@@ -5,7 +5,7 @@ const Cc = Components.classes;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-const VERSION = "2.6.9.22";
+const VERSION = "2.6.9.23rc1";
 const SERVICE_CTRID = "@maone.net/noscript-service;1";
 const SERVICE_ID = "{31aec909-8e86-4397-9380-63a59e0c5ff5}";
 const EXTENSION_ID = "{73a6fe31-595d-460b-a920-fcc0f8843232}";
@@ -16,44 +16,7 @@ const SERVICE_CATS = ["app-startup"];
 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 = {};
-
-
-
-function IS_INCLUDED(name) name in _INCLUDED;
-
-function INCLUDE(name) {
-  if (arguments.length > 1)
-    for (var j = 0, len = arguments.length; j < len; j++)
-      INCLUDE(arguments[j]);
-  else if (!(name in _INCLUDED)) {
-    try {
-      _INCLUDED[name] = true;
-      let t = Date.now();
-      LOADER.loadSubScript("chrome://noscript/content/" + name + ".js");
-      // dump((t - TIME0) + " - loaded " + name + " in " + (Date.now() - t) + "\n")
-    } catch(e) {
-      let msg = "INCLUDE " + name + ": " + e + "\n" + e.stack;
-      Cu.reportError(msg);
-      dump(msg + "\n");
-    }
-  }
-}
-
-function LAZY_INCLUDE(name) {
-  if (arguments.length > 1)
-    for (var j = 0, len = arguments.length; j < len; j++)
-      arguments.callee(arguments[j]);
-  else if (!(name in this)) {
-    __defineGetter__(name, function() {
-      delete this[name];
-      if (ns.consoleDump) ns.dump(name + " kickstarted at " + (new Error().stack));
-      INCLUDE(name);
-      return this[name];
-    });
-  }
-}
-
+LOADER.loadSubScript("chrome://noscript/content/loader.js");
 
 const SERVICE_CONSTRUCTOR = function() {
 
@@ -74,7 +37,7 @@ const SERVICE_FACTORY = {
     var i = new SERVICE_CONSTRUCTOR();
     return this._instance = i;
   },
-  
+
   createInstance: function (outer, iid) {
     if (outer != null)
       throw Cr.NS_ERROR_NO_AGGREGATION;
@@ -100,9 +63,9 @@ var Module = {
       compMgr.QueryInterface(Ci.nsIComponentRegistrar
         ).registerFactoryLocation(SERVICE_CID,
         SERVICE_CTRID,
-        SERVICE_CTRID, 
+        SERVICE_CTRID,
         fileSpec,
-        location, 
+        location,
         type);
       const catMan = this.categoryManager;
       for (var j = 0, len = SERVICE_CATS.length; j < len; j++) {
@@ -120,7 +83,7 @@ var Module = {
       } catch(e) {}
     }
   },
-  
+
   unregisterSelf: function(compMgr, fileSpec, location) {
     compMgr.QueryInterface(Ci.nsIComponentRegistrar
       ).unregisterFactoryLocation(SERVICE_CID, fileSpec);
@@ -133,10 +96,10 @@ var Module = {
   getClassObject: function (compMgr, cid, iid) {
     if (cid.equals(SERVICE_CID))
       return SERVICE_FACTORY;
-  
+
     if (!iid.equals(Ci.nsIFactory))
       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-    
+
     throw Cr.NS_ERROR_NO_INTERFACE;
   },
 
@@ -203,7 +166,7 @@ DUMMY_OBJ.wrappedJSObject = DUMMY_OBJ;
 const DUMMY_FUNC = function() {}
 const DUMMY_ARRAY = [];
 
-const SERVICE_IIDS = 
+const SERVICE_IIDS =
 [
 Ci.nsIContentPolicy,
 Ci.nsIObserver,
@@ -227,9 +190,9 @@ function xpcom_generateQI(iids) {
 
 const SiteUtils = new function() {
   const _domainPattern = this.domainPattern = /^[\w\u0080-\uffff][\w\-\.\u0080-\uffff]*$/;
-  this.ios = IOS;  
+  this.ios = IOS;
   this.uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
-  
+
   function sorter(a, b) {
     if (a == b) return 0;
     if (!a) return 1;
@@ -239,29 +202,29 @@ const SiteUtils = new function() {
         (dp.test(b) ? (a < b ? -1 : 1) : -1)
       : (dp.test(b) ? 1 : a < b ? -1 : 1);
   }
-  
+
   this.sort = function(ss) {
     return ss.sort(sorter);
   };
-  
+
   this.getSite = function(url) {
-    if (!url || 
+    if (!url ||
         url.charCodeAt(0) < 33  && // needs trimming
         !(url = url.replace(/^\s*(.*?)\s*$/, '$1'))) {
       return "";
     }
-    
+
     if (url.indexOf(":") == -1) {
       return this.domainMatch(url);
     }
-    
+
     var scheme;
     try {
       scheme = this.ios.extractScheme(url).toLowerCase();
       switch (scheme) {
         case "http": case "https": // commonest case first
           break;
-        case "javascript": case "data": 
+        case "javascript": case "data":
           return "";
         case "about":
           return url.split(/[\?#]/, 1)[0];
@@ -276,8 +239,8 @@ const SiteUtils = new function() {
     try {
       let uri = this.uriFixup.createExposableURI( // fix wyciwyg: and zaps userpass
                 IOUtil.unwrapURL(url) // unwrap JAR and view-source uris
-      ); 
-      
+      );
+
       try  {
         return uri.prePath;
       } catch(exNoPrePath) {
@@ -288,17 +251,17 @@ const SiteUtils = new function() {
           : scheme;
       }
     } catch(ex) {
-      return url.slice(-2) === ":0" ? this.getSite(url.slice(0, -2)) + ":0" : ""; 
+      return url.slice(-2) === ":0" ? this.getSite(url.slice(0, -2)) + ":0" : "";
     }
   };
-  
+
   this.list2set = function(sl) {
     // kill duplicates
     var prevSite = "";
     var site;
     for (var j = sl.length; j--> 0;) {
       site = sl[j];
-      if ((!site) || site == prevSite) { 
+      if ((!site) || site == prevSite) {
         sl.splice(j, 1);
       } else {
         prevSite = site;
@@ -306,27 +269,27 @@ const SiteUtils = new function() {
     }
     return sl;
   };
-  
+
   this.sortedSet = function(sl) {
     return this.list2set(this.sort(sl));
   }
-  
+
   this.splitString = function(s) {
     return s && /\S/.test(s) && s.split(/\s+/) || [];
   };
-  
+
   this.domainMatch = function(url) {
      const m = url.match(this.domainPattern);
      return m ? m[0].toLowerCase() : "";
   };
-  
+
   this.sanitizeList = function(sl) {
     for (var j = sl.length; j-- > 0; ) {
       sl[j] = this.getSite(sl[j]);
     }
     return sl;
   };
-  
+
   this.sanitizeMap = function(sm) {
     var site;
     delete sm[""];
@@ -339,23 +302,23 @@ const SiteUtils = new function() {
     }
     return sm;
   };
-  
+
   this.sanitizeString = function(s) {
-    return this.set2string(this.string2set(s)); 
+    return this.set2string(this.string2set(s));
   };
-  
+
   this.string2set = function(s) {
     return this.sortedSet(this.sanitizeList(this.splitString(s)));
   };
-  
+
   this.set2string = function(ss) {
     return ss.join(" ");
   };
-  
+
   this.crop = function(url, max) {
     max = max || 1000;
     if (url.length > max) {
-        return this.crop(url.substring(0, max / 2)) + "\n[...]\n" + 
+        return this.crop(url.substring(0, max / 2)) + "\n[...]\n" +
           this.crop(url.substring(url.length - max / 2));
     }
     return url.replace(/\w{20}/g, "$&\u200B");
@@ -417,7 +380,7 @@ PolicySites.prototype = {
     for (var s in sm) {
       sl.push(s);
     }
-    
+
     this._sitesString = SiteUtils.set2string(SiteUtils.sort(sl));
     this._sitesList = null;
     return this._sitesMap = sm;
@@ -450,7 +413,7 @@ PolicySites.prototype = {
     } catch(ex) {
       change = true;
     }
-    
+
     if (change) {
       this.settingPref = true;
       try {
@@ -466,7 +429,7 @@ PolicySites.prototype = {
     if (!site) return "";
     const sm = this.sitesMap;
     var match;
-    var dots; // track "dots" for fix to 2nd level domain policy lookup flaw 
+    var dots; // track "dots" for fix to 2nd level domain policy lookup flaw
     var pos = site.indexOf(':') + 1;
     if (pos > 0 && (pos == site.length || site[pos] == '/')) {
       if (sm[match = site.substring(0, pos)]) return match; // scheme match
@@ -485,7 +448,7 @@ PolicySites.prototype = {
         return submatch; // domain/subdomain match
       }
     }
-    
+
     if (sm[match]
         && (dots > 1 || sm[site]) // strict CAPS-style matching
         ) return match; // host match
@@ -507,11 +470,11 @@ PolicySites.prototype = {
   },
   remove: function(sites, keepUp, keepDown) {
     if (!sites) return false;
-    if (!(typeof(sites) == "object" && "push" in sites)) 
+    if (!(typeof(sites) == "object" && "push" in sites))
       return this.remove([sites], keepUp, keepDown);
     keepUp = keepUp || false;
     keepDown = keepDown || false;
-    
+
     const sm = this.sitesMap;
     var change = false;
     var site, match;
@@ -536,7 +499,7 @@ PolicySites.prototype = {
           this._remove(site);
         }
       }
-    
+
       if (site in sm) {
         this._remove(site);
         change = true;
@@ -545,16 +508,16 @@ PolicySites.prototype = {
     if (change) this.sitesMap = this._sitesMap;
     return change;
   },
-  
+
   _add: function(site) {
     return (site in this.sitesMap ? false : this.sitesMap[site] = true);
   },
-  
+
   add: function(sites) {
     if (!sites) return false;
-    if (!(typeof(sites) == "object" && "push" in sites)) 
+    if (!(typeof(sites) == "object" && "push" in sites))
       return this.add([sites]);
-    
+
     var change = false;
     var site;
     for (var j = sites.length; j-- > 0;) {
@@ -584,13 +547,13 @@ AddressMatcher.prototype = {
   rx: null,
   networks: null,
   netMatching: false,
-  
+
   _universal: { test: function(s) { return true; } },
-  
+
   _specRx: /^((?:ht|f)tps?:\/*)([^\/]*)/i,
   test:  function(u) {
     if (!this.rx) return false;
-    
+
     let spec = this._specRx.exec(u);
 
     if (spec) {
@@ -603,21 +566,21 @@ AddressMatcher.prototype = {
         // handle IDN
         if (host.substring(0, 4) === "xn--") {
           try {
-            if (this.rx.test(spec[1] + DNS.idn.convertACEtoUTF8(host) + spec.input.substring(spec[0].length))) 
+            if (this.rx.test(spec[1] + DNS.idn.convertACEtoUTF8(host) + spec.input.substring(spec[0].length)))
               return true;
           } catch (e) {}
         }
     }
-    
+
     return this.rx.test(u);
   },
-  
+
   testURI: function(uri) this.test(uri.spec),
-  
+
   _networkTest: function(uri, canDoDNS, allIPs) {
     var res = this.rx && this.rx.test(uri.spec || uri);
     if (res || !canDoDNS) return res;
-    
+
     if (!uri.spec) {
       uri = IOS.newURI(uri, null, null);
     }
@@ -626,9 +589,9 @@ AddressMatcher.prototype = {
       if (!host) return false;
       if (Network.isNet(host))
         return this.testIP(host);
-      
+
       var dnsRecord = DNS.resolve(host);
-      if (dnsRecord && dnsRecord.valid) 
+      if (dnsRecord && dnsRecord.valid)
         return allIPs ? dnsRecord.entries.every(this.testIP, this)
                       : dnsRecord.entries.some(this.testIP, this);
     } catch(e) {
@@ -636,21 +599,21 @@ AddressMatcher.prototype = {
     }
     return false;
   },
-  
+
   testIP: function(ip) {
      return this.networks.some(function(n) n.test(ip));
   },
-  
+
   parse: function(s) {
     try {
       var universal = false;
-      var rxs = s && s.split(/\s+/).map(function(p) {      
+      var rxs = s && s.split(/\s+/).map(function(p) {
         if (p === '*') {
           universal = true;
         }
-       
+
         if (universal || !/\S+/.test(p)) return null;
-        
+
         if (Network.isNet(p)) {
           var net;
           if (!this.netMatching) {
@@ -660,16 +623,16 @@ AddressMatcher.prototype = {
           } else {
             this.networks.push(net = new Network(p));
           }
-          
+
           if (p.indexOf("/") > -1 || (net.ipv4 ? net.mask < 32 : net.mask < 128))
             return null; // is a whole network, using IP for URL doesn't make sense
-          
+
           if (p.indexOf(":") > -1)
             p = "[" + p + "]"; // prepare IPv6 URL host
         }
-        
+
         if(!/[^\w\-\[\]/:%@;&#\?\.\*]/.test(p)) {
-         
+
           // either simple or glob
           const hasPath = /^(?:\w+:\/\/|)[^\/]+\//.test(p);
           const hasScheme = /^[a-z][\w\-]+:(?:\/+|[^/]*\D|$)/.test(p);
@@ -679,7 +642,7 @@ AddressMatcher.prototype = {
           if (!hasScheme) { // adjust for no protocol
             if (p.substring(0, 2) === '\\.') {
               // al_9x's proposed syntactic sugar to match both *.x.y and x.y
-              p = "(?:[^/]+\\.)?" + p.substring(2); 
+              p = "(?:[^/]+\\.)?" + p.substring(2);
             }
             p = "[a-z]\\w+://" + p;
           }
@@ -690,19 +653,19 @@ AddressMatcher.prototype = {
             // adjust for no path
              p += "(?::\\d+)?(?:[/\\?#]|$)";
           }
-          
+
           if (!/\*/.test(p)) {
             // simple "starts with..." site matching
             return '^' + p;
           }
-          
+
           // glob matching
           if (p.slice(-1) == '*') p = p.slice(0, -1); // optimize trailing *
-          else if (hasPath) p += '$'; 
+          else if (hasPath) p += '$';
 
           return '^' + p.replace(/\*/g, '.*?').replace(/^([^\/:]+:\/*)\.\*/, "$1[^/]*");
-        } 
-        
+        }
+
         return p;
       }, this).filter(function(p) { return p !== null });
 
@@ -710,8 +673,8 @@ AddressMatcher.prototype = {
         this.test = this._universal.test;
         return this._universal;
       }
-      
-      if (rxs.length !== 0) { 
+
+      if (rxs.length !== 0) {
         try {
           return new RegExp(rxs.join("|"));
         } catch(e) {
@@ -741,15 +704,15 @@ function Network(s) {
   var parts = s.split("/");
   var addr = parts[0];
   var smask;
-  
+
   if (!this._isIPV4(addr))
     this.ipv4 = false;
-  
+
   if (parts.length > 1) {
     this.mask = parseInt(parts[1]);
-    
+
     var defMask = this.ipv4 ? 32 : 128;
-    
+
     if (this.mask != defMask) {
       if (this.mask > defMask) this.mask = defMask;
       else {
@@ -773,7 +736,7 @@ Network.prototype = {
   mask: 32,
   ipv4Mask: 0xffffffff,
   ipv6Mask: [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff],
-  
+
   _isIPV4: function(addr) {
     return addr.indexOf(":") < 0;
   },
@@ -790,19 +753,19 @@ Network.prototype = {
     }
     return ret;
   },
-  
+
   test: function(addr) {
     addr = this.parse(addr);
     if (typeof(addr) === "number")
       return this.addr === addr;
-    
-    if (typeof(this.addr) === "number") return false;   
+
+    if (typeof(this.addr) === "number") return false;
     for (var j = this.addr.length; j-- > 0;) {
       if (addr[j] !== this.addr[j]) return false;
     }
     return true;
   },
-  
+
   parse: function(addr) {
     return this._isIPV4(addr) ? this._parseIPV4(addr) : this._parseIPV6(addr);
   },
@@ -846,7 +809,7 @@ Network.prototype = {
     }
     return ret & this.ipv4Mask;
   },
-  
+
   toString: function() {
     return this.src;
   }
@@ -889,17 +852,17 @@ SyntaxChecker.prototype = {
 const IO = {
   readFile: function(file, charset) {
     var res;
-    
+
     const is = Cc["@mozilla.org/network/file-input-stream;1"]
       .createInstance(Ci.nsIFileInputStream );
     is.init(file ,0x01, 256 /*0400*/, null);
     const sis = Cc["@mozilla.org/scriptableinputstream;1"]
       .createInstance(Ci.nsIScriptableInputStream);
     sis.init(is);
-    
+
     res = sis.read(sis.available());
     is.close();
-    
+
     if (charset !== null) { // use "null" if you want uncoverted data...
       const unicodeConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
         .createInstance(Ci.nsIScriptableUnicodeConverter);
@@ -910,7 +873,7 @@ const IO = {
       }
       res = unicodeConverter.ConvertToUnicode(res);
     }
-  
+
     return res;
   },
   writeFile: function(file, content, charset) {
@@ -921,7 +884,7 @@ const IO = {
     } catch(ex) {
       unicodeConverter.charset = "UTF-8";
     }
-    
+
     content = unicodeConverter.ConvertFromUnicode(content);
     const os = Cc["@mozilla.org/network/file-output-stream;1"]
       .createInstance(Ci.nsIFileOutputStream);
@@ -929,7 +892,7 @@ const IO = {
     os.write(content, content.length);
     os.close();
   },
-  
+
   safeWriteFile: function(file, content, charset) {
     var tmp = file.clone();
     var name = file.leafName;
@@ -953,7 +916,7 @@ const IOUtil = {
   proxiedDNS: 0,
 
   attachToChannel: function(channel, key, requestInfo) {
-    if (channel instanceof Ci.nsIWritablePropertyBag2) 
+    if (channel instanceof Ci.nsIWritablePropertyBag2)
       channel.setPropertyAsInterface(key, requestInfo);
   },
   extractFromChannel: function(channel, key, preserve) {
@@ -983,19 +946,19 @@ const IOUtil = {
     var ref = this.extractInternalReferrer(channel);
     return ref && ref.spec || null;
   },
-  
+
   getProxyInfo: function(channel) {
-    return Ci.nsIProxiedChannel && (channel instanceof Ci.nsIProxiedChannel) 
+    return Ci.nsIProxiedChannel && (channel instanceof Ci.nsIProxiedChannel)
     ? channel.proxyInfo
     : Cc["@mozilla.org/network/protocol-proxy-service;1"]
         .getService(Ci.nsIProtocolProxyService)
         .resolve(channel.URI, 0);
   },
-  
-  
+
+
   canDoDNS: function(channel) {
     if (!channel || IOS.offline) return false;
-    
+
     var proxyInfo = this.getProxyInfo(channel);
     switch(this.proxiedDNS) {
       case 1:
@@ -1003,16 +966,16 @@ const IOUtil = {
       case 2:
         return true;
       default:
-        return !proxyInfo || proxyInfo.type == "direct";   
+        return !proxyInfo || proxyInfo.type == "direct";
     }
 
   },
-  
+
   abort: function(channel, noNetwork) {
     if (ns.consoleDump) ns.dump("Aborting " + channel.name + " @ " + new Error().stack);
     channel.cancel(Cr.NS_ERROR_ABORT);
   },
-  
+
   findWindow: function(channel) {
     for each(var cb in [channel.notificationCallbacks,
                        channel.loadGroup && channel.loadGroup.notificationCallbacks]) {
@@ -1021,7 +984,7 @@ const IOUtil = {
         // For Gecko 1.9.1
           return cb.getInterface(Ci.nsILoadContext).associatedWindow;
         } catch(e) {}
-        
+
         try {
           // For Gecko 1.9.0
           return cb.getInterface(Ci.nsIDOMWindow);
@@ -1030,12 +993,12 @@ const IOUtil = {
     }
     return null;
   },
-  
+
   _protocols: {}, // caching them we gain a 33% speed boost in URI creation :)
   newURI: function(url) {
     try {
       let scheme =  url.substring(0, url.indexOf(':'));
-      return (this._protocols[scheme] || 
+      return (this._protocols[scheme] ||
         (this._protocols[scheme] =
           Cc["@mozilla.org/network/protocol;1?name=" + scheme]
           .getService(Ci.nsIProtocolHandler)))
@@ -1044,12 +1007,12 @@ const IOUtil = {
       return IOS.newURI(url, null, null);
     }
   },
-  
-  unwrapURL: function(url) {  
+
+  unwrapURL: function(url) {
     try {
       if (!(url instanceof Ci.nsIURI))
         url = this.newURI(url);
-      
+
       switch (url.scheme) {
         case "view-source":
           return this.unwrapURL(url.path);
@@ -1066,11 +1029,11 @@ const IOUtil = {
       }
     }
     catch (e) {}
-    
+
     return url;
   },
-  
-  
+
+
   get _channelFlags() {
     delete this._channelFlags;
     const constRx = /^[A-Z_]+$/;
@@ -1090,22 +1053,22 @@ const IOUtil = {
     }
     return hf.join("\n");
   },
-  
+
   queryNotificationCallbacks: function(chan, iid) {
     var cb;
     try {
       cb = chan.notificationCallbacks.getInterface(iid);
       if (cb) return cb;
     } catch(e) {}
-    
+
     try {
       return chan.loadGroup && chan.loadGroup.notificationCallbacks.getInterface(iid);
     } catch(e) {}
-    
+
     return null;
   },
-  
- 
+
+
   anonymizeURI: function(uri, cookie) {
     if (uri instanceof Ci.nsIURL) {
       uri.query = this.anonymizeQS(uri.query, cookie);
@@ -1118,17 +1081,17 @@ const IOUtil = {
     parts[1] = this.anonymizeQS(parts[1], cookie);
     return parts.join("?");
   },
-  
+
   _splitName: function(nv) nv.split("=")[0],
   _qsRx: /[&=]/,
   _anonRx: /(?:auth|s\w+(?:id|key)$)/,
   anonymizeQS: function(qs, cookie) {
     if (!qs) return qs;
     if (!this._qsRx.test(qs)) return '';
-    
+
     var cookieNames, hasCookies;
     if ((hasCookies = !!cookie)) cookieNames = cookie.split(/\s*;\s*/).map(this._splitName)
-    
+
     let parms = qs.split("&");
     for (j = parms.length; j-- > 0;) {
       let nv = parms[j].split("=");
@@ -1143,17 +1106,17 @@ const IOUtil = {
     delete this.TLDService;
     return this.TLDService = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService);
   }
-  
+
 };
 
 
 var Thread = {
-  
+
   hostRunning: true,
   activeLoops: 0,
   _timers: [],
-  
-  spin: function(ctrl) { 
+
+  spin: function(ctrl) {
     ctrl.startTime = ctrl.startTime || Date.now();
     ctrl.timeout = false;
     this.activeLoops++;
@@ -1162,7 +1125,7 @@ var Thread = {
     ctrl.elapsed = Date.now() - ctrl.startTime;
     return ctrl.timeout;
   },
-  
+
   _spinInternal: function(ctrl) {
     var t = ctrl.startTime;
     var maxTime = parseInt(ctrl.maxTime)
@@ -1177,25 +1140,25 @@ var Thread = {
       }
     } else while(ctrl.running && this.hostRunning) this.yield();
   },
-  
+
   yield: function() {
     this.current.processNextEvent(true);
   },
-  
+
   yieldAll: function() {
     var t = this.current;
     while(t.hasPendingEvents()) t.processNextEvent(false);
   },
-  
+
   get current() {
     delete this.current;
-    var obj = "@mozilla.org/thread-manager;1" in Cc 
-      ? Cc["@mozilla.org/thread-manager;1"].getService() 
+    var obj = "@mozilla.org/thread-manager;1" in Cc
+      ? Cc["@mozilla.org/thread-manager;1"].getService()
       : Cc["@mozilla.org/thread;1"].createInstance(Ci.nsIThread);
     this.__defineGetter__("current", function() { return obj.currentThread; });
-    return this.current; 
+    return this.current;
   },
-  
+
   get currentQueue() {
     delete this.currentQueue;
     var eqs = null;
@@ -1208,9 +1171,9 @@ var Thread = {
       ? function() { return eqs.getSpecialEventQueue(IFace.CURRENT_THREAD_EVENT_QUEUE); }
       : this.__lookupGetter__("current")
     );
-    return this.currentQueue;  
+    return this.currentQueue;
   },
-  
+
   delay: function(callback, time, self, args) {
     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     this._timers.push(timer);
@@ -1219,11 +1182,11 @@ var Thread = {
       context: { callback: callback, args: args || DUMMY_ARRAY, self: self || null }
     }, time || 1, 0);
   },
-  
+
   dispatch: function(runnable) {
     this.current.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
   },
-  
+
   asap: function(callback, self, args) {
     this.current.dispatch({
       run: function() {
@@ -1244,7 +1207,7 @@ var Thread = {
       timer.cancel();
     }
   }
-  
+
 };
 
 
@@ -1263,14 +1226,6 @@ LAZY_INCLUDE(
   "JSURL"
 );
 
-__defineGetter__("STS", function() {
-  delete this.STS;
-  if (ns.geckoVersionCheck("4.0") >= 0) // Gecko >= 4 has built-in HSTS
-    return STS = { __noSuchMethod__: function() false };
-  INCLUDE("STS");
-  return STS;
-});
-
 __defineGetter__("ABE", function() {
   if (ns.consoleDump) ns.dump("ABE kickstart at " + (new Error().stack));
   delete this.ABE;
@@ -1289,13 +1244,13 @@ var ns = {
 ,
   get ABE() ABE,
   get OriginTracer() OriginTracer,
-  
+
   AddressMatcher: AddressMatcher,
   Thread: Thread,
 
-  // nsIObserver implementation 
+  // nsIObserver implementation
   observe: function(subject, topic, data) {
-    
+
     switch (topic) {
       case "content-document-global-created":
         this.onWindowCreated(subject, data);
@@ -1304,7 +1259,7 @@ var ns = {
         this.beforeScripting(subject, data);
       return;
     }
-    
+
     if (subject instanceof Ci.nsIPrefBranch2) {
       this.syncPrefs(subject, data);
     } else {
@@ -1313,8 +1268,8 @@ var ns = {
         case "xpcom-shutdown":
           this.unregister();
           break;
-        
-        case "profile-before-change": 
+
+        case "profile-before-change":
           this.dispose();
           Thread.hostRunning = false;
           break;
@@ -1330,34 +1285,31 @@ var ns = {
           ns.checkVersion();
           INCLUDE("Removal");
           break;
-        
+
         case "private-browsing":
           if (data == "enter") {
-            STS.enterPrivateBrowsing();
             if (!("_realDump_" in this)) this._realDump_ = this.dump;
             this.dump = DUMMY_FUNC;
           }
           if (data == "exit") {
             this.eraseTemp();
-            STS.exitPrivateBrowsing();
             this.dump = this._realDump_ || DUMMY_FUNC;
           }
-        // break; 
+        // break;
         case "browser:purge-session-history":
-          STS.eraseDB();
           this.eraseTemp();
         break;
-        
-        
+
+
       }
     }
   },
-    
+
   httpObserver: {
     observe: function(channel, topic, data) {
       try {
         if (channel instanceof Ci.nsIHttpChannel) {
-          
+
           if (channel.status) {
             if (ns.consoleDump)
               ns.dump("Unexpected! HTTP observer called on aborted channel " +
@@ -1365,7 +1317,7 @@ var ns = {
                         new Error().stack);
             return;
           }
-          
+
           let ncb = channel.notificationCallbacks;
           let loadFlags = channel.loadFlags;
           if (!(loadFlags || ncb || channel.owner)) {
@@ -1376,10 +1328,10 @@ var ns = {
               }
             } catch(e) {}
           }
-          
+
           if (ncb) {
             const IBCL = Ci.nsIBadCertListener2;
-            let bgReq = ncb instanceof Ci.nsIXMLHttpRequest || ncb instanceof IBCL 
+            let bgReq = ncb instanceof Ci.nsIXMLHttpRequest || ncb instanceof IBCL
               || ("responseXML" in ncb); // for some reason, since Gecko 15 (new XMLHttpRequest() instanceof Ci.nsIXMLHttpRequest) === false
             if (!bgReq) try { bgReq = ncb.getInterface(IBCL); } catch (e) {}
             if (bgReq && !ns.isCheckedChannel(channel)) {
@@ -1389,10 +1341,10 @@ var ns = {
                 return;
             }
           }
-          
+
           let abeReq = ns.requestWatchdog.onHttpStart(channel);
 
-          if (abeReq && abeReq.isDoc) ns._handleDocJS(abeReq.window, channel, true);   
+          if (abeReq && abeReq.isDoc) ns._handleDocJS(abeReq.window, channel, true);
         }
 
       } catch (e) {
@@ -1400,7 +1352,7 @@ var ns = {
       }
     }
   },
-  
+
   earlyHttpObserver: {
     observe: function(channel, topic, data) {
       INCLUDE("Policy");
@@ -1411,7 +1363,7 @@ var ns = {
       if (channel instanceof Ci.nsIHttpChannel) PolicyState.attach(channel);
     }
   },
-  
+
   OBSERVED_TOPICS: ["profile-before-change", "xpcom-shutdown", "profile-after-change", "sessionstore-windows-restored",
                     "browser:purge-session-history", "private-browsing",
                     "content-document-global-created", "document-element-inserted"],
@@ -1432,23 +1384,23 @@ var ns = {
     OS.removeObserver(this.httpObserver, "http-on-modify-request");
   }
 ,
-  
+
   // Preference driven properties
   autoAllow: false,
 
   consoleDump: 0,
   consoleLog: false,
-  
+
   truncateTitle: true,
   truncateTitleLen: 255,
-  
+
   showBlankSources: false,
   showPlaceholder: true,
   showUntrustedPlaceholder: true,
   collapseObject: false,
   clearClick: 3,
 
-  
+
   forbidSomeContent: true,
   contentBlocker: false,
 
@@ -1460,48 +1412,48 @@ var ns = {
   forbidMedia: true,
   forbidFonts: true,
   forbidWebGL: false,
-  forbidIFrames: false, 
+  forbidIFrames: false,
   forbidIFramesContext: 2, // 0 = all iframes, 1 = different site, 2 = different domain, 3 = different base domain
   forbidFrames: false,
-  
+
   alwaysBlockUntrustedContent: true,
   docShellJSBlocking: 1, // 0 - don't touch docShells, 1 - block untrusted, 2 - block not whitelisted
-  
+
   forbidXBL: 4,
   forbidXHR: 1,
   injectionCheck: 2,
   injectionCheckSubframes: true,
-  
+
   jsredirectIgnore: false,
   jsredirectFollow: false,
   jsredirectForceShow: false,
   emulateFrameBreak: true,
-  
+
   jsHack: null,
   jsHackRegExp: null,
-  
+
   dropXssProtection: true,
   flashPatch: true,
   silverlightPatch: true,
-  
+
   nselNever: false,
   nselForce: true,
 
   filterXGetRx: "(?:<+(?=[^<>=\\d\\. ])|[\\\\'\"\\x00-\\x07\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F])",
   filterXGetUserRx: "",
-  
-  
+
+
   whitelistRegExp: null,
-  allowedMimeRegExp: null, 
+  allowedMimeRegExp: null,
   hideOnUnloadRegExp: null,
   requireReloadRegExp: null,
   ignorePorts: true,
-  
+
   inclusionTypeChecking: true,
   nosniff: true,
-  
+
   fakeScriptLoadEvents: {},
-  
+
   resetDefaultPrefs: function(prefs, exclude) {
     exclude = exclude || [];
     const root = prefs.root;
@@ -1519,22 +1471,22 @@ var ns = {
     }
     this.savePrefs();
   },
-  
+
   resetDefaultGeneralPrefs: function() {
     this.resetDefaultPrefs(this.prefs, ['version']);
   },
-  
+
   resetDefaultSitePrefs: function() {
     this.eraseTemp();
     this.setJSEnabled(this.splitList(this.getPref("default")), true, true);
   },
-  
+
   resetDefaults: function() {
     this.resetDefaultGeneralPrefs();
     this.jsEnabled = false;
     this.resetDefaultSitePrefs();
   },
-  
+
   syncPrefs: function(branch, name) {
     switch (name) {
       case "sites":
@@ -1586,7 +1538,7 @@ var ns = {
           this.forbidMedia || this.forbidFonts ||
           this.forbidIFrames || this.forbidFrames;
       break;
-      
+
       case "docShellJSBlocking":
       case "emulateFrameBreak":
       case "filterXPost":
@@ -1594,7 +1546,7 @@ var ns = {
       case "autoAllow":
       case "contentBlocker":
       case "alwaysShowObjectSources":
-      
+
       case "showUntrustedPlaceholder":
       case "collapseObject":
       case "truncateTitle":
@@ -1622,14 +1574,14 @@ var ns = {
       case "removeSMILKeySniffer":
       case "restrictSubdocScripting":
       case "globalHttpsWhitelist":
-        this[name] = this.getPref(name, this[name]);  
+        this[name] = this.getPref(name, this[name]);
       break;
-      
+
       case  "cascadePermissions":
-        this[name] = this.geckoVersionCheck("24") >= 0 && this.getPref(name, this[name]);  
+        this[name] = this.geckoVersionCheck("24") >= 0 && this.getPref(name, this[name]);
       break;
-    
-      case "fakeScriptLoadEvents.enabled":   
+
+      case "fakeScriptLoadEvents.enabled":
       case "fakeScriptLoadEvents.onlyRequireJS":
       case "fakeScriptLoadEvents.exceptions":
       case "fakeScriptLoadEvents.docExceptions":
@@ -1637,20 +1589,20 @@ var ns = {
         let value = this.getPref(name);
         this.fakeScriptLoadEvents[sub] = typeof value === "boolean" ? value : AddressMatcher.create(value);
       break;
-    
+
       case "liveConnectInterception":
         this[name] = this.geckoVersionCheck("16.0") === -1 && this.getPref(name, this[name]);
       break;
-    
+
       case "sync.enabled":
         this._updateSync();
       break;
-      
+
       case "subscription.trustedURL":
       case "subscription.untrustedURL":
         this.setPref("subscription.lastCheck", 0);
       break;
-      
+
       case "proxiedDNS":
       case "asyncNetworking":
         IOUtil[name] = this.getPref(name, IOUtil[name]);
@@ -1666,28 +1618,28 @@ var ns = {
       case "global":
         this.globalJS = this.getPref(name, false);
       break;
-      
+
       case "alwaysBlockUntrustedContent":
         this[name] = this.getPref(name, this[name]);
         this.initContentPolicy();
       break;
-      
+
       case "forbidMetaRefreshRemember":
         if (!this.getPref(name)) this.metaRefreshWhitelist = {};
       break;
-      
+
       // single rx
       case "filterXGetRx":
       case "filterXGetUserRx":
         this.updateRxPref(name, this[name], "g");
       break;
-      
+
       // multiple rx
       case "filterXExceptions":
       case "jsHackRegExp":
         this.updateRxPref(name, "", "", this.rxParsers.multi);
       break;
-      
+
       // multiple rx autoanchored
       case "hideOnUnloadRegExp":
         this.updateStyleSheet("." + this.hideObjClassName + " {display: none !important}", true);
@@ -1695,15 +1647,15 @@ var ns = {
       case "whitelistRegExp":
         this.updateRxPref(name, "", "^", this.rxParsers.multi);
       break;
-      
+
       case "allowedMimeRegExp":
         this.updateRxPref(name, "", "^i", this.rxParsers.multi);
       break;
-        
+
       case "safeJSRx":
         this.initSafeJSRx();
       break;
-      
+
       case "allowClipboard":
         this.updateExtraPerm(name, "Clipboard", ["cutcopy", "paste"]);
       break;
@@ -1716,18 +1668,18 @@ var ns = {
       case "clearClick":
         this.updateCssPref(name);
       break;
-      
+
       case "policynames":
         this.setupJSCaps();
       break;
-    
+
       case "clearClick.exceptions":
       case "clearClick.subexceptions":
         ClearClickHandler.prototype[name.split('.')[1]] = AddressMatcher.create(this.getPref(name, ''));
       break;
-      
+
       case "secureCookies":
-        HTTPS[name] = this.getPref(name, HTTPS[name]);  
+        HTTPS[name] = this.getPref(name, HTTPS[name]);
       break;
       case "secureCookiesExceptions":
       case "secureCookiesForced":
@@ -1736,13 +1688,10 @@ var ns = {
         HTTPS[name] = AddressMatcher.create(this.getPref(name, ''));
       break;
 
-      case "STS.enabled":
-        STS.enabled = this.getPref(name);
-      break;
-    
+
     }
   },
-  
+
   rxParsers: {
     simple: function(s, flags) {
       var anchor = /\^/.test(flags);
@@ -1769,7 +1718,7 @@ var ns = {
       this[name] = null;
     } else
     {
-      
+
       try {
         this[name] = parseRx(this.getPref(name, def), flags);
       } catch(e) {
@@ -1778,8 +1727,8 @@ var ns = {
       }
     }
   },
-  
-  
+
+
   updateExtraPerm: function(prefName, baseName, names) {
     var cpName;
     var enabled = this.getPref(prefName, false);
@@ -1800,7 +1749,7 @@ var ns = {
       this.setupJSCaps();
     }
   },
-  
+
   updateCssPref: function(name) {
     var value = this[name] = this.getPref(name);
     var sheet;
@@ -1816,7 +1765,7 @@ var ns = {
         sheet = '.__noscriptPlaceholder__ { direction: ltr !important; display: inline-block !important; } ' +
                 '.__noscriptPlaceholder__ > .__noscriptPlaceholder__1 { display: inline-block !important; position: relative !important;' +
                 'outline-color: #fc0 !important; outline-style: solid !important; outline-width: 1px !important; outline-offset: -1px !important;' +
-                'cursor: pointer !important; background: #ffffe0 url("' + 
+                'cursor: pointer !important; background: #ffffe0 url("' +
                     this.pluginPlaceholder + '") no-repeat left top !important; opacity: 0.6 !important; margin-top: 0px !important; margin-bottom: 0px !important;} ' +
                 '.__noscriptPlaceholder__1 > .__noscriptPlaceholder__2 { display: inline-block !important; background-repeat: no-repeat !important; background-color: transparent !important; width: 100%; height: 100%; display: block; margin: 0px; border: none } ' +
                 'noscript .__noscriptPlaceholder__ { display: inline !important; }' +
@@ -1827,7 +1776,7 @@ var ns = {
                 '.__noscriptPlaceholder__1 > .msg { text-align: center !important; bottom: 0 !important; left: 0 !important; width: 100% !important; position: absolute !important; font-size: 12px !important; font-weight: bold !important; font-family: sans-serif !important; }'
       break;
       case "clearClick":
-        sheet = "body:not([id]) { cursor: auto !important } " + 
+        sheet = "body:not([id]) { cursor: auto !important } " +
                 ".__noscriptOpaqued__ { opacity: 1 !important; visibility: visible; filter: none !important } " +
                 "iframe.__noscriptOpaqued__ { display: block !important; } " +
                 "object.__noscriptOpaqued__, embed.__noscriptOpaqued__ { display: inline !important } " +
@@ -1836,14 +1785,14 @@ var ns = {
                 ".__noscriptNoScrolling__ { overflow: hidden !important } " +
                 ".__noscriptHidden__ { visibility: hidden !important } " +
                 ".__noscriptBlank__ { background-color: white !important; color: white !important; border-color: white !important; background-image: none !important }";
-                
+
       break;
       default:
         return;
     };
     this.updateStyleSheet(sheet, value);
   },
-  
+
   get sss() {
     delete this.sss;
     try {
@@ -1853,7 +1802,7 @@ var ns = {
       return this.sss = null;
     }
   },
-  
+
   updateStyleSheet: function(sheet, enabled) {
     const sss = this.sss;
     if (!sss) return;
@@ -1864,17 +1813,17 @@ var ns = {
       try {
         if (enabled) sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
       } catch(e) {
-        this.log("[NoScript CSS] Can't register " + uri + ", " + e); 
+        this.log("[NoScript CSS] Can't register " + uri + ", " + e);
       }
     }
   },
-  
+
   get getString() {
     delete this.getString;
     const ss = new this.Strings("noscript");
     return this.getString = function(name, parms) { return ss.getString(name, parms) };
   },
-  
+
   get Strings() {
     delete this.Strings;
     INCLUDE('Strings');
@@ -1902,7 +1851,7 @@ var ns = {
     return v;
   },
   pluginPlaceholder: "",
-  
+
   _initResources: function() {
     const ios = IOS;
     var resProt = ios.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
@@ -1914,16 +1863,16 @@ var ns = {
     }
     this.pluginPlaceholder = this.skinBase + "icon32.png";
   },
-  
+
   init: function() {
     if (this._inited) return false;
-    
+
     let t = Date.now();
-    
+
     this._inited = true;
-    
+
     this._initResources();
-    
+
     OS.addObserver(this, "em-action-requested", true);
 
     const prefSrv = this.prefService = Cc["@mozilla.org/preferences-service;1"]
@@ -1935,17 +1884,17 @@ var ns = {
 
     this.policyPB = prefSrv.getBranch("capability.policy." + this.POLICY_NAME + ".").QueryInterface(PBI);
     this.prefs = prefSrv.getBranch("noscript.").QueryInterface(PBI);
-     
+
     this.policyPB.addObserver("sites", this, true);
-    
+
     this.prefs.addObserver("", this, true);
     this.mozJSPref = prefSrv.getBranch("javascript.").QueryInterface(PBI);
     this.mozJSPref.addObserver("enabled", this, true);
-    
+
     this.mandatorySites.sitesString = this.getPref("mandatory", "chrome: about: resource:");
-    
+
     this.captureExternalProtocols();
-    
+
     this._batchPrefs = true;
     for each(var p in [
       "autoAllow",
@@ -1953,8 +1902,8 @@ var ns = {
       "allowedMimeRegExp", "hideOnUnloadRegExp", "requireReloadRegExp",
       "consoleDump", "consoleLog", "contentBlocker", "alwaysShowObjectSources",
       "docShellJSBlocking",
-      "filterXPost", "filterXGet", 
-      "filterXGetRx", "filterXGetUserRx", 
+      "filterXPost", "filterXGet",
+      "filterXGetRx", "filterXGetUserRx",
       "filterXExceptions",
       "forbidJava", "forbidFlash", "forbidSilverlight", "forbidPlugins", "forbidMedia", "forbidFonts", "forbidWebGL",
       "forbidIFrames", "forbidIFramesContext", "forbidFrames", "forbidData",
@@ -1989,11 +1938,11 @@ var ns = {
     }
     this._batchPrefs = false;
 
-    
-    
-    
+
+
+
     this.setupJSCaps();
-    
+
     // locking management
     if ((this.locked = this.prefs.prefIsLocked("default"))) {
       try {
@@ -2015,76 +1964,68 @@ var ns = {
       // init jsPolicySites from prefs
       this.syncPrefs(this.policyPB, "sites");
     }
-    
+
     this.syncPrefs(this.mozJSPref, "enabled");
       if (this.consoleDump) ns.dump("T1 " + (Date.now() - t));
     if (this.getPref("tempGlobal", false))
       this.jsEnabled = false;
-   
+
     this.eraseTemp();
-    
+
     Thread.delay(this.checkSubscriptions, 10000, this);
-    
+
     this.reloadWhereNeeded(); // init snapshot
-    
+
     this._updateSync();
-    
+
     this._initE10s();
-    
-    if (this.consoleDump) this.dump("Init done in " + (Date.now() - t));  
+
+    if (this.consoleDump) this.dump("Init done in " + (Date.now() - t));
     return true;
   },
-  
-  globalMM: null,
+
+
   _initE10s: function() {
-    if (! ("@mozilla.org/globalmessagemanager;1" in Cc)) return;
-    this.globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
-        .getService(Ci.nsIMessageListenerManager)
-        .QueryInterface(Ci.nsIFrameScriptLoader)
-        .QueryInterface(Ci.nsIMessageBroadcaster);
-    this.globalMM.loadFrameScript("chrome://noscript/content/frameScript.js", true);
+    INCLUDE("parentProcess");
   },
   _disposeE10s: function() {
-    this.globalMM.removeDelayedFrameScript("chrome://noscript/content/frameScript.js");
+    if (IPC.parent) IPC.parent.dispose();
   },
-  
-  
+
+
   dispose: function() {
     try {
       if(!this._inited) return;
       this._inited = false;
-      
+
       this.shouldLoad = this.shouldProcess = CP_NOP;
-      
+
       OS.removeObserver(this, "em-action-requested");
-      
+
       if (this.httpStarted) {
         this.categoryManager.deleteCategoryEntry("net-channel-event-sinks", this.CTRID, false);
         this.requestWatchdog.dispose();
         Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).removeProgressListener(this);
       }
-      
+
       this.prefs.removeObserver("", this);
       this.mozJSPref.removeObserver("enabled", this);
       this.resetJSCaps();
       this.eraseTemp();
       if (typeof PolicyState === "object") PolicyState.reset();
-      
+
       if (this.placesPrefs) this.placesPrefs.dispose();
-      
-      STS.dispose();
-      
-      
+
       this.savePrefs(true);
-      
+      this._disposeE10s();
       if(this.consoleDump & LOG_LEAKS) this.reportLeaks();
     } catch(e) {
       this.dump(e + " while disposing.");
     }
-    
+
   },
-  
- 
+
+
   onVersionChanged: function(prev) {
     if (!this.getPref("allowWhitelistUpdates")) {
       return;
@@ -2096,11 +2037,11 @@ var ns = {
         "google.com": "googleapis.com gstatic.com", // required by most Google services and also by external resources
         "addons.mozilla.org": "paypal.com paypalobjects.com" // required for the "Contribute" AMO feature not to break badly with no warning
       },
-      
+
       "2.2.9rc2": {
         "addons.mozilla.org": "persona.org"
       },
-      
+
       "2.4.9rc2": {
         "!browserid.org": "persona.org"
       },
@@ -2123,7 +2064,7 @@ var ns = {
         "prototypejs.org": "bootstrapcdn.com" // Used by many sites, mostly for styles and fonts
       }
     };
-    
+
     for (let v in versions) {
       if (this.versionComparator.compare(prev, v) < 0) {
         let cascading = versions[v];
@@ -2131,7 +2072,7 @@ var ns = {
           let newSite = cascading[site].split(/\s+/);
           let replace = site[0] === "!";
           if (replace) site = site.substring(1);
-          if (this.isJSEnabled(site)) { 
+          if (this.isJSEnabled(site)) {
             this.jsPolicySites.remove(newSite, true, false);
             this.setJSEnabled(newSite, true);
             if (replace) this.jsPolicySites.remove(site, true, false);
@@ -2140,7 +2081,7 @@ var ns = {
       }
     }
   },
- 
+
   reportLeaks: function() {
     // leakage detection
     var parent = "__parent__" in this ? this.__parent__ : Cu.getGlobalForObject(this);
@@ -2149,31 +2090,31 @@ var ns = {
       this.dump(v + " = " + parent[v] + "\n");
     }
   },
-  
+
   get profiler() {
     delete this.profiler;
     INCLUDE("Profiler");
     return this.profiler = Profiler;
   },
-  
+
   httpStarted: false,
   get requestWatchdog() {
     if (ns.consoleDump) ns.dump("RW kickstart at " + new Error().stack);
     this.httpStarted = true;
-     
+
     INCLUDE("RequestWatchdog");
-    
+
     this.initContentPolicy(true);
-    
+
     Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).addProgressListener(this,
                              nsIWebProgress.NOTIFY_LOCATION | nsIWebProgress.NOTIFY_STATE_REQUEST | nsIWebProgress.NOTIFY_STATUS |
                             ("NOTIFY_REFRESH" in nsIWebProgress ? nsIWebProgress.NOTIFY_REFRESH : 0));
     this.categoryManager.addCategoryEntry("net-channel-event-sinks", this.CTRID, this.CTRID, false, true);
-    
+
     delete this.requestWatchdog;
     return this.requestWatchdog = new RequestWatchdog();
   },
-  
+
   captureExternalProtocols: function() {
     try {
       const pb = this.prefService.getDefaultBranch("network.protocol-handler.");
@@ -2193,9 +2134,9 @@ var ns = {
       }
     } catch(e) {}
   },
-  
+
   extraCapturedProtocols: null,
-  
+
   mandatorySites: new PolicySites(),
   isMandatory: function(s) {
     return s && this.mandatorySites.matches(s);
@@ -2215,12 +2156,12 @@ var ns = {
     for (var p in sites) {
       if ((b
           ? (p[0] != "g" || this.globalJS) && sites[p].add(s)
-          : sites[p].remove(s, true, true) // keeps up and down, see #eraseTemp() 
+          : sites[p].remove(s, true, true) // keeps up and down, see #eraseTemp()
       ) && this.usingCAPS) sites[p].toPref(this.prefs, p);
     }
     return b;
   },
-  
+
   untrustedSites: new PolicySites(),
   isUntrusted: function(s) {
     return !!this.untrustedSites.matches(s);
@@ -2238,7 +2179,7 @@ var ns = {
     }
     this.untrustedSites.toPref(this.prefs, "untrusted");
   },
-  
+
   manualSites: new PolicySites(),
   isManual: function(s) {
     return !!this.manualSites.matches(s);
@@ -2265,7 +2206,7 @@ var ns = {
     }
     return b;
   },
-  
+
   autoTemp: function(site) {
     if (!(this.isUntrusted(site) || this.isManual(site) || this.isJSEnabled(site))) {
       this.setTemp(site, true);
@@ -2307,21 +2248,21 @@ var ns = {
   isGlobalHttps: function(win, /*optional */ s) {
     let allow = false;
     if (s && !this._isHttpsAndNotUntrusted(s)) return false;
-    
+
     for (;; win = win.parent) {
       let site = this.getSite(this.getPrincipalOrigin(win.document));
       if (!(allow = s && site === s || this._isHttpsAndNotUntrusted(site)) || win === win.parent)
         break;
       s = site;
     }
-    
+
     return allow;
   },
   get proxyService() {
     delete this.proxyService;
     return this.proxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci.nsIProtocolProxyService);
   },
-  
+
   isProxied: function(site) {
     this.isProxied = "proxyConfigType" in this.proxyService
       ? this._isProxied : this._isProxiedSite;
@@ -2335,7 +2276,7 @@ var ns = {
     }
     return true;
   },
-  _isProxiedSite: function(uri) { // Gecko < 2 has no proxyConfigType, so we must resolve per URI 
+  _isProxiedSite: function(uri) { // Gecko < 2 has no proxyConfigType, so we must resolve per URI
     try {
       if (!(uri instanceof Ci.nsIURI)) {
         uri = IOS.newURI(uri || "https://noscript.net/", null, null);
@@ -2351,14 +2292,14 @@ var ns = {
      if (this.globalJS) {
       return !(this.alwaysBlockUntrustedContent && this.untrustedSites.matches(s));
     }
-    
+
     if (this.untrustedSites.matches(s) || this.isForbiddenByHttpsStatus(s)) return false;
-    
+
     let enabled = !!(this.jsPolicySites.matches(s));
-    
+
     if (window) {
       let top = window.top;
-      enabled = enabled || 
+      enabled = enabled ||
                this.globalHttpsWhitelist && s.indexOf("https:") === 0 && (window === top || this.isGlobalHttps(window));
       if (enabled ? this.restrictSubdocScripting : this.cascadePermissions) {
         let topOrigin = this.getPrincipalOrigin(top.document);
@@ -2368,41 +2309,41 @@ var ns = {
           let topSite = this.getSite(topOrigin);
           if (topSite !== s) enabled = this.isJSEnabled(topSite, enabled && this.restrictSubdocScripting && window);
         }
-      }   
+      }
     }
     return enabled;
   },
   setJSEnabled: function(site, is, fromScratch, cascadeTrust) {
-        
+
     const ps = this.jsPolicySites;
     if (fromScratch) ps.sitesString = this.mandatorySites.sitesString;
     if (is) {
       ps.add(site);
       if (!fromScratch) {
-        if (this.untrustedSites.remove(site, false, !cascadeTrust)) 
+        if (this.untrustedSites.remove(site, false, !cascadeTrust))
           this.persistUntrusted();
-        
+
         this.setManual(site, false);
       }
     } else {
       ps.remove(site, false, true);
-      
+
       if (typeof(site) == "string") {
         this._removeAutoPorts(site);
       }
-      
+
       if (this.forbidImpliesUntrust) {
         this.setUntrusted(site, true);
       } else {
         this.setManual(site, true);
       }
     }
-    
+
     this.flushCAPS();
-    
+
     return is;
   },
-  
+
   _buggyIPV6rx: /^[^/:]+:\/\/[^[](?:[0-9a-f]*:){2}/,
   getPrincipalOrigin: function(node) {
     let p = node.nodePrincipal;
@@ -2416,7 +2357,7 @@ var ns = {
     }
     return origin;
   },
-  
+
   _removeAutoPorts: function(site) {
     // remove temporary permissions implied by this site for non-standard ports
 
@@ -2426,34 +2367,34 @@ var ns = {
       if (/:0$/.test(site)) site = site.replace(portRx, '');
       else return;
     }
-    
+
     const tempSites = this.tempSites;
     var portSites = this.tempSites.sitesString.match(/\S+:[1-9]\d*(?=\s|$)/g);
     if (!portSites) return;
-    
-    
+
+
     var domain = SiteUtils.domainMatch(site);
     var filter;
-    
+
     if (domain) {
       const dotDomain = "." + domain;
       const dLen = dotDomain.length;
       filter = function(d) {
         d = this.getDomain(d);
-        return d === domain || d.length > dLen && d.slice(- dLen) === dotDomain; 
+        return d === domain || d.length > dLen && d.slice(- dLen) === dotDomain;
       };
     } else {
       filter = function(s) { return s.replace(portRx, '') === site; };
     }
-    
+
     var doomedSites = portSites.filter(filter, this);
-    
+
     if (doomedSites.length) {
       tempSites.remove(doomedSites);
       this.jsPolicySites.remove(doomedSites);
     }
   },
-  
+
   get forbidImpliesUntrust() {
     return this.globalJS || this.autoAllow || this.getPref("forbidImpliesUntrust", false);
   }
@@ -2464,16 +2405,16 @@ var ns = {
     if (this.whitelistRegExp && this.whitelistRegExp.test(site)) {
       return true;
     }
-    
+
     if (!policy) policy = this.jsPolicySites;
-   
+
     let map = policy.sitesMap;
-    
+
     if (this.portRx.test(site)) {
       let portRx = this.portRx;
       if (this.ignorePorts && policy.matches(site.replace(/:\d+$/, '')))
         return true;
-      
+
       // port matching, with "0" as port wildcard  and * as nth level host wildcard
       let key = site.replace(portRx, ":0");
       if (key in map || site in map) return true;
@@ -2495,7 +2436,7 @@ var ns = {
   flushCAPS: function(sitesString) {
     const ps = this.usingCAPS ? this.jsPolicySites : this.getPermanentSites();
     if (sitesString) ps.sitesString = sitesString;
-    
+
     // dump("Flushing " + ps.sitesString);
     ps.toPref(this.policyPB);
   }
@@ -2507,7 +2448,7 @@ var ns = {
   }
 ,
   get placesPrefs() {
-    if (!this.getPref("placesPrefs", false)) return null; 
+    if (!this.getPref("placesPrefs", false)) return null;
     delete this.placesPrefs;
     try {
       INCLUDE('PlacesPrefs');
@@ -2523,7 +2464,7 @@ var ns = {
     if (this.placesPrefs && !skipPlaces) this.placesPrefs.save();
     return res;
   },
-  
+
   sortedSiteSet: function(s) { return  SiteUtils.sortedSet(s); }
 ,
   get supportsCAPS() {
@@ -2536,14 +2477,14 @@ var ns = {
   globalJS: false,
   get jsEnabled() {
     if (!this.usingCAPS) return this.mozJSEnabled && this.globalJS;
-    
+
     if (!this.mozJSEnabled) return false;
     try {
       return this.caps.getCharPref("default.javascript.enabled") !== "noAccess";
     } catch(ex) {
       return this.jsEnabled = this.globalJS;
     }
-       
+
     return this.jsEnabled;
   }
 ,
@@ -2557,7 +2498,7 @@ var ns = {
     } catch(e) {}
     if (this.supportsCAPS)
       this.defaultCaps.setCharPref(prefName, enabled || !this.usingCAPS ? "allAccess" : "noAccess");
-    
+
     this.setPref("global", enabled);
     if (enabled) {
       this.mozJSPref.setBoolPref("enabled", true);
@@ -2568,7 +2509,7 @@ var ns = {
   getSite: function(url) {
     return SiteUtils.getSite(url);
   },
-  
+
   getQuickSite: function(url, level) {
     var site = null;
     if (level > 0 && !this.jsEnabled) {
@@ -2580,23 +2521,23 @@ var ns = {
     }
     return site;
   },
-  
+
   get preferredSiteLevel() {
     return this.getPref("showAddress", false) ? 1 : this.getPref("showDomain", false) ? 2 : 3;
   },
-  
-  
+
+
   getDomain: function(site, force) {
     try {
       const url = (site instanceof Ci.nsIURL) ? site : IOUtil.newURI(site);
       const host = url.host;
-      return force || (this.ignorePorts || url.port === -1) && host[host.length - 1] != "." && 
+      return force || (this.ignorePorts || url.port === -1) && host[host.length - 1] != "." &&
             (host.lastIndexOf(".") > 0 || host == "localhost") ? host : '';
     } catch(e) {
       return '';
     }
   },
-  
+
   get _tldService() {
     delete this._tldService;
     return this._tldService = IOUtil.TLDService;
@@ -2604,10 +2545,10 @@ var ns = {
 
   getBaseDomain: function(domain) {
     if (!domain || DNS.isIP(domain)) return domain; // IP
-    
+
     var pos = domain.lastIndexOf('.');
     if (pos < 1 || (pos = domain.lastIndexOf('.', pos - 1)) < 1) return domain;
-    
+
     try {
       return this._tldService.getBaseDomainFromHost(domain);
     } catch(e) {
@@ -2649,62 +2590,62 @@ var ns = {
   },
   reloadWhereNeeded: function(reloadPolicy) {
     if (arguments.length === 0) reloadPolicy = this.RELOAD_ALL;
-    
+
     const trusted = this.jsPolicySites;
     const untrusted = this.untrustedSites;
     const global = this.jsEnabled;
-    
+
     var snapshot = this._lastSnapshot;
     var lastTrusted = snapshot.trusted;
     var lastUntrusted = snapshot.untrusted;
     var lastGlobal = snapshot.global;
     var lastObjects = snapshot.objects || this.objectWhitelist;
-    
+
     snapshot.global = global;
     snapshot.trusted = trusted.clone();
     snapshot.untrusted = untrusted.clone();
     snapshot.objects = this.objectWhitelist;
-    
+
     this.initContentPolicy();
-    
+
     if (!lastTrusted ||
         global == lastGlobal &&
-        lastObjects == this.objectWhitelist && 
+        lastObjects == this.objectWhitelist &&
         trusted.equals(lastTrusted) &&
         untrusted.equals(lastUntrusted)
-       ) 
+       )
       return;
-    
+
     let mustReload = !(
         reloadPolicy === this.RELOAD_NO ||
         !this.getPref("autoReload") ||
         global != lastGlobal && !this.getPref("autoReload.global")
       );
-    
+
     const currentTabOnly = reloadPolicy === this.RELOAD_CURRENT ||
       !this.getPref("autoReload.allTabs") ||
       global != lastGlobal && !this.getPref("autoReload.allTabsOnGlobal");
-    
+
     var useHistory = this.getPref("xss.reload.useHistory", false);
     var useHistoryExceptCurrent = this.getPref("xss.reload.useHistory.exceptCurrent", true);
-      
-    
-    
+
+
+
     const nsIWebNavigation = Ci.nsIWebNavigation;
     const nsIURL = Ci.nsIURL;
     const LOAD_FLAGS = nsIWebNavigation.LOAD_FLAGS_NONE;
- 
+
     const untrustedReload = !this.getPref("xss.trustReloads", false);
 
     var bi = DOM.createBrowserIterator();
     var isCurrentTab = true;
-    
+
     (function checkAndReload() {
 
       var browser;
 
       for (let ts = Date.now(), elapsed = 0; elapsed < 30 && (browser = bi.next()); elapsed = Date.now() - ts) {
-        
+
         if (WinScript.supported) {
           this.traverseDocShells(function(docShell) {
             let site = this.getSite(docShell.currentURI.spec);
@@ -2714,15 +2655,15 @@ var ns = {
             return false;
           }, this, browser);
         }
-        
+
         let sites = this.getSites(browser);
         let noFrames = sites.docSites.length === 1;
-        
+
         for (j = 0, len = sites.length; j < len; j++) {
           let site = sites[j];
-          
+
           let checkTop;
-          
+
           if (j === 0 && (noFrames || !isCurrentTab)) // top level, if unchanged and forbidden we won't reload
           {
             checkTop = sites.topSite === site;
@@ -2739,25 +2680,25 @@ var ns = {
               }
             }
           } else checkTop = false;
-          
+
           let prevStatus = !(lastGlobal
             ? this.alwaysBlockUntrustedContent && lastUntrusted.matches(site)
             : !(lastTrusted.matches(site) || this.checkShorthands(site, lastTrusted)) || lastUntrusted.matches(site)
           );
           let currStatus = this.isJSEnabled(site) || !!this.checkShorthands(site);
-          
+
           if (currStatus != prevStatus) {
             let forceReload = mustReload;
             const win =  browser.contentWindow;
             const wu = win.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIDOMWindowUtils);
             const rw = this.requestWatchdog;
-            
-            
+
+
             let canSuppressEvents = "suppressEventHandling" in wu;
             if (canSuppressEvents) wu.suppressEventHandling(true);
             // check XSS
-            
+
             let xss = this.traverseDocShells(function(docShell) {
               let site = this.getSite(docShell.currentURI.spec);
 
@@ -2766,9 +2707,9 @@ var ns = {
                   (lastGlobal
                     ? this.alwaysBlockUntrustedContent && lastUntrusted.matches(site)
                     : !(lastTrusted.matches(site) || this.checkShorthands(site, lastTrusted)) || lastUntrusted.matches(site)
-                  )                          
+                  )
                 ) {
-                
+
                 let channel = docShell.currentDocumentChannel;
                 if (channel instanceof Ci.nsIHttpChannel) {
                   try {
@@ -2795,10 +2736,10 @@ var ns = {
                     return true; // better err on the safe side
                   }
                 }
-              } 
+              }
               return false;
             }, this, browser);
-            
+
             if (xss) {
               forceReload = true;
               useHistoryExceptCurrent = true;
@@ -2809,9 +2750,9 @@ var ns = {
             } else {
               if (canSuppressEvents) wu.suppressEventHandling(false);
             }
-            
+
             rw.setUntrustedReloadInfo(browser, true);
-            
+
             let webNav = browser.webNavigation;
             let uri = webNav.currentURI;
             if (uri.schemeIs("http") || uri.schemeIs("https")) {
@@ -2825,7 +2766,7 @@ var ns = {
                   this.requestWatchdog.setUntrustedReloadInfo(browser, site != sites[j] && !trusted.matches(site));
                 } catch(e) {}
               }
-              
+
               if (useHistory && forceReload) {
                 if (useHistoryExceptCurrent) {
                   useHistoryExceptCurrent = false;
@@ -2846,8 +2787,8 @@ var ns = {
             break;
           }
         }
-        
-        if (mustReload && j === len) { 
+
+        if (mustReload && j === len) {
           // check plugin objects
           if (this.consoleDump & LOG_CONTENT_BLOCK) {
             this.dump("Checking object permission changes...");
@@ -2859,22 +2800,22 @@ var ns = {
              this.quickReload(browser.webNavigation);
           }
         }
-        
+
         if (currentTabOnly) {
           mustReload = false;
           continue;
         }
-        
+
         isCurrentTab = false;
       }
-      
+
       if (browser) Thread.delay(checkAndReload, 1, this);
-      
+
     }).apply(this);
-    
+
   },
-  
-  
+
+
   reloadAllowedObjects: function(browser, mime) {
     if (mime === "WebGL") {
       let curURL = browser.currentURI.spec;
@@ -2888,14 +2829,14 @@ var ns = {
         }
       }
     }
-    
+
     if (this.getPref("autoReload.onMultiContent", false)) {
       this.quickReload(browser.webNavigation);
       return;
     }
     var reloadEmbedders = this.getPref("autoReload.embedders");
     var canReloadPage = reloadEmbedders == 1 ? this.getPref("autoReload") : !!(reloadEmbedders);
-    
+
     var sites = this.getSites(browser);
     var egroup, j, e;
     for each (egroup in sites.pluginExtras) {
@@ -2931,7 +2872,7 @@ var ns = {
         return true;
       }
     }
- 
+
      for each (let egroup in sites.pluginExtras) {
       for (let j = 0, len = egroup.length; j < len; j++) {
         let e = egroup[j];
@@ -2943,14 +2884,14 @@ var ns = {
     }
     return false;
   },
-  
+
   quickReload: function(webNav, checkNullCache) {
     if (!(webNav instanceof Ci.nsIWebNavigation)) {
       webNav = DOM.getDocShellForWindow(webNav);
     }
-    
+
     var uri = webNav.currentURI;
-    
+
     if (checkNullCache && (webNav instanceof Ci.nsIWebPageDescriptor)) {
       try {
         var ch = IOS.newChannel(uri.spec, null, null);
@@ -2970,22 +2911,22 @@ var ns = {
         } catch(e1) {}
       }
     }
-    
+
 
     if (uri.schemeIs("http") || uri.schemeIs("https")) {
       this.requestWatchdog.noscriptReload = uri.spec;
     }
     webNav.reload(webNav.LOAD_FLAGS_CHARSET_CHANGE);
   },
-  
+
   getPermanentSites: function(whitelist, templist) {
     whitelist = (whitelist || this.jsPolicySites).clone();
     whitelist.remove((templist || this.tempSites).sitesList, true, true);
     return whitelist;
   },
-  
+
   eraseTemp: function() {
-    // remove temporary PUNCTUALLY: 
+    // remove temporary PUNCTUALLY:
     // keeps ancestors because the may be added as permanent after the temporary allow;
     // keeps descendants because they may already have been made permanent before the temporary, and then shadowed
     this.jsPolicySites.remove(this.tempSites.sitesList, true, true);
@@ -2993,28 +2934,28 @@ var ns = {
     if (this.untrustedSites.add(this.gTempSites.sitesList)) {
       this.persistUntrusted();
     }
-    
+
     this.tempSites.sitesString = this.gTempSites.sitesString = "";
-    
-    this.setPref("temp", ""); 
+
+    this.setPref("temp", "");
     this.setPref("gtemp", "");
-    
+
     this.setJSEnabled(this.mandatorySites.sitesList, true); // add mandatory
     this.resetAllowedObjects();
     if (this.hasClearClickHandler) this.clearClickHandler.resetWhitelist();
   }
-  
+
 ,
   _observingPolicies: false,
   _editingPolicies: false,
   setupJSCaps: function() {
     if (this._editingPolicies) return;
-    
+
     if (!this.supportsCAPS) {
       this.resetJSCaps();
       if (!(this.allowLocalLinks || this.allowClipboard)) return;
     }
-    
+
     this._editingPolicies = true;
     try {
       const POLICY_NAME = this.POLICY_NAME;
@@ -3022,9 +2963,9 @@ var ns = {
       var prefString = "", originalPrefString = "";
       var exclusive = this.getPref("excaps", true);
       try {
-        
-        prefArray = this.splitList(prefString = originalPrefString = 
-          (this.caps.prefHasUserValue("policynames") 
+
+        prefArray = this.splitList(prefString = originalPrefString =
+          (this.caps.prefHasUserValue("policynames")
             ? this.caps.getCharPref("policynames")
             : this.getPref("policynames") // saved value from dirty exit
           )
@@ -3044,15 +2985,15 @@ var ns = {
       } catch(ex) {
         prefString = POLICY_NAME;
       }
-      
+
       this.caps.setCharPref(POLICY_NAME + ".javascript.enabled", "allAccess");
-      
+
       try {
         this.caps.clearUserPref("policynames");
       } catch(e) {}
       this.defaultCaps.setCharPref("policynames", prefString);
 
-      
+
       if (!this._observingPolicies) {
         this.caps.addObserver("policynames", this, true);
         this._observingPolicies = true;
@@ -3076,7 +3017,7 @@ var ns = {
       let prefString = SiteUtils.splitString(
        exclusive ? this.getPref("policynames", "") : this.caps.getCharPref("policynames")
       ).filter(function(s) s && s !== POLICY_NAME).join(" ");
-      
+
       if (prefString) {
         this.caps.setCharPref("policynames", prefString);
       } else {
@@ -3136,7 +3077,7 @@ var ns = {
       } catch(e2) {}
     }
   },
-  
+
   get json() {
     delete this.json;
     try {
@@ -3152,25 +3093,25 @@ var ns = {
       }
     }
   },
-  
+
   get placesSupported() {
     return !(this.builtInSync && this.getPref("sync.enabled")) &&
       ("nsINavBookmarksService" in Components.interfaces) &&
       this.geckoVersionCheck("2.0") < 0;
   },
-  
+
 
   get builtInSync() {
     var ret = false
-    
+
     try {
       ret = this.prefService.getDefaultBranch("services.sync.prefs.sync.javascript.").getBoolPref("enabled");
     } catch (e) {}
-    
+
     delete this.builtInSync;
     return this.builtInSync = ret;
   },
-  
+
   _updateSync: function() {
     let t = Date.now();
     this._clearSync();
@@ -3178,7 +3119,7 @@ var ns = {
     if (this.consoleDump) this.dump("Sync prefs inited in " + (Date.now() - t));
   },
   _initSync: function() {
-    
+
     try {
       let branch = this.prefService.getDefaultBranch("services.sync.prefs.sync.noscript.");
       for each (let key in this.prefs.getChildList("", {})) {
@@ -3201,7 +3142,7 @@ var ns = {
     } catch(e) {
       this.dump(e);
     }
-    
+
   },
   _clearSync: function() {
     try {
@@ -3215,7 +3156,7 @@ var ns = {
       this.dump(e);
     }
   },
-  
+
   _dontSerialize: ["version", "temp", "preset", "placesPrefs.ts", "mandatory", "default"],
   serializeConf: function(beauty) {
     if (!this.json) return '';
@@ -3227,21 +3168,21 @@ var ns = {
         prefs[key] = this.getPref(key);
       }
     }
-    
+
     const conf = this.json.encode({
       prefs: prefs,
       whitelist: this.getPermanentSites().sitesString,
       V: this.VERSION
     });
-    
+
     return beauty ? conf.replace(/([^\\]"[^"]*[,\{])"/g, "$1\r\n\"").replace(/},?(?:\n|$)/g, "\r\n$&") : conf;
   },
-  
+
   restoreConf: function(s) {
     try {
       const json = this.json.decode(s.replace(/[\n\r]/g, ''));
       if (json.ABE) ABE.restoreJSONRules(json.ABE);
-      
+
       const prefs = json.prefs;
       const exclude = this._dontSerialize;
       for (let key in prefs) {
@@ -3249,13 +3190,13 @@ var ns = {
           this.setPref(key, prefs[key]);
         }
       }
-      
+
       if (prefs.global != ns.jsEnabled) ns.jsEnabled = prefs.global;
-      
+
       this.flushCAPS(json.whitelist);
-      this.setPref("temp", ""); 
+      this.setPref("temp", "");
       this.setPref("gtemp", "");
-      
+
       return true;
     } catch(e) {
       this.dump("Cannot restore configuration: " + e);
@@ -3264,9 +3205,9 @@ var ns = {
   }
 ,
   applyPreset: function(preset) {
-   
+
     this.resetDefaultPrefs(this.prefs, ['version', 'temp', 'untrusted', 'preset']);
-    
+
     switch(preset) {
       case "off":
         this.setPref("ABE.enabled", false);
@@ -3284,7 +3225,7 @@ var ns = {
       default:
         return;
     }
-    
+
     this.setPref("preset", preset);
     this.savePrefs();
   }
@@ -3323,10 +3264,10 @@ var ns = {
     IO.writeFile(file, content);
   }
 ,
-  
+
   getAllowObjectMessage: function(extras) {
     let url = SiteUtils.crop(extras.url).replace(/\S{80}/g, "$&\n");
-    let details = extras.mime + " " + (extras.tag || (extras.mime === "WebGL" ? "<CANVAS>" : "<OBJECT>")) + " / " + extras.originSite; 
+    let details = extras.mime + " " + (extras.tag || (extras.mime === "WebGL" ? "<CANVAS>" : "<OBJECT>")) + " / " + extras.originSite;
     return this.getString("allowTemp", [url + "\n(" + details + ")\n"]);
   }
 ,
@@ -3339,11 +3280,11 @@ var ns = {
     ABE; // kickstart
     return this.wan = WAN;
   },
-  
+
   os: OS,
   siteUtils: SiteUtils,
   mimeService: null,
- 
+
   shouldLoad: function(aContentType) {
     if (aContentType === 5) {
       this.requestWatchdog;
@@ -3352,47 +3293,47 @@ var ns = {
     return CP_OK;
   },
   shouldProcess: CP_NOP,
-  
+
   initContentPolicy: function(force) {
     if (force) INCLUDE("Policy");
     else if (!this.httpStarted) return;
-    
+
     const last = this.getPref("cp.last");
     const catMan = this.categoryManager;
-    const cat = "content-policy"; 
+    const cat = "content-policy";
     if (last)
       try {
         catMan.deleteCategoryEntry(cat, this.CTRID, false);
       } catch (e) {}
-    
+
     var delegate;
-    
+
     if (this.httpStarted) {
       delegate = this.disabled ||
         (this.globalJS &&
-          !(this.alwaysBlockUntrustedContent || this.contentBlocker || HTTPS.httpsForced))   
+          !(this.alwaysBlockUntrustedContent || this.contentBlocker || HTTPS.httpsForced))
       ? NOPContentPolicy
       : MainContentPolicy;
-    
+
       for (var p in delegate) this[p] = delegate[p];
     } else delegate = null;
-    
+
     if (delegate !== NOPContentPolicy && (last || this.mimeService)) {
       // removing and adding the category late in the game allows to be the latest policy to run,
       // and nice to AdBlock Plus
       // this.dump("Adding category");
       catMan.addCategoryEntry(cat, this.CTRID, this.CTRID, false, true);
     } else this.dump("No category?!" + (delegate === NOPContentPolicy) + ", " + last + ", " + this.mimeService);
-    
-    
+
+
     if (!this.mimeService) {
       this.initSafeJSRx();
       this.mimeService = Cc['@mozilla.org/uriloader/external-helper-app-service;1']
         .getService(Ci.nsIMIMEService);
     }
   },
- 
-  
+
+
   guessMime: function(uriOrExt) {
     try {
       var ext = (uriOrExt instanceof Ci.nsIURL) ? uriOrExt.fileExtension : uriOrExt;
@@ -3401,7 +3342,7 @@ var ns = {
       return "";
     }
   },
-  
+
   pluginForMime: function(mimeType) {
     if (!mimeType) return null;
     try {
@@ -3411,28 +3352,28 @@ var ns = {
       return mime && mime.enabledPlugin || null;
     } catch(e) { return null; }
   },
-  
+
   _mediaTypeRx: /^(?:vide|audi)o\/|\/ogg$/i,
   isMediaType: function(mimeType) {
     return this._mediaTypeRx.test(mimeType);
   },
-  
+
   versionComparator: Cc["@mozilla.org/xpcom/version-comparator;1"].getService(Ci.nsIVersionComparator),
   geckoVersion: ("@mozilla.org/xre/app-info;1" in  Cc) ? Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).platformVersion : "0.0",
   geckoVersionCheck: function(v) this.versionComparator.compare(this.geckoVersion, v),
-  
-  
+
+
   cpConsoleFilter: [2, 5, 6, 7, 15],
   cpDump: function(msg, aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall, aPrincipal) {
-    this.dump("Content " + msg + " -- type: " + aContentType + ", location: " + (aContentLocation && aContentLocation.spec) + 
-      ", requestOrigin: " + (aRequestOrigin && aRequestOrigin.spec) + ", ctx: " + 
+    this.dump("Content " + msg + " -- type: " + aContentType + ", location: " + (aContentLocation && aContentLocation.spec) +
+      ", requestOrigin: " + (aRequestOrigin && aRequestOrigin.spec) + ", ctx: " +
         ((aContext instanceof Ci.nsIDOMHTMLElement) ? "<HTML " + aContext.tagName + ">" // try not to cause side effects of toString() during load
-          : aContext)  + 
+          : aContext)  +
         ", mime: " + aMimeTypeGuess + ", Internal: " + aInternalCall +
         ", principal.origin: " + (aPrincipal && aPrincipal.origin));
   },
   reject: function(what, args /* [aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aInternalCall, [aPrincipal] ] */) {
-    
+
     if (this.consoleDump) {
       if(this.consoleDump & LOG_CONTENT_BLOCK && args.length >= 6) {
         this.cpDump("BLOCKED " + what, args[0], args[1], args[2], args[3], args[4], args[5], args[6] && args[6]);
@@ -3449,10 +3390,10 @@ var ns = {
       case 5:
         if (args[3]) args[3].__noscriptBlocked = true;
     }
-    
+
     PolicyState.cancel(args);
-    
-    
+
+
     if (args[1]) {
       let win = DOM.findWindow(args[3]);
       let focusedWin = win;
@@ -3464,15 +3405,15 @@ var ns = {
         this.recordBlocked(focusedWin, this.getSite(args[1].spec) || "", this.getSite(win && win.location.href || args[2] && args[2].spec));
       }
     }
-    
+
     return CP_REJECT;
   },
-  
+
   nopXBL: "chrome://global/content/bindings/general.xml#basecontrol",
-   
+
   forbiddenXMLRequest: function(aRequestOrigin, aContentLocation, aContext, forbidDelegate) {
     let originURL, locationURL;
-    if (aContentLocation.schemeIs("chrome") || !aRequestOrigin || 
+    if (aContentLocation.schemeIs("chrome") || !aRequestOrigin ||
          // GreaseMonkey Ajax comes from resource: hidden window
          // Google Toolbar Ajax from about:blank
            aRequestOrigin.schemeIs("chrome") || aRequestOrigin.schemeIs("resource") ||
@@ -3480,18 +3421,18 @@ var ns = {
            // Web Developer extension "appears" to XHR towards about:blank
            (locationURL = aContentLocation.spec) == "about:blank"
           ) return false;
-    
+
     let locationSite = this.getSite(locationURL);
     if (this.ignorePorts && this.portRx.test(locationSite) &&
         this.isJSEnabled(locationSite.replace(this.portRx, '')) && this.autoTemp(locationSite))
       return false;
-    
+
     var win = aContext && aContext.defaultView;
     if(win) this.getExpando(win.top.document, "codeSites", []).push(locationSite);
-    
+
     return forbidDelegate.call(this, originURL, locationURL, win);
   },
-  
+
 
   addFlashVars: function(url, embed) {
     // add flashvars to have a better URL ID
@@ -3518,12 +3459,12 @@ var ns = {
     }
     return url;
   },
-  
+
   addObjectParams: function(url, embed) {
     if (embed instanceof Ci.nsIDOMElement) try {
       var params = embed.getElementsByTagName("param");
       if (!params.length) return url;
-      
+
       var pp = [];
       for(let j = params.length; j-- > 0;) {
         pp.push(encodeURIComponent(params[j].name) + "=" + encodeURIComponent(params[j].value));
@@ -3534,7 +3475,7 @@ var ns = {
     }
     return url;
   },
-  
+
   tagWindowlessObject: function(o) {
     const rx = /^(?:opaque|transparent)$/i;
     var b;
@@ -3553,33 +3494,33 @@ var ns = {
       if (this.consoleDump) this.dump("Couldn't tag object for window mode.");
     }
   },
-  
+
   isWindowlessObject: function(o) {
     return this.getExpando(o, "windowless") || o.settings && o.settings.windowless;
   },
-  
+
   resolveSilverlightURL: function(uri, embed) {
     if(!uri) return "";
-    
-    
+
+
     if (embed instanceof Ci.nsIDOMElement) try {
-      
+
       var url = "";
       var params = embed.getElementsByTagName("param");
       if (!params.length) return uri.spec;
-      
+
       var name, value, pp = [];
       for (var j = params.length; j-- > 0;) { // iteration inverse order is important for "source"!
         name = params[j].name;
         value = params[j].value;
         if(!(name && value)) continue;
-        
+
         if (!url && name.toLowerCase() == "source") {
           try {
              url = uri.resolve(value);
              continue;
           } catch(e) {
-            if (this.consoleDump)  
+            if (this.consoleDump)
               this.dump("Couldn't resolve Silverlight URL " + uri.spec + " + " + value + ":" + e);
             url = uri.spec;
           }
@@ -3592,7 +3533,7 @@ var ns = {
     }
     return uri.spec;
   },
-  
+
   tagForReplacement: function(embed, pluginExtras) {
     try {
       var doc = embed.ownerDocument;
@@ -3624,17 +3565,17 @@ var ns = {
         "] for replacement: " + ex);
     }
   },
-  
+
   blockLegacyFrame: function(frame, uri, sync) {
 
     var verbose = this.consoleDump & LOG_CONTENT_BLOCK;
     if(verbose) {
       this.dump("Redirecting blocked legacy frame " + uri.spec + ", sync=" + sync);
     }
-    
-    
+
+
     var url = this.createPluginDocumentURL(uri.spec, "iframe");
-    
+
     if(sync) {
       if (verbose) dump("Legacy frame SYNC, setting to " + url + "\n");
       frame.contentWindow.location = url;
@@ -3646,17 +3587,17 @@ var ns = {
       }, false);
     }
     return true;
-  
+
   },
-  
-  
+
+
   isPluginDocumentURL: function(url, tag) {
     try {
       return url.replace(/(src%3D%22).*?%22/i, '$1%22') == this.createPluginDocumentURL('', tag)
     } catch(e) {}
     return false;
   },
-  
+
   createPluginDocumentURL: function(url, tag) {
     tag = tag ? tag.toLowerCase() : "embed";
     return 'data:text/html;charset=utf-8,' +
@@ -3664,7 +3605,7 @@ var ns = {
           tag + ' src="' + url + '" width="100%" height="100%"></' +
           tag + '></body></html>');
   },
-  
+
   forbiddenIFrameContext: function(originURL, locationURL) {
     if (this.isForbiddenByHttpsStatus(originURL)) return false;
     var domain = this.getDomain(locationURL, true);
@@ -3674,8 +3615,8 @@ var ns = {
         return true;
       case 3: // different 2nd level domain or either untrusted parent or origin
         if (!(this.untrustedSites.matches(this.getSite(locationURL)) ||
-            this.untrustedSites.matches(this.getSite(originURL)))) 
-          return this.getBaseDomain(this.getDomain(originURL, true)) != 
+            this.untrustedSites.matches(this.getSite(originURL))))
+          return this.getBaseDomain(this.getDomain(originURL, true)) !=
             this.getBaseDomain(domain);
       case 2: // different domain (unless forbidden by HTTPS status)
         if (this.getDomain(originURL, true) != domain) return true;
@@ -3686,13 +3627,13 @@ var ns = {
      }
      return false;
   },
-  
+
   forbiddenXBLContext: function(originURL, locationURL, window) {
     if (locationURL == this.nopXBL) return false; // always allow our nop binding
-    
+
     var locationSite = this.getSite(locationURL);
     var originSite = this.getSite(originURL);
-   
+
     switch (this.forbidXBL) {
       case 4: // allow only XBL from the same trusted site or chrome (default)
         if (locationSite != originSite) return true; // chrome is checked by the caller checkXML
@@ -3709,7 +3650,7 @@ var ns = {
     }
     return true;
   },
-  
+
   forbiddenXHRContext: function(originURL, locationURL, window) {
     var locationSite = this.getSite(locationURL);
     // var originSite = this.getSite(originURL);
@@ -3726,8 +3667,8 @@ var ns = {
     }
     return true;
   },
-  
-  
+
+
   safeJSRx: false,
   initSafeJSRx: function() {
     try {
@@ -3740,11 +3681,11 @@ var ns = {
     var js = url.replace(/^javascript:/i, "");
     return this.safeJSRx && js != url && this.safeJSRx.test(js);
   },
-  
+
   isFirebugJSURL: function(url) {
     return url == "javascript: eval(__firebugTemp__);"
   },
-  
+
   isExternalScheme: function(scheme) {
     try {
       return IOS.getProtocolHandler(scheme).scheme != scheme;
@@ -3755,7 +3696,7 @@ var ns = {
   normalizeExternalURI: function(uri) {
     var uriSpec = uri.spec;
     var uriValid = URIValidator.validate(uriSpec);
-    var fixURI = this.getPref("fixURI", true) && 
+    var fixURI = this.getPref("fixURI", true) &&
       this.getPref("fixURI.exclude", "").split(/[^\w\-]+/)
           .indexOf(uri.scheme) < 0;
     var msg;
@@ -3781,7 +3722,7 @@ var ns = {
     // encode all you can (i.e. don't touch valid encoded and delims)
     if (fixURI) {
       try {
-        uriSpec = uriSpec.replace(/[^%]|%(?![\da-f]{2})/gi, encodeURI); 
+        uriSpec = uriSpec.replace(/[^%]|%(?![\da-f]{2})/gi, encodeURI);
         if (uriSpec != uri.spec) {
           if (this.consoleDump) this.dump("Encoded URI: " + uri.spec + " to " + uriSpec);
           uri.spec = uriSpec;
@@ -3795,11 +3736,11 @@ var ns = {
     }
     return true;
   },
-  
+
   syncUI: function(document) {
     this.os.notifyObservers(document.defaultView.top, "noscript:sync-ui", null);
   },
-  
+
   objectWhitelist: {},
   ALL_TYPES: ["*"],
   objectWhitelistLen: 0,
@@ -3825,12 +3766,12 @@ var ns = {
   },
   isAllowedObject: function(url, mime, site, originSite) {
     let types = this.objectWhitelist[this.objectKey(url, originSite)] || this.objectWhitelist[this.objectKey(url)];
-    if (types && (types == this.ALL_TYPES || types.indexOf(mime) > -1)) 
+    if (types && (types == this.ALL_TYPES || types.indexOf(mime) > -1))
       return true;
-    
-    
+
+
     if (typeof(site) === "undefined") site = this.getSite(url);
-    
+
     for (;site;) {
       types = this.objectWhitelist[this.objectKey(site, originSite)] || this.objectWhitelist[this.objectKey(site)];
       if (types && (types == this.ALL_TYPES || types.indexOf(mime) > -1))
@@ -3841,17 +3782,17 @@ var ns = {
       if (s === site) break;
       site = s;
     }
-        
+
     return false;
   },
   _moreURLPartsRx: /\..*\.|:\//,
   _chopURLPartRx: /.*?(?::\/+|\.)/,
-  
+
   // Fire.fm compatibility shim :(
   setAllowedObject: function(url, mime) {
     this.allowObject(url, mime);
   },
-  
+
   allowObject: function(url, mime, originSite) {
     let key = this.objectKey(url, originSite);
     if (key in this.objectWhitelist) {
@@ -3880,19 +3821,19 @@ var ns = {
     let doc = obj.ownerDocument;
     let suffix = encodeURIComponent(parentURL);
     if (!doc) return objectURL + "#!#@" + suffix;
-    
+
     let id = obj.id || "";
     let t = obj.tagName.toUpperCase();
-  
+
     const ytFrameURL = "https://www.youtube.com/embed/";
-    
+
     if ("IFRAME" === t && objectURL.substring(0, ytFrameURL.length) === ytFrameURL) {
       objectURL = ytFrameURL;
       id = "(ytFrame)";
     } else {
       objectURL = objectURL.replace(/[\?#].*/, '');
       if (!id) {
-        let ee = doc.getElementsByTagName(t); 
+        let ee = doc.getElementsByTagName(t);
 
         for (let j = ee.length; j-- > 0;) {
           if (ee[j] === obj) {
@@ -3904,12 +3845,12 @@ var ns = {
     }
     return objectURL + "#!#" + id + "@" + suffix;
   },
-  
+
   resetAllowedObjects: function() {
     this.objectWhitelist = {};
     this.objectWhitelistLen = 0;
   },
-  
+
   isAllowedMime: function(mime, site) (this.allowedMimeRegExp && (
                                         this.allowedMimeRegExp.test(mime) ||
                                         this.allowedMimeRegExp.test(mime + "@" + site)))
@@ -3918,7 +3859,7 @@ var ns = {
     if(!site) return;
     try {
       var doc = embed.ownerDocument;
-      
+
       if (doc) {
         var topDoc = doc.defaultView.top.document;
         var os = this.getExpando(topDoc, "objectSites");
@@ -3930,7 +3871,7 @@ var ns = {
       }
     } catch (ex) {}
   },
-  
+
   getPluginExtras: function(obj) {
     return this.getExpando(obj, "pluginExtras");
   },
@@ -3944,12 +3885,12 @@ var ns = {
         this.dump("Setting plugin extras");
       }
     }
-      
+
     return extras;
   },
-  
+
   getExpando: function(domObject, key, defValue) {
-    return domObject && domObject.__noscriptStorage && domObject.__noscriptStorage[key] || 
+    return domObject && domObject.__noscriptStorage && domObject.__noscriptStorage[key] ||
            (defValue ? this.setExpando(domObject, key, defValue) : null);
   },
   setExpando: function(domObject, key, value) {
@@ -3959,15 +3900,15 @@ var ns = {
     else if(this.consoleDump) this.dump("Warning: cannot set expando " + key + " to value " + value);
     return value;
   },
-  
+
   cleanupBrowser: function(browser) {
     delete browser.__noscriptStorage;
   },
-  
+
   hasVisibleLinks: function(document) {
     const w = document.defaultView;
     if (!w) return false;
-    
+
     const links = document.links;
     let toBeChecked = null;
     for (let j = 0, l; (l = links[j]); j++) {
@@ -3978,7 +3919,7 @@ var ns = {
       }
     }
     if (!toBeChecked) return false;
-    
+
     let hiddenAncestors = [];
     for (let j = toBeChecked.length; j-- > 0;) {
       let n = toBeChecked[j];
@@ -4002,7 +3943,7 @@ var ns = {
     if (form && form.offsetHeight) return true;
     return false;
   },
-  
+
   _SMILElements: ["set", "animation"],
   doRemoveSMILKeySniffers: function(document) {
     if (!this.removeSMILKeySniffer) return;
@@ -4017,20 +3958,20 @@ var ns = {
       }
     }
   },
-  
+
   detectJSRedirects: function(document) {
     if (this.jsredirectIgnore) return 0;
-    
+
     try {
       if (document.documentURI.indexOf("http") !== 0) return 0;
-      
+
       let window = document.defaultView;
       if (!window) return 0;
-      
+
       let hasVisibleLinks = this.hasVisibleLinks(document);
-      if (!this.jsredirectForceShow && hasVisibleLinks) 
+      if (!this.jsredirectForceShow && hasVisibleLinks)
         return 0;
-      
+
       let body = document.body;
       if (!body) return 0;
 
@@ -4054,7 +3995,7 @@ var ns = {
           l.style.display = "block";
           seen.push(l.href);
         }
-        
+
 
         for (let forms = document.forms, j = 0, f; f = forms[j]; j++) {
           if (f.action) {
@@ -4072,20 +4013,20 @@ var ns = {
           }
         }
       }
-      
+
       var code;
       var container = null;
-      
+
       code = body && body.getAttribute("onload");
       const sources = code ? [code] : [];
       var scripts = document.getElementsByTagName("script");
       for (let j = 0, len = scripts.length; j < len; j++)
         sources.push(scripts[j].textContent);
-      
+
       scripts = null;
-      
+
       if (!sources[0]) return 0;
-      
+
       var follow = false;
       const findURL = /(?:(?:\b(?:open|replace)\s*\(|(?:\b(?:href|location|src|path|pathname|search)|(?:[Pp]ath|UR[IL]|[uU]r[il]))\s*=)\s*['"]|['"](?=https?:\/\/\w|\w*[\.\/\?]))([\?\/\.\w\-%\&][^\s'"]*)/g;
       const MAX_TIME = 1000;
@@ -4096,7 +4037,7 @@ var ns = {
         findURL.lastIndex = 0;
         code = sources[j];
         for (let m; m = findURL.exec(code);) {
-          
+
           if (!container) {
             container = document.createElementNS(HTML_NS, "div");
             with (container.style) {
@@ -4108,9 +4049,9 @@ var ns = {
               minHeight = "32px";
               textAlign = "left";
             }
-            follow = this.jsredirectFollow && window == window.top &&  
+            follow = this.jsredirectFollow && window == window.top &&
               !window.frames[0] &&
-              !document.evaluate('//body[normalize-space()!=""]', document, null, 
+              !document.evaluate('//body[normalize-space()!=""]', document, null,
                 Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
             document.body.appendChild(container);
           }
@@ -4136,25 +4077,25 @@ var ns = {
           seen.push(a.href);
           a.appendChild(document.createTextNode(a.href));
           container.appendChild(document.createElementNS(HTML_NS, "br"));
-          
+
           if (seen.length >= MAX_LINKS || Date.now() - ts > MAX_TIME) break outerLoop;
         }
-        
+
         if (follow && seen.length == 1) {
-          this.log("[NoScript Following JS Redirection]: " + seen[0] + " FROM " + document.location.href); 
-          
+          this.log("[NoScript Following JS Redirection]: " + seen[0] + " FROM " + document.location.href);
+
           this.doFollowMetaRefresh({
             uri: seen[0],
             document: document
-          });  
+          });
         }
-        
+
         if (Date.now() - ts > MAX_TIME) break;
       }
       return seen.length;
-    } catch(e) { 
+    } catch(e) {
       this.dump(e.message + " while processing JS redirects");
-      return 0; 
+      return 0;
     }
   }
 ,
@@ -4178,18 +4119,18 @@ var ns = {
           scriptSrc = script.getAttribute("src");
           if (!/^[a-z]+:\/\//i.test(scriptSrc)) continue;
         } else continue;
-        
+
         let scriptSite = this.getSite(scriptSrc);
         if (scriptSite) {
           sites.push(scriptSite);
-          
+
           if (scriptSrc in surrogates) continue;
-          
+
           if (nselForce && isHTMLScript &&
               !(script.__nselForce ||
                 this.isJSEnabled(scriptSite, win) ||
                 this.isUntrusted(scriptSite))) {
-            
+
             this.showNextNoscriptElement(script);
           }
         }
@@ -4197,9 +4138,9 @@ var ns = {
     }
   }
 ,
-  
-  
-  showNextNoscriptElement: function(script) { 
+
+
+  showNextNoscriptElement: function(script) {
     const HTMLElement = Ci.nsIDOMHTMLElement;
     var child, el, j, doc, docShell;
     try {
@@ -4207,7 +4148,7 @@ var ns = {
 
         if (node instanceof HTMLElement) {
           script.__nselForce = true;
-          
+
           tag = node.tagName.toUpperCase();
           if (tag == "SCRIPT") {
             if (node.src) return;
@@ -4216,10 +4157,10 @@ var ns = {
           }
           if (tag != "NOSCRIPT")
             return;
-         
+
           child = node.firstChild;
           if (!(child && child.nodeType === 3)) break;
-          
+
           if (!doc) {
             doc = node.ownerDocument;
             docShell = this.dom.getDocShellForWindow(doc.defaultView);
@@ -4244,12 +4185,12 @@ var ns = {
       if (docShell) docShell.allowMetaRedirects = true;
     }
   },
-  
+
   metaRefreshWhitelist: {},
   processMetaRefresh: function(document, notifyCallback) {
     let win = document.defaultView;
     var docShell = DOM.getDocShellForWindow(win);
-    if (!this.forbidMetaRefresh ||    
+    if (!this.forbidMetaRefresh ||
        this.metaRefreshWhitelist[document.documentURI] ||
        this.isJSEnabled(this.getSite(document.documentURI), win) ||
        !document.getElementsByTagName("noscript")[0]
@@ -4261,7 +4202,7 @@ var ns = {
       var refresh, content, timeout, uri;
       var rr = document.getElementsByTagName("meta");
       if (!rr[0]) return;
-      
+
       var html5;
       try {
         html5 = this.prefService.getBoolPref("html5.parser.enable");
@@ -4270,7 +4211,7 @@ var ns = {
       }
 
       var node, nodeName;
-      const refreshRx = /refresh/i; 
+      const refreshRx = /refresh/i;
       for (var j = 0; (refresh = rr[j]); j++) {
         if (!refreshRx.test(refresh.httpEquiv)) continue;
         if (html5) { // older parser moves META outside the NOSCRIPT element if not in HEAD
@@ -4287,13 +4228,13 @@ var ns = {
             timeout = parseInt(content[0]) || 0;
             uri = uri.replace (/^\s*URL\s*=\s*/i, "");
             var isQuoted = /^['"]/.test(uri);
-            uri = isQuoted ? uri.match(/['"]([^'"]*)/)[1] : uri.replace(/\s[\s\S]*/, ''); 
+            uri = isQuoted ? uri.match(/['"]([^'"]*)/)[1] : uri.replace(/\s[\s\S]*/, '');
             try {
-              notifyCallback({ 
+              notifyCallback({
                 docShell: docShell,
                 document: document,
                 baseURI: docShell.currentURI,
-                uri: uri, 
+                uri: uri,
                 timeout: timeout
               });
             } catch(e) {
@@ -4318,7 +4259,7 @@ var ns = {
     if (forceRemember || this.getPref("forbidMetaRefresh.remember", false)) {
       this.metaRefreshWhitelist[document.documentURI] = metaRefreshInfo.uri;
     }
-    var docShell = metaRefreshInfo.docShell || DOM.getDocShellForWindow(document.defaultView); 
+    var docShell = metaRefreshInfo.docShell || DOM.getDocShellForWindow(document.defaultView);
     this.enableMetaRefresh(docShell);
     if (docShell instanceof Ci.nsIRefreshURI) {
       this.setupRefresh(docShell,
@@ -4332,7 +4273,7 @@ var ns = {
       this.metaRefreshWhitelist[document.documentURI] = null;
     }
   },
-  
+
   enableMetaRefresh: function(docShell) {
     if (docShell) {
       docShell.allowMetaRedirects = true;
@@ -4350,7 +4291,7 @@ var ns = {
       // if(this.consoleDump) dump("Disabled META refresh on " + (docShell.currentURI && docShell.currentURI.spec) + "\n");
     }
   },
-  
+
   setupRefresh: function(docShell, baseURI, header) {
     if (docShell instanceof Ci.nsIRefreshURI)
       try {
@@ -4382,15 +4323,15 @@ var ns = {
           try {
             sc = sc || new SyntaxChecker();
             var m;
-            if (sc.check(code) && 
-                (m = sc.lastFunction.toSource().match(this._frameBreakCapture)) && 
+            if (sc.check(code) &&
+                (m = sc.lastFunction.toSource().match(this._frameBreakCapture)) &&
                 (!m[1] || (m[1] == "top" || m[2] == "top") && m[1] != m[2])) {
               var top = w.top;
 
               var docShell = DOM.getDocShellForWindow(top);
               var allowJavascript = docShell.allowJavascript;
               var allowPlugins = docShell.allowPlugins;
-              if (allowJavascript) { // temporarily disable JS & plugins on the top frame to prevent counter-busting 
+              if (allowJavascript) { // temporarily disable JS & plugins on the top frame to prevent counter-busting
                 docShell.allowJavascript = docShell.allowPlugins = false;
                 top.addEventListener("pagehide", function(ev) {
                   ev.currentTarget.removeEventListener(ev.type, arguments.calle, false);
@@ -4412,7 +4353,7 @@ var ns = {
     }
     return false;
   },
-  
+
   knownFrames: {
     _history: {},
     add: function(url, parentSite) {
@@ -4428,7 +4369,7 @@ var ns = {
       this._history = {}
     }
   },
-  
+
   frameContentLoaded: function(w) {
     if (this.emulateFrameBreak && this.doEmulateFrameBreak(w)) return; // we're no more framed
 
@@ -4438,8 +4379,8 @@ var ns = {
       this.knownFrames.add(w.location.href, this.getSite(w.parent.location.href));
     }
   },
-  
-  
+
+
   handleBookmark: function(url, openCallback) {
     if (!url) return true;
     try {
@@ -4458,7 +4399,7 @@ var ns = {
     }
     return false;
   },
-  
+
   // applied to Places(UI)Utils
   placesCheckURLSecurity: function(node) {
     if(!this.__originalCheckURLSecurity(node)) return false;
@@ -4477,35 +4418,35 @@ var ns = {
       method._reentrant = false;
     }
   },
-  
-  
+
+
   executeJSURL: function(url, openCallback, fromURLBar) {
     var browserWindow = DOM.mostRecentBrowserWindow;
     var browser = browserWindow.noscriptOverlay.currentBrowser;
     if(!browser) return false;
-    
+
     var window = browser.contentWindow;
     if(!window) return false;
-    
+
     var site = this.getSite(window.document.documentURI) || this.getExpando(browser, "jsSite");
     if (this.mozJSEnabled && (!this.jsEnabled || this.isUntrusted(site))) {
       if(this.consoleDump) this.dump("Executing JS URL " + url + " on site " + site);
-    
+
       let docShell = DOM.getDocShellForWindow(window);
-    
+
       let snapshots = {
         globalJS: this.jsEnabled,
         docJS: docShell.allowJavascript,
         siteJS: this.jsPolicySites.sitesString,
         untrusted: this.untrustedSites.sitesString
       };
-      
+
       let siteJSEnabled = this.isJSEnabled(site, window);
-      
+
       let doc = window.document;
-      
+
       let focusListener = null;
-      
+
       try {
         WinScript.unblock(window);
         docShell.allowJavascript = true;
@@ -4520,14 +4461,14 @@ var ns = {
           for each(let et in ["focus", "blur"])
             browserWindow.addEventListener(et, focusListener, true);
         }
-        
+
         try {
           this.executingJSURL(doc, 1);
           let noJS = !(siteJSEnabled && snapshots.docJS);
           if (noJS) {
             this._patchTimeouts(window, true);
           }
-          
+
           let gecko24 = this.geckoVersionCheck("24") >= 0;
           if ((fromURLBar || noJS) && /^javascript:/i.test(url) && gecko24) {
             JSURL.load(url, doc);
@@ -4539,7 +4480,7 @@ var ns = {
           if (noJS) {
             this._patchTimeouts(window, false);
           }
-          
+
         } catch(e) {
           this.logError(e, true, "Bookmarklet or location scriptlet");
         }
@@ -4548,10 +4489,10 @@ var ns = {
       } finally {
         if (!siteJSEnabled) WinScript.block(window);
         this.setExpando(browser, "jsSite", site);
-        if (!docShell.isLoadingDocument && docShell.currentURI &&  
+        if (!docShell.isLoadingDocument && docShell.currentURI &&
             this.getSite(docShell.currentURI.spec) == site)
           docShell.allowJavascript = snapshots.docJS;
-        
+
         Thread.asap(function() {
           try {
             if (doc.defaultView && this.executingJSURL(doc) > 1) {
@@ -4560,28 +4501,28 @@ var ns = {
             }
             this.executingJSURL(doc, 0);
           } catch (e) {} // the document could be dead, e.g. after a javascript: non-void expression evaluation
-          
+
           if (focusListener)
             for each(let et in ["focus", "blur"])
               browserWindow.removeEventListener(et, focusListener, true);
-          
+
           if (this.jsEnabled != snapshots.globalJS)
             this.jsEnabled = snapshots.globalJS;
-          
+
           this.jsPolicySites.sitesString = snapshots.siteJS;
           this.untrustedSites.sitesString = snapshots.untrusted;
-          
+
           this.flushCAPS();
-          
+
           if (this.consoleDump & LOG_JS)
             this.dump("Restored snapshot permissions on " + site + "/" + (docShell.isLoadingDocument ? "loading" : docShell.currentURI.spec));
         }, this);
       }
     }
-    
+
     return false;
   },
-  
+
   _patchTimeouts: function(w, start) {
      this._runJS(w, start
       ? "if (!('__runTimeouts' in window)) " +
@@ -4606,24 +4547,24 @@ var ns = {
       : "if (('__runTimeouts' in window) && typeof(window.__runTimeouts) == 'function') window.__runTimeouts()"
     );
   },
-  
+
   _runJS: function(window, s) {
     window.location.href = "javascript:" + encodeURIComponent(s + "; void(0);");
   },
-  
+
   bookmarkletImport: function(scriptElem, src) {
     var doc = scriptElem.ownerDocument;
     ns.executingJSURL(doc, 1);
     var w = doc.defaultView;
-    
-    
+
+
     try {
       ns._patchTimeouts(w, true);
       var xhr = ns.createCheckedXHR("GET", src, function() {
         if (xhr.readyState === 4) {
           ns._runJS(doc.defaultView, xhr.responseText);
           var ev = doc.createEvent("HTMLEvents");
-          ev.initEvent("load", false, true);                             
+          ev.initEvent("load", false, true);
           Thread.asap(function() {
             scriptElem.dispatchEvent(ev);
             dispose();
@@ -4635,7 +4576,7 @@ var ns = {
       dispose();
       ns.dump(e);
     }
-    
+
     function dispose() {
       Thread.asap(function() {
         try {
@@ -4645,7 +4586,7 @@ var ns = {
       });
     };
   },
-  
+
   executingJSURL: function(doc, n) {
     const VAR = "JSURLExec";
     var v = this.getExpando(doc, VAR) || 0;
@@ -4654,26 +4595,26 @@ var ns = {
     }
     return v;
   },
-  
+
   isCheckedChannel: function(c) {
     return IOUtil.extractFromChannel(c, "noscript.checkedChannel", true);
   },
   setCheckedChannel: function(c, v) {
     IOUtil.attachToChannel(c, "noscript.checkedChannel", v ? DUMMY_OBJ : null);
   },
-  
+
   createCheckedXHR: function(method, url, async, window) {
     if (typeof(async) == "undefined") async = true;
     var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     xhr.open(method, url, !!async);
     this.setCheckedChannel(xhr.channel, true);
-    
+
     if (typeof(async) === "function")
       xhr.addEventListener("readystatechange", async, false);
-    
+
     var privacyContext = window && window.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebNavigation);
-    if ((privacyContext instanceof Ci.nsILoadContext) && ("usePrivateBrowsing" in privacyContext) 
+    if ((privacyContext instanceof Ci.nsILoadContext) && ("usePrivateBrowsing" in privacyContext)
             && privacyContext.usePrivateBrowsing) {
       if (xhr.channel instanceof Ci.nsIPrivateBrowsingChannel) {
         xhr.channel.setPrivate(true);
@@ -4681,10 +4622,10 @@ var ns = {
         xhr.channel.loadFlags |= xhr.channel.INHIBIT_PERSISTENT_CACHING;
       }
     }
-    
+
     return xhr;
   },
-  
+
   mimeEssentials: function(mime) {
      return mime && mime.replace(/^application\/(?:x-)?/, "") || "";
   },
@@ -4706,14 +4647,14 @@ var ns = {
             ? 'url("' + this.skinBase + "webgl" + size + '.png")'
             : 'url("moz-icon://noscript?size=' + size + '&contentType=' + mime.replace(/[^\w-\/]/g, '') + '")';
   },
-  
+
   _cachedObjectMimeRx: /^(?:text\/(?:javascript|css|x-c)|application\/(?:x-)?javascript)$/,
   isCachedObjectMime: function(mime) this._cachedObjectMimeRx.test(mime),
-  
+
   findPluginExtras: function(document) {
     return this.getExpando(document, "pluginExtras", []);
   },
-  
+
   appliesHere: function(pref, url) {
     return pref && ((ANYWHERE & pref) == ANYWHERE ||
        (this.isJSEnabled(this.getSite(url))
@@ -4721,7 +4662,7 @@ var ns = {
        )
       );
   },
-  
+
   _preprocessObjectInfo: function(doc) {
     const EMBED = Ci.nsIDOMHTMLEmbedElement,
           OBJECT = Ci.nsIDOMHTMLObjectElement;
@@ -4729,7 +4670,7 @@ var ns = {
     const pe = this.getExpando(doc, "pe");
     if (!pe) return null;
     this.setExpando(doc, "pe", null);
-    
+
     var ret = [];
     for (var j = pe.length; j-- > 0;) {
       let o = pe[j];
@@ -4738,59 +4679,59 @@ var ns = {
           o.embed = this._attachSilverlightExtras(o.embed, o.pluginExtras);
           if (!o.embed) continue; // skip unconditionally to prevent in-page Silverlight placeholders
         }
-        
+
         let embed = o.embed;
         if (this.getExpando(embed, "processed")) continue;
         this.setExpando(embed, "processed", true);
-        
+
         if (embed instanceof OBJECT || embed instanceof EMBED) {
           let node = embed;
           while ((node = node.parentNode) && !node.__noscriptBlocked)
             //  if (node instanceof OBJECT) o.embed = embed = node
             ;
-          
+
           if (node !== null) {
             pe.splice(j, 1);
             continue;
           }
         }
-        
+
         this.countObject(embed, o.pluginExtras.site);
-        
+
         this.setPluginExtras(embed, o.pluginExtras);
         if (embed.ownerDocument) ret.push(o);
-       } catch(e1) { 
-         if(this.consoleDump & LOG_CONTENT_BLOCK) 
-           this.dump("Error setting plugin extras: " + 
-             (o && o.pluginExtras && o.pluginExtras.url) + ", " + e1); 
+       } catch(e1) {
+         if(this.consoleDump & LOG_CONTENT_BLOCK)
+           this.dump("Error setting plugin extras: " +
+             (o && o.pluginExtras && o.pluginExtras.url) + ", " + e1);
        }
     }
     return ret;
   },
-  
+
   processObjectElements: function(document, sites, loaded) {
     const pluginExtras = this.findPluginExtras(document);
     sites.pluginCount += pluginExtras.length;
     sites.pluginExtras.push(pluginExtras);
-    
+
     const objInfo = this._preprocessObjectInfo(document);
     if (!objInfo) return;
-    
+
     var count = objInfo.length;
     if (count === 0) return;
-    
+
     sites.pluginCount += count;
-    
+
     const minSize = this.getPref("placeholderMinSize"),
           longTip = this.getPref("placeholderLongTip");
-    
+
     const skipCSS = /^(?:position|top|left|right|bottom)$/;
-    
+
     var replacements = null,
         collapse = this.collapseObject,
         forcedCSS = ";",
         pluginDocument = false;
-    
+
     try {
       pluginDocument = count == 1 && (
           objInfo[0].pluginExtras.url === document.URL && !objInfo[0].embed.nextSibling ||
@@ -4799,25 +4740,25 @@ var ns = {
       if (pluginDocument) {
         collapse = false;
         forcedCSS = ";outline-style: none !important;-moz-outline-style: none !important; width: 100%";
-        
+
       }
     } catch(e) {}
-    
+
     var win = document.defaultView;
 
     while (count--) {
       let oi = objInfo[count];
       let object = oi.embed;
       let extras = oi.pluginExtras;
-      
+
       try {
         extras.site = this.getSite(extras.url);
-        
+
         if(!this.showUntrustedPlaceholder && this.isUntrusted(extras.site))
           continue;
-        
+
         let msg = "";
-        
+
         let objectTag = object.tagName.toUpperCase();
         if (objectTag === "VIDEO") {
           // Youtube HTML5 hack
@@ -4827,24 +4768,24 @@ var ns = {
             if (rx.test(player.className)) player.className = player.className.replace(rx, '');
           }
         }
-        
+
         extras.tag = "<" + (this.isLegacyFrameReplacement(object) ? "FRAME" : objectTag) + ">";
-        extras.title =  extras.tag + ", " +  
+        extras.title =  extras.tag + ", " +
             this.mimeEssentials(extras.mime) + "@" +
             (longTip ? SiteUtils.crop(extras.url) : extras.url.replace(/[#\?].*/, ''));
-        
+
         if ((extras.alt = object.getAttribute("alt")))
           extras.title += ' "' + extras.alt + '"'
-        
-        
+
+
         let anchor = document.createElementNS(HTML_NS, "a");
         anchor.id = object.id;
         anchor.href = extras.url;
         anchor.setAttribute("title", extras.title);
-        
+
         this.setPluginExtras(anchor, extras);
         this.setExpando(anchor, "removedNode", object);
-     
+
         (replacements = replacements || []).push({object: object, placeholder: anchor, extras: extras });
 
         if (this.showPlaceholder && (object.offsetWidth || object.offsetHeight || !this.isCachedObjectMime(extras.mime))) {
@@ -4860,27 +4801,27 @@ var ns = {
           else anchor.style.visibility = "hidden";
           continue;
         }
-        
+
         object.className += " __noscriptObjectPatchMe__";
-        
+
         let innerDiv = document.createElementNS(HTML_NS, "div");
         innerDiv.className = "__noscriptPlaceholder__1";
-       
+
         let cssDef = "",
             restrictedSize,
             style = win.getComputedStyle(oi.embed, null);
-        
+
         if (style) {
           for (let cssCount = 0, cssLen = style.length; cssCount < cssLen; cssCount++) {
             let cssProp = style.item(cssCount);
             if (!skipCSS.test(cssProp))
               cssDef += cssProp + ": " + style.getPropertyValue(cssProp) + ";";
           }
-          
+
           innerDiv.setAttribute("style", cssDef + forcedCSS);
-          
+
           restrictedSize = (collapse || style.display === "none" || style.visibility === "hidden");
-      
+
           anchor.style.width = style.width;
           anchor.style.height = style.height;
           if (style.position !== "static") {
@@ -4891,25 +4832,25 @@ var ns = {
             anchor.style.right = style.right;
           }
         } else restrictedSize = collapse;
-        
+
         if (restrictedSize) {
           innerDiv.style.maxWidth = anchor.style.maxWidth = "32px";
           innerDiv.style.maxHeight = anchor.style.maxHeight = "32px";
         }
-        
+
         innerDiv.style.visibility = "visible";
-        
+
         let closeButton = innerDiv.appendChild(document.createElementNS(HTML_NS, "div"));
         closeButton.className = "closeButton";
-        
+
         anchor.appendChild(innerDiv);
-        
+
         // icon div
         innerDiv = innerDiv.appendChild(document.createElementNS(HTML_NS, "div"));
         innerDiv.className = "__noscriptPlaceholder__2";
-        
+
         let iconSize;
-        
+
         if(restrictedSize || style && (64 > (parseInt(style.width) || 0) || 64 > (parseInt(style.height) || 0))) {
           innerDiv.style.backgroundPosition = "bottom right";
           iconSize = 16;
@@ -4920,7 +4861,7 @@ var ns = {
             let aStyle = anchor.style, iStyle = innerDiv.parentNode.style;
             aStyle.overflow = "visible";
             aStyle.float = "left";
-            
+
             let isTop = !win.frameElement;
             aStyle.minWidth = iStyle.minWidth = Math.max(w, isTop ? minSize : Math.min(document.documentElement.offsetWidth - rect.left, minSize)) + "px";
             aStyle.minHeight = iStyle.minHeight = Math.max(h, isTop ? minSize : Math.min(document.documentElement.offsetHeight - rect.top, minSize)) + "px";
@@ -4937,11 +4878,11 @@ var ns = {
           }
         }
         innerDiv.style.backgroundImage = this.cssMimeIcon(extras.mime, iconSize);
-        
+
       } catch(objectEx) {
         ns.dump(objectEx + " processing plugin " + count + "@" + document.documentURI + "\n");
       }
-      
+
     }
 
     if (replacements) {
@@ -4949,7 +4890,7 @@ var ns = {
       this.delayExec(this.createPlaceholders, 0, replacements, pluginExtras, document);
     }
   },
-  
+
   get _objectPatch() {
     delete this._objectPatch;
     return this._objectPatch = function() {
@@ -4965,14 +4906,14 @@ var ns = {
       }
     }.toSource() + "()";
   },
-  
+
   patchObjects: function(document) {
     delete this.patchObjects;
     return (this.patchObjects = ("getElementsByClassName" in document)
       ? function(document) { ScriptSurrogate.executeDOM(document, this._objectPatch); }
       : DUMMY_FUNC).call(this, document);
   },
-  
+
   createPlaceholders: function(replacements, pluginExtras, document) {
     for each (let r in replacements) {
       try {
@@ -5007,7 +4948,7 @@ var ns = {
         }
         r.extras.placeholder = r.placeholder;
         this._collectPluginExtras(pluginExtras, r.extras);
-       
+
         ns.patchObjects(document);
       } catch(e) {
         this.dump(e);
@@ -5015,11 +4956,11 @@ var ns = {
     }
     this.syncUI(document);
   },
-  
+
   bind: function(f) {
     return "_bound" in f ? f._bound : f._bound = (function() { return f.apply(ns, arguments); });
   },
-  
+
   stackIsMine: function() {
     var s = Components.stack.caller;
     var f = s.filename.replace(/ line .*/, '');
@@ -5028,12 +4969,12 @@ var ns = {
     }
     return true;
   },
-  
+
   onPlaceholderClick: function(ev, anchor) {
     if (ev.button || !this.stackIsMine()) return;
     anchor = anchor || ev.currentTarget;
     const object = this.getExpando(anchor, "removedNode");
-    
+
     if (object) try {
       let shift = ev.shiftKey;
       let closeButton = ev.target.className === "closeButton";
@@ -5057,11 +4998,11 @@ var ns = {
       ev.stopPropagation();
     }
   },
-  
+
   onOverlayedPlaceholderClick: function(ev) {
     var el = ev.originalTarget;
     var doc = el.ownerDocument;
-    
+
     // check for cloned nodes, like on http://www.vmware.com/products/workstation/new.html
     for (let ph = el; ph.className && ph.className.indexOf("__noscriptPlaceholder__") !== -1; ph = ph.parentNode) {
       if (ph.href && ph.title) {
@@ -5069,7 +5010,7 @@ var ns = {
           this.onPlaceholderClick(ev, ph);
           return;
         }
-        
+
         let pluginExtras = this.findPluginExtras(doc);
         if (pluginExtras) {
           for (let j = pluginExtras.length; j-- > 0;) {
@@ -5078,7 +5019,7 @@ var ns = {
               let n = this.getExpando(o, "removedNode");
               this.setExpando(ph, "removedNode", n);
               this.setPluginExtras(ph, this.getPluginExtras(n));
-              this.onPlaceholderClick(ev, ph);            
+              this.onPlaceholderClick(ev, ph);
               return;
             }
           }
@@ -5087,21 +5028,21 @@ var ns = {
       }
     }
   },
-  
+
   checkAndEnablePlaceholder: function(anchor, object) {
     if (!(object || (object = this.getExpando(anchor, "removedNode")))) {
       if (ns.consoleDump) ns.dump("Missing node on placeholder!");
       return;
     }
-    
+
     if (ns.consoleDump) ns.dump("Enabling node from placeholder...");
-    
+
     const extras = this.getPluginExtras(anchor);
     const browser = DOM.findBrowserForNode(anchor);
- 
+
     if (!(extras && extras.url && extras.mime // && cache
       )) return;
-   
+
     this.delayExec(this.checkAndEnableObject, 1,
       {
         browser: browser,
@@ -5111,20 +5052,20 @@ var ns = {
         object: object
       });
   },
-  
+
   confirmEnableObject: function(win, extras) {
     // work around for Linux tooltip obstructing the confirmation dialog
     Thread.delay(function() {
       win.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindowUtils)
-        .sendMouseEvent("mousemove", win.document.body, 0, 0, 0, 0, 0);    
+        .sendMouseEvent("mousemove", win.document.body, 0, 0, 0, 0, 0);
     }, 100);
     return extras.skipConfirmation || win.noscriptUtil.confirm(
-      this.getAllowObjectMessage(extras), 
+      this.getAllowObjectMessage(extras),
       "confirmUnblock"
     );
   },
-  
+
   isLegacyFrameDocument: function(doc) {
     return (doc.defaultView.frameElement instanceof Ci.nsIDOMHTMLFrameElement) && this.isPluginDocumentURL(doc.URL, "iframe");
   },
@@ -5143,20 +5084,20 @@ var ns = {
   checkAndEnableObject:  function(ctx) {
     var extras = ctx.extras;
     if (!this.confirmEnableObject(ctx.window, extras)) return;
-    
+
 
     var mime = extras.mime;
     var url = extras.url;
-    
+
     this.allowObject(url, mime, extras.originSite);
     let a = ctx.anchor;
     var doc = a.ownerDocument;
-    
-  
+
+
     var isLegacyFrame = this.isLegacyFrameReplacement(ctx.object);
-     
+
     if (isLegacyFrame || (mime == doc.contentType && doc.body &&
-        (a === doc.body.firstChild && 
+        (a === doc.body.firstChild &&
          a === doc.body.lastChild ||
          (ctx.object instanceof Ci.nsIDOMHTMLEmbedElement) && ctx.object.src != url))
       ) { // stand-alone plugin or frame
@@ -5167,7 +5108,7 @@ var ns = {
           doc.defaultView.location.replace(url);
         } else this.quickReload(doc.defaultView, true);
         return;
-    } else if (this.requireReloadRegExp && this.requireReloadRegExp.test(mime) || 
+    } else if (this.requireReloadRegExp && this.requireReloadRegExp.test(mime) ||
                this.getExpando(ctx, "requiresReload") ||
                /#!flashvars#.*\b_YUIvid_=/.test(url)) {
       this.quickReload(doc.defaultView);
@@ -5178,13 +5119,13 @@ var ns = {
       this.quickReload(doc.defaultView);
       return;
     }
-    
-    
+
+
     if (url == doc.URL) { // full page content, just reload
       this.quickReload(doc.defaultView);
       return;
     }
-    
+
     this.setExpando(a, "removedNode", null);
     extras.allowed = true;
     extras.placeholder = null;
@@ -5193,8 +5134,8 @@ var ns = {
       if (ctx.object.parentNode) ctx.object.parentNode.removeChild(ctx.object);
       if ("_display" in ctx.object) ctx.object.style.display = ctx.object._display;
       var obj = ctx.object.cloneNode(true);
-      
-      
+
+
       function reload(slow) {
         ns.log(ns. getObjectURLWithDOM(obj, url, doc.documentURI));
         ns.allowObjectByDOM(obj, url, doc.documentURI, mime);
@@ -5209,12 +5150,12 @@ var ns = {
       let isMedia = win && ("HTMLMediaElement" in win) && (obj instanceof win.HTMLMediaElement);
 
       if (isMedia) {
-        
+
         if (jsEnabled && !obj.controls
             && !/(?:=[^&;]{10,}.*){2,}/.test(this.objectKey(url)) // try to avoid infinite loops when more than one long parameter is present in the object key
           ) {
           // we must reload, since the author-provided UI likely had no chance to wire events
-  
+
           let url = doc.URL;
           if (doc.getElementById("movie_player-html5")) {
             // Youtube HTML5 hack, autoclick thumbnail on page reload
@@ -5239,42 +5180,42 @@ var ns = {
               } catch(e) {}
             }, true);
           }
-          
-          reload(true); // normal reload because of http://forums.informaction.com/viewtopic.php?f=10&t=7195 
+
+          reload(true); // normal reload because of http://forums.informaction.com/viewtopic.php?f=10&t=7195
           return;
         }
         obj.autoplay = true;
       }
-      
-      let parent = a.parentNode; 
-      
+
+      let parent = a.parentNode;
+
       if (parent && parent.ownerDocument == doc) {
-        
+
         if (jsEnabled) {
-          
+
           if (/IFRAME/i.test(extras.tag) && /^https:\/\/www\.youtube\.com\/embed\//.test(url)) {
             reload();
             return;
           }
-          
+
           ScriptSurrogate.executeSandbox(doc,
             "env.a.__noSuchMethod__ = env.o.__noSuchMethod__ = function(m, a) { return env.n[m].apply(env.n, a) }",
             { a: a, o: ctx.object, n: obj }
           );
         }
-        
+
         this.setExpando(obj, "allowed", true);
         parent.replaceChild(obj, a);
         var style = doc.defaultView.getComputedStyle(obj, '');
-       
+
         let body = doc.body;
         if (body && body.clientWidth === obj.offsetWidth && body.clientHeight === obj.offsetHeight) {
           // full size applet/movie
           reload();
           return;
         }
-   
-        
+
+
         if (jsEnabled && ((obj.offsetWidth || parseInt(style.width)) < 2 || (obj.offsetHeight || parseInt(style.height)) < 2)
             && !/frame/i.test(extras.tag)) {
           let ds = DOM.getDocShellForWindow(doc.defaultView);
@@ -5290,7 +5231,7 @@ var ns = {
       }
     }, 10);
     return;
-    
+
   },
 
   getSites: function(browser) {
@@ -5307,8 +5248,8 @@ var ns = {
     }
     return sites;
   },
-  
-  
+
+
   _collectPluginExtras: function(pluginExtras, extras) {
     for (var e, j = pluginExtras.length; j-- > 0;) {
       e = pluginExtras[j];
@@ -5325,9 +5266,9 @@ var ns = {
     pluginExtras.push(extras);
     return true;
   },
-  
+
   _silverlightPatch: 'HTMLObjectElement.prototype.__defineGetter__("IsVersionSupported", function() ((/^application\\/x-silverlight\\b/.test(this.type)) ? function(n) true : undefined));',
-  
+
   _protectNamePatch: "let x=__lookupSetter__(\"name\");__defineSetter__(\"name\",function(n){let s=document.currentScript;if(s&&/\\bname\\b/.test(s.textContent)){console.log(\"NoScript prevented \\\"\" + n + \"\\\" from being assigned to window.name\")}else{x.call(this,n);}})",
   get _flashPatch() {
     delete this._flashPatch;
@@ -5338,34 +5279,34 @@ var ns = {
       HTMLObjectElement.prototype.setAttribute = function(n, v) {
         if (n == "type" && v == type && !this.data) {
           this._pendingType = v;
-          
-          
+
+
           this.SetVariable = function() this.__proto__.SetVariable.apply(this, arguments);
           this.GetVariable = function(n) {
             if (n !== "$version") return this.__proto__.SetVariable.apply(this, arguments);
-            
+
             if (!ver) {
               ver = navigator.plugins["Shockwave Flash"]
-                .description.match(/(\d+)\.(\d+)(?:\s*r(\d+))?/); 
+                .description.match(/(\d+)\.(\d+)(?:\s*r(\d+))?/);
               ver.shift();
               ver.push('99');
               ver = "WIN " + ver.join(",");
             }
-            
+
             return ver;
           }
         }
-        
+
         setAttribute.call(this, n, v);
         if (n === "data" && ("_pendingType" in this) && this._pendingType === type) {
           setAttribute.call(this, "type", type);
           this._pendingType = null;
         }
       };
-  
+
     }.toSource() + "()";
   },
-  
+
   _attachSilverlightExtras: function(embed, extras) {
     extras.silverlight = true;
     var pluginExtras = this.findPluginExtras(embed.ownerDocument);
@@ -5384,8 +5325,8 @@ var ns = {
     }
     return embed;
   },
-  
-  
+
+
   traverseObjects: function(callback, self, browser) {
     return this.traverseDocShells(function(docShell) {
       let document = docShell.document;
@@ -5400,22 +5341,22 @@ var ns = {
       return false;
     }, self, browser);
   },
-  
+
   traverseDocShells: function(callback, self, browser) {
     if (!browser) {
-      const bi = DOM.createBrowserIterator(); 
+      const bi = DOM.createBrowserIterator();
       while((browser = bi.next()))
         if (this.traverseDocShells(callback, self, browser))
           return true;
-      
+
       return false;
     }
-    
+
     const docShells = browser.docShell.getDocShellEnumerator(
         Ci.nsIDocShellTreeItem.typeContent,
         browser.docShell.ENUMERATE_FORWARDS
     );
-    
+
     const nsIDocShell = Ci.nsIDocShell;
     const nsIWebNavigation = Ci.nsIWebNavigation;
 
@@ -5432,28 +5373,28 @@ var ns = {
     }
     return false;
   },
-  
+
   _enumerateSites: function(browser, sites) {
 
     const nsIDocShell = Ci.nsIDocShell;
 
     var top;
-    
+
     this.traverseDocShells(function(docShell) {
-    
+
       let document = docShell.document;
       if (!document) return;
-      
+
       // Truncate title as needed
       if (this.truncateTitle && document.title.length > this.truncateTitleLen) {
         document.title = document.title.substring(0, this.truncateTitleLen);
       }
-      
+
       // Collect document / cached plugin URLs
       let win = document.defaultView;
       let docURI = document.documentURI;
       let url = this.getSite(docURI);
-      
+
       if (url) {
         try {
           let domain = document.domain
@@ -5469,7 +5410,7 @@ var ns = {
            sites.unshift(domain);
           }
         } catch(e) {}
-        
+
         sites.docSites.push(url);
         sites.push(url);
 
@@ -5479,7 +5420,7 @@ var ns = {
       }
 
       let domLoaded = !!this.getExpando(document, "contentLoaded");
-      
+
       if (win === (top || (top = win.top))) {
         sites.topSite = url;
         if (domLoaded) this.setExpando(browser, "allowPageURL", null);
@@ -5488,12 +5429,12 @@ var ns = {
       let loaded = !((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument);
       if (!(domLoaded || loaded))
         return;
-      
+
       this.processObjectElements(document, sites);
       this.processScriptElements(document, sites, url);
-      
+
     }, this, browser);
-    
+
     let document = top.document;
     let cache = this.getExpando(document, "objectSites");
     if(cache) {
@@ -5506,15 +5447,15 @@ var ns = {
       }
       if (!this.contentBlocker || this.alwaysShowObjectSources)
         sites.push.apply(sites, cache);
-      
+
       sites.push.apply(sites.pluginSites, cache);
     }
-    
+
     cache = this.getExpando(document, "codeSites");
     if(cache) sites.push.apply(sites, cache);
 
     const removeBlank = !(this.showBlankSources || sites.topSite == "about:blank");
-    
+
     for (let j = sites.length; j-- > 0;) {
       let url = sites[j];
       if (/:/.test(url) &&
@@ -5529,17 +5470,17 @@ var ns = {
         sites.splice(j, 1); // reject scheme-only URLs
       }
     }
-    
-    
+
+
     if (!sites.topSite) sites.topSite = sites[0] || '';
-    
-    return this.sortedSiteSet(sites); 
+
+    return this.sortedSiteSet(sites);
   },
-  
+
   findOverlay: function(browser) {
     return browser && browser.ownerDocument.defaultView.noscriptOverlay;
   },
-  
+
 
   // nsIChannelEventSink implementation
   asyncOnChannelRedirect: function(oldChan, newChan, flags, redirectCallback) {
@@ -5548,40 +5489,40 @@ var ns = {
   },
   onChannelRedirect: function(oldChan, newChan, flags) {
     const uri = newChan.URI;
-    
+
     if (flags === Ci.nsIChannelEventSink.REDIRECT_INTERNAL && oldChan.URI.spec === uri.spec)
-      return;    
-  
-    const rw = this.requestWatchdog;    
+      return;
+
+    const rw = this.requestWatchdog;
 
     IOUtil.attachToChannel(newChan, "noscript.redirectFrom", oldChan.URI);
-    
+
     ABE.updateRedirectChain(oldChan, newChan);
-    
+
     const ph = PolicyState.detach(oldChan);
 
     if (ph) {
       // 0: aContentType, 1: aContentLocation, 2: aRequestOrigin, 3: aContext, 4: aMimeTypeGuess, 5: aInternalCall
-      
+
       ph.contentLocation = uri;
-      
+
       var ctx = ph.context;
       var type = ph.contentType;
-         
-      if (type != 11 && !this.isJSEnabled(oldChan.URI.spec)) 
+
+      if (type != 11 && !this.isJSEnabled(oldChan.URI.spec))
         ph.requestOrigin = oldChan.URI;
-      
+
       try {
         ph.mimeType = newChan.contentType || oldChan.contentType || ph.mimeType;
       } catch(e) {}
-      
+
       var browser, win;
-   
+
       switch(type) {
         case 2: case 9: // script redirection? cache site for menu
           try {
             var site = this.getSite(uri.spec);
-            win = IOUtil.findWindow(newChan) || ctx && ((ctx instanceof Ci.nsIDOMWindow) ? ctx : ctx.ownerDocument.defaultView); 
+            win = IOUtil.findWindow(newChan) || ctx && ((ctx instanceof Ci.nsIDOMWindow) ? ctx : ctx.ownerDocument.defaultView);
             browser = win && DOM.findBrowserForNode(win);
             if (browser) {
               this.getRedirCache(browser, win.top.document.documentURI)
@@ -5593,7 +5534,7 @@ var ns = {
             if (this.consoleDump) this.dump(e);
           }
           break;
-        
+
         case 7: // frame
 
           ph.extra = CP_FRAMECHECK;
@@ -5604,7 +5545,7 @@ var ns = {
           }
           break;
       }
-      
+
       if (this.shouldLoad.apply(this, ph.toArray()) != CP_OK) {
         if (this.consoleDump) {
           this.dump("Blocked " + oldChan.URI.spec + " -> " + uri.spec + " redirection of type " + type);
@@ -5612,34 +5553,34 @@ var ns = {
         throw "NoScript aborted redirection to " + uri.spec;
       }
     }
-  
-    
+
+
     // Document transitions
-  
+
     if ((oldChan.loadFlags & rw.DOCUMENT_LOAD_FLAGS) || (newChan.loadFlags & rw.DOCUMENT_LOAD_FLAGS) && oldChan.URI.prePath != uri.prePath) {
       if (newChan instanceof Ci.nsIHttpChannel)
         HTTPS.onCrossSiteRequest(newChan, oldChan.URI.spec,
                                browser || DOM.findBrowserForNode(IOUtil.findWindow(oldChan)), rw);
 
     }
-    
+
   },
-  
+
   getRedirCache: function(browser, uri) {
     var redirCache = this.getExpando(browser, "redirCache", {});
     return redirCache[uri] || (redirCache[uri] = []);
   },
-  
+
   _recentlyBlockedMax: 40,
   recordBlocked: function(win, site, origin) {
     if (!(win && this.getPref("showRecentlyBlocked"))) return;
     let overlay = DOM.getChromeWindow(win).noscriptOverlay;
     if (!overlay) return;
-    
+
     const l = overlay.recentlyBlocked;
     let pos = l.length;
     while (pos-- > 0) if (l[pos].site === site) break;
-    
+
     let entry;
     if (pos > -1) {
       entry = l[pos];
@@ -5648,7 +5589,7 @@ var ns = {
       if (pos == l.length - 1) return;
       l.splice(pos, 1);
     } else entry = { site: site, origins: [origin] };
-    
+
     l.push(entry);
     if (l.length > this._recentlyBlockedMax) {
       overlay.recentlyBlocked = l.slice(- this._recentlyBlockedMax / 2);
@@ -5656,12 +5597,12 @@ var ns = {
   },
 
   cleanupRequest: DUMMY_FUNC,
-  
+
   get _inclusionTypeInternalExceptions() {
     delete this._inclusionTypeInternalExceptions;
     return this._inclusionTypeInternalExceptions = new AddressMatcher("https://*.ebaystatic.com/*");
   },
-  
+
   hasNoSniffHeader: function(channel) {
     for (let x = true, header = "X-Content-Type-Options";;) {
       try {
@@ -5676,12 +5617,12 @@ var ns = {
       }
     }
   },
-  
+
   get noBuiltInFrameOpt() {
     delete this.noBuiltInFrameOpt;
     return this.noBuiltInFrameOpt = this.geckoVersionCheck('1.9.2.10') < 0;
   },
-  
+
   checkInclusionType: function(channel) {
     try {
       if (channel instanceof Ci.nsIHttpChannel &&
@@ -5694,14 +5635,14 @@ var ns = {
           if (!(ctype === 2 || ctype === 4)) return true;
 
           let nosniff = ns.nosniff && ctype === 2;
-          
+
           if (nosniff) nosniff = this.hasNoSniffHeader(channel);
-          
+
           if (!(nosniff || ns.inclusionTypeChecking))
             return true;
-          
+
           let origin = ABE.getOriginalOrigin(channel) || ph.requestOrigin;
-          
+
           if (nosniff || origin && this.getBaseDomain(this.getDomain(origin)) !== this.getBaseDomain(channel.URI.host)) {
 
             var mime;
@@ -5720,21 +5661,21 @@ var ns = {
                     : /(?:script|\b(?:js(?:on)?)|css)\b/i) // allow css mime on js
                 : (PolicyUtil.isXSL(ph.context) || ph.mimeType.indexOf("/x") > 0) ? /\bx[ms]l/i : /\bcss\b/i
               ).test(mime);
-            
+
             if (okMime) return true;
-            
-            let uri = channel.URI; 
+
+            let uri = channel.URI;
             let url = uri.spec;
-            
+
 
             let disposition;
             try {
               disposition = channel.getResponseHeader("Content-disposition");
             } catch(e) {}
 
-            
+
             if (!disposition) {
-             
+
               let ext;
               if (uri instanceof Ci.nsIURL) {
                 ext = uri.fileExtension;
@@ -5749,13 +5690,13 @@ var ns = {
                    ctype === 4 && (ext == "css" || ext == "xsl" && (PolicyUtil.isXSL(ph.context) || ph.mimeType.indexOf("/x") > 0)))
                 ) {
                 // extension matches and not an attachment, likely OK
-                return true; 
+                return true;
               }
-              
+
               // extension doesn't match, let's check the mime
-              
-             
-             if ((/^text\/.*ml$|unknown/i.test(mime) || 
+
+
+             if ((/^text\/.*ml$|unknown/i.test(mime) ||
                     mime === "text/plain" && !(ext && /^(?:asc|log|te?xt)$/.test(ext)) // see Apache's magic file, turning any unkown ext file containing JS style comments into text/plain
                   ) && !this.getPref("inclusionTypeChecking.checkDynamic", false)) {
                 // text/html or xml or text/plain with non-text ext, let's assume a misconfigured dynamically served script/css
@@ -5766,13 +5707,13 @@ var ns = {
                 return true;
               }
             } else mime = mime + ", " + disposition;
-            
+
             if (this._inclusionTypeInternalExceptions.test(url) ||
               new AddressMatcher(this.getPref("inclusionTypeChecking.exceptions", "")).test(url))
             return true;
-            
+
             // every check failed, this is a fishy cross-site mistyped inclusion
-           
+
             this.log("[NoScript] Blocking " + (nosniff ? "nosniff " : "cross-site ") +
                      (ctype === 2 ? "Javascript" : ctype === 3 ? "image" : "CSS") +
                      " served from " +
@@ -5811,9 +5752,9 @@ var ns = {
           ns.dump(e);
         }
       }
-      
+
       var isObject;
-      
+
       const domWindow = IOUtil.findWindow(req);
       var ph = PolicyState.extract(req);
       if (ph) {
@@ -5825,16 +5766,16 @@ var ns = {
                 default:
                     return; // e.g. plugin content or XHR
             }
-        } 
+        }
       } else isObject = false;
-      
+
       if (domWindow && domWindow == domWindow.top && !isObject)
         return;
 
       var status = req.responseStatus;
       if (status >= 300 && status < 400) // redirect, wait for ultimate destination, see http://forums.informaction.com/viewtopic.php?f=7&t=2630
         return;
-      
+
       // X-Frame-Options
       if (this.noBuiltInFrameOpt &&
           ((req.loadFlags & req.LOAD_DOCUMENT_URI) || // must be a subdocument
@@ -5848,29 +5789,29 @@ var ns = {
         this.showFrameOptError(domWindow, req.URI.spec);
         return; // canceled by frame options
       }
-      
+
       if (!isObject) this.onBeforeLoad(req, domWindow, req.URI);
-      
+
     } catch(e) {
       if (this.consoleDump) this.dump(e);
     }
   },
-  
+
   loadErrorPage: function(w, errPageURL) {
     DOM.getDocShellForWindow(w).loadURI(errPageURL,
       ((this.geckoVersionCheck("1.9.1") < 0 ? 0x8000 : 0x0001) << 16) | 1,
       null, null, null);
   },
-  
+
   showFrameOptError: function(w, url) {
     this.log("X-FRAME-OPTIONS: blocked " + url, true);
     var f = w && w.frameElement;
     if (!f) return;
-    
+
     var browser = DOM.findBrowserForNode(w);
     if (browser)
       this.getRedirCache(browser, w.top.document.documentURI).push({site: this.getSite(url), type: 7});
-    
+
     const errPageURL = this.contentBase + "frameOptErr.xhtml";
     f.addEventListener("load", function(ev) {
       f.removeEventListener(ev.type, arguments.callee, false);
@@ -5878,47 +5819,47 @@ var ns = {
         f.contentWindow.document.getElementById("link")
           .setAttribute("href", url);
     }, false);
-    
+
     this.loadErrorPage(w, errPageURL);
   },
 
-  
+
   onBeforeLoad: function(req, domWindow, location) {
-    
+
     if (!domWindow) return;
-    
+
     const uri = location;
-    
+
     var docShell = null;
-    
-     
+
+
     var contentType;
     try {
       contentType = req.contentType;
     } catch(e) {
       contentType = "";
     }
-    
+
     var contentDisposition = "";
-    
+
     var isHTTP = req instanceof Ci.nsIHttpChannel;
     if (isHTTP) {
       try {
         contentDisposition = req.getResponseHeader("Content-disposition");
       } catch(e) {}
     }
-    
+
     const topWin = domWindow == domWindow.top;
 
     var browser = null;
     var overlay = null;
     var xssInfo = null;
-    
+
 
     if (topWin) {
-      
+
       if (domWindow instanceof Ci.nsIDOMChromeWindow) return;
-    
+
       browser = DOM.findBrowserForNode(domWindow);
       overlay = this.findOverlay(browser);
       if (overlay) {
@@ -5932,49 +5873,49 @@ var ns = {
             this.clearClickHandler.install(browser);
           }
         }
-        
+
       }
     }
-    
+
     if (IOUtil.extractFromChannel(req, "noscript.checkWindowName")) {
       this.requestWatchdog.checkWindowName(domWindow, req.URI.spec);
     }
-    
+
     if (this.onWindowSwitch && docShell &&
         (topWin || !this.executeEarlyScripts))
       this.onWindowSwitch(uri.spec, domWindow, docShell);
-      
-    
-    
+
+
+
 
     if (!/^attachment\b/i.test(contentDisposition) &&
         this.shouldLoad(7, uri, uri, domWindow.frameElement || domWindow, contentType,
                         domWindow.frameElement ? CP_FRAMECHECK : CP_SHOULDPROCESS) != CP_OK) {
-      
+
       req.loadFlags |= req.INHIBIT_CACHING;
-      
+
       if (this.consoleDump & LOG_CONTENT_INTERCEPT)
         this.dump("Media document content type detected");
 
       if(!topWin) {
         // check if this is an iframe
-        
+
         if (domWindow.frameElement && !(domWindow.frameElement instanceof Ci.nsIDOMHTMLFrameElement)
             && this.shouldLoad(5, uri, IOS.newURI(domWindow.parent.location.href, null, null),
                 domWindow.frameElement, contentType, CP_SHOULDPROCESS) == CP_OK)
             return;
-        
-        if (this.consoleDump & LOG_CONTENT_BLOCK) 
+
+        if (this.consoleDump & LOG_CONTENT_BLOCK)
           this.dump("Deferring framed media document");
-        
+
         var url = uri.spec;
-        
+
         browser = browser || DOM.findBrowserForNode(domWindow);
         this.getRedirCache(browser, domWindow.top.document.documentURI).push({site: this.getSite(url), type: 7});
         // defer separate embed processing for frames
-        
-        
-       
+
+
+
         docShell = docShell || DOM.getDocShellForWindow(domWindow);
         docShell.loadURI("data:" + req.contentType + ",",
                              Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY,
@@ -5990,13 +5931,13 @@ var ns = {
                              null, null, null);
           }
         });
-        
+
         return;
       }
-      
-      if (this.consoleDump & LOG_CONTENT_BLOCK) 
+
+      if (this.consoleDump & LOG_CONTENT_BLOCK)
         this.dump("Blocking top-level plugin document");
-      
+
       for each (let tag in ["embed", "video", "audio"]) {
         let embeds = domWindow.document.getElementsByTagName(tag);
         if (embeds.length > 0 && (tag !== "embed" || this._abortPluginDocLoads)) {
@@ -6011,9 +5952,9 @@ var ns = {
           }
         }
       }
-      
+
       if (xssInfo) overlay.notifyXSS(xssInfo);
-      
+
       return;
 
     } else {
@@ -6022,33 +5963,33 @@ var ns = {
       }
     }
   },
-  
+
   get _abortPluginDocLoads() {
     delete this._abortPluginDocLoads;
     return this._abortPluginDocLoads = this.geckoVersionCheck("18.0.1") < 0;
   },
-  
+
   hasClearClickHandler: false,
   get clearClickHandler() {
       delete this.clearClickHandler;
       this.hasClearClickHandler = true;
       return this.clearClickHandler = new ClearClickHandler(this);
   },
-  
-  DOC_JS_STATUS_KEY: "noscript.dsjsBlocked", 
+
+  DOC_JS_STATUS_KEY: "noscript.dsjsBlocked",
   _handleDocJS: function(win, req, requireNetwork) {
     const abeSandboxed = req instanceof Ci.nsIHttpChannel && ABE.isSandboxed(req);
     const docShellJSBlocking = this.docShellJSBlocking || abeSandboxed;
-        
+
     if (!docShellJSBlocking || (win instanceof Ci.nsIDOMChromeWindow)) return;
     const dump = this.consoleDump & LOG_JS;
     try {
-      
+
       let docShell = DOM.getDocShellForWindow(win) ||
                      DOM.getDocShellForWindow(IOUtil.findWindow(req));
-      
+
       if (requireNetwork == docShell.restoringDocument) return;
-      
+
       let url = req.URI.spec;
       if (!/^https?:/.test(url)) url = req.originalURI.spec;
 
@@ -6056,12 +5997,12 @@ var ns = {
         if (this.consoleDump) this.dump("DocShell not found for JS switching in " + url);
         return;
       }
-      
+
       if (abeSandboxed) {
         ABE.sandbox(docShell, true);
         return;
       }
-      
+
       let jsEnabled;
       if (docShellJSBlocking & 2) { // block not whitelisted
         jsEnabled = url && this.isJSEnabled(this.getSite(url)) || /^about:/.test(url);
@@ -6069,28 +6010,28 @@ var ns = {
         let site = this.getSite(url);
         jsEnabled = !(this.isUntrusted(site) || this.isForbiddenByHttpsStatus(site));
       } else return;
-      
+
       const prevStatus = docShell.allowJavascript;
       const BLOCKED_KEY = this.DOC_JS_STATUS_KEY;
       // Trying to be kind with other docShell-level blocking apps (such as Tab Mix Plus), we
       // check if we're the ones who actually blocked this docShell, or if this channel is out of our control
-      
+
       if (dump) this.dump("About to retrieve previously blocked info...");
       let prevBlocked = requireNetwork && (req.loadFlags & req.LOAD_REPLACE)
                             && IOUtil.extractFromChannel(req, BLOCKED_KEY, true) ||
                       this.getExpando(win, BLOCKED_KEY);
-                            
-      
+
+
       prevBlocked = prevBlocked ? prevBlocked.value : "?";
 
       if (dump)
         this.dump("DocShell JS Switch: " + url + " - " + jsEnabled + "/" + prevStatus + "/" + prevBlocked);
-      
+
       if (jsEnabled && !prevStatus) {
-        
+
         // be nice with other blockers
         if (!prevBlocked) return;
-        
+
         // purge body events
         try {
           var aa = win.document.body && win.document.body.attributes;
@@ -6112,8 +6053,8 @@ var ns = {
                 };
       dsjsBlocked.wrappedJSObject = dsjsBlocked;
       IOUtil.attachToChannel(req, BLOCKED_KEY, dsjsBlocked);
-      
-      
+
+
       ABE.sandbox(docShell, false);
       docShell.allowJavascript = jsEnabled;
     } catch(e2) {
@@ -6121,38 +6062,38 @@ var ns = {
         this.dump("Error switching docShell JS: " + e2 + e2.stack);
     }
   },
-  
+
   _pageModMaskRx: /^(?:chrome|resource|view-source):/,
   onWindowSwitch: function(url, win, docShell) {
     let channel = docShell.currentDocumentChannel;
-    
+
     if (IOUtil.extractFromChannel(channel, "noscript.xssChecked", true) &&
         this.filterBadCharsets(docShell)) return;
-    
+
     const doc = docShell.document;
     const flag = "__noScriptEarlyScripts__";
     if (flag in doc && doc[flag] === url) return;
     doc[flag] = url;
-   
+
     const site = this.getSite(url);
     var jsBlocked = !(docShell.allowJavascript && (this.jsEnabled || this.isJSEnabled(site, doc.defaultView)));
-    
-    
-    
+
+
+
     if (!((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument)) {
       // likely a document.open() page
       url = "wyciwyg:"; // don't execute on document.open() pages with a misleading URL
       jsBlocked = false;
     }
-    
-    if (this._pageModMaskRx.test(url)) return; 
-    
+
+    if (this._pageModMaskRx.test(url)) return;
+
     var scripts;
-    
+
     if (jsBlocked) {
-      
+
       this.blockEvents(doc.defaultView);
-      
+
       if (this.getPref("fixLinks")) {
         let newWin = doc.defaultView;
         newWin.addEventListener("click", this.bind(this.onContentClick), true);
@@ -6164,12 +6105,12 @@ var ns = {
         scripts = [this._toStaticHTMLDef];
         doc.addEventListener("NoScript:toStaticHTML", this._toStaticHTMLHandler, false, true);
       }
-      
+
       let dntPatch = DoNotTrack.getDOMPatch(docShell);
       if (dntPatch) {
         (scripts || (scripts = [])).push(dntPatch);
       }
-      
+
       if (this.forbidWebGL &&
           !(this.isAllowedObject(site, "WebGL", site, site) || this.isAllowedMime("WebGL", site))
         ) {
@@ -6180,7 +6121,7 @@ var ns = {
           this._webGLRecord(doc, site);
         }
       }
-        
+
       if (this.contentBlocker) {
         if (this.liveConnectInterception && this.forbidJava &&
             !this.isAllowedObject(site, "application/x-java-vm", site, site)) {
@@ -6191,44 +6132,42 @@ var ns = {
             !this.isAllowedObject(site, "audio/ogg", site, site))
           (scripts || (scripts = [])).push(this._audioApiInterceptionDef);
       }
-      
-      if (this.forbidFlash && this.flashPatch) 
+
+      if (this.forbidFlash && this.flashPatch)
         (scripts || (scripts = [])).push(this._flashPatch);
-      
+
       if (this.forbidSilverlight && this.silverlightPatch)
         (scripts || (scripts = [])).push(this._silverlightPatch);
 
       if( this.jsHackRegExp && this.jsHack && this.jsHackRegExp.test(url))
           (scripts || (scripts = [])).push(this.jsHack);
-          
+
       if (IOUtil.extractFromChannel(channel, "noscript.protectName") && this.getPref("protectWindowNameXAssignment")) {
         (scripts || (scripts = [])).push(this._protectNamePatch);
       }
     }
-    
+
     ScriptSurrogate.apply(doc, url, url, jsBlocked, scripts);
   },
-  
+
   onWindowCreated: function(window, site) {
     this.beforeScripting(window, site);
     (this.onWindowCreated = this._onWindowCreatedReal).apply(this, arguments);
   },
-  
+
   isBrowserOrigin: function(origin) /^(?:\[System Principal\]$|moz-safe-about:)/.test(origin),
-  
-  _onWindowCreatedReal: function(window, site) {
+
+  mustBlockJS(window, site, blocker) {
     let document = window.document;
     let origin = this.getPrincipalOrigin(document);
-    if (this.isBrowserOrigin(origin)) return;
+    if (this.isBrowserOrigin(origin)) return false;
     let blockIt;
-    let blocker = WinScript.supported ? WinScript : DocShellScript;
-    
-    if (this.consoleDump) ns.dump("Window created, origin: " + origin + ", site: " + site + ", URL: " + document.URL + ", location: " + window.location.href);
-    
+    if (this.consoleDump) this.dump("Window created, origin: " + origin + ", site: " + site + ", URL: " + document.URL + ", location: " + window.location.href);
+
     site = this.getSite(origin || site);
     if (site === 'moz-nullprincipal:') {
       site = this.getSite(document.URL);
-      
+
       if (!site) {
         // "special" URI (e.g. data:), let's use opener
         let docShell = DOM.getDocShellForWindow(window);
@@ -6239,9 +6178,9 @@ var ns = {
         }
       }
     }
-    
+
     window._NoScriptSite = site;
-     
+
     if (this.globalHttpsWhitelist && this.isGlobalHttps(window)) {
       blockIt = false;
     } else {
@@ -6257,45 +6196,28 @@ var ns = {
         }
       }
     }
-    
+
     if (typeof blockIt === "undefined")
       blockIt = !site || (this.usingCAPS && !this.restrictSubdocScripting ? this.isUntrusted(site) : !this.isJSEnabled(site));
-    
-    if (blockIt) {
+
+    return blockIt;
+  },
+
+  _onWindowCreatedReal: function(window, site) {
+    const blocker = WinScript.supported ? WinScript : DocShellScript;
+    if (this.mustBlockJS(window, site, blocker)) {
       blocker.block(window);
-      this._patchStyle(document);
     } else {
       blocker.unblock(window);
     }
   },
-  
-  _domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
-  _patchStyle: function(doc) {
-    let ss = this._domUtils.getAllStyleSheets(doc);
-    // reverse loop because the preference stylesheet is almost always the last one
-    for (let j = ss.length; j-- > 0;) { 
-      let s = ss[j];
-      if(s.href === "about:PreferenceStyleSheet") {
-          let rules = s.cssRules;
-          // skip 1st & 2nd, as they are HTML & SVG namespaces
-          for (let j = 2, len = rules.length; j < len; j++) {
-              let r = rules[j];
-              if (r.cssText === "noscript { display: none ! important; }") {
-                  s.deleteRule(j);
-                  break;
-              }
-          }
-          break;
-      }
-    }
- },
-  
+
   beforeScripting: function(subj, url) { // early stub
     INCLUDE("ScriptlessBGThumbs");
     if (!this.httpStarted) {
-      
+
       let url = subj.location || subj.documentURI;
-      
+
       if (/^(?:about|resource|chrome|file|moz-nullprincipal):/.test(url)) {
         if (/^file|moz-/.test(url))
           this.initContentPolicy(true);
@@ -6303,7 +6225,7 @@ var ns = {
       }
       if (this.consoleDump) ns.dump(url);
       this.requestWatchdog; // kickstart networking stuff
-      
+
     }
     this.executeEarlyScripts = this.onWindowSwitch;
     // replace legacy code paths
@@ -6321,16 +6243,16 @@ var ns = {
       this.executeEarlyScripts(docShell.document.documentURI, win, docShell);
     }
   },
-  
+
   blockEvents: function(window) {
     let et = ["start", "finish", "bounce"],
         eh = function(e) {  e.preventDefault(); e.stopPropagation(); };
-    
+
     return (this.blockEvents = function(window) {
       for each(let t in et) window.addEventListener(t, eh, true);
     })(window);
   },
-  
+
   get sanitizeHTML() {
     delete this.sanitizeHTML;
     return this.sanitizeHTML = ("nsIParserUtils" in Ci)
@@ -6390,7 +6312,7 @@ var ns = {
       }
     ).toString();
   },
-  
+
   _webGLSites: {},
   _webGLHandler: function(ev) {
     ns._webGLRecord(ev.target, ns.getSite(ev.target.documentURI || ev.target.ownerDocument.documentURI), true);
@@ -6400,7 +6322,7 @@ var ns = {
       url: site,
       site: site,
       originSite: site,
-      mime: "WebGL"            
+      mime: "WebGL"
     });
     let doc = ctx.ownerDocument || ctx;
     if (fromDOM) {
@@ -6419,7 +6341,7 @@ var ns = {
       var proto = HTMLCanvasElement.prototype;
       var getContext = proto.getContext;
       proto.getContext = function(type) {
-        
+
         if (type && type.toString().indexOf("webgl") !== -1) {
           var ev = this.ownerDocument.createEvent("Events");
           ev.initEvent("NoScript:WebGL", true, false);
@@ -6431,7 +6353,7 @@ var ns = {
       }
     }.toSource() + "()";
   },
-  
+
   liveConnectInterception: true,
   get _liveConnectInterceptionDef() {
     delete this._liveConnectInterceptionDef;
@@ -6450,7 +6372,7 @@ var ns = {
         w.__defineGetter__("java", k);
         w.__defineGetter__("Packages", k);
       }
-      
+
       try {
         dp(true);
         w.__defineGetter__("java", g);
@@ -6469,42 +6391,40 @@ var ns = {
   _disablePlugins: function(b) {
     ns.plugins.disabled = b;
   },
-  
+
   get plugins() {
     delete this.plugins;
     INCLUDE("Plugins");
     return this.plugins = Plugins;
   },
-  
+
   beforeManualAllow: function(win) {
     // reset prevBlock info, to forcibly allow docShell JS
     this.setExpando(win.document, "prevBlocked", { value: "m" });
   },
-  
+
   handleErrorPage: function(win, uri) {
     win = win && win.contentWindow || win;
     if (!win) return;
     var docShell = DOM.getDocShellForWindow(win);
     if (!docShell) return;
-    
+
     docShell.allowJavascript = true;
-    
-    if (!this.getPref("STS.expertErrorUI"))
-      STS.patchErrorPage(docShell, uri);
+
   },
-  
-  
+
+
   // start nsIWebProgressListener
-  
+
 
   onLinkIconAvailable: DUMMY_FUNC,
   onStateChange: function(wp, req, stateFlags, status) {
     var ph;
-    
+
     if (stateFlags & WP_STATE_START) {
       if (req instanceof Ci.nsIChannel) {
         // handle docshell JS switching and other early duties
-        
+
         if (PolicyState.isChecking(req.URI)) {
           // ContentPolicy couldn't complete! DOS attack?
           PolicyState.removeCheck(req.URI);
@@ -6512,9 +6432,9 @@ var ns = {
           this.log("Aborted " + req.URI.spec + " on start, possible DOS attack against content policy.");
           return;
         }
-        
+
         PolicyState.attach(req); // this is needed after bug 797684 fix, because http observers are notified later
-        
+
         if ((stateFlags & WP_STATE_START_DOC) == WP_STATE_START_DOC) {
           if (!(req instanceof Ci.nsIHttpChannel) && (
                 // prevent about:newTab breakage
@@ -6523,10 +6443,10 @@ var ns = {
                 req.URI.equals(DOM.browserWinURI)
               )
             ) return;
-          
+
           let w = wp.DOMWindow;
           if (w) {
-           
+
             if (w != w.top && w.frameElement) {
               ph = ph || PolicyState.extract(req);
               if (ph && this.shouldLoad(7, req.URI, ph.requestOrigin, w.frameElement, ph.mimeType, CP_FRAMECHECK) != CP_OK) { // late frame/iframe check
@@ -6536,13 +6456,13 @@ var ns = {
             }
             this._handleDocJS(w, req, false);
           }
-        } 
+        }
       }
     } else if ((stateFlags & WP_STATE_STOP))  {
       // STOP REQUEST
       if (req instanceof Ci.nsIHttpChannel) {
         this.cleanupRequest(req);
-      
+
         if (status === NS_ERROR_CONNECTION_REFUSED || status === NS_ERROR_NOT_AVAILABLE ||
             status === NS_ERROR_UNKNOWN_HOST) { // evict host from DNS cache to prevent DNS rebinding
           try {
@@ -6559,14 +6479,14 @@ var ns = {
       }
     }
   },
-  
+
   onLocationChange: function(wp, req, location) {
     if (req && (req instanceof Ci.nsIChannel)) try {
       let w = wp.DOMWindow;
       if (this.consoleDump & LOG_JS)
         this.dump("Location Change - req.URI: " + req.URI.spec + ", window.location: " +
                 (w && w.location.href) + ", location: " + location.spec);
-       
+
       this.setExpando(w, this.DOC_JS_STATUS_KEY, IOUtil.extractFromChannel(req, this.DOC_JS_STATUS_KEY, false));
       this.onBeforeLoad(req, w, location);
     } catch(e) {
@@ -6576,7 +6496,7 @@ var ns = {
   onLocationChange2: function(wp, req, location, flags) {
     this.onLocationChange(wp, req, location);
   },
-  
+
   onStatusChange: function(wp, req, status, msg) {
     if (status == 0x804b0003 && (req instanceof Ci.nsIChannel) && !ABE.isDeferred(req)) { // DNS resolving, check if we need to clear the cache
       try {
@@ -6593,18 +6513,18 @@ var ns = {
       } catch (e) {}
     }
   },
-  onSecurityChange: DUMMY_FUNC, 
+  onSecurityChange: DUMMY_FUNC,
   onProgressChange: DUMMY_FUNC,
   onRefreshAttempted: function(wp, uri, delay, sameURI) {
     if (delay == 0 && !sameURI)
       return true; // poor man's redirection
-    
+
     var pref = this.getPref("forbidBGRefresh");
     try {
       if (!pref || this.prefService.getBoolPref("accessibility.blockautorefresh"))
         return true; // let the browser do its thing
     } catch(e) {}
-    
+
     var win = wp.DOMWindow;
     var currentURL = win.location.href;
     if (!this.appliesHere(pref, currentURL))
@@ -6613,19 +6533,19 @@ var ns = {
     var browserWin = DOM.mostRecentBrowserWindow;
     if (!(browserWin && "noscriptOverlay" in browserWin))
       return true; // not a regular browser window
-    
+
     var exceptions = new AddressMatcher(this.getPref("forbidBGRefresh.exceptions"));
     if (exceptions && exceptions.test(currentURL))
       return true;
-    
+
     var browser = DOM.findBrowserForNode(win);
     var currentBrowser = browserWin.noscriptOverlay.currentBrowser;
     var docShell = DOM.getDocShellForWindow(win);
-        
+
     var uiArgs = Array.slice(arguments);
-    
+
     var ts = Date.now();
-    
+
     if (browser == currentBrowser) {
       win.addEventListener("blur", function(ev) {
         ev.currentTarget.removeEventListener(ev.type, arguments.callee, false);
@@ -6634,8 +6554,8 @@ var ns = {
       }, false);
       return true; // OK, this is the foreground tab
     }
-    
-    
+
+
      function hookFocus(bg) {
       ns.log("[NoScript] Blocking refresh on unfocused tab, " + currentURL + "->" + uri.spec, false);
       win.addEventListener("focus", function(ev) {
@@ -6651,9 +6571,9 @@ var ns = {
     }
     hookFocus(true);
     return false;
-  },  
+  },
   // end nsIWebProgressListener
-  
+
   _badCharsetRx: /\bUTF-?7\$|^armscii-8$/i,
   _goodCharsetRx: /^UTF-?8$/i,
   filterBadCharsets: function(docShell) {
@@ -6665,9 +6585,9 @@ var ns = {
       } catch (e) {
         cs = docShell.document.characterSet;
       }
-      
+
       if (this._goodCharsetRx.test(cs)) return false;
-      
+
       if(this._badCharsetRx.test(cs)) {
         this.log("[NoScript XSS] Neutralizing bad charset " + cs);
       } else {
@@ -6678,11 +6598,11 @@ var ns = {
           let exceptions = this.getPref("xss.checkCharset.exceptions");
           if (exceptions && AddressMatcher.create(exceptions).test(url)) return false;
         } catch (e) {}
-        
+
         let ic = this.injectionChecker;
         let unicode = /^UTF-?16/i.test(cs) && url.indexOf("\0") !== -1;
         let le = unicode && /LE$/i.test(cs);
-        
+
         function decode(u) {
           if (unicode) {
             let pos = u.indexOf("\0");
@@ -6693,14 +6613,14 @@ var ns = {
           }
           return ic.toUnicode(u, cs);
         }
-        
+
         function check(original, decoded) original === decoded || !ic.checkRecursive(decoded, 1);
-        
+
         let [filePath, query, ref] = ["filePath", "query", "ref"].map(function(p) unescape(uri[p]));
-        
+
         if ( // check...
             // ...whole URL
-            check(url, decode(url)) && 
+            check(url, decode(url)) &&
             // ...whole path
             check(filePath, decode(filePath)) &&
             // ...path parts
@@ -6712,7 +6632,7 @@ var ns = {
             // ... fragment
             check(ref, decode(ref))
           ) return false;
-            
+
         this.log("[NoScript XSS] Potential XSS with charset " + cs + ", aborting request");
       }
       /*
@@ -6730,11 +6650,11 @@ var ns = {
     }
     return false;
   },
-  
+
   _attemptNavigationInternal: function(doc, destURL, callback) {
     var cs = doc.characterSet;
     var uri = IOS.newURI(destURL, cs, IOS.newURI(doc.documentURI, cs, null));
-    
+
     if (/^https?:\/\//i.test(destURL)) callback(doc, uri);
     else {
       var done = false;
@@ -6755,21 +6675,21 @@ var ns = {
     // delay is needed on Gecko < 1.9 to detach browser context
     this.delayExec(this._attemptNavigationInternal, 0, doc, destURL, callback);
   },
-  
+
   // simulate onchange on selects if options look like URLs
   onContentChange: function(ev) {
     var s = ev.originalTarget;
     if (!(s instanceof Ci.nsIDOMHTMLSelectElement) ||
         s.hasAttribute("multiple") ||
         !/open|nav|location|\bgo|load/i.test(s.getAttribute("onchange"))) return;
-    
+
     var doc = s.ownerDocument;
     var url = doc.documentURI;
     if (this.isJSEnabled(this.getSite(url), doc.defaultView)) return;
-    
+
     var opt = s.options[s.selectedIndex];
     if (!opt) return;
-    
+
     if (/[\/\.]/.test(opt.value) && opt.value.indexOf("@") < 0) {
       this.attemptNavigation(doc, opt.value, function(doc, uri) {
         doc.defaultView.location.href = uri.spec;
@@ -6777,26 +6697,26 @@ var ns = {
       ev.preventDefault();
     }
   },
-  
+
   onContentClick: function(ev) {
-    
+
     if (ev.button == 2) return;
-    
+
     var a = ev.originalTarget;
-    
+
     if (a.__noscriptFixed) return;
-    
+
     var doc = a.ownerDocument;
     var url = doc.documentURI;
     if (this.isJSEnabled(this.getSite(url))) return;
-    
+
     var onclick;
-    
+
     while (!(a instanceof Ci.nsIDOMHTMLAnchorElement || a instanceof Ci.nsIDOMHTMLAreaElement)) {
       if (typeof(a.getAttribute) == "function" && (onclick = a.getAttribute("onclick"))) break;
       if (!(a = a.parentNode)) return;
     }
-    
+
     const href = a.getAttribute("href");
     // fix JavaScript links
     var jsURL;
@@ -6806,19 +6726,19 @@ var ns = {
     } else {
       jsURL = "";
     }
-    
+
     onclick = onclick || a.getAttribute("onclick");
-    var fixedHref = (onclick && this.extractJSLink(onclick)) || 
+    var fixedHref = (onclick && this.extractJSLink(onclick)) ||
                      (jsURL && this.extractJSLink(href)) || "";
-    
+
     onclick = onclick || href;
-    
+
     if (/\bsubmit\s*\(\s*\)/.test(onclick)) {
       var form;
       if (fixedHref) {
         form = doc.getElementById(fixedHref); // youtube
         if (!(form instanceof Ci.nsIDOMHTMLFormElement)) {
-          form = doc.forms.namedItem(fixedHref);   
+          form = doc.forms.namedItem(fixedHref);
         }
       }
       if (!form) {
@@ -6834,25 +6754,25 @@ var ns = {
       }
       return;
     }
-    
+
     if (fixedHref) {
       var callback;
       if (/^(?:button|input)$/i.test(a.tagName)) { // JS button
         if (a.type == "button" || (a.type == "submit" && !a.form)) {
-          callback = function(doc, uri) { doc.defaultView.location.href = uri.spec; }; 
+          callback = function(doc, uri) { doc.defaultView.location.href = uri.spec; };
         } else return;
       } else {
         var evClone = doc.createEvent("MouseEvents");
-        evClone.initMouseEvent("click",ev.canBubble, ev.cancelable, 
-                           ev.view, ev.detail, ev.screenX, ev.screenY, 
-                           ev.clientX, ev.clientY, 
+        evClone.initMouseEvent("click",ev.canBubble, ev.cancelable,
+                           ev.view, ev.detail, ev.screenX, ev.screenY,
+                           ev.clientX, ev.clientY,
                            ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey,
                            ev.button, ev.relatedTarget);
         callback =
           function(doc, uri) {
             a.setAttribute("href", fixedHref);
             var title = a.getAttribute("title");
-            a.setAttribute("title", title ? "[js] " + title : 
+            a.setAttribute("title", title ? "[js] " + title :
               (onclick || "") + " " + href
             );
             a.dispatchEvent(ev = evClone); // do not remove "ev = " -- for some reason, it works this way only :/
@@ -6865,9 +6785,9 @@ var ns = {
       }
     } else { // try processing history.go(n) //
       if(!onclick) return;
-      
+
       jsURL = onclick.match(/history\s*\.\s*(?:go\s*\(\s*(-?\d+)\s*\)|(back|forward)\s*\(\s*)/);
-      jsURL = jsURL && (jsURL = jsURL[1] || jsURL[2]) && (jsURL == "back" ? -1 : jsURL == "forward" ? 1 : jsURL); 
+      jsURL = jsURL && (jsURL = jsURL[1] || jsURL[2]) && (jsURL == "back" ? -1 : jsURL == "forward" ? 1 : jsURL);
 
       if (!jsURL) return;
       // jsURL now has our relative history index, let's navigate
@@ -6876,14 +6796,14 @@ var ns = {
       if (!docShell) return;
       var sh = docShell.sessionHistory;
       if (!sh) return;
-      
+
       var idx = sh.index + jsURL;
-      if (idx < 0 || idx >= sh.count) return; // out of history bounds 
+      if (idx < 0 || idx >= sh.count) return; // out of history bounds
       docShell.gotoIndex(idx);
       ev.preventDefault(); // probably not needed
     }
   },
-  
+
   extractJSLink: function(js) {
     const findLink = /(['"])(.*?)\1/g;
     const badURIChar = /[^\/\w-\?\.#%=&:@]/;
@@ -6903,39 +6823,39 @@ var ns = {
     }
     return href || "";
   },
-  
-  
+
+
   checkLocalLink: function(url, principal, fromPolicy) {
-    
+
     if (!this.allowLocalLinks || this.supportsCAPS && !fromPolicy)
       return fromPolicy;
-    
+
     if (url instanceof Ci.nsIURI) {
       if (!url.schemeIs("file")) return fromPolicy;
       url = url.spec;
     } else if (typeof url !== "string" || url.indexOf("file:///") !== 0) return fromPolicy;
     let site = principal.URI ? principal.URI.spec : principal.origin;
-    
+
     if (!/^(ht|f)tps?:/.test(site)) return fromPolicy;
-    
+
     let [to, from] = [ AddressMatcher.create(this.getPref("allowLocalLinks." + n, ""))
                         for each (n in ["to", "from"]) ];
-    
+
     return ((from
               ? from.test(site)
               : this.isJSEnabled(this.getSite(principal.origin)))
         && (!to || to.test(url))
       );
   },
-  
+
   createXSanitizer: function() {
     return new XSanitizer(this.filterXGetRx, this.filterXGetUserRx);
   },
-  
+
   get externalFilters() {
     delete this.externalFilters;
     if (("nsIProcess2" in Ci || // Fx 3.5
-         "runAsync" in Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess) // Fx >= 3.6 
+         "runAsync" in Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess) // Fx >= 3.6
         )) {
       INCLUDE("ExternalFilters");
       this.externalFilters = ExternalFilters;
@@ -6943,7 +6863,7 @@ var ns = {
     } else this.externalFilters = { enabled: false, supported: false };
     return this.externalFilters;
   },
-  
+
   callExternalFilters: function(ch, cached) {
     var ph = PolicyState.extract(ch);
     if (ph) {
@@ -6953,11 +6873,11 @@ var ns = {
       }
     }
   },
-  
+
   switchExternalFilter: function(filterName, domain, enabled) {
     var f = this.externalFilters.byName(filterName);
     if (!f) return;
-    
+
     var done;
     if (enabled) {
       done = f.removeDomainException(domain);
@@ -6965,12 +6885,12 @@ var ns = {
       done = f.addDomainException(domain);
     }
     if (!done) return;
-    
+
     this.delayExec(this.traverseObjects, 0,
       function(p) {
         const info = this.externalFilters.getObjFilterInfo(p);
         if (!info) return;
-        
+
         if (this.getBaseDomain(this.getDomain(info.url)) == domain) {
           this.externalFilters.log("Reloading object " + info.url);
           var anchor = p.nextSibling;
@@ -6979,7 +6899,7 @@ var ns = {
         }
       }, this);
   },
-  
+
   get compatEvernote() {
     delete this.compatEvernote;
     return this.compatEvernote = ("IWebClipper3" in Ci) && this.getPref("compat.evernote") && {
@@ -6994,21 +6914,21 @@ var ns = {
       }
     }
   },
-  
+
   get compatGNotes() {
     delete this.compatGNotes;
     return this.compatGNotes = ("@google.com/gnotes/app-context;1" in Cc) && this.getPref("compat.gnotes") &&
       "http://www.google.com/notebook/static_files/blank.html";
   },
-  
+
   consoleService: Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService),
-  
+
   log: function(msg, dump) {
     if (msg.stack) msg += msg.stack;
     this.consoleService.logStringMessage(msg);
     if (dump) this.dump(msg, true);
   },
-  
+
   logError: function(e, dump, cat) {
     var se = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
     se.init(e.message, e.fileName, /^javascript:/i.test(e.fileName) ? e.fileName : null,
@@ -7016,7 +6936,7 @@ var ns = {
     if (dump && this.consoleDump) this.dump(e.message, true);
     this.consoleService.logMessage(se);
   },
- 
+
   dump: function(msg, noConsole) {
     if (!this.consoleDump) return;
     if (msg.stack) msg += msg.stack;
@@ -7024,30 +6944,30 @@ var ns = {
     dump(msg + "\n");
     if(this.consoleLog && !noConsole) this.log(msg);
   },
-  
+
   ensureUIVisibility: function() {
     const window =  DOM.mostRecentBrowserWindow;
     try {
       const document = window.document;
       const addonBar = document.getElementById("addon-bar");
       if (!addonBar) return false;
-      
+
       const tbbId = "noscript-tbb";
       let tbb = document.getElementById(tbbId);
       if (tbb) return false;
-      
+
       let navBar = document.getElementById("nav-bar");
-      
+
       let [bar, refId] =
         addonBar.collapsed && navBar && !navBar.collapsed || !this.getPref("statusIcon", true)
         ? [navBar, "urlbar-container"]
         : [addonBar, "status-bar"];
-      
+
       set = bar.currentSet.split(/\s*,\s*/);
       if (set.indexOf(tbbId) > -1) return false;
-      
+
       set.splice(set.indexOf(refId), 0, tbbId);
-      
+
       bar.setAttribute("currentset", bar.currentSet = set.join(","));
       document.persist(bar.id, "currentset");
       try {
@@ -7062,19 +6982,19 @@ var ns = {
       return false;
     }
   },
-  
+
   firstRun: false,
   versionChecked: false,
   checkVersion: function() {
     if (this.versionChecked) return;
     this.versionChecked = true;
-    
+
     if (!this.getPref("visibleUIChecked", false) && this.ensureUIVisibility())
       this.setPref("visibleUIChecked", true);
 
     const ver =  this.VERSION;
     const prevVer = this.getPref("version", "");
-    
+
     if ((this.firstRun = prevVer != ver)) {
       if (prevVer) try {
         this.onVersionChanged(prevVer);
@@ -7097,11 +7017,11 @@ var ns = {
                 ns.savePrefs();
                 return;
               }
-              
+
               var browser = DOM.mostRecentBrowserWindow.getBrowser();
               if (typeof(browser.addTab) != "function") return;
-             
-              
+
+
               var url = "https://" + domain + "/?ver=" + ver;
               var hh = "X-IA-Post-Install: " + name + " " + ver;
               if (prevVer) {
@@ -7109,15 +7029,15 @@ var ns = {
                 hh += "; updatedFrom=" + prevVer;
               }
               hh += "\r\n";
-              
+
               var hs = Cc["@mozilla.org/io/string-input-stream;1"] .createInstance(Ci.nsIStringInputStream);
-              hs.setData(hh, hh.length); 
-              
-              
+              hs.setData(hh, hh.length);
+
+
               var b = (browser.selectedTab = browser.addTab()).linkedBrowser;
               b.stop();
               b.webNavigation.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, hs);
-              
+
             },
             onDataAvailable: function() {}
           }, {});
@@ -7125,7 +7045,7 @@ var ns = {
       }
     }
   },
-  
+
   checkSubscriptions: function() {
     var lastCheck = this.getPref("subscription.last_check");
     var checkInterval = this.getPref("subscription.checkInterval", 24) * 60000;
@@ -7134,7 +7054,7 @@ var ns = {
       this.delayExec(checkSubscriptions, lastCheck + checkInterval - now + 1000);
       return;
     }
-    
+
     function load(list, process, goOn) {
       var url = ns.getPref("subscription." + list + "URL");
       if (!url) {
@@ -7157,7 +7077,7 @@ var ns = {
       });
       xhr.send(null);
     }
-    
+
     load("untrusted",
       function(trusted, untrusted) {
         ns.untrustedSites.sitesString += " " + untrusted;
@@ -7181,5 +7101,5 @@ var ns = {
 ns.wrappedJSObject = ns;
 ns.__global__ = this; // debugging helper necessary on Gecko >= 13
 ns._e = function(f) {
-  return eval("(" + f + ")()"); 
+  return eval("(" + f + ")()");
 }
diff --git a/defaults/preferences/noscript.js b/defaults/preferences/noscript.js
index 3add348..8589835 100644
--- a/defaults/preferences/noscript.js
+++ b/defaults/preferences/noscript.js
@@ -29,7 +29,7 @@ pref("noscript.showBlockedObjects", true);
 pref("noscript.showExternalFilters", true);
 pref("noscript.showTempAllowPage", true);
 pref("noscript.showAllowPage", true);
-pref("noscript.mandatory", "chrome: blob: mediasource: moz-safe-about: about: about:addons about:blocked about:crashes about:home about:config about:neterror about:certerror about:memory about:plugins about:privatebrowsing about:sessionrestore about:support resource: about:srcdoc");
+pref("noscript.mandatory", "chrome: blob: mediasource: moz-safe-about: about: about:addons about:blocked about:crashes about:home about:config about:neterror about:certerror about:memory about:plugins about:preferences about:privatebrowsing about:sessionrestore about:support resource: about:srcdoc");
 pref("noscript.default", "about:blank addons.mozilla.org persona.org mozilla.net flashgot.net google.com gstatic.com googleapis.com paypal.com paypalobjects.com securecode.com securesuite.net firstdata.com firstdata.lv informaction.com yahoo.com yimg.com yahooapis.com youtube.com ytimg.com googlevideo.com maone.net noscript.net hotmail.com msn.com passport.com passport.net passportimages.com live.com live.net outlook.com afx.ms gfx.ms sfx.ms wlxrs.com ajax.aspnetcdn.com bootstrapcdn.com  [...]
 
 pref("noscript.allowWhitelistUpdates", true);
@@ -189,7 +189,7 @@ pref("noscript.jsHackRegExp", "");
 pref("noscript.canonicalFQDN", false);
 
 pref("noscript.allowedMimeRegExp", "");
-pref("noscript.alwaysBlockUntrustedContent", true); 
+pref("noscript.alwaysBlockUntrustedContent", true);
 
 pref("noscript.consoleLog", false);
 
@@ -253,6 +253,8 @@ pref("noscript.sanitizePaste", true);
 pref("noscript.surrogate.enabled", true);
 pref("noscript.surrogate.debug", false);
 pref("noscript.surrogate.sandbox", true);
+pref("noscript.surrogate.2mdn.replacment", "if('Proxy' in window){let _f=function(){};google={};Object.defineProperty(google,'__noSuchMethod__',{configurable:true,enumerable:false,value:_f});let ima={};ima.AdsManagerLoadedEvent=ima.AdErrorEvent={Type:new Proxy({},{get:function(){return 0}}),};ima.AdsLoader=ima.AdsRequest=ima.AdDisplayContainer=function(){return new Proxy({},{get:function(){return _f}});};google.ima=ima;}")
+pref("noscript.surrogate.2mdn.sources", ".2mdn.net");
 pref("noscript.surrogate.360Haven.sources", "@www.360haven.com");
 pref("noscript.surrogate.360Haven.replacement", "Object.defineProperty(window,'adblock',{get:function() false,set: function() false});Object.defineProperty(window,'google_ad_client',{get: function () { return {__noSuchMethod__: function() this}}});Object.defineProperty(window.HTMLBodyElement.prototype,'innerHTML',{get:function() ''});");
 pref("noscript.surrogate.adagionet.sources", ".adagionet.com");
@@ -389,9 +391,6 @@ pref("noscript.recentlyBlockedCount", 10);
 pref("noscript.showRecentlyBlocked", true);
 pref("noscript.recentlyBlockedLevel", 0);
 
-pref("noscript.STS.enabled", true);
-pref("noscript.STS.expertErrorUI", false);
-
 pref("noscript.frameOptions.enabled", true);
 pref("noscript.frameOptions.parentWhitelist", "https://mail.google.com/*");
 pref("noscript.logDNS", false);
@@ -430,4 +429,4 @@ pref("noscript.ABE.migration", 0);
 
 pref("noscript.smartClickToPlay", true);
 
-pref("noscript.removalWarning", true);
\ No newline at end of file
+pref("noscript.removalWarning", true);
diff --git a/install.rdf b/install.rdf
index 3351ac5..2682a42 100644
--- a/install.rdf
+++ b/install.rdf
@@ -5,7 +5,7 @@
  
    <em:id>{73a6fe31-595d-460b-a920-fcc0f8843232}</em:id>
    <em:name>NoScript</em:name>
-   <em:version>2.6.9.22</em:version>
+   <em:version>2.6.9.23rc1</em:version>
    <em:description>Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach  prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)</em:description>
    <em:creator>Giorgio Maone</em:creator>
    <em:type>2</em:type>
@@ -14,7 +14,7 @@
    <em:contributor>Algimantas Margevi&#x10d;ius (Lithuanian translation)</em:contributor> 
    <em:contributor>Asaf Bartov & baryoni (Hebrew translation)</em:contributor>
    <em:contributor>Alf and Liesbeth (Dutch translation)</em:contributor>
-   <em:contributor>Alexander Sokolov and Sergei Smirnov (Russian translation)</em:contributor>
+   <em:contributor>Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</em:contributor>
    <em:contributor>Batuhan Çetin and eveterinary (Turkish translation)</em:contributor>
    <em:contributor>Baurzhan Muftakhidinov (Kazakh translation)</em:contributor>
    <em:contributor>Beerboy & Haebaru (Japanese translation)</em:contributor>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/noscript.git



More information about the Pkg-mozext-commits mailing list