forked from mirrors/gecko-dev
MozReview-Commit-ID: 9bcb4p7tP2u --HG-- extra : rebase_source : 4b9cbdef3e5caec7e79e28228773cfcaf3c484ba extra : source : a797359211bccf7aa567b1e741ecde9bb05ae875
139 lines
4.9 KiB
JavaScript
139 lines
4.9 KiB
JavaScript
"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 = (fire, 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;
|
|
}
|
|
|
|
// Check hosts permissions for both the resource being requested,
|
|
const hosts = context.extension.whiteListedHosts;
|
|
if (!hosts.matchesIgnoringPath(NetUtil.newURI(data.url))) {
|
|
return;
|
|
}
|
|
// and the origin that is loading the resource.
|
|
const origin = data.documentUrl;
|
|
const own = origin && origin.startsWith(context.extension.getURL());
|
|
if (origin && !own && !hosts.matchesIgnoringPath(NetUtil.newURI(origin))) {
|
|
return;
|
|
}
|
|
|
|
let browserData = {tabId: -1, windowId: -1};
|
|
if (data.browser) {
|
|
browserData = tabTracker.getBrowserData(data.browser);
|
|
}
|
|
if (filter.tabId != null && browserData.tabId != filter.tabId) {
|
|
return;
|
|
}
|
|
if (filter.windowId != null && browserData.windowId != filter.windowId) {
|
|
return;
|
|
}
|
|
|
|
let data2 = {
|
|
requestId: data.requestId,
|
|
url: data.url,
|
|
originUrl: data.originUrl,
|
|
documentUrl: data.documentUrl,
|
|
method: data.method,
|
|
tabId: browserData.tabId,
|
|
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;
|
|
}
|
|
|
|
let optional = ["requestHeaders", "responseHeaders", "statusCode", "statusLine", "error", "redirectUrl",
|
|
"requestBody", "scheme", "realm", "isProxy", "challenger"];
|
|
for (let opt of optional) {
|
|
if (opt in data) {
|
|
data2[opt] = data[opt];
|
|
}
|
|
}
|
|
|
|
return fire.sync(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(),
|
|
onAuthRequired: new WebRequestEventManager(context, "onAuthRequired").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.
|
|
},
|
|
},
|
|
};
|
|
});
|