playwright/browser_patches/firefox/juggler/content/NetworkMonitor.js
Dmitry Gozman f2af30cf90
browser(firefox): properly instrument requests intercepted by service worker (#2594)
When httpChannel is intercepted by Service Worker:
- it gets an internal redirect to another channel with the same id;
- once serivce worker responds, the channel gets the data, but
  does not get any onResponse notifications.

So, we update our ResponseBodyListener (the nsIRequestObserver implementation)
to the new request and force onResponse from there once data is available or
request finishes.
2020-06-16 17:19:01 -07:00

57 lines
1.5 KiB
JavaScript

/* 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;
this._requestDetails.set(httpChannel.channelId, {
frameId: frame.id(),
});
} catch (e) {
// Accessing loadContext.associatedWindow sometimes throws.
}
}
requestDetails(channelId) {
return this._requestDetails.get(channelId) || null;
}
dispose() {
this._requestDetails.clear();
helper.removeListeners(this._eventListeners);
}
}
var EXPORTED_SYMBOLS = ['NetworkMonitor'];
this.NetworkMonitor = NetworkMonitor;