diff --git a/browser_patches/firefox/BUILD_NUMBER b/browser_patches/firefox/BUILD_NUMBER index 0a468d3fd9a33..71807cfffe9a0 100644 --- a/browser_patches/firefox/BUILD_NUMBER +++ b/browser_patches/firefox/BUILD_NUMBER @@ -1,2 +1,2 @@ -1173 -Changed: yurys@chromium.org Thu Sep 10 12:35:25 PDT 2020 +1174 +Changed: lushnikov@chromium.org Tue Sep 29 02:02:37 MDT 2020 diff --git a/browser_patches/firefox/juggler/Helper.js b/browser_patches/firefox/juggler/Helper.js index c26cb6ec578b1..aedd7a1eeb513 100644 --- a/browser_patches/firefox/juggler/Helper.js +++ b/browser_patches/firefox/juggler/Helper.js @@ -6,6 +6,7 @@ const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerat const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); class Helper { + addObserver(handler, topic) { Services.obs.addObserver(handler, topic); return () => Services.obs.removeObserver(handler, topic); @@ -112,6 +113,12 @@ class Helper { } return ''; } + + browsingContextToFrameId(browsingContext) { + if (!browsingContext) + return undefined; + return 'frame-' + browsingContext.id; + } } var EXPORTED_SYMBOLS = [ "Helper" ]; diff --git a/browser_patches/firefox/juggler/NetworkObserver.js b/browser_patches/firefox/juggler/NetworkObserver.js index e271468d29f0c..62578d9ad7079 100644 --- a/browser_patches/firefox/juggler/NetworkObserver.js +++ b/browser_patches/firefox/juggler/NetworkObserver.js @@ -489,10 +489,24 @@ class NetworkRequest { const pageNetwork = this._activePageNetwork(); if (!pageNetwork) return; - const causeType = this.httpChannel.loadInfo ? this.httpChannel.loadInfo.externalContentPolicyType : Ci.nsIContentPolicy.TYPE_OTHER; - const internalCauseType = this.httpChannel.loadInfo ? this.httpChannel.loadInfo.internalContentPolicyType : Ci.nsIContentPolicy.TYPE_OTHER; + const loadInfo = this.httpChannel.loadInfo; + const causeType = loadInfo?.externalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER; + const internalCauseType = loadInfo?.internalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER; + + let browsingContext = loadInfo?.frameBrowsingContext || loadInfo?.browsingContext; + // TODO: Unfortunately, requests from web workers don't have frameBrowsingContext or + // browsingContext. + // + // We fail to attribute them to the original frames on the browser side, but we + // can use load context top frame to attribute them to the top frame at least. + if (!browsingContext) { + const loadContext = helper.getLoadContext(this.httpChannel); + browsingContext = loadContext?.topFrameElement?.browsingContext; + } + pageNetwork.emit(PageNetwork.Events.Request, { url: this.httpChannel.URI.spec, + frameId: helper.browsingContextToFrameId(browsingContext), isIntercepted, requestId: this.requestId, redirectedFrom: this.redirectedFromId, diff --git a/browser_patches/firefox/juggler/content/FrameTree.js b/browser_patches/firefox/juggler/content/FrameTree.js index 46adfa727924e..21dbbdac4ef76 100644 --- a/browser_patches/firefox/juggler/content/FrameTree.js +++ b/browser_patches/firefox/juggler/content/FrameTree.js @@ -318,7 +318,7 @@ class Frame { this._runtime = runtime; this._docShell = docShell; this._children = new Set(); - this._frameId = helper.generateId(); + this._frameId = helper.browsingContextToFrameId(this._docShell.browsingContext); this._parentFrame = null; this._url = ''; if (docShell.domWindow && docShell.domWindow.location) diff --git a/browser_patches/firefox/juggler/content/NetworkMonitor.js b/browser_patches/firefox/juggler/content/NetworkMonitor.js deleted file mode 100644 index 6cec455d599b9..0000000000000 --- a/browser_patches/firefox/juggler/content/NetworkMonitor.js +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; -const Ci = Components.interfaces; -const Cr = Components.results; -const Cu = Components.utils; - -const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); - -const helper = new Helper(); - -class NetworkMonitor { - constructor(rootDocShell, frameTree) { - this._frameTree = frameTree; - this._requestDetails = new Map(); - - this._eventListeners = [ - helper.addObserver(this._onRequest.bind(this), 'http-on-opening-request'), - ]; - } - - _onRequest(channel) { - if (!(channel instanceof Ci.nsIHttpChannel)) - return; - const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); - const loadContext = helper.getLoadContext(httpChannel); - if (!loadContext) - return; - try { - const window = loadContext.associatedWindow; - const frame = this._frameTree.frameForDocShell(window.docShell); - if (!frame) - return; - const typeId = httpChannel.loadInfo ? httpChannel.loadInfo.internalContentPolicyType : Ci.nsIContentPolicy.TYPE_OTHER; - // Channel ids are not unique. We combine them with the typeId - // to better distinguish requests. For example, favicon requests - // have the same channel id as their associated document request. - const channelKey = httpChannel.channelId + ':' + typeId; - this._requestDetails.set(channelKey, { - frameId: frame.id(), - }); - } catch (e) { - // Accessing loadContext.associatedWindow sometimes throws. - } - } - - requestDetails(channelKey) { - return this._requestDetails.get(channelKey) || null; - } - - dispose() { - this._requestDetails.clear(); - helper.removeListeners(this._eventListeners); - } -} - -var EXPORTED_SYMBOLS = ['NetworkMonitor']; -this.NetworkMonitor = NetworkMonitor; - diff --git a/browser_patches/firefox/juggler/content/PageAgent.js b/browser_patches/firefox/juggler/content/PageAgent.js index 124df808d43ee..172da22358f4e 100644 --- a/browser_patches/firefox/juggler/content/PageAgent.js +++ b/browser_patches/firefox/juggler/content/PageAgent.js @@ -112,7 +112,7 @@ class FrameData { } class PageAgent { - constructor(messageManager, browserChannel, sessionId, frameTree, networkMonitor) { + constructor(messageManager, browserChannel, sessionId, frameTree) { this._messageManager = messageManager; this._browserChannel = browserChannel; this._sessionId = sessionId; @@ -120,7 +120,6 @@ class PageAgent { this._browserRuntime = browserChannel.connect(sessionId + 'runtime'); this._frameTree = frameTree; this._runtime = frameTree.runtime(); - this._networkMonitor = networkMonitor; this._frameData = new Map(); this._workerData = new Map(); @@ -146,7 +145,6 @@ class PageAgent { navigate: this._navigate.bind(this), reload: this._reload.bind(this), removeScriptToEvaluateOnNewDocument: this._removeScriptToEvaluateOnNewDocument.bind(this), - requestDetails: this._requestDetails.bind(this), screenshot: this._screenshot.bind(this), scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this), setCacheDisabled: this._setCacheDisabled.bind(this), @@ -170,10 +168,6 @@ class PageAgent { this._dataTransfer = null; } - _requestDetails({channelKey}) { - return this._networkMonitor.requestDetails(channelKey); - } - async _setEmulatedMedia({type, colorScheme}) { const docShell = this._frameTree.mainFrame().docShell(); const cv = docShell.contentViewer; diff --git a/browser_patches/firefox/juggler/content/main.js b/browser_patches/firefox/juggler/content/main.js index 630ba41b3ed09..54437bfa7ac2d 100644 --- a/browser_patches/firefox/juggler/content/main.js +++ b/browser_patches/firefox/juggler/content/main.js @@ -5,19 +5,17 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTree.js'); -const {NetworkMonitor} = ChromeUtils.import('chrome://juggler/content/content/NetworkMonitor.js'); const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js'); const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js'); let frameTree; -let networkMonitor; const helper = new Helper(); const messageManager = this; const sessions = new Map(); function createContentSession(channel, sessionId) { - const pageAgent = new PageAgent(messageManager, channel, sessionId, frameTree, networkMonitor); + const pageAgent = new PageAgent(messageManager, channel, sessionId, frameTree); sessions.set(sessionId, [pageAgent]); pageAgent.enable(); } @@ -118,7 +116,6 @@ function initialize() { frameTree.addScriptToEvaluateOnNewDocument(script); for (const { name, script } of bindings) frameTree.addBinding(name, script); - networkMonitor = new NetworkMonitor(docShell, frameTree); const channel = SimpleChannel.createForMessageManager('content::page', messageManager); @@ -180,7 +177,6 @@ function initialize() { for (const sessionId of sessions.keys()) disposeContentSession(sessionId); - networkMonitor.dispose(); frameTree.dispose(); }), ]; diff --git a/browser_patches/firefox/juggler/jar.mn b/browser_patches/firefox/juggler/jar.mn index 2347d489e3448..419fb2d9f4e93 100644 --- a/browser_patches/firefox/juggler/jar.mn +++ b/browser_patches/firefox/juggler/jar.mn @@ -18,7 +18,6 @@ juggler.jar: content/protocol/AccessibilityHandler.js (protocol/AccessibilityHandler.js) content/content/main.js (content/main.js) content/content/FrameTree.js (content/FrameTree.js) - content/content/NetworkMonitor.js (content/NetworkMonitor.js) content/content/PageAgent.js (content/PageAgent.js) content/content/Runtime.js (content/Runtime.js) content/content/WorkerMain.js (content/WorkerMain.js) diff --git a/browser_patches/firefox/juggler/protocol/NetworkHandler.js b/browser_patches/firefox/juggler/protocol/NetworkHandler.js index 49e2fe3f0186f..b2a0c64d2ec03 100644 --- a/browser_patches/firefox/juggler/protocol/NetworkHandler.js +++ b/browser_patches/firefox/juggler/protocol/NetworkHandler.js @@ -16,13 +16,9 @@ const helper = new Helper(); class NetworkHandler { constructor(target, session, contentChannel) { this._session = session; - this._contentPage = contentChannel.connect(session.sessionId() + 'page'); - this._httpActivity = new Map(); this._enabled = false; this._pageNetwork = NetworkObserver.instance().pageNetworkForTarget(target); - this._requestInterception = false; this._eventListeners = []; - this._pendingRequstWillBeSentEvents = new Set(); } async enable() { @@ -51,9 +47,6 @@ class NetworkHandler { this._pageNetwork.enableRequestInterception(); else this._pageNetwork.disableRequestInterception(); - // Right after we enable/disable request interception we need to await all pending - // requestWillBeSent events before successfully returning from the method. - await Promise.all(Array.from(this._pendingRequstWillBeSentEvents)); } async resumeInterceptedRequest({requestId, method, headers, postData}) { @@ -69,89 +62,23 @@ class NetworkHandler { } dispose() { - this._contentPage.dispose(); helper.removeListeners(this._eventListeners); } - _ensureHTTPActivity(requestId) { - let activity = this._httpActivity.get(requestId); - if (!activity) { - activity = { - _id: requestId, - _lastSentEvent: null, - request: null, - response: null, - complete: null, - failed: null, - }; - this._httpActivity.set(requestId, activity); - } - return activity; - } - - _reportHTTPAcitivityEvents(activity) { - // State machine - sending network events. - if (!activity._lastSentEvent && activity.request) { - this._session.emitEvent('Network.requestWillBeSent', activity.request); - activity._lastSentEvent = 'requestWillBeSent'; - } - if (activity._lastSentEvent === 'requestWillBeSent' && activity.response) { - this._session.emitEvent('Network.responseReceived', activity.response); - activity._lastSentEvent = 'responseReceived'; - } - if (activity._lastSentEvent === 'responseReceived' && activity.complete) { - this._session.emitEvent('Network.requestFinished', activity.complete); - activity._lastSentEvent = 'requestFinished'; - } - if (activity._lastSentEvent && activity.failed) { - this._session.emitEvent('Network.requestFailed', activity.failed); - activity._lastSentEvent = 'requestFailed'; - } - - // Clean up if request lifecycle is over. - if (activity._lastSentEvent === 'requestFinished' || activity._lastSentEvent === 'requestFailed') - this._httpActivity.delete(activity._id); - } - async _onRequest(eventDetails, channelKey) { - let pendingRequestCallback; - let pendingRequestPromise = new Promise(x => pendingRequestCallback = x); - this._pendingRequstWillBeSentEvents.add(pendingRequestPromise); - let details = null; - try { - details = await this._contentPage.send('requestDetails', {channelKey}); - } catch (e) { - pendingRequestCallback(); - this._pendingRequstWillBeSentEvents.delete(pendingRequestPromise); - return; - } - const frameId = details ? details.frameId : undefined; - const activity = this._ensureHTTPActivity(eventDetails.requestId); - activity.request = { - frameId, - ...eventDetails, - }; - this._reportHTTPAcitivityEvents(activity); - pendingRequestCallback(); - this._pendingRequstWillBeSentEvents.delete(pendingRequestPromise); + this._session.emitEvent('Network.requestWillBeSent', eventDetails); } async _onResponse(eventDetails) { - const activity = this._ensureHTTPActivity(eventDetails.requestId); - activity.response = eventDetails; - this._reportHTTPAcitivityEvents(activity); + this._session.emitEvent('Network.responseReceived', eventDetails); } async _onRequestFinished(eventDetails) { - const activity = this._ensureHTTPActivity(eventDetails.requestId); - activity.complete = eventDetails; - this._reportHTTPAcitivityEvents(activity); + this._session.emitEvent('Network.requestFinished', eventDetails); } async _onRequestFailed(eventDetails) { - const activity = this._ensureHTTPActivity(eventDetails.requestId); - activity.failed = eventDetails; - this._reportHTTPAcitivityEvents(activity); + this._session.emitEvent('Network.requestFailed', eventDetails); } }