Skip to content

Commit 2631e1a

Browse files
authored
browser(firefox): use browsingContextID for frame IDs (#3999)
BrowsingContextIDs are consistent across the processes, so we can use them to target frames in both browser and content processes. This will aid browser-side navigation. As a nice side-effect, we can drop a round-trip to the content process for every `requestWillBeSent` event since we *almost* always can attribute all network events to the proper parent frames. I say "almost", because we in fact **fail** to correctly attribute requests from workers that are instantiated by subframes. This, however, is not working in Chromium ATM, so I consider this to be a minor regression that is worth the simplification.
1 parent b3497b3 commit 2631e1a

File tree

9 files changed

+32
-156
lines changed

9 files changed

+32
-156
lines changed

browser_patches/firefox/BUILD_NUMBER

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1173
2-
Changed: yurys@chromium.org Thu Sep 10 12:35:25 PDT 2020
1+
1174
2+
Changed: lushnikov@chromium.org Tue Sep 29 02:02:37 MDT 2020

browser_patches/firefox/juggler/Helper.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerat
66
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
77

88
class Helper {
9+
910
addObserver(handler, topic) {
1011
Services.obs.addObserver(handler, topic);
1112
return () => Services.obs.removeObserver(handler, topic);
@@ -112,6 +113,12 @@ class Helper {
112113
}
113114
return '<unknown error>';
114115
}
116+
117+
browsingContextToFrameId(browsingContext) {
118+
if (!browsingContext)
119+
return undefined;
120+
return 'frame-' + browsingContext.id;
121+
}
115122
}
116123

117124
var EXPORTED_SYMBOLS = [ "Helper" ];

browser_patches/firefox/juggler/NetworkObserver.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,24 @@ class NetworkRequest {
489489
const pageNetwork = this._activePageNetwork();
490490
if (!pageNetwork)
491491
return;
492-
const causeType = this.httpChannel.loadInfo ? this.httpChannel.loadInfo.externalContentPolicyType : Ci.nsIContentPolicy.TYPE_OTHER;
493-
const internalCauseType = this.httpChannel.loadInfo ? this.httpChannel.loadInfo.internalContentPolicyType : Ci.nsIContentPolicy.TYPE_OTHER;
492+
const loadInfo = this.httpChannel.loadInfo;
493+
const causeType = loadInfo?.externalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER;
494+
const internalCauseType = loadInfo?.internalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER;
495+
496+
let browsingContext = loadInfo?.frameBrowsingContext || loadInfo?.browsingContext;
497+
// TODO: Unfortunately, requests from web workers don't have frameBrowsingContext or
498+
// browsingContext.
499+
//
500+
// We fail to attribute them to the original frames on the browser side, but we
501+
// can use load context top frame to attribute them to the top frame at least.
502+
if (!browsingContext) {
503+
const loadContext = helper.getLoadContext(this.httpChannel);
504+
browsingContext = loadContext?.topFrameElement?.browsingContext;
505+
}
506+
494507
pageNetwork.emit(PageNetwork.Events.Request, {
495508
url: this.httpChannel.URI.spec,
509+
frameId: helper.browsingContextToFrameId(browsingContext),
496510
isIntercepted,
497511
requestId: this.requestId,
498512
redirectedFrom: this.redirectedFromId,

browser_patches/firefox/juggler/content/FrameTree.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ class Frame {
318318
this._runtime = runtime;
319319
this._docShell = docShell;
320320
this._children = new Set();
321-
this._frameId = helper.generateId();
321+
this._frameId = helper.browsingContextToFrameId(this._docShell.browsingContext);
322322
this._parentFrame = null;
323323
this._url = '';
324324
if (docShell.domWindow && docShell.domWindow.location)

browser_patches/firefox/juggler/content/NetworkMonitor.js

Lines changed: 0 additions & 61 deletions
This file was deleted.

browser_patches/firefox/juggler/content/PageAgent.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,14 @@ class FrameData {
112112
}
113113

114114
class PageAgent {
115-
constructor(messageManager, browserChannel, sessionId, frameTree, networkMonitor) {
115+
constructor(messageManager, browserChannel, sessionId, frameTree) {
116116
this._messageManager = messageManager;
117117
this._browserChannel = browserChannel;
118118
this._sessionId = sessionId;
119119
this._browserPage = browserChannel.connect(sessionId + 'page');
120120
this._browserRuntime = browserChannel.connect(sessionId + 'runtime');
121121
this._frameTree = frameTree;
122122
this._runtime = frameTree.runtime();
123-
this._networkMonitor = networkMonitor;
124123

125124
this._frameData = new Map();
126125
this._workerData = new Map();
@@ -146,7 +145,6 @@ class PageAgent {
146145
navigate: this._navigate.bind(this),
147146
reload: this._reload.bind(this),
148147
removeScriptToEvaluateOnNewDocument: this._removeScriptToEvaluateOnNewDocument.bind(this),
149-
requestDetails: this._requestDetails.bind(this),
150148
screenshot: this._screenshot.bind(this),
151149
scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
152150
setCacheDisabled: this._setCacheDisabled.bind(this),
@@ -170,10 +168,6 @@ class PageAgent {
170168
this._dataTransfer = null;
171169
}
172170

173-
_requestDetails({channelKey}) {
174-
return this._networkMonitor.requestDetails(channelKey);
175-
}
176-
177171
async _setEmulatedMedia({type, colorScheme}) {
178172
const docShell = this._frameTree.mainFrame().docShell();
179173
const cv = docShell.contentViewer;

browser_patches/firefox/juggler/content/main.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,17 @@
55
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
66
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
77
const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTree.js');
8-
const {NetworkMonitor} = ChromeUtils.import('chrome://juggler/content/content/NetworkMonitor.js');
98
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
109
const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js');
1110

1211
let frameTree;
13-
let networkMonitor;
1412
const helper = new Helper();
1513
const messageManager = this;
1614

1715
const sessions = new Map();
1816

1917
function createContentSession(channel, sessionId) {
20-
const pageAgent = new PageAgent(messageManager, channel, sessionId, frameTree, networkMonitor);
18+
const pageAgent = new PageAgent(messageManager, channel, sessionId, frameTree);
2119
sessions.set(sessionId, [pageAgent]);
2220
pageAgent.enable();
2321
}
@@ -118,7 +116,6 @@ function initialize() {
118116
frameTree.addScriptToEvaluateOnNewDocument(script);
119117
for (const { name, script } of bindings)
120118
frameTree.addBinding(name, script);
121-
networkMonitor = new NetworkMonitor(docShell, frameTree);
122119

123120
const channel = SimpleChannel.createForMessageManager('content::page', messageManager);
124121

@@ -180,7 +177,6 @@ function initialize() {
180177
for (const sessionId of sessions.keys())
181178
disposeContentSession(sessionId);
182179

183-
networkMonitor.dispose();
184180
frameTree.dispose();
185181
}),
186182
];

browser_patches/firefox/juggler/jar.mn

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ juggler.jar:
1818
content/protocol/AccessibilityHandler.js (protocol/AccessibilityHandler.js)
1919
content/content/main.js (content/main.js)
2020
content/content/FrameTree.js (content/FrameTree.js)
21-
content/content/NetworkMonitor.js (content/NetworkMonitor.js)
2221
content/content/PageAgent.js (content/PageAgent.js)
2322
content/content/Runtime.js (content/Runtime.js)
2423
content/content/WorkerMain.js (content/WorkerMain.js)

browser_patches/firefox/juggler/protocol/NetworkHandler.js

Lines changed: 4 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,9 @@ const helper = new Helper();
1616
class NetworkHandler {
1717
constructor(target, session, contentChannel) {
1818
this._session = session;
19-
this._contentPage = contentChannel.connect(session.sessionId() + 'page');
20-
this._httpActivity = new Map();
2119
this._enabled = false;
2220
this._pageNetwork = NetworkObserver.instance().pageNetworkForTarget(target);
23-
this._requestInterception = false;
2421
this._eventListeners = [];
25-
this._pendingRequstWillBeSentEvents = new Set();
2622
}
2723

2824
async enable() {
@@ -51,9 +47,6 @@ class NetworkHandler {
5147
this._pageNetwork.enableRequestInterception();
5248
else
5349
this._pageNetwork.disableRequestInterception();
54-
// Right after we enable/disable request interception we need to await all pending
55-
// requestWillBeSent events before successfully returning from the method.
56-
await Promise.all(Array.from(this._pendingRequstWillBeSentEvents));
5750
}
5851

5952
async resumeInterceptedRequest({requestId, method, headers, postData}) {
@@ -69,89 +62,23 @@ class NetworkHandler {
6962
}
7063

7164
dispose() {
72-
this._contentPage.dispose();
7365
helper.removeListeners(this._eventListeners);
7466
}
7567

76-
_ensureHTTPActivity(requestId) {
77-
let activity = this._httpActivity.get(requestId);
78-
if (!activity) {
79-
activity = {
80-
_id: requestId,
81-
_lastSentEvent: null,
82-
request: null,
83-
response: null,
84-
complete: null,
85-
failed: null,
86-
};
87-
this._httpActivity.set(requestId, activity);
88-
}
89-
return activity;
90-
}
91-
92-
_reportHTTPAcitivityEvents(activity) {
93-
// State machine - sending network events.
94-
if (!activity._lastSentEvent && activity.request) {
95-
this._session.emitEvent('Network.requestWillBeSent', activity.request);
96-
activity._lastSentEvent = 'requestWillBeSent';
97-
}
98-
if (activity._lastSentEvent === 'requestWillBeSent' && activity.response) {
99-
this._session.emitEvent('Network.responseReceived', activity.response);
100-
activity._lastSentEvent = 'responseReceived';
101-
}
102-
if (activity._lastSentEvent === 'responseReceived' && activity.complete) {
103-
this._session.emitEvent('Network.requestFinished', activity.complete);
104-
activity._lastSentEvent = 'requestFinished';
105-
}
106-
if (activity._lastSentEvent && activity.failed) {
107-
this._session.emitEvent('Network.requestFailed', activity.failed);
108-
activity._lastSentEvent = 'requestFailed';
109-
}
110-
111-
// Clean up if request lifecycle is over.
112-
if (activity._lastSentEvent === 'requestFinished' || activity._lastSentEvent === 'requestFailed')
113-
this._httpActivity.delete(activity._id);
114-
}
115-
11668
async _onRequest(eventDetails, channelKey) {
117-
let pendingRequestCallback;
118-
let pendingRequestPromise = new Promise(x => pendingRequestCallback = x);
119-
this._pendingRequstWillBeSentEvents.add(pendingRequestPromise);
120-
let details = null;
121-
try {
122-
details = await this._contentPage.send('requestDetails', {channelKey});
123-
} catch (e) {
124-
pendingRequestCallback();
125-
this._pendingRequstWillBeSentEvents.delete(pendingRequestPromise);
126-
return;
127-
}
128-
const frameId = details ? details.frameId : undefined;
129-
const activity = this._ensureHTTPActivity(eventDetails.requestId);
130-
activity.request = {
131-
frameId,
132-
...eventDetails,
133-
};
134-
this._reportHTTPAcitivityEvents(activity);
135-
pendingRequestCallback();
136-
this._pendingRequstWillBeSentEvents.delete(pendingRequestPromise);
69+
this._session.emitEvent('Network.requestWillBeSent', eventDetails);
13770
}
13871

13972
async _onResponse(eventDetails) {
140-
const activity = this._ensureHTTPActivity(eventDetails.requestId);
141-
activity.response = eventDetails;
142-
this._reportHTTPAcitivityEvents(activity);
73+
this._session.emitEvent('Network.responseReceived', eventDetails);
14374
}
14475

14576
async _onRequestFinished(eventDetails) {
146-
const activity = this._ensureHTTPActivity(eventDetails.requestId);
147-
activity.complete = eventDetails;
148-
this._reportHTTPAcitivityEvents(activity);
77+
this._session.emitEvent('Network.requestFinished', eventDetails);
14978
}
15079

15180
async _onRequestFailed(eventDetails) {
152-
const activity = this._ensureHTTPActivity(eventDetails.requestId);
153-
activity.failed = eventDetails;
154-
this._reportHTTPAcitivityEvents(activity);
81+
this._session.emitEvent('Network.requestFailed', eventDetails);
15582
}
15683
}
15784

0 commit comments

Comments
 (0)