| Index: lib/child/elemHide.js |
| =================================================================== |
| --- a/lib/child/elemHide.js |
| +++ b/lib/child/elemHide.js |
| @@ -11,17 +11,17 @@ |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| /** |
| - * @fileOverview Hit counts for element hiding. |
| + * @fileOverview Serves CSS for element hiding and processes hits. |
| */ |
| try |
| { |
| // Hack: SDK loader masks our Components object with a getter. |
| let proto = Object.getPrototypeOf(this); |
| let property = Object.getOwnPropertyDescriptor(proto, "Components"); |
| if (property && property.get) |
| @@ -36,22 +36,16 @@ let {XPCOMUtils} = Cu.import("resource:/ |
| let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
| let {shouldAllowAsync} = require("child/contentPolicy"); |
| let {getFrames, isPrivate} = require("child/utils"); |
| let {RequestNotifier} = require("child/requestNotifier"); |
| let {port} = require("messaging"); |
| let {Utils} = require("utils"); |
| -// The allowXBL binding below won't have any effect on the element. For elements |
| -// that should be hidden however we don't return any binding at all, this makes |
| -// Gecko stop constructing the node - it cannot be shown. |
| -const allowXBL = "<bindings xmlns='http://www.mozilla.org/xbl'><binding id='dummy' bindToUntrustedContent='true'/></bindings>"; |
| -const hideXBL = "<bindings xmlns='http://www.mozilla.org/xbl'/>"; |
| - |
| const notImplemented = () => Cr.NS_ERROR_NOT_IMPLEMENTED; |
| /** |
| * about: URL module used to count hits. |
| * @class |
| */ |
| let AboutHandler = |
| { |
| @@ -91,24 +85,28 @@ let AboutHandler = |
| getURIFlags: function(uri) |
| { |
| return Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT; |
| }, |
| newChannel: function(uri, loadInfo) |
| { |
| - let match = /\?(?:hit(\d+)|css)$/.exec(uri.path); |
| - if (!match) |
| - throw Cr.NS_ERROR_FAILURE; |
| + let match = /\?hit(\d+)$/.exec(uri.path); |
| + if (match) |
| + return new HitRegistrationChannel(uri, loadInfo, match[1]); |
| - if (match[1]) |
| - return new HitRegistrationChannel(uri, loadInfo, match[1]); |
| - else |
| - return new StyleDataChannel(uri, loadInfo); |
| + match = /\?css(?:=(.*?))?$/.exec(uri.path); |
| + if (match) |
| + { |
| + return new StyleDataChannel(uri, loadInfo, |
| + match[1] ? decodeURIComponent(match[1]) : null); |
| + } |
| + |
| + throw Cr.NS_ERROR_FAILURE; |
| }, |
| QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory, Ci.nsIAboutModule]) |
| }; |
| AboutHandler.init(); |
| /** |
| * Base class for channel implementations, subclasses usually only need to |
| @@ -210,65 +208,49 @@ BaseChannel.prototype = { |
| QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest]) |
| }; |
| /** |
| * Channel returning CSS data for the global stylesheet. |
|
kzar
2016/10/06 12:10:46
Nit: I guess this comment should be updated now it
Wladimir Palant
2016/10/06 12:27:28
Done.
|
| * @constructor |
| */ |
| -function StyleDataChannel(uri, loadInfo) |
| +function StyleDataChannel(uri, loadInfo, domain) |
| { |
| BaseChannel.call(this, uri, loadInfo); |
| + this._domain = domain; |
| } |
| StyleDataChannel.prototype = { |
| __proto__: BaseChannel.prototype, |
| contentType: "text/css", |
| + _domain: null, |
| _getResponse: function() |
| { |
| function escapeChar(match) |
| { |
| return "\\" + match.charCodeAt(0).toString(16) + " "; |
| } |
| // Would be great to avoid sync messaging here but nsIStyleSheetService |
| // insists on opening channels synchronously. |
| - let domains = port.emitSync("getSelectors"); |
| + let [selectors, keys] = (this._domain ? |
| + port.emitSync("getSelectorsForDomain", this._domain) : |
|
kzar
2016/10/06 12:10:46
Dumb question but how does getSelectorsForDomain a
Wladimir Palant
2016/10/06 12:27:28
This is the content process - we cannot require El
kzar
2016/10/06 13:02:32
Ah I see.
|
| + port.emitSync("getUnconditionalSelectors")); |
| let cssPrefix = "{-moz-binding: url(about:abp-elemhide?hit"; |
| let cssSuffix = "#dummy) !important;}\n"; |
| let result = []; |
| - for (let [domain, selectors] of domains) |
| + for (let i = 0; i < selectors.length; i++) |
| { |
| - if (domain) |
| - { |
| - result.push('@-moz-document domain("', |
| - domain.replace(/[^\x01-\x7F]/g, escapeChar) |
| - .split(",").join('"),domain("'), |
| - '"){\n'); |
| - } |
| - else |
| - { |
| - // Only allow unqualified rules on a few protocols to prevent them |
| - // from blocking chrome content |
| - result.push('@-moz-document url-prefix("http://"),', |
| - 'url-prefix("https://"),url-prefix("mailbox://"),', |
| - 'url-prefix("imap://"),url-prefix("news://"),', |
| - 'url-prefix("snews://"){\n'); |
| - } |
| - |
| - for (let [selector, key] of selectors) |
| - { |
| - result.push(selector.replace(/[^\x01-\x7F]/g, escapeChar), |
| - cssPrefix, key, cssSuffix); |
| - } |
| - |
| - result.push("}\n"); |
| + let selector = selectors[i]; |
| + let key = keys[i]; |
| + result.push(selector.replace(/[^\x01-\x7F]/g, escapeChar), |
| + cssPrefix, key, cssSuffix); |
| } |
| return result.join(""); |
| } |
| }; |
| /** |
| * Channel returning data for element hiding hits. |
| @@ -281,24 +263,27 @@ function HitRegistrationChannel(uri, loa |
| } |
| HitRegistrationChannel.prototype = { |
| __proto__: BaseChannel.prototype, |
| key: null, |
| contentType: "text/xml", |
| _getResponse: function() |
| { |
| - return new Promise((resolve, reject) => |
| + let window = Utils.getRequestWindow(this); |
| + port.emitWithResponse("registerElemHideHit", { |
| + key: this.key, |
| + frames: getFrames(window), |
| + isPrivate: isPrivate(window) |
| + }).then(hit => |
| { |
| - let window = Utils.getRequestWindow(this); |
| - shouldAllowAsync(window, window.document, "ELEMHIDE", this.key, allow => |
| - { |
| - resolve(allow ? allowXBL : hideXBL); |
| - }); |
| + if (hit) |
| + RequestNotifier.addNodeData(window.document, window.top, hit); |
| }); |
| + return "<bindings xmlns='http://www.mozilla.org/xbl'/>"; |
| } |
| }; |
| let observer = { |
| QueryInterface: XPCOMUtils.generateQI([ |
| Ci.nsIObserver, Ci.nsISupportsWeakReference |
| ]), |
| @@ -370,16 +355,34 @@ let observer = { |
| catch (e) |
| { |
| // Ignore NS_ERROR_ILLEGAL_VALUE - it will be thrown if we try to add |
| // the stylesheet multiple times to the same document (the observer |
| // will be notified twice for some documents). |
| if (e.result != Cr.NS_ERROR_ILLEGAL_VALUE) |
| throw e; |
| } |
| + |
| + let host = subject.location.hostname; |
| + if (host) |
| + { |
| + try |
| + { |
| + utils.loadSheetUsingURIString(this.styleURL.spec + "=" + |
| + encodeURIComponent(host), Ci.nsIStyleSheetService.USER_SHEET); |
| + } |
| + catch (e) |
| + { |
| + // Ignore NS_ERROR_ILLEGAL_VALUE - it will be thrown if we try to add |
| + // the stylesheet multiple times to the same document (the observer |
| + // will be notified twice for some documents). |
| + if (e.result != Cr.NS_ERROR_ILLEGAL_VALUE) |
| + throw e; |
| + } |
| + } |
| } |
| else if (filter) |
| { |
| RequestNotifier.addNodeData(window.document, window.top, { |
| contentType, docDomain, thirdParty, location, filter, filterType |
| }); |
| } |
| }); |