author | Panos Astithas <past@mozilla.com> |
Fri, 24 Apr 2015 21:38:09 +0300 | |
changeset 242939 | 019d595855ed9a1b1052983cf00134e771c5d9ad |
parent 242938 | de4f4de880fd428dce92c94ef168532f57dff547 |
child 242940 | cba10c0c94343d97b88d78242bafefaff0245ee9 |
push id | 28714 |
push user | kwierso@gmail.com |
push date | Fri, 08 May 2015 17:29:48 +0000 |
treeherder | mozilla-central@5e8adf0e7f2c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | vporof |
bugs | 862341 |
milestone | 40.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/devtools/webconsole/test/head.js +++ b/browser/devtools/webconsole/test/head.js @@ -10,17 +10,16 @@ let {console} = Cu.import("resource://gr let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); let {Task} = Cu.import("resource://gre/modules/Task.jsm", {}); let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); let {require, TargetFactory} = devtools; let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils"); let {Messages} = require("devtools/webconsole/console-output"); const asyncStorage = require("devtools/toolkit/shared/async-storage"); -// promise._reportErrors = true; // please never leave me. //Services.prefs.setBoolPref("devtools.debugger.log", true); let gPendingOutputTest = 0; // The various categories of messages. const CATEGORY_NETWORK = 0; const CATEGORY_CSS = 1; const CATEGORY_JS = 2;
--- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -200,17 +200,16 @@ function WebConsoleFrame(aWebConsoleOwne this.owner = aWebConsoleOwner; this.hudId = this.owner.hudId; this.window = this.owner.iframeWindow; this._repeatNodes = {}; this._outputQueue = []; this._itemDestroyQueue = []; this._pruneCategoriesQueue = {}; - this._networkRequests = {}; this.filterPrefs = {}; this.output = new ConsoleOutput(this); this._toggleFilter = this._toggleFilter.bind(this); this._onPanelSelected = this._onPanelSelected.bind(this); this._flushMessageQueue = this._flushMessageQueue.bind(this); this._onToolboxPrefChanged = this._onToolboxPrefChanged.bind(this); @@ -249,24 +248,16 @@ WebConsoleFrame.prototype = { /** * Holds the initialization promise object. * @private * @type object */ _initDefer: null, /** - * Holds the network requests currently displayed by the Web Console. Each key - * represents the connection ID and the value is network request information. - * @private - * @type object - */ - _networkRequests: null, - - /** * Last time when we displayed any message in the output. * * @private * @type number * Timestamp in milliseconds since the Unix epoch. */ _lastOutputFlush: 0, @@ -1523,29 +1514,24 @@ WebConsoleFrame.prototype = { node._objectActors = new Set([aPacket.message.actor]); } return node; }, /** * Log network event. * - * @param object aActor - * The network event actor to log. + * @param object networkInfo + * The network request information to log. * @return nsIDOMElement|null * The message element to display in the Web Console output. */ - logNetEvent: function WCF_logNetEvent(aActor) + logNetEvent: function(networkInfo) { - let actorId = aActor.actor; - let networkInfo = this._networkRequests[actorId]; - if (!networkInfo) { - return null; - } - + let actorId = networkInfo.actor; let request = networkInfo.request; let clipboardText = request.method + " " + request.url; let severity = SEVERITY_LOG; if (networkInfo.isXHR) { clipboardText = request.method + " XHR " + request.url; severity = SEVERITY_INFO; } let mixedRequest = @@ -1793,94 +1779,39 @@ WebConsoleFrame.prototype = { let node = this.createMessageNode(CATEGORY_JS, SEVERITY_WARNING, l10n.getStr("ConsoleAPIDisabled")); this.outputMessage(CATEGORY_JS, node); }, /** * Handle the network events coming from the remote Web Console. * - * @param object aActor - * The NetworkEventActor grip. + * @param object networkInfo + * The network request information. */ - handleNetworkEvent: function WCF_handleNetworkEvent(aActor) + handleNetworkEvent: function(networkInfo) { - let networkInfo = { - node: null, - actor: aActor.actor, - discardRequestBody: true, - discardResponseBody: true, - startedDateTime: aActor.startedDateTime, - request: { - url: aActor.url, - method: aActor.method, - }, - isXHR: aActor.isXHR, - response: {}, - timings: {}, - updates: [], // track the list of network event updates - private: aActor.private, - }; - - this._networkRequests[aActor.actor] = networkInfo; - this.outputMessage(CATEGORY_NETWORK, this.logNetEvent, [aActor]); + this.outputMessage(CATEGORY_NETWORK, this.logNetEvent, [networkInfo]); }, /** * Handle network event updates coming from the server. * - * @param string aActorId - * The network event actor ID. - * @param string aType - * Update type. - * @param object aPacket + * @param object networkInfo + * The network request information. + * @param object packet * Update details. */ - handleNetworkEventUpdate: - function WCF_handleNetworkEventUpdate(aActorId, aType, aPacket) + handleNetworkEventUpdate: function(networkInfo, packet) { - let networkInfo = this._networkRequests[aActorId]; - if (!networkInfo) { - return; - } - - networkInfo.updates.push(aType); - - switch (aType) { - case "requestHeaders": - networkInfo.request.headersSize = aPacket.headersSize; - break; - case "requestPostData": - networkInfo.discardRequestBody = aPacket.discardRequestBody; - networkInfo.request.bodySize = aPacket.dataSize; - break; - case "responseStart": - networkInfo.response.httpVersion = aPacket.response.httpVersion; - networkInfo.response.status = aPacket.response.status; - networkInfo.response.statusText = aPacket.response.statusText; - networkInfo.response.headersSize = aPacket.response.headersSize; - networkInfo.discardResponseBody = aPacket.response.discardResponseBody; - break; - case "responseContent": - networkInfo.response.content = { - mimeType: aPacket.mimeType, - }; - networkInfo.response.bodySize = aPacket.contentSize; - networkInfo.discardResponseBody = aPacket.discardResponseBody; - break; - case "eventTimings": - networkInfo.totalTime = aPacket.totalTime; - break; - } - - if (networkInfo.node && this._updateNetMessage(aActorId)) { + if (networkInfo.node && this._updateNetMessage(packet.from)) { this.emit("new-messages", new Set([{ update: true, node: networkInfo.node, - response: aPacket, + response: packet, }])); } // For unit tests we pass the HTTP activity object to the test callback, // once requests complete. if (this.owner.lastFinishedRequestCallback && networkInfo.updates.indexOf("responseContent") > -1 && networkInfo.updates.indexOf("eventTimings") > -1) { @@ -1895,17 +1826,17 @@ WebConsoleFrame.prototype = { * @private * @param string aActorId * The network event actor ID for which you want to update the message. * @return boolean * |true| if the message node was updated, or |false| otherwise. */ _updateNetMessage: function WCF__updateNetMessage(aActorId) { - let networkInfo = this._networkRequests[aActorId]; + let networkInfo = this.webConsoleClient.getNetworkRequest(aActorId); if (!networkInfo || !networkInfo.node) { return; } let messageNode = networkInfo.node; let updates = networkInfo.updates; let hasEventTimings = updates.indexOf("eventTimings") > -1; let hasResponseStart = updates.indexOf("responseStart") > -1; @@ -2441,18 +2372,18 @@ WebConsoleFrame.prototype = { if (category == CATEGORY_NETWORK) { let connectionId = null; if (methodOrNode == this.logNetEvent) { connectionId = args[0].actor; } else if (typeof methodOrNode != "function") { connectionId = methodOrNode._connectionId; } - if (connectionId && connectionId in this._networkRequests) { - delete this._networkRequests[connectionId]; + if (connectionId && this.webConsoleClient.hasNetworkRequest(connectionId)) { + this.webConsoleClient.removeNetworkRequest(connectionId); this._releaseObject(connectionId); } } else if (category == CATEGORY_WEBDEV && methodOrNode == this.logConsoleAPIMessage) { args[0].arguments.forEach((aValue) => { if (WebConsoleUtils.isActorGrip(aValue)) { this._releaseObject(aValue.actor); @@ -2519,17 +2450,17 @@ WebConsoleFrame.prototype = { aNode.category == CATEGORY_SECURITY) { let repeatNode = aNode.getElementsByClassName("message-repeats")[0]; if (repeatNode && repeatNode._uid) { delete this._repeatNodes[repeatNode._uid]; } } else if (aNode._connectionId && aNode.category == CATEGORY_NETWORK) { - delete this._networkRequests[aNode._connectionId]; + this.webConsoleClient.removeNetworkRequest(aNode._connectionId); this._releaseObject(aNode._connectionId); } else if (aNode.classList.contains("inlined-variables-view")) { let view = aNode._variablesView; if (view) { view.controller.releaseActors(); } aNode._variablesView = null; @@ -3013,17 +2944,17 @@ WebConsoleFrame.prototype = { gDevTools.off("pref-changed", this._onToolboxPrefChanged); this._repeatNodes = {}; this._outputQueue.forEach(this._destroyItem, this); this._outputQueue = []; this._itemDestroyQueue.forEach(this._destroyItem, this); this._itemDestroyQueue = []; this._pruneCategoriesQueue = {}; - this._networkRequests = {}; + this.webConsoleClient.clearNetworkRequests(); if (this._outputTimerInitialized) { this._outputTimerInitialized = false; this._outputTimer.cancel(); } this._outputTimer = null; if (this.jsterm) { this.jsterm.destroy(); @@ -3967,17 +3898,17 @@ JSTerm.prototype = { let node; while ((node = outputNode.firstChild)) { hud.removeOutputMessage(node); } hud.groupDepth = 0; hud._outputQueue.forEach(hud._destroyItem, hud); hud._outputQueue = []; - hud._networkRequests = {}; + this.webConsoleClient.clearNetworkRequests(); hud._repeatNodes = {}; if (aClearStorage) { this.webConsoleClient.clearMessagesCache(); } this._sidebarDestroy(); @@ -5109,18 +5040,16 @@ WebConsoleConnectionProxy.prototype = { this._connectTimer = null; }); let client = this.client = this.target.client; client.addListener("logMessage", this._onLogMessage); client.addListener("pageError", this._onPageError); client.addListener("consoleAPICall", this._onConsoleAPICall); - client.addListener("networkEvent", this._onNetworkEvent); - client.addListener("networkEventUpdate", this._onNetworkEventUpdate); client.addListener("fileActivity", this._onFileActivity); client.addListener("reflowActivity", this._onReflowActivity); client.addListener("lastPrivateContextExited", this._onLastPrivateContextExited); this.target.on("will-navigate", this._onTabNavigated); this.target.on("navigate", this._onTabNavigated); this._consoleActor = this.target.form.consoleActor; if (this.target.isTabActor) { @@ -5175,16 +5104,18 @@ WebConsoleConnectionProxy.prototype = { aResponse.message); this._connectDefer.reject(aResponse); return; } this.webConsoleClient = aWebConsoleClient; this._hasNativeConsoleAPI = aResponse.nativeConsoleAPI; + this.webConsoleClient.on("networkEvent", this._onNetworkEvent); + this.webConsoleClient.on("networkEventUpdate", this._onNetworkEventUpdate); let msgs = ["PageError", "ConsoleAPI"]; this.webConsoleClient.getCachedMessages(msgs, this._onCachedMessages); this.owner._updateReflowActivityListener(); }, /** @@ -5270,43 +5201,44 @@ WebConsoleConnectionProxy.prototype = { } }, /** * The "networkEvent" message type handler. We redirect any message to * the UI for displaying. * * @private - * @param string aType + * @param string type * Message type. - * @param object aPacket - * The message received from the server. + * @param object networkInfo + * The network request information. */ - _onNetworkEvent: function WCCP__onNetworkEvent(aType, aPacket) + _onNetworkEvent: function(type, networkInfo) { - if (this.owner && aPacket.from == this._consoleActor) { - this.owner.handleNetworkEvent(aPacket.eventActor); + if (this.owner) { + this.owner.handleNetworkEvent(networkInfo); } }, /** * The "networkEventUpdate" message type handler. We redirect any message to * the UI for displaying. * * @private - * @param string aType + * @param string type * Message type. - * @param object aPacket + * @param object packet * The message received from the server. + * @param object networkInfo + * The network request information. */ - _onNetworkEventUpdate: function WCCP__onNetworkEvenUpdatet(aType, aPacket) + _onNetworkEventUpdate: function(type, { packet, networkInfo }) { if (this.owner) { - this.owner.handleNetworkEventUpdate(aPacket.from, aPacket.updateType, - aPacket); + this.owner.handleNetworkEventUpdate(networkInfo, packet); } }, /** * The "fileActivity" message type handler. We redirect any message to * the UI for displaying. * * @private @@ -5396,21 +5328,21 @@ WebConsoleConnectionProxy.prototype = { if (!this.client) { this._disconnecter.resolve(null); return this._disconnecter.promise; } this.client.removeListener("logMessage", this._onLogMessage); this.client.removeListener("pageError", this._onPageError); this.client.removeListener("consoleAPICall", this._onConsoleAPICall); - this.client.removeListener("networkEvent", this._onNetworkEvent); - this.client.removeListener("networkEventUpdate", this._onNetworkEventUpdate); this.client.removeListener("fileActivity", this._onFileActivity); this.client.removeListener("reflowActivity", this._onReflowActivity); this.client.removeListener("lastPrivateContextExited", this._onLastPrivateContextExited); + this.webConsoleClient.off("networkEvent", this._onNetworkEvent); + this.webConsoleClient.off("networkEventUpdate", this._onNetworkEventUpdate); this.target.off("will-navigate", this._onTabNavigated); this.target.off("navigate", this._onTabNavigated); this.client = null; this.webConsoleClient = null; this.target = null; this.connected = false; this.owner = null;
--- a/toolkit/devtools/webconsole/client.js +++ b/toolkit/devtools/webconsole/client.js @@ -3,16 +3,17 @@ /* 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 {Cc, Ci, Cu} = require("chrome"); const DevToolsUtils = require("devtools/toolkit/DevToolsUtils"); +const EventEmitter = require("devtools/toolkit/event-emitter"); loader.lazyImporter(this, "LongStringClient", "resource://gre/modules/devtools/dbg-client.jsm"); /** * A WebConsoleClient is used as a front end for the WebConsoleActor that is * created on the server, hiding implementation details. * * @param object aDebuggerClient @@ -23,47 +24,161 @@ loader.lazyImporter(this, "LongStringCli */ function WebConsoleClient(aDebuggerClient, aResponse) { this._actor = aResponse.from; this._client = aDebuggerClient; this._longStrings = {}; this.traits = aResponse.traits || {}; this.events = []; + this._networkRequests = new Map(); this.pendingEvaluationResults = new Map(); this.onEvaluationResult = this.onEvaluationResult.bind(this); + this.onNetworkEvent = this._onNetworkEvent.bind(this); + this.onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this); this._client.addListener("evaluationResult", this.onEvaluationResult); + this._client.addListener("networkEvent", this.onNetworkEvent); + this._client.addListener("networkEventUpdate", this.onNetworkEventUpdate); + EventEmitter.decorate(this); } exports.WebConsoleClient = WebConsoleClient; WebConsoleClient.prototype = { _longStrings: null, traits: null, + /** + * Holds the network requests currently displayed by the Web Console. Each key + * represents the connection ID and the value is network request information. + * @private + * @type object + */ + _networkRequests: null, + + getNetworkRequest(actorId) { + return this._networkRequests.get(actorId); + }, + + hasNetworkRequest(actorId) { + return this._networkRequests.has(actorId); + }, + + removeNetworkRequest(actorId) { + this._networkRequests.delete(actorId); + }, + get actor() { return this._actor; }, /** + * The "networkEvent" message type handler. We redirect any message to + * the UI for displaying. + * + * @private + * @param string type + * Message type. + * @param object packet + * The message received from the server. + */ + _onNetworkEvent: function (type, packet) + { + if (packet.from == this._actor) { + let actor = packet.eventActor; + let networkInfo = { + node: null, + actor: actor.actor, + discardRequestBody: true, + discardResponseBody: true, + startedDateTime: actor.startedDateTime, + request: { + url: actor.url, + method: actor.method, + }, + isXHR: actor.isXHR, + response: {}, + timings: {}, + updates: [], // track the list of network event updates + private: actor.private, + }; + this._networkRequests.set(actor.actor, networkInfo); + + this.emit("networkEvent", networkInfo); + } + }, + + /** + * The "networkEventUpdate" message type handler. We redirect any message to + * the UI for displaying. + * + * @private + * @param string type + * Message type. + * @param object packet + * The message received from the server. + */ + _onNetworkEventUpdate: function (type, packet) + { + let networkInfo = this.getNetworkRequest(packet.from); + if (!networkInfo) { + return; + } + + networkInfo.updates.push(packet.updateType); + + switch (packet.updateType) { + case "requestHeaders": + networkInfo.request.headersSize = packet.headersSize; + break; + case "requestPostData": + networkInfo.discardRequestBody = packet.discardRequestBody; + networkInfo.request.bodySize = packet.dataSize; + break; + case "responseStart": + networkInfo.response.httpVersion = packet.response.httpVersion; + networkInfo.response.status = packet.response.status; + networkInfo.response.statusText = packet.response.statusText; + networkInfo.response.headersSize = packet.response.headersSize; + networkInfo.discardResponseBody = packet.response.discardResponseBody; + break; + case "responseContent": + networkInfo.response.content = { + mimeType: packet.mimeType, + }; + networkInfo.response.bodySize = packet.contentSize; + networkInfo.discardResponseBody = packet.discardResponseBody; + break; + case "eventTimings": + networkInfo.totalTime = packet.totalTime; + break; + } + + this.emit("networkEventUpdate", { + packet: packet, + networkInfo + }); + }, + + /** * Retrieve the cached messages from the server. * * @see this.CACHED_MESSAGES - * @param array aTypes + * @param array types * The array of message types you want from the server. See * this.CACHED_MESSAGES for known types. * @param function aOnResponse * The function invoked when the response is received. */ - getCachedMessages: function WCC_getCachedMessages(aTypes, aOnResponse) + getCachedMessages: function WCC_getCachedMessages(types, aOnResponse) { let packet = { to: this._actor, type: "getCachedMessages", - messageTypes: aTypes, + messageTypes: types, }; this._client.request(packet, aOnResponse); }, /** * Inspect the properties of an object. * * @param string aActor @@ -468,15 +583,23 @@ WebConsoleClient.prototype = { * detaches from the console actor. * * @param function aOnResponse * Function to invoke when the server response is received. */ detach: function WCC_detach(aOnResponse) { this._client.removeListener("evaluationResult", this.onEvaluationResult); + this._client.removeListener("networkEvent", this.onNetworkEvent); + this._client.removeListener("networkEventUpdate", this.onNetworkEventUpdate); this.stopListeners(null, aOnResponse); this._longStrings = null; this._client = null; this.pendingEvaluationResults.clear(); this.pendingEvaluationResults = null; + this.clearNetworkRequests(); + this._networkRequests = null; }, + + clearNetworkRequests: function () { + this._networkRequests.clear(); + } };