зеркало из https://github.com/mozilla/gecko-dev.git
bug 1158264 - Flag requests coming from service workers. r=vporof
This commit is contained in:
Родитель
c7c2eba05c
Коммит
335ab17e50
|
@ -74,6 +74,16 @@ netmonitor.security.hostHeader=Host %S:
|
|||
# Organization: <Not Available>
|
||||
netmonitor.security.notAvailable=<Not Available>
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.status.cached):
|
||||
# This string is used as tooltip text over the status icon when a request is
|
||||
# served from cached.
|
||||
netmonitor.status.cached=cached
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.status.serviceWorker):
|
||||
# This string is used as tooltip text over the status icon when a request is
|
||||
# served from a service worker.
|
||||
netmonitor.status.serviceWorker=service worker
|
||||
|
||||
# LOCALIZATION NOTE (collapseDetailsPane): This is the tooltip for the button
|
||||
# that collapses the network details pane in the UI.
|
||||
collapseDetailsPane=Hide request details
|
||||
|
@ -184,6 +194,11 @@ networkMenu.sizeUnavailable=—
|
|||
# cached.
|
||||
networkMenu.sizeCached=cached
|
||||
|
||||
# LOCALIZATION NOTE (networkMenu.sizeServiceWorker): This is the label displayed
|
||||
# in the network menu specifying the transferred of a request computed
|
||||
# by a service worker.
|
||||
networkMenu.sizeServiceWorker=service worker
|
||||
|
||||
# LOCALIZATION NOTE (networkMenu.totalMS): This is the label displayed
|
||||
# in the network menu specifying the time for a request to finish (in milliseconds).
|
||||
networkMenu.totalMS=→ %S ms
|
||||
|
|
|
@ -606,10 +606,10 @@ NetworkEventsHandler.prototype = {
|
|||
* The network request information.
|
||||
*/
|
||||
_onNetworkEvent: function(type, networkInfo) {
|
||||
let { actor, startedDateTime, request: { method, url }, isXHR, fromCache } = networkInfo;
|
||||
let { actor, startedDateTime, request: { method, url }, isXHR, fromCache, fromServiceWorker } = networkInfo;
|
||||
|
||||
NetMonitorView.RequestsMenu.addRequest(
|
||||
actor, startedDateTime, method, url, isXHR, fromCache
|
||||
actor, startedDateTime, method, url, isXHR, fromCache, fromServiceWorker
|
||||
);
|
||||
window.emit(EVENTS.NETWORK_EVENT, actor);
|
||||
},
|
||||
|
|
|
@ -538,9 +538,11 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
* True if this request was initiated via XHR.
|
||||
* @param boolean aFromCache
|
||||
* Indicates if the result came from the browser cache
|
||||
* @param boolean aFromServiceWorker
|
||||
* Indicates if the request has been intercepted by a Service Worker
|
||||
*/
|
||||
addRequest: function(aId, aStartedDateTime, aMethod, aUrl, aIsXHR, aFromCache) {
|
||||
this._addQueue.push([aId, aStartedDateTime, aMethod, aUrl, aIsXHR, aFromCache]);
|
||||
addRequest: function(aId, aStartedDateTime, aMethod, aUrl, aIsXHR, aFromCache, aFromServiceWorker) {
|
||||
this._addQueue.push([aId, aStartedDateTime, aMethod, aUrl, aIsXHR, aFromCache, aFromServiceWorker]);
|
||||
|
||||
// Lazy updating is disabled in some tests.
|
||||
if (!this.lazyUpdate) {
|
||||
|
@ -1349,7 +1351,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
let widget = NetMonitorView.RequestsMenu.widget;
|
||||
let isScrolledToBottom = widget.isScrolledToBottom();
|
||||
|
||||
for (let [id, startedDateTime, method, url, isXHR, fromCache] of this._addQueue) {
|
||||
for (let [id, startedDateTime, method, url, isXHR, fromCache, fromServiceWorker] of this._addQueue) {
|
||||
// Convert the received date/time string to a unix timestamp.
|
||||
let unixTime = Date.parse(startedDateTime);
|
||||
|
||||
|
@ -1368,7 +1370,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
method: method,
|
||||
url: url,
|
||||
isXHR: isXHR,
|
||||
fromCache: fromCache
|
||||
fromCache: fromCache,
|
||||
fromServiceWorker: fromServiceWorker
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1470,7 +1473,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
requestItem.attachment.status = value;
|
||||
this.updateMenuView(requestItem, key, {
|
||||
status: value,
|
||||
cached: requestItem.attachment.fromCache
|
||||
cached: requestItem.attachment.fromCache,
|
||||
serviceWorker: requestItem.attachment.fromServiceWorker
|
||||
});
|
||||
break;
|
||||
case "statusText":
|
||||
|
@ -1479,6 +1483,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
requestItem.attachment.statusText);
|
||||
if(requestItem.attachment.fromCache) {
|
||||
text += " (cached)";
|
||||
} else if(requestItem.attachment.fromServiceWorker) {
|
||||
text += " (service worker)";
|
||||
}
|
||||
|
||||
this.updateMenuView(requestItem, key, text);
|
||||
|
@ -1495,6 +1501,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
requestItem.attachment.transferredSize = 0;
|
||||
this.updateMenuView(requestItem, key, 'cached');
|
||||
}
|
||||
else if(requestItem.attachment.fromServiceWorker) {
|
||||
requestItem.attachment.transferredSize = 0;
|
||||
this.updateMenuView(requestItem, key, 'service worker');
|
||||
}
|
||||
else {
|
||||
requestItem.attachment.transferredSize = value;
|
||||
this.updateMenuView(requestItem, key, value);
|
||||
|
@ -1523,7 +1533,9 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
case "eventTimings":
|
||||
requestItem.attachment.eventTimings = value;
|
||||
this._createWaterfallView(
|
||||
requestItem, value.timings, requestItem.attachment.fromCache
|
||||
requestItem, value.timings,
|
||||
requestItem.attachment.fromCache ||
|
||||
requestItem.attachment.fromServiceWorker
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1682,7 +1694,16 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
}
|
||||
case "status": {
|
||||
let node = $(".requests-menu-status-icon", target);
|
||||
node.setAttribute("code", aValue.cached ? "cached" : aValue.status);
|
||||
let code;
|
||||
if (aValue.cached) {
|
||||
code = L10N.getStr("netmonitor.status.cached");
|
||||
code = "cached";
|
||||
} else if (aValue.serviceWorker) {
|
||||
code = L10N.getStr("netmonitor.status.serviceWorker");
|
||||
} else {
|
||||
code = aValue.status;
|
||||
}
|
||||
node.setAttribute("code", code);
|
||||
let codeNode = $(".requests-menu-status-code", target);
|
||||
codeNode.setAttribute("value", aValue.status);
|
||||
break;
|
||||
|
@ -1712,6 +1733,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
text = L10N.getStr("networkMenu.sizeCached");
|
||||
node.classList.add('theme-comment');
|
||||
}
|
||||
else if(aValue === "service worker") {
|
||||
text = L10N.getStr("networkMenu.sizeServiceWorker");
|
||||
node.classList.add('theme-comment');
|
||||
}
|
||||
else {
|
||||
let kb = aValue / 1024;
|
||||
let size = L10N.numberWithDecimals(kb, CONTENT_SIZE_DECIMALS);
|
||||
|
@ -1763,7 +1788,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
* @param object aTimings
|
||||
* An object containing timing information.
|
||||
* @param boolean aFromCache
|
||||
* Indicates if the result came from the browser cache
|
||||
* Indicates if the result came from the browser cache or a service worker
|
||||
*/
|
||||
_createWaterfallView: function(aItem, aTimings, aFromCache) {
|
||||
let { target, attachment } = aItem;
|
||||
|
@ -2690,7 +2715,15 @@ NetworkDetailsView.prototype = {
|
|||
}
|
||||
|
||||
if (aData.status) {
|
||||
$("#headers-summary-status-circle").setAttribute("code", aData.fromCache ? "cached" : aData.status);
|
||||
let code;
|
||||
if (aData.fromCache) {
|
||||
code = L10N.getStr("netmonitor.status.cached");
|
||||
} else if (aData.fromServiceWorker) {
|
||||
code = L10N.getStr("netmonitor.status.serviceWorker");
|
||||
} else {
|
||||
code = aData.status;
|
||||
}
|
||||
$("#headers-summary-status-circle").setAttribute("code", code);
|
||||
$("#headers-summary-status-value").setAttribute("value", aData.status + " " + aData.statusText);
|
||||
$("#headers-summary-status").removeAttribute("hidden");
|
||||
} else {
|
||||
|
|
|
@ -36,6 +36,8 @@ support-files =
|
|||
sjs_sorting-test-server.sjs
|
||||
sjs_status-codes-test-server.sjs
|
||||
test-image.png
|
||||
service-workers/status-codes.html
|
||||
service-workers/status-codes-service-worker.js
|
||||
|
||||
[browser_net_aaa_leaktest.js]
|
||||
[browser_net_accessibility-01.js]
|
||||
|
@ -43,6 +45,7 @@ support-files =
|
|||
[browser_net_api-calls.js]
|
||||
[browser_net_autoscroll.js]
|
||||
[browser_net_cached-status.js]
|
||||
[browser_net_service-worker-status.js]
|
||||
[browser_net_charts-01.js]
|
||||
[browser_net_charts-02.js]
|
||||
[browser_net_charts-03.js]
|
||||
|
|
|
@ -61,7 +61,7 @@ var test = Task.async(function*() {
|
|||
details: {
|
||||
status: 200,
|
||||
statusText: "OK (cached)",
|
||||
fromCache: true,
|
||||
displayedStatus : "cached",
|
||||
type: "plain",
|
||||
fullMimeType: "text/plain; charset=utf-8"
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ var test = Task.async(function*() {
|
|||
details: {
|
||||
status: 301,
|
||||
statusText: "Moved Permanently (cached)",
|
||||
fromCache: true,
|
||||
displayedStatus: "cached",
|
||||
type: "html",
|
||||
fullMimeType: "text/html; charset=utf-8"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests if requests intercepted by service workers have the correct status code
|
||||
*/
|
||||
|
||||
// Service workers only work on https
|
||||
const URL = EXAMPLE_URL.replace("http:", "https:");
|
||||
|
||||
const TEST_URL = URL + "service-workers/status-codes.html";
|
||||
|
||||
var test = Task.async(function*() {
|
||||
let [tab, debuggee, monitor] = yield initNetMonitor(TEST_URL, null, true);
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, NetMonitorView } = monitor.panelWin;
|
||||
let { RequestsMenu, NetworkDetails } = NetMonitorView;
|
||||
|
||||
const REQUEST_DATA = [
|
||||
{
|
||||
method: 'GET',
|
||||
uri: URL + "service-workers/test/200",
|
||||
details: {
|
||||
status: 200,
|
||||
statusText: 'OK (service worker)',
|
||||
displayedStatus: 'service worker',
|
||||
type: "plain",
|
||||
fullMimeType: "text/plain; charset=UTF-8"
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
info("Registering the service worker...");
|
||||
yield debuggee.registerServiceWorker();
|
||||
|
||||
info("Performing requests...");
|
||||
debuggee.performRequests();
|
||||
yield waitForNetworkEvents(monitor, REQUEST_DATA.length);
|
||||
|
||||
let index = 0;
|
||||
for (let request of REQUEST_DATA) {
|
||||
let item = RequestsMenu.getItemAtIndex(index);
|
||||
|
||||
info("Verifying request #" + index);
|
||||
yield verifyRequestItemTarget(item, request.method, request.uri, request.details);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
yield teardown(monitor);
|
||||
finish();
|
||||
});
|
|
@ -283,7 +283,7 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
info("Visible index of item: " + visibleIndex);
|
||||
|
||||
let { fuzzyUrl, status, statusText, type, fullMimeType,
|
||||
transferred, size, time, fromCache } = aData;
|
||||
transferred, size, time, displayedStatus } = aData;
|
||||
let { attachment, target } = aRequestItem
|
||||
|
||||
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||
|
@ -330,7 +330,7 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
info("Displayed status: " + value);
|
||||
info("Displayed code: " + codeValue);
|
||||
info("Tooltip status: " + tooltip);
|
||||
is(value, fromCache ? "cached" : status, "The displayed status is correct.");
|
||||
is(value, displayedStatus ? displayedStatus : status, "The displayed status is correct.");
|
||||
is(codeValue, status, "The displayed status code is correct.");
|
||||
is(tooltip, status + " " + statusText, "The tooltip status is correct.");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
addEventListener("fetch", function(event) {
|
||||
let response = new Response("Service worker response");
|
||||
event.respondWith(response);
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Status codes test</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function get(url) {
|
||||
return new Promise(done => {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", url);
|
||||
document.documentElement.appendChild(iframe);
|
||||
iframe.contentWindow.onload = done;
|
||||
});
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register("status-codes-service-worker.js")
|
||||
.then(() => navigator.serviceWorker.ready);
|
||||
}
|
||||
|
||||
function performRequests() {
|
||||
return get("test/200");
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -283,6 +283,11 @@ WebConsoleActor.prototype =
|
|||
*/
|
||||
networkMonitor: null,
|
||||
|
||||
/**
|
||||
* The NetworkMonitor instance living in the same (child) process.
|
||||
*/
|
||||
networkMonitorChild: null,
|
||||
|
||||
/**
|
||||
* The ConsoleProgressListener instance.
|
||||
*/
|
||||
|
@ -343,6 +348,10 @@ WebConsoleActor.prototype =
|
|||
this.networkMonitor.destroy();
|
||||
this.networkMonitor = null;
|
||||
}
|
||||
if (this.networkMonitorChild) {
|
||||
this.networkMonitorChild.destroy();
|
||||
this.networkMonitorChild = null;
|
||||
}
|
||||
if (this.consoleProgressListener) {
|
||||
this.consoleProgressListener.destroy();
|
||||
this.consoleProgressListener = null;
|
||||
|
@ -587,14 +596,21 @@ WebConsoleActor.prototype =
|
|||
case "NetworkActivity":
|
||||
if (!this.networkMonitor) {
|
||||
if (appId || messageManager) {
|
||||
// Start a network monitor in the parent process to listen to
|
||||
// most requests than happen in parent
|
||||
this.networkMonitor =
|
||||
new NetworkMonitorChild(appId, messageManager,
|
||||
this.parentActor.actorID, this);
|
||||
this.networkMonitor.init();
|
||||
// Spawn also one in the child to listen to service workers
|
||||
this.networkMonitorChild = new NetworkMonitor({ window: window },
|
||||
this);
|
||||
this.networkMonitorChild.init();
|
||||
}
|
||||
else {
|
||||
this.networkMonitor = new NetworkMonitor({ window: window }, this);
|
||||
this.networkMonitor.init();
|
||||
}
|
||||
this.networkMonitor.init();
|
||||
}
|
||||
startedListeners.push(listener);
|
||||
break;
|
||||
|
@ -677,6 +693,10 @@ WebConsoleActor.prototype =
|
|||
this.networkMonitor.destroy();
|
||||
this.networkMonitor = null;
|
||||
}
|
||||
if (this.networkMonitorChild) {
|
||||
this.networkMonitorChild.destroy();
|
||||
this.networkMonitorChild = null;
|
||||
}
|
||||
stoppedListeners.push(listener);
|
||||
break;
|
||||
case "FileActivity":
|
||||
|
@ -1734,6 +1754,7 @@ NetworkEventActor.prototype =
|
|||
method: this._request.method,
|
||||
isXHR: this._isXHR,
|
||||
fromCache: this._fromCache,
|
||||
fromServiceWorker: this._fromServiceWorker,
|
||||
private: this._private,
|
||||
};
|
||||
},
|
||||
|
@ -1778,6 +1799,7 @@ NetworkEventActor.prototype =
|
|||
this._startedDateTime = aNetworkEvent.startedDateTime;
|
||||
this._isXHR = aNetworkEvent.isXHR;
|
||||
this._fromCache = aNetworkEvent.fromCache;
|
||||
this._fromServiceWorker = aNetworkEvent.fromServiceWorker;
|
||||
|
||||
for (let prop of ['method', 'url', 'httpVersion', 'headersSize']) {
|
||||
this._request[prop] = aNetworkEvent[prop];
|
||||
|
|
|
@ -105,7 +105,8 @@ WebConsoleClient.prototype = {
|
|||
timings: {},
|
||||
updates: [], // track the list of network event updates
|
||||
private: actor.private,
|
||||
fromCache: actor.fromCache
|
||||
fromCache: actor.fromCache,
|
||||
fromServiceWorker: actor.fromServiceWorker
|
||||
};
|
||||
this._networkRequests.set(actor.actor, networkInfo);
|
||||
|
||||
|
|
|
@ -491,6 +491,7 @@ function NetworkMonitor(aFilters, aOwner)
|
|||
this.openResponses = {};
|
||||
this._httpResponseExaminer =
|
||||
DevToolsUtils.makeInfallible(this._httpResponseExaminer).bind(this);
|
||||
this._serviceWorkerRequest = this._serviceWorkerRequest.bind(this);
|
||||
}
|
||||
exports.NetworkMonitor = NetworkMonitor;
|
||||
|
||||
|
@ -546,15 +547,35 @@ NetworkMonitor.prototype = {
|
|||
{
|
||||
this.responsePipeSegmentSize = Services.prefs
|
||||
.getIntPref("network.buffer.cache.size");
|
||||
|
||||
gActivityDistributor.addObserver(this);
|
||||
this.interceptedChannels = new Set();
|
||||
|
||||
if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
|
||||
gActivityDistributor.addObserver(this);
|
||||
Services.obs.addObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-response", false);
|
||||
Services.obs.addObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-cached-response", false);
|
||||
}
|
||||
// In child processes, only watch for service worker requests
|
||||
// everything else only happens in the parent process
|
||||
Services.obs.addObserver(this._serviceWorkerRequest,
|
||||
"service-worker-synthesized-response", false);
|
||||
},
|
||||
|
||||
_serviceWorkerRequest: function(aSubject, aTopic, aData)
|
||||
{
|
||||
let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
if (!this._matchRequest(channel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.interceptedChannels.add(aSubject);
|
||||
|
||||
// On e10s, we never receive http-on-examine-cached-response, so fake one.
|
||||
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
|
||||
this._httpResponseExaminer(channel, "http-on-examine-cached-response");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -628,10 +649,18 @@ NetworkMonitor.prototype = {
|
|||
this.openResponses[response.id] = response;
|
||||
|
||||
if (aTopic === "http-on-examine-cached-response") {
|
||||
// Service worker requests emits cached-reponse notification on non-e10s,
|
||||
// and we fake one on e10s.
|
||||
let fromServiceWorker = this.interceptedChannels.has(channel);
|
||||
this.interceptedChannels.delete(channel);
|
||||
|
||||
// If this is a cached response, there never was a request event
|
||||
// so we need to construct one here so the frontend gets all the
|
||||
// expected events.
|
||||
let httpActivity = this._createNetworkEvent(channel, { fromCache: true });
|
||||
let httpActivity = this._createNetworkEvent(channel, {
|
||||
fromCache: !fromServiceWorker,
|
||||
fromServiceWorker: fromServiceWorker
|
||||
});
|
||||
httpActivity.owner.addResponseStart({
|
||||
httpVersion: response.httpVersion,
|
||||
remoteAddress: "",
|
||||
|
@ -806,7 +835,7 @@ NetworkMonitor.prototype = {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
_createNetworkEvent: function(aChannel, { timestamp, extraStringData, fromCache }) {
|
||||
_createNetworkEvent: function(aChannel, { timestamp, extraStringData, fromCache, fromServiceWorker }) {
|
||||
let win = NetworkHelper.getWindowForRequest(aChannel);
|
||||
let httpActivity = this.createActivityObject(aChannel);
|
||||
|
||||
|
@ -830,6 +859,7 @@ NetworkMonitor.prototype = {
|
|||
event.headersSize = 0;
|
||||
event.startedDateTime = (timestamp ? new Date(Math.round(timestamp / 1000)) : new Date()).toISOString();
|
||||
event.fromCache = fromCache;
|
||||
event.fromServiceWorker = fromServiceWorker;
|
||||
|
||||
if (extraStringData) {
|
||||
event.headersSize = extraStringData.length;
|
||||
|
@ -1189,12 +1219,17 @@ NetworkMonitor.prototype = {
|
|||
destroy: function NM_destroy()
|
||||
{
|
||||
if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
|
||||
gActivityDistributor.removeObserver(this);
|
||||
Services.obs.removeObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-response");
|
||||
Services.obs.removeObserver(this._httpResponseExaminer,
|
||||
"http-on-examine-cached-response");
|
||||
}
|
||||
|
||||
gActivityDistributor.removeObserver(this);
|
||||
Services.obs.removeObserver(this._serviceWorkerRequest,
|
||||
"service-worker-synthesized-response");
|
||||
|
||||
this.interceptedChannels.clear();
|
||||
this.openRequests = {};
|
||||
this.openResponses = {};
|
||||
this.owner = null;
|
||||
|
|
Загрузка…
Ссылка в новой задаче