diff options
Diffstat (limited to 'toolkit/components/webextensions/ext-webRequest.js')
-rw-r--r-- | toolkit/components/webextensions/ext-webRequest.js | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/toolkit/components/webextensions/ext-webRequest.js b/toolkit/components/webextensions/ext-webRequest.js new file mode 100644 index 000000000..f92330131 --- /dev/null +++ b/toolkit/components/webextensions/ext-webRequest.js @@ -0,0 +1,115 @@ +"use strict"; + +var {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern", + "resource://gre/modules/MatchPattern.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "WebRequest", + "resource://gre/modules/WebRequest.jsm"); + +Cu.import("resource://gre/modules/ExtensionManagement.jsm"); +Cu.import("resource://gre/modules/ExtensionUtils.jsm"); +var { + SingletonEventManager, +} = ExtensionUtils; + +// EventManager-like class specifically for WebRequest. Inherits from +// SingletonEventManager. Takes care of converting |details| parameter +// when invoking listeners. +function WebRequestEventManager(context, eventName) { + let name = `webRequest.${eventName}`; + let register = (callback, filter, info) => { + let listener = data => { + // Prevent listening in on requests originating from system principal to + // prevent tinkering with OCSP, app and addon updates, etc. + if (data.isSystemPrincipal) { + return; + } + + let data2 = { + requestId: data.requestId, + url: data.url, + originUrl: data.originUrl, + method: data.method, + type: data.type, + timeStamp: Date.now(), + frameId: data.type == "main_frame" ? 0 : ExtensionManagement.getFrameId(data.windowId), + parentFrameId: ExtensionManagement.getParentFrameId(data.parentWindowId, data.windowId), + }; + + const maybeCached = ["onResponseStarted", "onBeforeRedirect", "onCompleted", "onErrorOccurred"]; + if (maybeCached.includes(eventName)) { + data2.fromCache = !!data.fromCache; + } + + if ("ip" in data) { + data2.ip = data.ip; + } + + extensions.emit("fill-browser-data", data.browser, data2); + + let optional = ["requestHeaders", "responseHeaders", "statusCode", "statusLine", "error", "redirectUrl", + "requestBody"]; + for (let opt of optional) { + if (opt in data) { + data2[opt] = data[opt]; + } + } + + return context.runSafe(callback, data2); + }; + + let filter2 = {}; + filter2.urls = new MatchPattern(filter.urls); + if (filter.types) { + filter2.types = filter.types; + } + if (filter.tabId) { + filter2.tabId = filter.tabId; + } + if (filter.windowId) { + filter2.windowId = filter.windowId; + } + + let info2 = []; + if (info) { + for (let desc of info) { + if (desc == "blocking" && !context.extension.hasPermission("webRequestBlocking")) { + Cu.reportError("Using webRequest.addListener with the blocking option " + + "requires the 'webRequestBlocking' permission."); + } else { + info2.push(desc); + } + } + } + + WebRequest[eventName].addListener(listener, filter2, info2); + return () => { + WebRequest[eventName].removeListener(listener); + }; + }; + + return SingletonEventManager.call(this, context, name, register); +} + +WebRequestEventManager.prototype = Object.create(SingletonEventManager.prototype); + +extensions.registerSchemaAPI("webRequest", "addon_parent", context => { + return { + webRequest: { + onBeforeRequest: new WebRequestEventManager(context, "onBeforeRequest").api(), + onBeforeSendHeaders: new WebRequestEventManager(context, "onBeforeSendHeaders").api(), + onSendHeaders: new WebRequestEventManager(context, "onSendHeaders").api(), + onHeadersReceived: new WebRequestEventManager(context, "onHeadersReceived").api(), + onBeforeRedirect: new WebRequestEventManager(context, "onBeforeRedirect").api(), + onResponseStarted: new WebRequestEventManager(context, "onResponseStarted").api(), + onErrorOccurred: new WebRequestEventManager(context, "onErrorOccurred").api(), + onCompleted: new WebRequestEventManager(context, "onCompleted").api(), + handlerBehaviorChanged: function() { + // TODO: Flush all caches. + }, + }, + }; +}); |