Bug 1397448: Part 1 - Generate WebRequest message objects in WebRequest.jsm. r?mixedpuppy
Aside from moving this logic closer to the place the input data is generated,
this significantly reduces the number of cross-compartment wrappers involved
in creating those messages, especially with JSM global sharing enabled.
MozReview-Commit-ID: 6IvetcHnMfC
--- a/toolkit/components/extensions/ext-webRequest.js
+++ b/toolkit/components/extensions/ext-webRequest.js
@@ -41,47 +41,20 @@ function WebRequestEventManager(context,
}
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.windowId,
- parentFrameId: data.parentWindowId,
- };
+ let event = data.serialize(eventName);
+ event.tabId = browserData.tabId;
- 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", "proxyInfo"];
- for (let opt of optional) {
- if (opt in data) {
- data2[opt] = data[opt];
- }
- }
-
- return fire.sync(data2);
+ return fire.sync(event);
};
let filter2 = {};
if (filter.urls) {
let perms = new MatchPatternSet([...context.extension.whiteListedHosts.patterns,
...context.extension.optionalOrigins.patterns]);
filter2.urls = new MatchPatternSet(filter.urls);
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -178,16 +178,50 @@ class ResponseHeaderChanger extends Head
if (name.toLowerCase() === "content-type") {
value = this.channel._contentType || value;
}
yield [name, value];
}
}
}
+const MAYBE_CACHED_EVENTS = new Set([
+ "onResponseStarted", "onBeforeRedirect", "onCompleted", "onErrorOccurred",
+]);
+
+const OPTIONAL_PROPERTIES = [
+ "requestHeaders", "responseHeaders", "statusCode", "statusLine", "error", "redirectUrl",
+ "requestBody", "scheme", "realm", "isProxy", "challenger", "proxyInfo", "ip",
+];
+
+function serializeRequestData(eventName) {
+ let data = {
+ requestId: this.requestId,
+ url: this.url,
+ originUrl: this.originUrl,
+ documentUrl: this.documentUrl,
+ method: this.method,
+ type: this.type,
+ timeStamp: Date.now(),
+ frameId: this.windowId,
+ parentFrameId: this.parentWindowId,
+ };
+
+ if (MAYBE_CACHED_EVENTS.has(eventName)) {
+ data.fromCache = !!this.fromCache;
+ }
+
+ for (let opt of OPTIONAL_PROPERTIES) {
+ if (typeof this[opt] !== "undefined") {
+ data[opt] = this[opt];
+ }
+ }
+ return data;
+}
+
var HttpObserverManager;
var nextFakeRequestId = 1;
var ContentPolicyManager = {
policyData: new Map(),
policies: new Map(),
idMap: new Map(),
@@ -208,17 +242,17 @@ var ContentPolicyManager = {
let callback = this.policies.get(id);
if (!callback) {
// It's possible that this listener has been removed and the
// child hasn't learned yet.
continue;
}
let response = null;
let listenerKind = "onStop";
- let data = Object.assign({requestId, browser}, msg.data);
+ let data = Object.assign({requestId, browser, serialize: serializeRequestData}, msg.data);
data.URI = data.url;
delete data.ids;
try {
response = callback(data);
if (response) {
if (response.cancel) {
listenerKind = "onError";
@@ -689,16 +723,18 @@ HttpObserverManager = {
isSystemPrincipal: channel.isSystemLoad,
windowId: channel.windowId,
parentWindowId: channel.parentWindowId,
ip: channel.remoteAddress,
proxyInfo: channel.proxyInfo,
+
+ serialize: serializeRequestData,
};
// force the protocol to be ws again.
if (data.type == "websocket" && data.url.startsWith("http")) {
data.url = `ws${data.url.substring(4)}`;
}
return Object.assign(data, extraData);