Index: lib/contentPolicy.js |
=================================================================== |
--- a/lib/contentPolicy.js |
+++ b/lib/contentPolicy.js |
@@ -162,6 +162,7 @@ |
let wndLocation = originWindow.location.href; |
let docDomain = getHostname(wndLocation); |
let match = null; |
+ let [sitekey, sitekeyWnd] = getSitekey(wnd); |
if (!match && Prefs.enabled) |
{ |
let testWnd = wnd; |
@@ -170,29 +171,7 @@ |
{ |
let testWndLocation = parentWndLocation; |
parentWndLocation = (testWnd == testWnd.parent ? testWndLocation : getWindowLocation(testWnd.parent)); |
- match = Policy.isWhitelisted(testWndLocation, parentWndLocation); |
- |
- if (!(match instanceof WhitelistFilter)) |
- { |
- let keydata = (testWnd.document && testWnd.document.documentElement ? testWnd.document.documentElement.getAttribute("data-adblockkey") : null); |
- if (keydata && keydata.indexOf("_") >= 0) |
- { |
- let [key, signature] = keydata.split("_", 2); |
- let keyMatch = defaultMatcher.matchesByKey(testWndLocation, key.replace(/=/g, ""), docDomain); |
- if (keyMatch && Utils.crypto) |
- { |
- // Website specifies a key that we know but is the signature valid? |
- let uri = Services.io.newURI(testWndLocation, null, null); |
- let params = [ |
- uri.path.replace(/#.*/, ""), // REQUEST_URI |
- uri.asciiHost, // HTTP_HOST |
- Utils.httpProtocol.userAgent // HTTP_USER_AGENT |
- ]; |
- if (Utils.verifySignature(key, signature, params.join("\0"))) |
- match = keyMatch; |
- } |
- } |
- } |
+ match = Policy.isWhitelisted(testWndLocation, parentWndLocation, sitekey); |
if (match instanceof WhitelistFilter) |
{ |
@@ -204,7 +183,11 @@ |
if (testWnd.parent == testWnd) |
break; |
else |
+ { |
+ if (testWnd == sitekeyWnd) |
+ [sitekey, sitekeyWnd] = getSitekey(testWnd.parent); |
testWnd = testWnd.parent; |
+ } |
} |
} |
@@ -260,7 +243,7 @@ |
if (!match && Prefs.enabled) |
{ |
- match = defaultMatcher.matchesAny(locationText, Policy.typeDescr[contentType] || "", docDomain, thirdParty); |
+ match = defaultMatcher.matchesAny(locationText, Policy.typeDescr[contentType] || "", docDomain, thirdParty, sitekey); |
if (match instanceof BlockingFilter && node.ownerDocument && !(contentType in Policy.nonVisual)) |
{ |
let prefCollapse = (match.collapse != null ? match.collapse : !Prefs.fastcollapse); |
@@ -297,10 +280,11 @@ |
/** |
* Checks whether a page is whitelisted. |
* @param {String} url |
- * @param {String} [parentUrl] location of the parent page |
+ * @param {String} (optional) parentUrl location of the parent page |
+ * @param {String} (optional) sitekey public key provided on the page |
* @return {Filter} filter that matched the URL or null if not whitelisted |
*/ |
- isWhitelisted: function(url, parentUrl) |
+ isWhitelisted: function(url, parentUrl, sitekey) |
{ |
if (!url) |
return null; |
@@ -318,7 +302,7 @@ |
if (index >= 0) |
url = url.substring(0, index); |
- let result = defaultMatcher.matchesAny(url, "DOCUMENT", getHostname(parentUrl), false); |
+ let result = defaultMatcher.matchesAny(url, "DOCUMENT", getHostname(parentUrl), false, sitekey); |
return (result instanceof WhitelistFilter ? result : null); |
}, |
@@ -329,10 +313,12 @@ |
*/ |
isWindowWhitelisted: function(wnd) |
{ |
- return Policy.isWhitelisted(getWindowLocation(wnd)); |
+ let url = getWindowLocation(wnd); |
+ let parentUrl = (wnd.parent) ? getWindowLocation(wnd.parent) : url; |
+ let [sitekey, sitekeyWnd] = getSitekey(wnd); |
+ return Policy.isWhitelisted(url, parentUrl, sitekey); |
}, |
- |
/** |
* Asynchronously re-checks filters for given nodes. |
*/ |
@@ -691,6 +677,50 @@ |
} |
/** |
+ * Retrieves the sitekey of a window. |
+ */ |
+function getSitekey(wnd) |
+{ |
+ let sitekey = null; |
+ |
+ if (Utils.crypto) |
+ { |
+ while (wnd) |
+ { |
+ if (wnd.document && wnd.document.documentElement) |
+ { |
+ let foundKey = wnd.document.documentElement.getAttribute("data-adblockkey"); |
+ if (foundKey && foundKey.indexOf("_") > - 1) |
+ { |
+ let [key, signature] = foundKey.split("_", 2); |
+ |
+ // Website specifies a key but is the signature valid? |
+ let uri = Services.io.newURI(getWindowLocation(wnd), null, null); |
+ let host = uri.asciiHost; |
+ if (uri.port > 0) |
+ host += ":" + uri.port; |
+ let params = [ |
+ uri.path.replace(/#.*/, ""), // REQUEST_URI |
+ host, // HTTP_HOST |
+ Utils.httpProtocol.userAgent // HTTP_USER_AGENT |
+ ]; |
+ if (Utils.verifySignature(key, signature, params.join("\0"))) |
+ sitekey = foundKey; |
+ } |
+ break; |
+ } |
+ |
+ if (wnd === wnd.top) |
+ break; |
+ |
+ wnd = wnd.parent; |
+ } |
+ } |
+ |
+ return [sitekey, wnd]; |
+} |
+ |
+/** |
* Retrieves the location of a window. |
* @param wnd {nsIDOMWindow} |
* @return {String} window location or null on failure |