Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/child/elemHide.js

Issue 29345667: Issue 4139 - Don't save element hiding filters on disk (Closed)
Patch Set: Rebased and updated dependency Created June 17, 2016, 12:10 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dependencies ('k') | lib/elemHideStylesheet.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/child/elemHide.js
===================================================================
--- a/lib/child/elemHide.js
+++ b/lib/child/elemHide.js
@@ -30,24 +30,27 @@ try
catch (e)
{
Cu.reportError(e);
}
let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
let {shouldAllowAsync} = require("child/contentPolicy");
+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 =
{
classID: Components.ID("{55fb7be0-1dd2-11b2-98e6-9e97caf8ba67}"),
classDescription: "Element hiding hit registration protocol handler",
@@ -85,97 +88,208 @@ let AboutHandler =
getURIFlags: function(uri)
{
return Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
},
newChannel: function(uri, loadInfo)
{
- let match = /\?(\d+)/.exec(uri.path);
+ let match = /\?(\d+|css)$/.exec(uri.path);
if (!match)
throw Cr.NS_ERROR_FAILURE;
- return new HitRegistrationChannel(uri, loadInfo, match[1]);
+ if (match[1] == "css")
+ return new StyleDataChannel(uri, loadInfo);
+ else
+ return new HitRegistrationChannel(uri, loadInfo, match[1]);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory, Ci.nsIAboutModule])
};
AboutHandler.init();
/**
- * Channel returning data for element hiding hits.
+ * Base class for channel implementations, subclasses usually only need to
+ * override BaseChannel._getResponse() method.
* @constructor
*/
-function HitRegistrationChannel(uri, loadInfo, key)
+function BaseChannel(uri, loadInfo)
{
- this.key = key;
this.URI = this.originalURI = uri;
this.loadInfo = loadInfo;
}
-HitRegistrationChannel.prototype = {
- key: null,
+BaseChannel.prototype = {
URI: null,
originalURI: null,
contentCharset: "utf-8",
contentLength: 0,
- contentType: "text/xml",
+ contentType: null,
owner: Utils.systemPrincipal,
securityInfo: null,
notificationCallbacks: null,
loadFlags: 0,
loadGroup: null,
name: null,
status: Cr.NS_OK,
- asyncOpen: function(listener, context)
+ _getResponse: notImplemented,
+
+ _checkSecurity: function()
{
- let processResponse = (allow) =>
+ if (!this.loadInfo.triggeringPrincipal.equals(Utils.systemPrincipal))
+ throw Cr.NS_ERROR_FAILURE;
+ },
+
+ asyncOpen: function()
+ {
+ Promise.resolve(this._getResponse()).then(data =>
{
- let data = (allow ? allowXBL : hideXBL);
- let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
+ let stream = Cc["@mozilla.org/io/string-input-stream;1"]
+ .createInstance(Ci.nsIStringInputStream);
stream.setData(data, data.length);
- try {
+ try
+ {
listener.onStartRequest(this, context);
- } catch(e) {}
- try {
+ }
+ catch(e)
+ {
+ // Listener failing isn't our problem
+ }
+
+ try
+ {
listener.onDataAvailable(this, context, stream, 0, stream.available());
- } catch(e) {}
- try {
+ }
+ catch(e)
+ {
+ // Listener failing isn't our problem
+ }
+
+ try
+ {
listener.onStopRequest(this, context, Cr.NS_OK);
- } catch(e) {}
- };
-
- let window = Utils.getRequestWindow(this);
- shouldAllowAsync(window, window.document, "ELEMHIDE", this.key, processResponse);
+ }
+ catch(e)
+ {
+ // Listener failing isn't our problem
+ }
+ });
},
asyncOpen2: function(listener)
{
- if (!this.loadInfo.triggeringPrincipal.equals(Utils.systemPrincipal))
- throw Cr.NS_ERROR_FAILURE;
+ this._checkSecurity();
this.asyncOpen(listener, null);
},
open: function()
{
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+ let data = this._getResponse();
+ if (typeof data.then == "function")
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+
+ let stream = Cc["@mozilla.org/io/string-input-stream;1"]
+ .createInstance(Ci.nsIStringInputStream);
+ stream.setData(data, data.length);
+ return stream;
},
- isPending: function()
+
+ open2: function()
{
- return false;
+ this._checkSecurity();
+ return this.open();
},
- cancel: function()
- {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
- suspend: function()
- {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
- resume: function()
- {
- throw Cr.NS_ERROR_NOT_IMPLEMENTED;
- },
+
+ isPending: () => false,
+ cancel: notImplemented,
+ suspend: notImplemented,
+ resume: notImplemented,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest])
};
+
+/**
+ * Channel returning CSS data for the global stylesheet.
+ * @constructor
+ */
+function StyleDataChannel(uri, loadInfo)
+{
+ BaseChannel.call(this, uri, loadInfo);
+}
+StyleDataChannel.prototype = {
+ __proto__: BaseChannel.prototype,
+ contentType: "text/css",
+
+ _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 cssPrefix = "{-moz-binding: url(about:abp-elemhidehit?";
+ let cssSuffix = "#dummy) !important;}\n";
+ let result = [];
+
+ for (let [domain, selectors] of domains)
+ {
+ 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");
+ }
+
+ return result.join("");
+ }
+};
+
+/**
+ * Channel returning data for element hiding hits.
+ * @constructor
+ */
+function HitRegistrationChannel(uri, loadInfo, key)
+{
+ BaseChannel.call(this, uri, loadInfo);
+ this.key = key;
+}
+HitRegistrationChannel.prototype = {
+ __proto__: BaseChannel.prototype,
+ key: null,
+ contentType: "text/xml",
+
+ _getResponse: function()
+ {
+ return new Promise((resolve, reject) =>
+ {
+ let window = Utils.getRequestWindow(this);
+ shouldAllowAsync(window, window.document, "ELEMHIDE", this.key, allow =>
+ {
+ resolve(allow ? allowXBL : hideXBL);
+ });
+ });
+ }
+};
« no previous file with comments | « dependencies ('k') | lib/elemHideStylesheet.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld