mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-11 05:39:41 +02:00
Differential Revision: https://phabricator.services.mozilla.com/D29446 --HG-- extra : moz-landing-system : lando
153 lines
5.1 KiB
JavaScript
153 lines
5.1 KiB
JavaScript
"use strict";
|
|
|
|
// This file expects tabTracker to be defined in the global scope (e.g.
|
|
// by ext-utils.js).
|
|
/* global tabTracker */
|
|
|
|
ChromeUtils.defineModuleGetter(this, "WebRequest",
|
|
"resource://gre/modules/WebRequest.jsm");
|
|
|
|
// The guts of a WebRequest event handler. Takes care of converting
|
|
// |details| parameter when invoking listeners.
|
|
function registerEvent(extension, eventName, fire, filter, info, remoteTab = null) {
|
|
let listener = async data => {
|
|
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 event = data.serialize(eventName);
|
|
event.tabId = browserData.tabId;
|
|
if (data.originAttributes) {
|
|
event.incognito = data.originAttributes.privateBrowsingId > 0;
|
|
if (extension.hasPermission("cookies")) {
|
|
event.cookieStoreId = getCookieStoreIdForOriginAttributes(data.originAttributes);
|
|
}
|
|
}
|
|
if (data.registerTraceableChannel) {
|
|
// If this is a primed listener, no tabParent was passed in here,
|
|
// but the convert() callback later in this function will be called
|
|
// when the background page is started. Force that to happen here
|
|
// after which we'll have a valid tabParent.
|
|
if (fire.wakeup) {
|
|
await fire.wakeup();
|
|
}
|
|
data.registerTraceableChannel(extension.policy, remoteTab);
|
|
}
|
|
|
|
return fire.sync(event);
|
|
};
|
|
|
|
let filter2 = {};
|
|
if (filter.urls) {
|
|
let perms = new MatchPatternSet([...extension.whiteListedHosts.patterns,
|
|
...extension.optionalOrigins.patterns]);
|
|
|
|
filter2.urls = new MatchPatternSet(filter.urls);
|
|
|
|
if (!perms.overlapsAll(filter2.urls)) {
|
|
Cu.reportError("The webRequest.addListener filter doesn't overlap with host permissions.");
|
|
}
|
|
}
|
|
if (filter.types) {
|
|
filter2.types = filter.types;
|
|
}
|
|
if (filter.tabId) {
|
|
filter2.tabId = filter.tabId;
|
|
}
|
|
if (filter.windowId) {
|
|
filter2.windowId = filter.windowId;
|
|
}
|
|
if (filter.incognito !== undefined) {
|
|
filter2.incognito = filter.incognito;
|
|
}
|
|
|
|
let blockingAllowed = extension.hasPermission("webRequestBlocking");
|
|
|
|
let info2 = [];
|
|
if (info) {
|
|
for (let desc of info) {
|
|
if (desc == "blocking" && !blockingAllowed) {
|
|
// This is usually checked in the child process (based on the API schemas, where these options
|
|
// should be checked with the "webRequestBlockingPermissionRequired" postprocess property),
|
|
// but it is worth to also check it here just in case a new webRequest has been added and
|
|
// it has not yet using the expected postprocess property).
|
|
Cu.reportError("Using webRequest.addListener with the blocking option " +
|
|
"requires the 'webRequestBlocking' permission.");
|
|
} else {
|
|
info2.push(desc);
|
|
}
|
|
}
|
|
}
|
|
|
|
let listenerDetails = {
|
|
addonId: extension.id,
|
|
extension: extension.policy,
|
|
blockingAllowed,
|
|
};
|
|
WebRequest[eventName].addListener(
|
|
listener, filter2, info2,
|
|
listenerDetails);
|
|
|
|
return {
|
|
unregister: () => { WebRequest[eventName].removeListener(listener); },
|
|
convert(_fire, context) {
|
|
fire = _fire;
|
|
remoteTab = context.xulBrowser.frameLoader.remoteTab;
|
|
},
|
|
};
|
|
}
|
|
|
|
function makeWebRequestEvent(context, name) {
|
|
return new EventManager({
|
|
context,
|
|
name: `webRequest.${name}`,
|
|
persistent: {
|
|
module: "webRequest",
|
|
event: name,
|
|
},
|
|
register: (fire, filter, info) => {
|
|
return registerEvent(context.extension, name, fire, filter, info,
|
|
context.xulBrowser.frameLoader.remoteTab).unregister;
|
|
},
|
|
}).api();
|
|
}
|
|
|
|
this.webRequest = class extends ExtensionAPI {
|
|
primeListener(extension, event, fire, params) {
|
|
return registerEvent(extension, event, fire, ...params);
|
|
}
|
|
|
|
getAPI(context) {
|
|
return {
|
|
webRequest: {
|
|
onBeforeRequest: makeWebRequestEvent(context, "onBeforeRequest"),
|
|
onBeforeSendHeaders: makeWebRequestEvent(context, "onBeforeSendHeaders"),
|
|
onSendHeaders: makeWebRequestEvent(context, "onSendHeaders"),
|
|
onHeadersReceived: makeWebRequestEvent(context, "onHeadersReceived"),
|
|
onAuthRequired: makeWebRequestEvent(context, "onAuthRequired"),
|
|
onBeforeRedirect: makeWebRequestEvent(context, "onBeforeRedirect"),
|
|
onResponseStarted: makeWebRequestEvent(context, "onResponseStarted"),
|
|
onErrorOccurred: makeWebRequestEvent(context, "onErrorOccurred"),
|
|
onCompleted: makeWebRequestEvent(context, "onCompleted"),
|
|
getSecurityInfo: function(requestId, options = {}) {
|
|
return WebRequest.getSecurityInfo({
|
|
id: requestId,
|
|
extension: context.extension.policy,
|
|
remoteTab: context.xulBrowser.frameLoader.remoteTab,
|
|
options,
|
|
});
|
|
},
|
|
handlerBehaviorChanged: function() {
|
|
// TODO: Flush all caches.
|
|
},
|
|
},
|
|
};
|
|
}
|
|
};
|