diff --git a/browser/devtools/webconsole/HUDService-content.js b/browser/devtools/webconsole/HUDService-content.js index d4aa54ff2dd4..05bb00241cd3 100644 --- a/browser/devtools/webconsole/HUDService-content.js +++ b/browser/devtools/webconsole/HUDService-content.js @@ -18,7 +18,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm", tempScope); Cu.import("resource://gre/modules/Services.jsm", tempScope); Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", tempScope); Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope); -Cu.import("resource://gre/modules/devtools/NetworkHelper.jsm", tempScope); +Cu.import("resource:///modules/NetworkHelper.jsm", tempScope); Cu.import("resource://gre/modules/NetUtil.jsm", tempScope); let XPCOMUtils = tempScope.XPCOMUtils; diff --git a/browser/devtools/webconsole/HUDService.jsm b/browser/devtools/webconsole/HUDService.jsm index 02fd3452c531..945e21c1b5b7 100644 --- a/browser/devtools/webconsole/HUDService.jsm +++ b/browser/devtools/webconsole/HUDService.jsm @@ -529,12 +529,28 @@ WebConsole.prototype = { */ _asyncRequests: null, + /** + * Message names that the HUD listens for. These messages come from the remote + * Web Console content script. + * + * @private + * @type array + */ + _messageListeners: ["WebConsole:Initialized", "WebConsole:NetworkActivity", + "WebConsole:FileActivity", "WebConsole:LocationChange"], + /** * The xul:panel that holds the Web Console when it is positioned as a window. * @type nsIDOMElement */ consolePanel: null, + /** + * The current tab location. + * @type string + */ + contentLocation: "", + /** * Getter for the xul:popupset that holds any popups we open. * @type nsIDOMElement @@ -605,6 +621,7 @@ WebConsole.prototype = { this.iframeWindow = this.iframe.contentWindow.wrappedJSObject; this.ui = new this.iframeWindow.WebConsoleFrame(this, position); + this._setupMessageManager(); }, /** @@ -749,8 +766,8 @@ WebConsole.prototype = { */ getPanelTitle: function WC_getPanelTitle() { - let url = this.ui ? this.ui.contentLocation : ""; - return l10n.getFormatStr("webConsoleWindowTitleAndURL", [url]); + return l10n.getFormatStr("webConsoleWindowTitleAndURL", + [this.contentLocation]); }, positions: { @@ -974,16 +991,16 @@ WebConsole.prototype = { }, /** - * Handler for page location changes. If the Web Console is + * Handler for the "WebConsole:LocationChange" message. If the Web Console is * opened in a panel the panel title is updated. * - * @param string aURI - * New page location. - * @param string aTitle - * New page title. + * @param object aMessage + * The message received from the content script. It needs to hold two + * properties: location and title. */ - onLocationChange: function WC_onLocationChange(aURI, aTitle) + onLocationChange: function WC_onLocationChange(aMessage) { + this.contentLocation = aMessage.location; if (this.consolePanel) { this.consolePanel.label = this.getPanelTitle(); } @@ -1019,6 +1036,12 @@ WebConsole.prototype = { */ destroy: function WC_destroy(aOnDestroy) { + this.sendMessageToContent("WebConsole:Destroy", {}); + + this._messageListeners.forEach(function(aName) { + this.messageManager.removeMessageListener(aName, this.ui); + }, this); + // Make sure that the console panel does not try to call // deactivateHUDForContext() again. this.consoleWindowUnregisterOnHide = false; diff --git a/browser/devtools/webconsole/Makefile.in b/browser/devtools/webconsole/Makefile.in index ed66e5a9fb71..2fa5c1f0962c 100644 --- a/browser/devtools/webconsole/Makefile.in +++ b/browser/devtools/webconsole/Makefile.in @@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk EXTRA_JS_MODULES = \ HUDService.jsm \ PropertyPanel.jsm \ + NetworkHelper.jsm \ NetworkPanel.jsm \ AutocompletePopup.jsm \ $(NULL) diff --git a/toolkit/devtools/webconsole/NetworkHelper.jsm b/browser/devtools/webconsole/NetworkHelper.jsm similarity index 95% rename from toolkit/devtools/webconsole/NetworkHelper.jsm rename to browser/devtools/webconsole/NetworkHelper.jsm index a2dd3bb077c2..4db6b03b5717 100644 --- a/toolkit/devtools/webconsole/NetworkHelper.jsm +++ b/browser/devtools/webconsole/NetworkHelper.jsm @@ -99,6 +99,8 @@ var NetworkHelper = return conv.ConvertToUnicode(aText); } catch (ex) { + Cu.reportError("NH_convertToUnicode(aText, '" + + aCharset + "') exception: " + ex); return aText; } }, @@ -175,24 +177,8 @@ var NetworkHelper = readPostTextFromPage: function NH_readPostTextFromPage(aDocShell, aCharset) { let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); - return this.readPostTextFromPageViaWebNav(webNav, aCharset); - }, - - /** - * Reads the posted text from the page's cache, given an nsIWebNavigation - * object. - * - * @param nsIWebNavigation aWebNav - * @param string aCharset - * @returns string or null - * Returns the posted string if it was possible to read from - * aWebNav, otherwise null. - */ - readPostTextFromPageViaWebNav: - function NH_readPostTextFromPageViaWebNav(aWebNav, aCharset) - { - if (aWebNav instanceof Ci.nsIWebPageDescriptor) { - let descriptor = aWebNav.currentDescriptor; + if (webNav instanceof Ci.nsIWebPageDescriptor) { + let descriptor = webNav.currentDescriptor; if (descriptor instanceof Ci.nsISHEntry && descriptor.postData && descriptor instanceof Ci.nsISeekableStream) { diff --git a/browser/devtools/webconsole/NetworkPanel.jsm b/browser/devtools/webconsole/NetworkPanel.jsm index a2eeee9da4b1..91ce3fff4fe8 100644 --- a/browser/devtools/webconsole/NetworkPanel.jsm +++ b/browser/devtools/webconsole/NetworkPanel.jsm @@ -16,7 +16,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "mimeService", "@mozilla.org/mime;1", "nsIMIMEService"); XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper", - "resource://gre/modules/devtools/NetworkHelper.jsm"); + "resource:///modules/NetworkHelper.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); @@ -76,17 +76,9 @@ function NetworkPanel(aParent, aHttpActivity) }, false); // Set the document object and update the content once the panel is loaded. - this.iframe.addEventListener("load", function onLoad() { - if (!self.iframe) { - return; - } - - self.iframe.removeEventListener("load", onLoad, true); - self.update(); - }, true); - - this.panel.addEventListener("popupshown", function onPopupShown() { - self.panel.removeEventListener("popupshown", onPopupShown, true); + this.panel.addEventListener("load", function onLoad() { + self.panel.removeEventListener("load", onLoad, true); + self.document = self.iframe.contentWindow.document; self.update(); }, true); @@ -102,6 +94,12 @@ function NetworkPanel(aParent, aHttpActivity) NetworkPanel.prototype = { + /** + * Callback is called once the NetworkPanel is processed completely. Used by + * unit tests. + */ + isDoneCallback: null, + /** * The current state of the output. */ @@ -120,20 +118,6 @@ NetworkPanel.prototype = _contentType: null, - /** - * Function callback invoked whenever the panel content is updated. This is - * used only by tests. - * - * @private - * @type function - */ - _onUpdate: null, - - get document() { - return this.iframe && this.iframe.contentWindow ? - this.iframe.contentWindow.document : null; - }, - /** * Small helper function that is nearly equal to l10n.getFormatStr * except that it prefixes aName with "NetworkPanel.". @@ -166,8 +150,9 @@ NetworkPanel.prototype = return this._contentType; } - let request = this.httpActivity.request; - let response = this.httpActivity.response; + let entry = this.httpActivity.log.entries[0]; + let request = entry.request; + let response = entry.response; let contentType = ""; let types = response.content ? @@ -251,7 +236,7 @@ NetworkPanel.prototype = */ get _isResponseCached() { - return this.httpActivity.response.status == 304; + return this.httpActivity.log.entries[0].response.status == 304; }, /** @@ -262,7 +247,7 @@ NetworkPanel.prototype = */ get _isRequestBodyFormData() { - let requestBody = this.httpActivity.request.postData.text; + let requestBody = this.httpActivity.log.entries[0].request.postData.text; return this._fromDataRegExp.test(requestBody); }, @@ -356,8 +341,9 @@ NetworkPanel.prototype = */ _displayRequestHeader: function NP__displayRequestHeader() { - let request = this.httpActivity.request; - let requestTime = new Date(this.httpActivity.startedDateTime); + let entry = this.httpActivity.log.entries[0]; + let request = entry.request; + let requestTime = new Date(entry.startedDateTime); this._appendTextNode("headUrl", request.url); this._appendTextNode("headMethod", request.method); @@ -378,9 +364,8 @@ NetworkPanel.prototype = * * @returns void */ - _displayRequestBody: function NP__displayRequestBody() - { - let postData = this.httpActivity.request.postData; + _displayRequestBody: function NP__displayRequestBody() { + let postData = this.httpActivity.log.entries[0].request.postData; this._displayNode("requestBody"); this._appendTextNode("requestBodyContent", postData.text); }, @@ -391,9 +376,8 @@ NetworkPanel.prototype = * * @returns void */ - _displayRequestForm: function NP__processRequestForm() - { - let postData = this.httpActivity.request.postData.text; + _displayRequestForm: function NP__processRequestForm() { + let postData = this.httpActivity.log.entries[0].request.postData.text; let requestBodyLines = postData.split("\n"); let formData = requestBodyLines[requestBodyLines.length - 1]. replace(/\+/g, " ").split("&"); @@ -433,8 +417,9 @@ NetworkPanel.prototype = */ _displayResponseHeader: function NP__displayResponseHeader() { - let timing = this.httpActivity.timings; - let response = this.httpActivity.response; + let entry = this.httpActivity.log.entries[0]; + let timing = entry.timings; + let response = entry.response; this._appendTextNode("headStatus", [response.httpVersion, response.status, @@ -468,16 +453,16 @@ NetworkPanel.prototype = _displayResponseImage: function NP__displayResponseImage() { let self = this; - let timing = this.httpActivity.timings; - let request = this.httpActivity.request; + let entry = this.httpActivity.log.entries[0]; + let timing = entry.timings; + let request = entry.request; let cached = ""; if (this._isResponseCached) { cached = "Cached"; } - let imageNode = this.document.getElementById("responseImage" + - cached + "Node"); + let imageNode = this.document.getElementById("responseImage" + cached +"Node"); imageNode.setAttribute("src", request.url); // This function is called to set the imageInfo. @@ -513,8 +498,9 @@ NetworkPanel.prototype = */ _displayResponseBody: function NP__displayResponseBody() { - let timing = this.httpActivity.timings; - let response = this.httpActivity.response; + let entry = this.httpActivity.log.entries[0]; + let timing = entry.timings; + let response = entry.response; let cached = this._isResponseCached ? "Cached" : ""; this._appendTextNode("responseBody" + cached + "Info", @@ -533,7 +519,7 @@ NetworkPanel.prototype = */ _displayResponseBodyUnknownType: function NP__displayResponseBodyUnknownType() { - let timing = this.httpActivity.timings; + let timing = this.httpActivity.log.entries[0].timings; this._displayNode("responseBodyUnknownType"); this._appendTextNode("responseBodyUnknownTypeInfo", @@ -551,7 +537,7 @@ NetworkPanel.prototype = */ _displayNoResponseBody: function NP_displayNoResponseBody() { - let timing = this.httpActivity.timings; + let timing = this.httpActivity.log.entries[0].timings; this._displayNode("responseNoBody"); this._appendTextNode("responseNoBodyInfo", @@ -571,10 +557,11 @@ NetworkPanel.prototype = return; } - let updates = this.httpActivity.updates; - let timing = this.httpActivity.timings; - let request = this.httpActivity.request; - let response = this.httpActivity.response; + let stages = this.httpActivity.meta.stages; + let entry = this.httpActivity.log.entries[0]; + let timing = entry.timings; + let request = entry.request; + let response = entry.response; switch (this._state) { case this._INIT: @@ -584,7 +571,7 @@ NetworkPanel.prototype = case this._DISPLAYED_REQUEST_HEADER: // Process the request body if there is one. - if (!this.httpActivity.discardRequestBody && request.postData.text) { + if (!this.httpActivity.meta.discardRequestBody && request.postData) { // Check if we send some form data. If so, display the form data special. if (this._isRequestBodyFormData) { this._displayRequestForm(); @@ -597,6 +584,9 @@ NetworkPanel.prototype = // FALL THROUGH case this._DISPLAYED_REQUEST_BODY: + // There is always a response header. Therefore we can skip here if + // we don't have a response header yet and don't have to try updating + // anything else in the NetworkPanel. if (!response.headers.length || !Object.keys(timing).length) { break; } @@ -605,13 +595,13 @@ NetworkPanel.prototype = // FALL THROUGH case this._DISPLAYED_RESPONSE_HEADER: - if (updates.indexOf("responseContent") == -1 || - updates.indexOf("eventTimings") == -1) { + if (stages.indexOf("REQUEST_STOP") == -1 || + stages.indexOf("TRANSACTION_CLOSE") == -1) { break; } this._state = this._TRANSITION_CLOSED; - if (this.httpActivity.discardResponseBody) { + if (this.httpActivity.meta.discardResponseBody) { break; } @@ -627,11 +617,8 @@ NetworkPanel.prototype = else if (response.content.text) { this._displayResponseBody(); } - break; - } - if (this._onUpdate) { - this._onUpdate(); + break; } } } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js b/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js index bc8b371fad34..6aa629ceea85 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js @@ -10,12 +10,10 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-599725-response-headers.sjs"; -function performTest(lastFinishedRequest, aConsole) +function performTest(lastFinishedRequest) { ok(lastFinishedRequest, "page load was logged"); - let headers = null; - function readHeader(aName) { for (let header of headers) { @@ -26,16 +24,13 @@ function performTest(lastFinishedRequest, aConsole) return null; } - aConsole.webConsoleClient.getResponseHeaders(lastFinishedRequest.actor, - function (aResponse) { - headers = aResponse.headers; - ok(headers, "we have the response headers"); - ok(!readHeader("Content-Type"), "we do not have the Content-Type header"); - isnot(readHeader("Content-Length"), 60, "Content-Length != 60"); - executeSoon(finishTest); - }); + let headers = lastFinishedRequest.log.entries[0].response.headers; + ok(headers, "we have the response headers"); + ok(!readHeader("Content-Type"), "we do not have the Content-Type header"); + isnot(readHeader("Content-Length"), 60, "Content-Length != 60"); HUDService.lastFinishedRequestCallback = null; + executeSoon(finishTest); } function test() diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js b/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js index a65c4dfcd1dc..bc1b25b027b2 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_600183_charset.js @@ -10,49 +10,39 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-600183-charset.html"; -function performTest(lastFinishedRequest, aConsole) +function performTest(lastFinishedRequest) { ok(lastFinishedRequest, "charset test page was loaded and logged"); - aConsole.webConsoleClient.getResponseContent(lastFinishedRequest.actor, - function (aResponse) { - ok(!aResponse.contentDiscarded, "response body was not discarded"); + let body = lastFinishedRequest.log.entries[0].response.content.text; + ok(body, "we have the response body"); - let body = aResponse.content.text; - ok(body, "we have the response body"); - - let chars = "\u7684\u95ee\u5019!"; // 的问候! - isnot(body.indexOf("

" + chars + "

"), -1, - "found the chinese simplified string"); - executeSoon(finishTest); - }); + let chars = "\u7684\u95ee\u5019!"; // 的问候! + isnot(body.indexOf("

" + chars + "

"), -1, + "found the chinese simplified string"); HUDService.lastFinishedRequestCallback = null; + executeSoon(finishTest); } function test() { addTab("data:text/html;charset=utf-8,Web Console - bug 600183 test"); + let initialLoad = true; + browser.addEventListener("load", function onLoad() { - browser.removeEventListener("load", onLoad, true); + if (initialLoad) { + openConsole(null, function(hud) { - openConsole(null, function(hud) { - hud.ui.saveRequestAndResponseBodies = true; + hud.ui.saveRequestAndResponseBodies = true; + HUDService.lastFinishedRequestCallback = performTest; - waitForSuccess({ - name: "saveRequestAndResponseBodies update", - validatorFn: function() - { - return hud.ui.saveRequestAndResponseBodies; - }, - successFn: function() - { - HUDService.lastFinishedRequestCallback = performTest; - content.location = TEST_URI; - }, - failureFn: finishTest, + content.location = TEST_URI; }); - }); + initialLoad = false; + } else { + browser.removeEventListener("load", onLoad, true); + } }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js index 5623f52b2cb2..9115014843af 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_602572_log_bodies_checkbox.js @@ -86,17 +86,8 @@ function onpopupshown2(aEvent) }); }, false); - waitForSuccess({ - name: "saveRequestAndResponseBodies update", - validatorFn: function() - { - return huds[1].ui.saveRequestAndResponseBodies; - }, - successFn: function() - { - menupopups[1].hidePopup(); - }, - failureFn: finishTest, + executeSoon(function() { + menupopups[1].hidePopup(); }); } @@ -156,17 +147,8 @@ function onpopupshown1(aEvent) }, tabs[runCount*2 + 1].linkedBrowser.contentWindow); }, false); - waitForSuccess({ - name: "saveRequestAndResponseBodies update", - validatorFn: function() - { - return huds[0].ui.saveRequestAndResponseBodies; - }, - successFn: function() - { - menupopups[0].hidePopup(); - }, - failureFn: finishTest, + executeSoon(function() { + menupopups[0].hidePopup(); }); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js b/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js index ef84dcadce9d..ef77af4bb6b9 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js @@ -10,86 +10,20 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-630733-response-redirect-headers.sjs"; let lastFinishedRequests = {}; -let webConsoleClient; -function requestDoneCallback(aHttpRequest ) +function requestDoneCallback(aHttpRequest) { - let status = aHttpRequest.response.status; + let status = aHttpRequest.log.entries[0].response.status; lastFinishedRequests[status] = aHttpRequest; } -function consoleOpened(hud) -{ - webConsoleClient = hud.ui.webConsoleClient; - hud.ui.saveRequestAndResponseBodies = true; - - waitForSuccess({ - name: "saveRequestAndResponseBodies update", - validatorFn: function() - { - return hud.ui.saveRequestAndResponseBodies; - }, - successFn: function() - { - HUDService.lastFinishedRequestCallback = requestDoneCallback; - waitForSuccess(waitForResponses); - content.location = TEST_URI; - }, - failureFn: finishTest, - }); - - let waitForResponses = { - name: "301 and 404 responses", - validatorFn: function() - { - return "301" in lastFinishedRequests && - "404" in lastFinishedRequests; - }, - successFn: getHeaders, - failureFn: finishTest, - }; -} - -function getHeaders() +function performTest(aEvent) { HUDService.lastFinishedRequestCallback = null; ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently"); ok("404" in lastFinishedRequests, "request 2: 404 Not found"); - webConsoleClient.getResponseHeaders(lastFinishedRequests["301"].actor, - function (aResponse) { - lastFinishedRequests["301"].response.headers = aResponse.headers; - - webConsoleClient.getResponseHeaders(lastFinishedRequests["404"].actor, - function (aResponse) { - lastFinishedRequests["404"].response.headers = aResponse.headers; - executeSoon(getContent); - }); - }); -} - -function getContent() -{ - webConsoleClient.getResponseContent(lastFinishedRequests["301"].actor, - function (aResponse) { - lastFinishedRequests["301"].response.content = aResponse.content; - lastFinishedRequests["301"].discardResponseBody = aResponse.contentDiscarded; - - webConsoleClient.getResponseContent(lastFinishedRequests["404"].actor, - function (aResponse) { - lastFinishedRequests["404"].response.content = aResponse.content; - lastFinishedRequests["404"].discardResponseBody = - aResponse.contentDiscarded; - - webConsoleClient = null; - executeSoon(performTest); - }); - }); -} - -function performTest() -{ function readHeader(aName) { for (let header of headers) { @@ -100,7 +34,7 @@ function performTest() return null; } - let headers = lastFinishedRequests["301"].response.headers; + let headers = lastFinishedRequests["301"].log.entries[0].response.headers; is(readHeader("Content-Type"), "text/html", "we do have the Content-Type header"); is(readHeader("Content-Length"), 71, "Content-Length is correct"); @@ -108,17 +42,14 @@ function performTest() "Content-Length is correct"); is(readHeader("x-foobar-bug630733"), "bazbaz", "X-Foobar-bug630733 is correct"); - - let body = lastFinishedRequests["301"].response.content; + let body = lastFinishedRequests["301"].log.entries[0].response.content; ok(!body.text, "body discarded for request 1"); - ok(lastFinishedRequests["301"].discardResponseBody, - "body discarded for request 1 (confirmed)"); - headers = lastFinishedRequests["404"].response.headers; + headers = lastFinishedRequests["404"].log.entries[0].response.headers; ok(!readHeader("Location"), "no Location header"); ok(!readHeader("x-foobar-bug630733"), "no X-Foobar-bug630733 header"); - body = lastFinishedRequests["404"].response.content.text; + body = lastFinishedRequests["404"].log.entries[0].response.content.text; isnot(body.indexOf("404"), -1, "body is correct for request 2"); @@ -130,8 +61,19 @@ function test() { addTab("data:text/html;charset=utf-8,

Web Console test for bug 630733"); - browser.addEventListener("load", function onLoad(aEvent) { - browser.removeEventListener(aEvent.type, onLoad, true); - openConsole(null, consoleOpened); + browser.addEventListener("load", function onLoad1(aEvent) { + browser.removeEventListener(aEvent.type, onLoad1, true); + + openConsole(null, function(hud) { + hud.ui.saveRequestAndResponseBodies = true; + HUDService.lastFinishedRequestCallback = requestDoneCallback; + + browser.addEventListener("load", function onLoad2(aEvent) { + browser.removeEventListener(aEvent.type, onLoad2, true); + executeSoon(performTest); + }, true); + + content.location = TEST_URI; + }); }, true); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js b/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js index ba4b5e628e25..f717d329cc93 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632817.js @@ -25,7 +25,7 @@ function test() hud = aHud; HUDService.lastFinishedRequestCallback = function(aRequest) { - lastRequest = aRequest; + lastRequest = aRequest.log.entries[0]; if (requestCallback) { requestCallback(); } diff --git a/browser/devtools/webconsole/test/browser_webconsole_netlogging.js b/browser/devtools/webconsole/test/browser_webconsole_netlogging.js index 62dc1995247b..be698f41aaa5 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_netlogging.js +++ b/browser/devtools/webconsole/test/browser_webconsole_netlogging.js @@ -21,6 +21,7 @@ const TEST_DATA_JSON_CONTENT = let lastRequest = null; let requestCallback = null; +let lastActivity = null; function test() { @@ -32,34 +33,19 @@ function test() openConsole(null, function(aHud) { hud = aHud; - HUDService.lastFinishedRequestCallback = requestCallbackWrapper; + HUDService.lastFinishedRequestCallback = function(aRequest) { + lastRequest = aRequest.log.entries[0]; + lastActivity = aRequest; + if (requestCallback) { + requestCallback(); + } + }; executeSoon(testPageLoad); }); }, true); } -function requestCallbackWrapper(aRequest) -{ - lastRequest = aRequest; - - hud.ui.webConsoleClient.getResponseContent(lastRequest.actor, - function(aResponse) { - lastRequest.response.content = aResponse.content; - lastRequest.discardResponseBody = aResponse.contentDiscarded; - - hud.ui.webConsoleClient.getRequestPostData(lastRequest.actor, - function(aResponse) { - lastRequest.request.postData = aResponse.postData; - lastRequest.discardRequestBody = aResponse.postDataDiscarded; - - if (requestCallback) { - requestCallback(); - } - }); - }); -} - function testPageLoad() { requestCallback = function() { @@ -69,10 +55,8 @@ function testPageLoad() is(lastRequest.request.url, TEST_NETWORK_REQUEST_URI, "Logged network entry is page load"); is(lastRequest.request.method, "GET", "Method is correct"); - ok(!lastRequest.request.postData.text, "No request body was stored"); - ok(lastRequest.discardRequestBody, "Request body was discarded"); + ok(!lastRequest.request.postData, "No request body was stored"); ok(!lastRequest.response.content.text, "No response body was stored"); - ok(lastRequest.discardResponseBody, "Response body was discarded"); lastRequest = null; requestCallback = null; @@ -83,29 +67,14 @@ function testPageLoad() } function testPageLoadBody() -{ - // Turn on logging of request bodies and check again. - hud.ui.saveRequestAndResponseBodies = true; - - waitForSuccess({ - name: "saveRequestAndResponseBodies update", - validatorFn: function() - { - return hud.ui.saveRequestAndResponseBodies; - }, - successFn: testPageLoadBodyAfterSettingUpdate, - failureFn: finishTest, - }); -} - -function testPageLoadBodyAfterSettingUpdate() { let loaded = false; let requestCallbackInvoked = false; + // Turn on logging of request bodies and check again. + hud.ui.saveRequestAndResponseBodies = true; requestCallback = function() { ok(lastRequest, "Page load was logged again"); - ok(!lastRequest.discardResponseBody, "Response body was not discarded"); is(lastRequest.response.content.text.indexOf(""), 0, "Response body's beginning is okay"); @@ -135,8 +104,7 @@ function testXhrGet() requestCallback = function() { ok(lastRequest, "testXhrGet() was logged"); is(lastRequest.request.method, "GET", "Method is correct"); - ok(!lastRequest.request.postData.text, "No request body was sent"); - ok(!lastRequest.discardRequestBody, "Request body was not discarded"); + ok(!lastRequest.request.postData, "No request body was sent"); is(lastRequest.response.content.text, TEST_DATA_JSON_CONTENT, "Response is correct"); @@ -197,18 +165,19 @@ function testNetworkPanel() { // Open the NetworkPanel. The functionality of the NetworkPanel is tested // within separate test files. - let networkPanel = hud.ui.openNetworkPanel(hud.ui.filterBox, lastRequest); + let networkPanel = hud.ui.openNetworkPanel(hud.ui.filterBox, lastActivity); + is(networkPanel, hud.ui.filterBox._netPanel, + "Network panel stored on anchor node"); - networkPanel.panel.addEventListener("popupshown", function onPopupShown() { - networkPanel.panel.removeEventListener("popupshown", onPopupShown, true); + networkPanel.panel.addEventListener("load", function onLoad(aEvent) { + networkPanel.panel.removeEventListener(aEvent.type, onLoad, true); - is(hud.ui.filterBox._netPanel, networkPanel, - "Network panel stored on anchor node"); ok(true, "NetworkPanel was opened"); // All tests are done. Shutdown. networkPanel.panel.hidePopup(); lastRequest = null; + lastActivity = null; HUDService.lastFinishedRequestCallback = null; executeSoon(finishTest); }, true); diff --git a/browser/devtools/webconsole/test/browser_webconsole_network_panel.js b/browser/devtools/webconsole/test/browser_webconsole_network_panel.js index 138285b3b687..d0c1a5b37f87 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_network_panel.js +++ b/browser/devtools/webconsole/test/browser_webconsole_network_panel.js @@ -65,36 +65,42 @@ function testGen() { let filterBox = hud.ui.filterBox; let httpActivity = { - updates: [], - discardRequestBody: true, - discardResponseBody: true, - startedDateTime: (new Date()).toISOString(), - request: { - url: "http://www.testpage.com", - method: "GET", - cookies: [], - headers: [ - { name: "foo", value: "bar" }, - ], + meta: { + stages: [], + discardRequestBody: true, + discardResponseBody: true, }, - response: { - headers: [], - content: {}, + log: { + entries: [{ + startedDateTime: (new Date()).toISOString(), + request: { + url: "http://www.testpage.com", + method: "GET", + cookies: [], + headers: [ + { name: "foo", value: "bar" }, + ], + }, + response: { + headers: [], + content: {}, + }, + timings: {}, + }], }, - timings: {}, }; + let entry = httpActivity.log.entries[0]; + let networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); is(filterBox._netPanel, networkPanel, "Network panel stored on the anchor object"); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -117,8 +123,8 @@ function testGen() { // Test request body. info("test 2: request body"); - httpActivity.discardRequestBody = false; - httpActivity.request.postData = { text: "hello world" }; + httpActivity.meta.discardRequestBody = false; + entry.request.postData = { text: "hello world" }; networkPanel.update(); checkIsVisible(networkPanel, { @@ -135,12 +141,12 @@ function testGen() { // Test response header. info("test 3: response header"); - httpActivity.timings.wait = 10; - httpActivity.response.httpVersion = "HTTP/3.14"; - httpActivity.response.status = 999; - httpActivity.response.statusText = "earthquake win"; - httpActivity.response.content.mimeType = "text/html"; - httpActivity.response.headers.push( + entry.timings.wait = 10; + entry.response.httpVersion = "HTTP/3.14"; + entry.response.status = 999; + entry.response.statusText = "earthquake win"; + entry.response.content.mimeType = "text/html"; + entry.response.headers.push( { name: "Content-Type", value: "text/html" }, { name: "leaveHouses", value: "true" } ); @@ -164,8 +170,8 @@ function testGen() { info("test 4"); - httpActivity.discardResponseBody = false; - httpActivity.timings.receive = 2; + httpActivity.meta.discardResponseBody = false; + entry.timings.receive = 2; networkPanel.update(); checkIsVisible(networkPanel, { @@ -181,7 +187,7 @@ function testGen() { info("test 5"); - httpActivity.updates.push("responseContent", "eventTimings"); + httpActivity.meta.stages.push("REQUEST_STOP", "TRANSACTION_CLOSE"); networkPanel.update(); checkNodeContent(networkPanel, "responseNoBodyInfo", "2ms"); @@ -199,22 +205,20 @@ function testGen() { // Second run: Test for cookies and response body. info("test 6: cookies and response body"); - httpActivity.request.cookies.push( + entry.request.cookies.push( { name: "foo", value: "bar" }, { name: "hello", value: "world" } ); - httpActivity.response.content.text = "get out here"; + entry.response.content.text = "get out here"; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); is(filterBox._netPanel, networkPanel, "Network panel stored on httpActivity object"); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -238,17 +242,15 @@ function testGen() { // Check image request. info("test 7: image request"); - httpActivity.response.headers[1].value = "image/png"; - httpActivity.response.content.mimeType = "image/png"; - httpActivity.request.url = TEST_IMG; + entry.response.headers[1].value = "image/png"; + entry.response.content.mimeType = "image/png"; + entry.request.url = TEST_IMG; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -289,17 +291,15 @@ function testGen() { // Check cached image request. info("test 8: cached image request"); - httpActivity.response.httpVersion = "HTTP/1.1"; - httpActivity.response.status = 304; - httpActivity.response.statusText = "Not Modified"; + entry.response.httpVersion = "HTTP/1.1"; + entry.response.status = 304; + entry.response.statusText = "Not Modified"; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -321,19 +321,17 @@ function testGen() { // Test sent form data. info("test 9: sent form data"); - httpActivity.request.postData.text = [ + entry.request.postData.text = [ "Content-Type: application/x-www-form-urlencoded", "Content-Length: 59", "name=rob&age=20" ].join("\n"); networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -354,15 +352,13 @@ function testGen() { // Test no space after Content-Type: info("test 10: no space after Content-Type header in post data"); - httpActivity.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n"; + entry.request.postData.text = "Content-Type:application/x-www-form-urlencoded\n"; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -383,18 +379,16 @@ function testGen() { info("test 11: cached data"); - httpActivity.request.url = TEST_ENCODING_ISO_8859_1; - httpActivity.response.headers[1].value = "application/json"; - httpActivity.response.content.mimeType = "application/json"; - httpActivity.response.content.text = "my cached data is here!"; + entry.request.url = TEST_ENCODING_ISO_8859_1; + entry.response.headers[1].value = "application/json"; + entry.response.content.mimeType = "application/json"; + entry.response.content.text = "my cached data is here!"; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; @@ -418,16 +412,14 @@ function testGen() { // Test a response with a content type that can't be displayed in the // NetworkPanel. info("test 12: unknown content type"); - httpActivity.response.headers[1].value = "application/x-shockwave-flash"; - httpActivity.response.content.mimeType = "application/x-shockwave-flash"; + entry.response.headers[1].value = "application/x-shockwave-flash"; + entry.response.content.mimeType = "application/x-shockwave-flash"; networkPanel = hud.ui.openNetworkPanel(filterBox, httpActivity); - networkPanel._onUpdate = function() { - networkPanel._onUpdate = null; - executeSoon(function() { - testDriver.next(); - }); - }; + networkPanel.panel.addEventListener("load", function onLoad() { + networkPanel.panel.removeEventListener("load", onLoad, true); + testDriver.next(); + }, true); yield; diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 703b9e4ed4cb..ab9742080f91 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -216,6 +216,13 @@ WebConsoleFrame.prototype = { */ proxy: null, + /** + * Tells if the Web Console initialization via message manager completed. + * @private + * @type boolean + */ + _messageManagerInitComplete: false, + /** * Getter for the xul:popupset that holds any popups we open. * @type nsIDOMElement @@ -283,12 +290,6 @@ WebConsoleFrame.prototype = { */ groupDepth: 0, - /** - * The current tab location. - * @type string - */ - contentLocation: "", - /** * The JSTerm object that manage the console's input. * @see JSTerm @@ -330,16 +331,16 @@ WebConsoleFrame.prototype = { * The new value you want to set. */ set saveRequestAndResponseBodies(aValue) { - let newValue = !!aValue; - let preferences = { - "NetworkMonitor.saveRequestAndResponseBodies": newValue, + this._saveRequestAndResponseBodies = aValue; + + let message = { + preferences: { + "NetworkMonitor.saveRequestAndResponseBodies": + this._saveRequestAndResponseBodies, + }, }; - this.webConsoleClient.setPreferences(preferences, function(aResponse) { - if (!aResponse.error) { - this._saveRequestAndResponseBodies = newValue; - } - }.bind(this)); + this.owner.sendMessageToContent("WebConsole:SetPreferences", message); }, /** @@ -351,8 +352,9 @@ WebConsoleFrame.prototype = { this.proxy = new WebConsoleConnectionProxy(this); this.proxy.initServer(); this.proxy.connect(function() { - this.saveRequestAndResponseBodies = this._saveRequestAndResponseBodies; - this._onInitComplete(); + if (this._messageManagerInitComplete) { + this._onInitComplete(); + } }.bind(this)); }, @@ -651,6 +653,50 @@ WebConsoleFrame.prototype = { } }, + /** + * Handler for all of the messages coming from the Web Console content script. + * + * @private + * @param object aMessage + * A MessageManager object that holds the remote message. + */ + receiveMessage: function WCF_receiveMessage(aMessage) + { + if (!aMessage.json || aMessage.json.hudId != this.hudId) { + return; + } + + switch (aMessage.name) { + case "WebConsole:Initialized": + this._onMessageManagerInitComplete(); + break; + case "WebConsole:NetworkActivity": + this.handleNetworkActivity(aMessage.json); + break; + case "WebConsole:FileActivity": + this.outputMessage(CATEGORY_NETWORK, this.logFileActivity, + [aMessage.json.uri]); + break; + case "WebConsole:LocationChange": + this.owner.onLocationChange(aMessage.json); + break; + } + }, + + /** + * Callback method used to track the Web Console initialization via message + * manager. + * + * @private + */ + _onMessageManagerInitComplete: function WCF__onMessageManagerInitComplete() + { + this._messageManagerInitComplete = true; + if (this.proxy.connected) { + this._onInitComplete(); + } + }, + /** * The event handler that is called whenever a user switches a filter on or * off. @@ -1258,21 +1304,22 @@ WebConsoleFrame.prototype = { }, /** - * Log network event. + * Log network activity. * - * @param object aActorId - * The network event actor ID to log. + * @param object aHttpActivity + * The HTTP activity to log. * @return nsIDOMElement|undefined * The message element to display in the Web Console output. */ - logNetEvent: function WCF_logNetEvent(aActorId) + logNetActivity: function WCF_logNetActivity(aConnectionId) { - let networkInfo = this._networkRequests[aActorId]; + let networkInfo = this._networkRequests[aConnectionId]; if (!networkInfo) { return; } - let request = networkInfo.request; + let entry = networkInfo.httpActivity.log.entries[0]; + let request = entry.request; let msgNode = this.document.createElementNS(XUL_NS, "hbox"); @@ -1300,7 +1347,8 @@ WebConsoleFrame.prototype = { let severity = SEVERITY_LOG; let mixedRequest = - WebConsoleUtils.isMixedHTTPSRequest(request.url, this.contentLocation); + WebConsoleUtils.isMixedHTTPSRequest(request.url, + this.owner.contentLocation); if (mixedRequest) { urlNode.classList.add("webconsole-mixed-content"); this.makeMixedContentNode(linkNode); @@ -1321,18 +1369,18 @@ WebConsoleFrame.prototype = { let messageNode = this.createMessageNode(CATEGORY_NETWORK, severity, msgNode, null, null, clipboardText); - messageNode._connectionId = aActorId; + messageNode._connectionId = entry.connection; messageNode.url = request.url; this.makeOutputMessageLink(messageNode, function WCF_net_message_link() { if (!messageNode._panelOpen) { - this.openNetworkPanel(messageNode, networkInfo); + this.openNetworkPanel(messageNode, networkInfo.httpActivity); } }.bind(this)); networkInfo.node = messageNode; - this._updateNetMessage(aActorId); + this._updateNetMessage(entry.connection); return messageNode; }, @@ -1393,17 +1441,6 @@ WebConsoleFrame.prototype = { return outputNode; }, - /** - * Handle the file activity messages coming from the remote Web Console. - * - * @param string aFileURI - * The file URI that was requested. - */ - handleFileActivity: function WCF_handleFileActivity(aFileURI) - { - this.outputMessage(CATEGORY_NETWORK, this.logFileActivity, [aFileURI]); - }, - /** * Inform user that the Web Console API has been replaced by a script * in a content page. @@ -1416,122 +1453,86 @@ WebConsoleFrame.prototype = { }, /** - * Handle the network events coming from the remote Web Console. + * Handle the "WebConsole:NetworkActivity" message coming from the remote Web + * Console. * - * @param object aActor - * The NetworkEventActor grip. + * @param object aMessage + * The HTTP activity object. This object needs to hold two properties: + * - meta - some metadata about the request log: + * - stages - the stages the network request went through. + * - discardRequestBody and discardResponseBody - booleans that tell + * if the network request/response body was discarded or not. + * - log - the request and response information. This is a HAR-like + * object. See HUDService-content.js + * NetworkMonitor.createActivityObject(). */ - handleNetworkEvent: function WCF_handleNetworkEvent(aActor) + handleNetworkActivity: function WCF_handleNetworkActivity(aMessage) { - let networkInfo = { - node: null, - actor: aActor.actor, - discardRequestBody: true, - discardResponseBody: true, - startedDateTime: aActor.startedDateTime, - request: { - url: aActor.url, - method: aActor.method, - }, - response: {}, - timings: {}, - updates: [], // track the list of network event updates - }; + let stage = aMessage.meta.stages[aMessage.meta.stages.length - 1]; + let entry = aMessage.log.entries[0]; - this._networkRequests[aActor.actor] = networkInfo; - this.outputMessage(CATEGORY_NETWORK, this.logNetEvent, [aActor.actor]); - }, + if (stage == "REQUEST_HEADER") { + let networkInfo = { + node: null, + httpActivity: aMessage, + }; - /** - * Handle network event updates coming from the server. - * - * @param string aActorId - * The network event actor ID. - * @param string aType - * Update type. - * @param object aPacket - * Update details. - */ - handleNetworkEventUpdate: - function WCF_handleNetworkEventUpdate(aActorId, aType, aPacket) - { - let networkInfo = this._networkRequests[aActorId]; - if (!networkInfo) { + this._networkRequests[entry.connection] = networkInfo; + this.outputMessage(CATEGORY_NETWORK, this.logNetActivity, + [entry.connection]); + return; + } + else if (!(entry.connection in this._networkRequests)) { 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; - } + let networkInfo = this._networkRequests[entry.connection]; + networkInfo.httpActivity = aMessage; if (networkInfo.node) { - this._updateNetMessage(aActorId); + this._updateNetMessage(entry.connection); } // 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) { - this.owner.lastFinishedRequestCallback(networkInfo, this); + aMessage.meta.stages.indexOf("REQUEST_STOP") > -1 && + aMessage.meta.stages.indexOf("TRANSACTION_CLOSE") > -1) { + this.owner.lastFinishedRequestCallback(aMessage); } }, /** * Update an output message to reflect the latest state of a network request, - * given a network event actor ID. + * given a network connection ID. * * @private - * @param string aActorId - * The network event actor ID for which you want to update the message. + * @param string aConnectionId + * The connection ID to update. */ - _updateNetMessage: function WCF__updateNetMessage(aActorId) + _updateNetMessage: function WCF__updateNetMessage(aConnectionId) { - let networkInfo = this._networkRequests[aActorId]; + let networkInfo = this._networkRequests[aConnectionId]; 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; - let request = networkInfo.request; - let response = networkInfo.response; + let httpActivity = networkInfo.httpActivity; + let stages = httpActivity.meta.stages; + let hasTransactionClose = stages.indexOf("TRANSACTION_CLOSE") > -1; + let hasResponseHeader = stages.indexOf("RESPONSE_HEADER") > -1; + let entry = httpActivity.log.entries[0]; + let request = entry.request; + let response = entry.response; - if (hasEventTimings || hasResponseStart) { + if (hasTransactionClose || hasResponseHeader) { let status = []; if (response.httpVersion && response.status) { status = [response.httpVersion, response.status, response.statusText]; } - if (hasEventTimings) { - status.push(l10n.getFormatStr("NetworkPanel.durationMS", - [networkInfo.totalTime])); + if (hasTransactionClose) { + status.push(l10n.getFormatStr("NetworkPanel.durationMS", [entry.time])); } let statusText = "[" + status.join(" ") + "]"; @@ -1542,7 +1543,7 @@ WebConsoleFrame.prototype = { messageNode.clipboardText = [request.method, request.url, statusText] .join(" "); - if (hasResponseStart && response.status >= MIN_HTTP_ERROR_CODE && + if (hasResponseHeader && response.status >= MIN_HTTP_ERROR_CODE && response.status <= MAX_HTTP_ERROR_CODE) { this.setMessageType(messageNode, CATEGORY_NETWORK, SEVERITY_ERROR); } @@ -1566,138 +1567,27 @@ WebConsoleFrame.prototype = { */ openNetworkPanel: function WCF_openNetworkPanel(aNode, aHttpActivity) { - let actor = aHttpActivity.actor; - - if (actor) { - this.webConsoleClient.getRequestHeaders(actor, function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getRequestHeaders:" + - aResponse.error); - return; - } - - aHttpActivity.request.headers = aResponse.headers; - - this.webConsoleClient.getRequestCookies(actor, onRequestCookies); - }.bind(this)); - } - - let onRequestCookies = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getRequestCookies:" + - aResponse.error); - return; - } - - aHttpActivity.request.cookies = aResponse.cookies; - - this.webConsoleClient.getResponseHeaders(actor, onResponseHeaders); - }.bind(this); - - let onResponseHeaders = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getResponseHeaders:" + - aResponse.error); - return; - } - - aHttpActivity.response.headers = aResponse.headers; - - this.webConsoleClient.getResponseCookies(actor, onResponseCookies); - }.bind(this); - - let onResponseCookies = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getResponseCookies:" + - aResponse.error); - return; - } - - aHttpActivity.response.cookies = aResponse.cookies; - - this.webConsoleClient.getRequestPostData(actor, onRequestPostData); - }.bind(this); - - let onRequestPostData = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getRequestPostData:" + - aResponse.error); - return; - } - - aHttpActivity.request.postData = aResponse.postData; - aHttpActivity.discardRequestBody = aResponse.postDataDiscarded; - - this.webConsoleClient.getResponseContent(actor, onResponseContent); - }.bind(this); - - let onResponseContent = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getResponseContent:" + - aResponse.error); - return; - } - - aHttpActivity.response.content = aResponse.content; - aHttpActivity.discardResponseBody = aResponse.contentDiscarded; - - this.webConsoleClient.getEventTimings(actor, onEventTimings); - }.bind(this); - - let onEventTimings = function(aResponse) { - if (aResponse.error) { - Cu.reportError("WCF_openNetworkPanel getEventTimings:" + - aResponse.error); - return; - } - - aHttpActivity.timings = aResponse.timings; - - openPanel(); - }.bind(this); - - let openPanel = function() { - aNode._netPanel = netPanel; - - let panel = netPanel.panel; - panel.openPopup(aNode, "after_pointer", 0, 0, false, false); - panel.sizeTo(450, 500); - panel.setAttribute("hudId", this.hudId); - - panel.addEventListener("popuphiding", function WCF_netPanel_onHide() { - panel.removeEventListener("popuphiding", WCF_netPanel_onHide); - - aNode._panelOpen = false; - aNode._netPanel = null; - }); - - aNode._panelOpen = true; - }.bind(this); - let netPanel = new NetworkPanel(this.popupset, aHttpActivity); netPanel.linkNode = aNode; + aNode._netPanel = netPanel; - if (!actor) { - openPanel(); - } + let panel = netPanel.panel; + panel.openPopup(aNode, "after_pointer", 0, 0, false, false); + panel.sizeTo(450, 500); + panel.setAttribute("hudId", aHttpActivity.hudId); + + panel.addEventListener("popuphiding", function WCF_netPanel_onHide() { + panel.removeEventListener("popuphiding", WCF_netPanel_onHide); + + aNode._panelOpen = false; + aNode._netPanel = null; + }); + + aNode._panelOpen = true; return netPanel; }, - /** - * Handler for page location changes. - * - * @param string aURI - * New page location. - * @param string aTitle - * New page title. - */ - onLocationChange: function WCF_onLocationChange(aURI, aTitle) - { - this.contentLocation = aURI; - this.owner.onLocationChange(aURI, aTitle); - }, - /** * Output a message node. This filters a node appropriately, then sends it to * the output, regrouping and pruning output as necessary. @@ -1957,7 +1847,7 @@ WebConsoleFrame.prototype = { if (category == CATEGORY_NETWORK) { let connectionId = null; - if (methodOrNode == this.logNetEvent) { + if (methodOrNode == this.logNetActivity) { connectionId = args[0]; } else if (typeof methodOrNode != "function") { @@ -1965,7 +1855,6 @@ WebConsoleFrame.prototype = { } if (connectionId && connectionId in this._networkRequests) { delete this._networkRequests[connectionId]; - this._releaseObject(connectionId); } } else if (category == CATEGORY_WEBDEV && @@ -2061,10 +1950,8 @@ WebConsoleFrame.prototype = { } delete this._cssNodes[desc + location]; } - else if (aNode._connectionId && - aNode.classList.contains("webconsole-msg-network")) { + else if (aNode.classList.contains("webconsole-msg-network")) { delete this._networkRequests[aNode._connectionId]; - this._releaseObject(aNode._connectionId); } else if (aNode.classList.contains("webconsole-msg-inspector")) { this.pruneConsoleDirNode(aNode); @@ -2537,11 +2424,11 @@ WebConsoleFrame.prototype = { }, /** - * Release an actor. + * Release an object actor. * * @private * @param string aActor - * The actor ID you want to release. + * The object actor ID you want to release. */ _releaseObject: function WCF__releaseObject(aActor) { @@ -3814,10 +3701,6 @@ function WebConsoleConnectionProxy(aWebConsole) this._onPageError = this._onPageError.bind(this); this._onConsoleAPICall = this._onConsoleAPICall.bind(this); - this._onNetworkEvent = this._onNetworkEvent.bind(this); - this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this); - this._onFileActivity = this._onFileActivity.bind(this); - this._onLocationChange = this._onLocationChange.bind(this); } WebConsoleConnectionProxy.prototype = { @@ -3883,19 +3766,13 @@ WebConsoleConnectionProxy.prototype = { 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("locationChange", this._onLocationChange); - let listeners = ["PageError", "ConsoleAPI", "NetworkActivity", - "FileActivity", "LocationChange"]; + let listeners = ["PageError", "ConsoleAPI"]; client.connect(function(aType, aTraits) { client.listTabs(function(aResponse) { let tab = aResponse.tabs[aResponse.selected]; this._consoleActor = tab.consoleActor; - this.owner.onLocationChange(tab.url, tab.title); client.attachConsole(tab.consoleActor, listeners, this._onAttachConsole.bind(this, aCallback)); }.bind(this)); @@ -3993,80 +3870,6 @@ WebConsoleConnectionProxy.prototype = { } }, - /** - * The "networkEvent" message type handler. We redirect any message to - * the UI for displaying. - * - * @private - * @param string aType - * Message type. - * @param object aPacket - * The message received from the server. - */ - _onNetworkEvent: function WCCP__onNetworkEvent(aType, aPacket) - { - if (this.owner && aPacket.from == this._consoleActor) { - this.owner.handleNetworkEvent(aPacket.eventActor); - } - }, - - /** - * The "networkEventUpdate" message type handler. We redirect any message to - * the UI for displaying. - * - * @private - * @param string aType - * Message type. - * @param object aPacket - * The message received from the server. - */ - _onNetworkEventUpdate: function WCCP__onNetworkEvenUpdatet(aType, aPacket) - { - if (this.owner) { - this.owner.handleNetworkEventUpdate(aPacket.from, aPacket.updateType, - aPacket); - } - }, - - /** - * The "fileActivity" message type handler. We redirect any message to - * the UI for displaying. - * - * @private - * @param string aType - * Message type. - * @param object aPacket - * The message received from the server. - */ - _onFileActivity: function WCCP__onFileActivity(aType, aPacket) - { - if (this.owner && aPacket.from == this._consoleActor) { - this.owner.handleFileActivity(aPacket.uri); - } - }, - - /** - * The "locationChange" message type handler. We redirect any message to - * the UI for displaying. - * - * @private - * @param string aType - * Message type. - * @param object aPacket - * The message received from the server. - */ - _onLocationChange: function WCCP__onLocationChange(aType, aPacket) - { - if (!this.owner || aPacket.from != this._consoleActor) { - return; - } - - this.owner.onLocationChange(aPacket.uri, aPacket.title); - if (aPacket.state == "stop" && !aPacket.nativeConsoleAPI) { - this.owner.logWarningAboutReplacedAPI(); - } - }, - /** * Release an object actor. * @@ -4095,10 +3898,6 @@ WebConsoleConnectionProxy.prototype = { 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("locationChange", this._onLocationChange); this.client.close(aOnDisconnect); this.client = null; diff --git a/toolkit/devtools/debugger/dbg-client.jsm b/toolkit/devtools/debugger/dbg-client.jsm index b88f821c75f5..0c1eb8f321ae 100644 --- a/toolkit/devtools/debugger/dbg-client.jsm +++ b/toolkit/devtools/debugger/dbg-client.jsm @@ -168,10 +168,6 @@ const ThreadStateTypes = { */ const UnsolicitedNotifications = { "consoleAPICall": "consoleAPICall", - "fileActivity": "fileActivity", - "locationChange": "locationChange", - "networkEvent": "networkEvent", - "networkEventUpdate": "networkEventUpdate", "newScript": "newScript", "tabDetached": "tabDetached", "tabNavigated": "tabNavigated", diff --git a/toolkit/devtools/webconsole/WebConsoleClient.jsm b/toolkit/devtools/webconsole/WebConsoleClient.jsm index da27e34f1e07..45e7301118fd 100644 --- a/toolkit/devtools/webconsole/WebConsoleClient.jsm +++ b/toolkit/devtools/webconsole/WebConsoleClient.jsm @@ -117,143 +117,6 @@ WebConsoleClient.prototype = { this._client.request(packet); }, - /** - * Set Web Console-related preferences on the server. - * - * @param object aPreferences - * An object with the preferences you want to change. - * @param function [aOnResponse] - * Optional function to invoke when the response is received. - */ - setPreferences: function WCC_setPreferences(aPreferences, aOnResponse) - { - let packet = { - to: this._actor, - type: "setPreferences", - preferences: aPreferences, - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the request headers from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getRequestHeaders: function WCC_getRequestHeaders(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getRequestHeaders", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the request cookies from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getRequestCookies: function WCC_getRequestCookies(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getRequestCookies", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the request post data from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getRequestPostData: function WCC_getRequestPostData(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getRequestPostData", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the response headers from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getResponseHeaders: function WCC_getResponseHeaders(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getResponseHeaders", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the response cookies from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getResponseCookies: function WCC_getResponseCookies(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getResponseCookies", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the response content from the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getResponseContent: function WCC_getResponseContent(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getResponseContent", - }; - this._client.request(packet, aOnResponse); - }, - - /** - * Retrieve the timing information for the given NetworkEventActor. - * - * @param string aActor - * The NetworkEventActor ID. - * @param function aOnResponse - * The function invoked when the response is received. - */ - getEventTimings: function WCC_getEventTimings(aActor, aOnResponse) - { - let packet = { - to: aActor, - type: "getEventTimings", - }; - this._client.request(packet, aOnResponse); - }, - /** * Start the given Web Console listeners. * diff --git a/toolkit/devtools/webconsole/WebConsoleUtils.jsm b/toolkit/devtools/webconsole/WebConsoleUtils.jsm index c8a64b42efae..992f0aa9e412 100644 --- a/toolkit/devtools/webconsole/WebConsoleUtils.jsm +++ b/toolkit/devtools/webconsole/WebConsoleUtils.jsm @@ -18,20 +18,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services", XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIStorage", "resource://gre/modules/ConsoleAPIStorage.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", - "resource://gre/modules/NetUtil.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper", - "resource://gre/modules/devtools/NetworkHelper.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "gActivityDistributor", - "@mozilla.org/network/http-activity-distributor;1", - "nsIHttpActivityDistributor"); - var EXPORTED_SYMBOLS = ["WebConsoleUtils", "JSPropertyProvider", "JSTermHelpers", - "PageErrorListener", "ConsoleAPIListener", - "NetworkResponseListener", "NetworkMonitor", - "ConsoleProgressListener"]; + "PageErrorListener", "ConsoleAPIListener"]; // Match the function name from the result of toString() or toSource(). // @@ -1866,1124 +1854,3 @@ function JSTermHelpers(aOwner) return String(aString); }; } - - -(function(_global, WCU) { -/////////////////////////////////////////////////////////////////////////////// -// Network logging -/////////////////////////////////////////////////////////////////////////////// - -// The maximum uint32 value. -const PR_UINT32_MAX = 4294967295; - -// HTTP status codes. -const HTTP_MOVED_PERMANENTLY = 301; -const HTTP_FOUND = 302; -const HTTP_SEE_OTHER = 303; -const HTTP_TEMPORARY_REDIRECT = 307; - -// The maximum number of bytes a NetworkResponseListener can hold. -const RESPONSE_BODY_LIMIT = 1048576; // 1 MB - -/** - * The network response listener implements the nsIStreamListener and - * nsIRequestObserver interfaces. This is used within the NetworkMonitor feature - * to get the response body of the request. - * - * The code is mostly based on code listings from: - * - * http://www.softwareishard.com/blog/firebug/ - * nsitraceablechannel-intercept-http-traffic/ - * - * @constructor - * @param object aOwner - * The response listener owner. This object needs to hold the - * |openResponses| object. - * @param object aHttpActivity - * HttpActivity object associated with this request. See NetworkMonitor - * for more information. - */ -function NetworkResponseListener(aOwner, aHttpActivity) -{ - this.owner = aOwner; - this.receivedData = ""; - this.httpActivity = aHttpActivity; - this.bodySize = 0; -} - -NetworkResponseListener.prototype = { - QueryInterface: - XPCOMUtils.generateQI([Ci.nsIStreamListener, Ci.nsIInputStreamCallback, - Ci.nsIRequestObserver, Ci.nsISupports]), - - /** - * This NetworkResponseListener tracks the NetworkMonitor.openResponses object - * to find the associated uncached headers. - * @private - */ - _foundOpenResponse: false, - - /** - * The response listener owner. - */ - owner: null, - - /** - * The response will be written into the outputStream of this nsIPipe. - * Both ends of the pipe must be blocking. - */ - sink: null, - - /** - * The HttpActivity object associated with this response. - */ - httpActivity: null, - - /** - * Stores the received data as a string. - */ - receivedData: null, - - /** - * The network response body size. - */ - bodySize: null, - - /** - * The nsIRequest we are started for. - */ - request: null, - - /** - * Set the async listener for the given nsIAsyncInputStream. This allows us to - * wait asynchronously for any data coming from the stream. - * - * @param nsIAsyncInputStream aStream - * The input stream from where we are waiting for data to come in. - * @param nsIInputStreamCallback aListener - * The input stream callback you want. This is an object that must have - * the onInputStreamReady() method. If the argument is null, then the - * current callback is removed. - * @return void - */ - setAsyncListener: function NRL_setAsyncListener(aStream, aListener) - { - // Asynchronously wait for the stream to be readable or closed. - aStream.asyncWait(aListener, 0, 0, Services.tm.mainThread); - }, - - /** - * Stores the received data, if request/response body logging is enabled. It - * also does limit the number of stored bytes, based on the - * RESPONSE_BODY_LIMIT constant. - * - * Learn more about nsIStreamListener at: - * https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIStreamListener - * - * @param nsIRequest aRequest - * @param nsISupports aContext - * @param nsIInputStream aInputStream - * @param unsigned long aOffset - * @param unsigned long aCount - */ - onDataAvailable: - function NRL_onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) - { - this._findOpenResponse(); - let data = NetUtil.readInputStreamToString(aInputStream, aCount); - - this.bodySize += aCount; - - if (!this.httpActivity.discardResponseBody && - this.receivedData.length < RESPONSE_BODY_LIMIT) { - this.receivedData += NetworkHelper. - convertToUnicode(data, aRequest.contentCharset); - } - }, - - /** - * See documentation at - * https://developer.mozilla.org/En/NsIRequestObserver - * - * @param nsIRequest aRequest - * @param nsISupports aContext - */ - onStartRequest: function NRL_onStartRequest(aRequest) - { - this.request = aRequest; - this._findOpenResponse(); - // Asynchronously wait for the data coming from the request. - this.setAsyncListener(this.sink.inputStream, this); - }, - - /** - * Handle the onStopRequest by closing the sink output stream. - * - * For more documentation about nsIRequestObserver go to: - * https://developer.mozilla.org/En/NsIRequestObserver - */ - onStopRequest: function NRL_onStopRequest() - { - this._findOpenResponse(); - this.sink.outputStream.close(); - }, - - /** - * Find the open response object associated to the current request. The - * NetworkMonitor._httpResponseExaminer() method saves the response headers in - * NetworkMonitor.openResponses. This method takes the data from the open - * response object and puts it into the HTTP activity object, then sends it to - * the remote Web Console instance. - * - * @private - */ - _findOpenResponse: function NRL__findOpenResponse() - { - if (!this.owner || this._foundOpenResponse) { - return; - } - - let openResponse = null; - - for each (let item in this.owner.openResponses) { - if (item.channel === this.httpActivity.channel) { - openResponse = item; - break; - } - } - - if (!openResponse) { - return; - } - this._foundOpenResponse = true; - - delete this.owner.openResponses[openResponse.id]; - - this.httpActivity.owner.addResponseHeaders(openResponse.headers); - this.httpActivity.owner.addResponseCookies(openResponse.cookies); - }, - - /** - * Clean up the response listener once the response input stream is closed. - * This is called from onStopRequest() or from onInputStreamReady() when the - * stream is closed. - * @return void - */ - onStreamClose: function NRL_onStreamClose() - { - if (!this.httpActivity) { - return; - } - // Remove our listener from the request input stream. - this.setAsyncListener(this.sink.inputStream, null); - - this._findOpenResponse(); - - if (!this.httpActivity.discardResponseBody && this.receivedData.length) { - this._onComplete(this.receivedData); - } - else if (!this.httpActivity.discardResponseBody && - this.httpActivity.responseStatus == 304) { - // Response is cached, so we load it from cache. - let charset = this.request.contentCharset || this.httpActivity.charset; - NetworkHelper.loadFromCache(this.httpActivity.url, charset, - this._onComplete.bind(this)); - } - else { - this._onComplete(); - } - }, - - /** - * Handler for when the response completes. This function cleans up the - * response listener. - * - * @param string [aData] - * Optional, the received data coming from the response listener or - * from the cache. - */ - _onComplete: function NRL__onComplete(aData) - { - let response = { - mimeType: "", - text: aData || "", - }; - - // TODO: Bug 787981 - use LongStringActor for strings that are too long. - - try { - response.mimeType = this.request.contentType; - } - catch (ex) { } - - if (response.mimeType && this.request.contentCharset) { - response.mimeType += "; charset=" + this.request.contentCharset; - } - - this.receivedData = ""; - - this.httpActivity.owner. - addResponseContent(response, this.httpActivity.discardResponseBody); - - this.httpActivity.channel = null; - this.httpActivity.owner = null; - this.httpActivity = null; - this.sink = null; - this.inputStream = null; - this.request = null; - this.owner = null; - }, - - /** - * The nsIInputStreamCallback for when the request input stream is ready - - * either it has more data or it is closed. - * - * @param nsIAsyncInputStream aStream - * The sink input stream from which data is coming. - * @returns void - */ - onInputStreamReady: function NRL_onInputStreamReady(aStream) - { - if (!(aStream instanceof Ci.nsIAsyncInputStream) || !this.httpActivity) { - return; - } - - let available = -1; - try { - // This may throw if the stream is closed normally or due to an error. - available = aStream.available(); - } - catch (ex) { } - - if (available != -1) { - if (available != 0) { - // Note that passing 0 as the offset here is wrong, but the - // onDataAvailable() method does not use the offset, so it does not - // matter. - this.onDataAvailable(this.request, null, aStream, 0, available); - } - this.setAsyncListener(aStream, this); - } - else { - this.onStreamClose(); - } - }, -}; - -/** - * The network monitor uses the nsIHttpActivityDistributor to monitor network - * requests. The nsIObserverService is also used for monitoring - * http-on-examine-response notifications. All network request information is - * routed to the remote Web Console. - * - * @constructor - * @param nsIDOMWindow aWindow - * The window that we monitor network requests for. - * @param object aOwner - * The network monitor owner. This object needs to hold: - * - onNetworkEvent(aRequestInfo). This method is invoked once for every - * new network request and it is given one arguments: the initial network - * request information. onNetworkEvent() must return an object which - * holds several add*() methods which are used to add further network - * request/response information. - * - saveRequestAndResponseBodies property which tells if you want to log - * request and response bodies. - */ -function NetworkMonitor(aWindow, aOwner) -{ - this.window = aWindow; - this.owner = aOwner; - this.openRequests = {}; - this.openResponses = {}; - this._httpResponseExaminer = this._httpResponseExaminer.bind(this); -} - -NetworkMonitor.prototype = { - httpTransactionCodes: { - 0x5001: "REQUEST_HEADER", - 0x5002: "REQUEST_BODY_SENT", - 0x5003: "RESPONSE_START", - 0x5004: "RESPONSE_HEADER", - 0x5005: "RESPONSE_COMPLETE", - 0x5006: "TRANSACTION_CLOSE", - - 0x804b0003: "STATUS_RESOLVING", - 0x804b000b: "STATUS_RESOLVED", - 0x804b0007: "STATUS_CONNECTING_TO", - 0x804b0004: "STATUS_CONNECTED_TO", - 0x804b0005: "STATUS_SENDING_TO", - 0x804b000a: "STATUS_WAITING_FOR", - 0x804b0006: "STATUS_RECEIVING_FROM" - }, - - // Network response bodies are piped through a buffer of the given size (in - // bytes). - responsePipeSegmentSize: null, - - owner: null, - - /** - * Whether to save the bodies of network requests and responses. Disabled by - * default to save memory. - */ - get saveRequestAndResponseBodies() - this.owner && this.owner.saveRequestAndResponseBodies, - - /** - * Object that holds the HTTP activity objects for ongoing requests. - */ - openRequests: null, - - /** - * Object that holds response headers coming from this._httpResponseExaminer. - */ - openResponses: null, - - /** - * The network monitor initializer. - */ - init: function NM_init() - { - this.responsePipeSegmentSize = Services.prefs - .getIntPref("network.buffer.cache.size"); - - gActivityDistributor.addObserver(this); - - Services.obs.addObserver(this._httpResponseExaminer, - "http-on-examine-response", false); - }, - - /** - * Observe notifications for the http-on-examine-response topic, coming from - * the nsIObserverService. - * - * @private - * @param nsIHttpChannel aSubject - * @param string aTopic - * @returns void - */ - _httpResponseExaminer: function NM__httpResponseExaminer(aSubject, aTopic) - { - // The httpResponseExaminer is used to retrieve the uncached response - // headers. The data retrieved is stored in openResponses. The - // NetworkResponseListener is responsible with updating the httpActivity - // object with the data from the new object in openResponses. - - if (!this.owner || aTopic != "http-on-examine-response" || - !(aSubject instanceof Ci.nsIHttpChannel)) { - return; - } - - let channel = aSubject.QueryInterface(Ci.nsIHttpChannel); - // Try to get the source window of the request. - let win = NetworkHelper.getWindowForRequest(channel); - if (!win || win.top !== this.window) { - return; - } - - let response = { - id: gSequenceId(), - channel: channel, - headers: [], - cookies: [], - }; - - let setCookieHeader = null; - - channel.visitResponseHeaders({ - visitHeader: function NM__visitHeader(aName, aValue) { - let lowerName = aName.toLowerCase(); - if (lowerName == "set-cookie") { - setCookieHeader = aValue; - } - response.headers.push({ name: aName, value: aValue }); - } - }); - - if (!response.headers.length) { - return; // No need to continue. - } - - if (setCookieHeader) { - response.cookies = NetworkHelper.parseSetCookieHeader(setCookieHeader); - } - - // Determine the HTTP version. - let httpVersionMaj = {}; - let httpVersionMin = {}; - - channel.QueryInterface(Ci.nsIHttpChannelInternal); - channel.getResponseVersion(httpVersionMaj, httpVersionMin); - - response.status = channel.responseStatus; - response.statusText = channel.responseStatusText; - response.httpVersion = "HTTP/" + httpVersionMaj.value + "." + - httpVersionMin.value; - - this.openResponses[response.id] = response; - }, - - /** - * Begin observing HTTP traffic that originates inside the current tab. - * - * @see https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIHttpActivityObserver - * - * @param nsIHttpChannel aChannel - * @param number aActivityType - * @param number aActivitySubtype - * @param number aTimestamp - * @param number aExtraSizeData - * @param string aExtraStringData - */ - observeActivity: - function NM_observeActivity(aChannel, aActivityType, aActivitySubtype, - aTimestamp, aExtraSizeData, aExtraStringData) - { - if (!this.owner || - aActivityType != gActivityDistributor.ACTIVITY_TYPE_HTTP_TRANSACTION && - aActivityType != gActivityDistributor.ACTIVITY_TYPE_SOCKET_TRANSPORT) { - return; - } - - if (!(aChannel instanceof Ci.nsIHttpChannel)) { - return; - } - - aChannel = aChannel.QueryInterface(Ci.nsIHttpChannel); - - if (aActivitySubtype == - gActivityDistributor.ACTIVITY_SUBTYPE_REQUEST_HEADER) { - this._onRequestHeader(aChannel, aTimestamp, aExtraStringData); - return; - } - - // Iterate over all currently ongoing requests. If aChannel can't - // be found within them, then exit this function. - let httpActivity = null; - for each (let item in this.openRequests) { - if (item.channel === aChannel) { - httpActivity = item; - break; - } - } - - if (!httpActivity) { - return; - } - - let transCodes = this.httpTransactionCodes; - - // Store the time information for this activity subtype. - if (aActivitySubtype in transCodes) { - let stage = transCodes[aActivitySubtype]; - if (stage in httpActivity.timings) { - httpActivity.timings[stage].last = aTimestamp; - } - else { - httpActivity.timings[stage] = { - first: aTimestamp, - last: aTimestamp, - }; - } - } - - switch (aActivitySubtype) { - case gActivityDistributor.ACTIVITY_SUBTYPE_REQUEST_BODY_SENT: - this._onRequestBodySent(httpActivity); - break; - case gActivityDistributor.ACTIVITY_SUBTYPE_RESPONSE_HEADER: - this._onResponseHeader(httpActivity, aExtraStringData); - break; - case gActivityDistributor.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE: - this._onTransactionClose(httpActivity); - break; - default: - break; - } - }, - - /** - * Handler for ACTIVITY_SUBTYPE_REQUEST_HEADER. When a request starts the - * headers are sent to the server. This method creates the |httpActivity| - * object where we store the request and response information that is - * collected through its lifetime. - * - * @private - * @param nsIHttpChannel aChannel - * @param number aTimestamp - * @param string aExtraStringData - * @return void - */ - _onRequestHeader: - function NM__onRequestHeader(aChannel, aTimestamp, aExtraStringData) - { - // Try to get the source window of the request. - let win = NetworkHelper.getWindowForRequest(aChannel); - if (!win || win.top !== this.window) { - return; - } - - let httpActivity = this.createActivityObject(aChannel); - httpActivity.charset = win.document.characterSet; // see NM__onRequestBodySent() - - httpActivity.timings.REQUEST_HEADER = { - first: aTimestamp, - last: aTimestamp - }; - - let httpVersionMaj = {}; - let httpVersionMin = {}; - let event = {}; - event.startedDateTime = new Date(Math.round(aTimestamp / 1000)).toISOString(); - event.headersSize = aExtraStringData.length; - event.method = aChannel.requestMethod; - event.url = aChannel.URI.spec; - - // Determine the HTTP version. - aChannel.QueryInterface(Ci.nsIHttpChannelInternal); - aChannel.getRequestVersion(httpVersionMaj, httpVersionMin); - - event.httpVersion = "HTTP/" + httpVersionMaj.value + "." + - httpVersionMin.value; - - event.discardRequestBody = !this.saveRequestAndResponseBodies; - event.discardResponseBody = !this.saveRequestAndResponseBodies; - - let headers = []; - let cookies = []; - let cookieHeader = null; - - // Copy the request header data. - aChannel.visitRequestHeaders({ - visitHeader: function NM__visitHeader(aName, aValue) - { - if (aName == "Cookie") { - cookieHeader = aValue; - } - headers.push({ name: aName, value: aValue }); - } - }); - - if (cookieHeader) { - cookies = NetworkHelper.parseCookieHeader(cookieHeader); - } - - httpActivity.owner = this.owner.onNetworkEvent(event); - - this._setupResponseListener(httpActivity); - - this.openRequests[httpActivity.id] = httpActivity; - - httpActivity.owner.addRequestHeaders(headers); - httpActivity.owner.addRequestCookies(cookies); - }, - - /** - * Create the empty HTTP activity object. This object is used for storing all - * the request and response information. - * - * This is a HAR-like object. Conformance to the spec is not guaranteed at - * this point. - * - * TODO: Bug 708717 - Add support for network log export to HAR - * - * @see http://www.softwareishard.com/blog/har-12-spec - * @param nsIHttpChannel aChannel - * The HTTP channel for which the HTTP activity object is created. - * @return object - * The new HTTP activity object. - */ - createActivityObject: function NM_createActivityObject(aChannel) - { - return { - id: gSequenceId(), - channel: aChannel, - charset: null, // see NM__onRequestHeader() - url: aChannel.URI.spec, - discardRequestBody: !this.saveRequestAndResponseBodies, - discardResponseBody: !this.saveRequestAndResponseBodies, - timings: {}, // internal timing information, see NM_observeActivity() - responseStatus: null, // see NM__onResponseHeader() - owner: null, // the activity owner which is notified when changes happen - }; - }, - - /** - * Setup the network response listener for the given HTTP activity. The - * NetworkResponseListener is responsible for storing the response body. - * - * @private - * @param object aHttpActivity - * The HTTP activity object we are tracking. - */ - _setupResponseListener: function NM__setupResponseListener(aHttpActivity) - { - let channel = aHttpActivity.channel; - channel.QueryInterface(Ci.nsITraceableChannel); - - // The response will be written into the outputStream of this pipe. - // This allows us to buffer the data we are receiving and read it - // asynchronously. - // Both ends of the pipe must be blocking. - let sink = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe); - - // The streams need to be blocking because this is required by the - // stream tee. - sink.init(false, false, this.responsePipeSegmentSize, PR_UINT32_MAX, null); - - // Add listener for the response body. - let newListener = new NetworkResponseListener(this, aHttpActivity); - - // Remember the input stream, so it isn't released by GC. - newListener.inputStream = sink.inputStream; - newListener.sink = sink; - - let tee = Cc["@mozilla.org/network/stream-listener-tee;1"]. - createInstance(Ci.nsIStreamListenerTee); - - let originalListener = channel.setNewListener(tee); - - tee.init(originalListener, sink.outputStream, newListener); - }, - - /** - * Handler for ACTIVITY_SUBTYPE_REQUEST_BODY_SENT. The request body is logged - * here. - * - * @private - * @param object aHttpActivity - * The HTTP activity object we are working with. - */ - _onRequestBodySent: function NM__onRequestBodySent(aHttpActivity) - { - if (aHttpActivity.discardRequestBody) { - return; - } - - let sentBody = NetworkHelper. - readPostTextFromRequest(aHttpActivity.channel, - aHttpActivity.charset); - - if (!sentBody && aHttpActivity.url == this.window.location.href) { - // If the request URL is the same as the current page URL, then - // we can try to get the posted text from the page directly. - // This check is necessary as otherwise the - // NetworkHelper.readPostTextFromPageViaWebNav() - // function is called for image requests as well but these - // are not web pages and as such don't store the posted text - // in the cache of the webpage. - let webNav = this.window.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIWebNavigation); - sentBody = NetworkHelper. - readPostTextFromPageViaWebNav(webNav, aHttpActivity.charset); - } - - if (sentBody) { - aHttpActivity.owner.addRequestPostData({ text: sentBody }); - } - }, - - /** - * Handler for ACTIVITY_SUBTYPE_RESPONSE_HEADER. This method stores - * information about the response headers. - * - * @private - * @param object aHttpActivity - * The HTTP activity object we are working with. - * @param string aExtraStringData - * The uncached response headers. - */ - _onResponseHeader: - function NM__onResponseHeader(aHttpActivity, aExtraStringData) - { - // aExtraStringData contains the uncached response headers. The first line - // contains the response status (e.g. HTTP/1.1 200 OK). - // - // Note: The response header is not saved here. Calling the - // channel.visitResponseHeaders() methood at this point sometimes causes an - // NS_ERROR_NOT_AVAILABLE exception. - // - // We could parse aExtraStringData to get the headers and their values, but - // that is not trivial to do in an accurate manner. Hence, we save the - // response headers in this._httpResponseExaminer(). - - let headers = aExtraStringData.split(/\r\n|\n|\r/); - let statusLine = headers.shift(); - let statusLineArray = statusLine.split(" "); - - let response = {}; - response.httpVersion = statusLineArray.shift(); - response.status = statusLineArray.shift(); - response.statusText = statusLineArray.join(" "); - response.headersSize = aExtraStringData.length; - - aHttpActivity.responseStatus = response.status; - - // Discard the response body for known response statuses. - switch (parseInt(response.status)) { - case HTTP_MOVED_PERMANENTLY: - case HTTP_FOUND: - case HTTP_SEE_OTHER: - case HTTP_TEMPORARY_REDIRECT: - aHttpActivity.discardResponseBody = true; - break; - } - - response.discardResponseBody = aHttpActivity.discardResponseBody; - - aHttpActivity.owner.addResponseStart(response); - }, - - /** - * Handler for ACTIVITY_SUBTYPE_TRANSACTION_CLOSE. This method updates the HAR - * timing information on the HTTP activity object and clears the request - * from the list of known open requests. - * - * @private - * @param object aHttpActivity - * The HTTP activity object we work with. - */ - _onTransactionClose: function NM__onTransactionClose(aHttpActivity) - { - let result = this._setupHarTimings(aHttpActivity); - aHttpActivity.owner.addEventTimings(result.total, result.timings); - delete this.openRequests[aHttpActivity.id]; - }, - - /** - * Update the HTTP activity object to include timing information as in the HAR - * spec. The HTTP activity object holds the raw timing information in - * |timings| - these are timings stored for each activity notification. The - * HAR timing information is constructed based on these lower level data. - * - * @param object aHttpActivity - * The HTTP activity object we are working with. - * @return object - * This object holds two properties: - * - total - the total time for all of the request and response. - * - timings - the HAR timings object. - */ - _setupHarTimings: function NM__setupHarTimings(aHttpActivity) - { - let timings = aHttpActivity.timings; - let harTimings = {}; - - // Not clear how we can determine "blocked" time. - harTimings.blocked = -1; - - // DNS timing information is available only in when the DNS record is not - // cached. - harTimings.dns = timings.STATUS_RESOLVING && timings.STATUS_RESOLVED ? - timings.STATUS_RESOLVED.last - - timings.STATUS_RESOLVING.first : -1; - - if (timings.STATUS_CONNECTING_TO && timings.STATUS_CONNECTED_TO) { - harTimings.connect = timings.STATUS_CONNECTED_TO.last - - timings.STATUS_CONNECTING_TO.first; - } - else if (timings.STATUS_SENDING_TO) { - harTimings.connect = timings.STATUS_SENDING_TO.first - - timings.REQUEST_HEADER.first; - } - else { - harTimings.connect = -1; - } - - if ((timings.STATUS_WAITING_FOR || timings.STATUS_RECEIVING_FROM) && - (timings.STATUS_CONNECTED_TO || timings.STATUS_SENDING_TO)) { - harTimings.send = (timings.STATUS_WAITING_FOR || - timings.STATUS_RECEIVING_FROM).first - - (timings.STATUS_CONNECTED_TO || - timings.STATUS_SENDING_TO).last; - } - else { - harTimings.send = -1; - } - - if (timings.RESPONSE_START) { - harTimings.wait = timings.RESPONSE_START.first - - (timings.REQUEST_BODY_SENT || - timings.STATUS_SENDING_TO).last; - } - else { - harTimings.wait = -1; - } - - if (timings.RESPONSE_START && timings.RESPONSE_COMPLETE) { - harTimings.receive = timings.RESPONSE_COMPLETE.last - - timings.RESPONSE_START.first; - } - else { - harTimings.receive = -1; - } - - let totalTime = 0; - for (let timing in harTimings) { - let time = Math.max(Math.round(harTimings[timing] / 1000), -1); - harTimings[timing] = time; - if (time > -1) { - totalTime += time; - } - } - - return { - total: totalTime, - timings: harTimings, - }; - }, - - /** - * Suspend Web Console activity. This is called when all Web Consoles are - * closed. - */ - destroy: function NM_destroy() - { - Services.obs.removeObserver(this._httpResponseExaminer, - "http-on-examine-response"); - - gActivityDistributor.removeObserver(this); - - this.openRequests = {}; - this.openResponses = {}; - this.owner = null; - this.window = null; - }, -}; - -_global.NetworkMonitor = NetworkMonitor; -_global.NetworkResponseListener = NetworkResponseListener; -})(this, WebConsoleUtils); - - -/** - * A WebProgressListener that listens for location changes. - * - * This progress listener is used to track file loads and other kinds of - * location changes. - * - * @constructor - * @param object aBrowser - * The xul:browser for which we need to track location changes. - * @param object aOwner - * The listener owner which needs to implement two methods: - * - onFileActivity(aFileURI) - * - onLocationChange(aState, aTabURI, aPageTitle) - */ -function ConsoleProgressListener(aBrowser, aOwner) -{ - this.browser = aBrowser; - this.owner = aOwner; -} - -ConsoleProgressListener.prototype = { - /** - * Constant used for startMonitor()/stopMonitor() that tells you want to - * monitor file loads. - */ - MONITOR_FILE_ACTIVITY: 1, - - /** - * Constant used for startMonitor()/stopMonitor() that tells you want to - * monitor page location changes. - */ - MONITOR_LOCATION_CHANGE: 2, - - /** - * Tells if you want to monitor file activity. - * @private - * @type boolean - */ - _fileActivity: false, - - /** - * Tells if you want to monitor location changes. - * @private - * @type boolean - */ - _locationChange: false, - - /** - * Tells if the console progress listener is initialized or not. - * @private - * @type boolean - */ - _initialized: false, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, - Ci.nsISupportsWeakReference]), - - /** - * Initialize the ConsoleProgressListener. - * @private - */ - _init: function CPL__init() - { - if (this._initialized) { - return; - } - - this._initialized = true; - this.browser.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_ALL); - }, - - /** - * Start a monitor/tracker related to the current nsIWebProgressListener - * instance. - * - * @param number aMonitor - * Tells what you want to track. Available constants: - * - this.MONITOR_FILE_ACTIVITY - * Track file loads. - * - this.MONITOR_LOCATION_CHANGE - * Track location changes for the top window. - */ - startMonitor: function CPL_startMonitor(aMonitor) - { - switch (aMonitor) { - case this.MONITOR_FILE_ACTIVITY: - this._fileActivity = true; - break; - case this.MONITOR_LOCATION_CHANGE: - this._locationChange = true; - break; - default: - throw new Error("ConsoleProgressListener: unknown monitor type " + - aMonitor + "!"); - } - this._init(); - }, - - /** - * Stop a monitor. - * - * @param number aMonitor - * Tells what you want to stop tracking. See this.startMonitor() for - * the list of constants. - */ - stopMonitor: function CPL_stopMonitor(aMonitor) - { - switch (aMonitor) { - case this.MONITOR_FILE_ACTIVITY: - this._fileActivity = false; - break; - case this.MONITOR_LOCATION_CHANGE: - this._locationChange = false; - break; - default: - throw new Error("ConsoleProgressListener: unknown monitor type " + - aMonitor + "!"); - } - - if (!this._fileActivity && !this._locationChange) { - this.destroy(); - } - }, - - onStateChange: - function CPL_onStateChange(aProgress, aRequest, aState, aStatus) - { - if (!this.owner) { - return; - } - - if (this._fileActivity) { - this._checkFileActivity(aProgress, aRequest, aState, aStatus); - } - - if (this._locationChange) { - this._checkLocationChange(aProgress, aRequest, aState, aStatus); - } - }, - - /** - * Check if there is any file load, given the arguments of - * nsIWebProgressListener.onStateChange. If the state change tells that a file - * URI has been loaded, then the remote Web Console instance is notified. - * @private - */ - _checkFileActivity: - function CPL__checkFileActivity(aProgress, aRequest, aState, aStatus) - { - if (!(aState & Ci.nsIWebProgressListener.STATE_START)) { - return; - } - - let uri = null; - if (aRequest instanceof Ci.imgIRequest) { - let imgIRequest = aRequest.QueryInterface(Ci.imgIRequest); - uri = imgIRequest.URI; - } - else if (aRequest instanceof Ci.nsIChannel) { - let nsIChannel = aRequest.QueryInterface(Ci.nsIChannel); - uri = nsIChannel.URI; - } - - if (!uri || !uri.schemeIs("file") && !uri.schemeIs("ftp")) { - return; - } - - this.owner.onFileActivity(uri.spec); - }, - - /** - * Check if the current window.top location is changing, given the arguments - * of nsIWebProgressListener.onStateChange. If that is the case, the remote - * Web Console instance is notified. - * @private - */ - _checkLocationChange: - function CPL__checkLocationChange(aProgress, aRequest, aState, aStatus) - { - let isStart = aState & Ci.nsIWebProgressListener.STATE_START; - let isStop = aState & Ci.nsIWebProgressListener.STATE_STOP; - let isNetwork = aState & Ci.nsIWebProgressListener.STATE_IS_NETWORK; - let isWindow = aState & Ci.nsIWebProgressListener.STATE_IS_WINDOW; - - // Skip non-interesting states. - if (!isNetwork || !isWindow || - aProgress.DOMWindow != this.browser.contentWindow) { - return; - } - - if (isStart && aRequest instanceof Ci.nsIChannel) { - this.owner.onLocationChange("start", aRequest.URI.spec, ""); - } - else if (isStop) { - let window = this.browser.contentWindow; - this.owner.onLocationChange("stop", window.location.href, - window.document.title); - } - }, - - onLocationChange: function() {}, - onStatusChange: function() {}, - onProgressChange: function() {}, - onSecurityChange: function() {}, - - /** - * Destroy the ConsoleProgressListener. - */ - destroy: function CPL_destroy() - { - if (!this._initialized) { - return; - } - - this._initialized = false; - this._fileActivity = false; - this._locationChange = false; - - if (this.browser.removeProgressListener) { - this.browser.removeProgressListener(this); - } - - this.browser = null; - this.owner = null; - }, -}; - -function gSequenceId() -{ - return gSequenceId.n++; -} -gSequenceId.n = 0; diff --git a/toolkit/devtools/webconsole/dbg-webconsole-actors.js b/toolkit/devtools/webconsole/dbg-webconsole-actors.js index 385670b42533..dec4f6754d4a 100644 --- a/toolkit/devtools/webconsole/dbg-webconsole-actors.js +++ b/toolkit/devtools/webconsole/dbg-webconsole-actors.js @@ -24,18 +24,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener", XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIListener", "resource://gre/modules/devtools/WebConsoleUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ConsoleProgressListener", - "resource://gre/modules/devtools/WebConsoleUtils.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "JSTermHelpers", "resource://gre/modules/devtools/WebConsoleUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "JSPropertyProvider", "resource://gre/modules/devtools/WebConsoleUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "NetworkMonitor", - "resource://gre/modules/devtools/WebConsoleUtils.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIStorage", "resource://gre/modules/ConsoleAPIStorage.jsm"); @@ -57,11 +51,6 @@ function WebConsoleActor(aConnection, aTabActor) this._objectActorsPool = new ActorPool(this.conn); this.conn.addActorPool(this._objectActorsPool); - - this._networkEventActorsPool = new ActorPool(this.conn); - this.conn.addActorPool(this._networkEventActorsPool); - - this._prefs = {}; } WebConsoleActor.prototype = @@ -78,26 +67,10 @@ WebConsoleActor.prototype = * @private * @type object * @see ActorPool - * @see WebConsoleObjectActor * @see this.objectGrip() */ _objectActorsPool: null, - /** - * Actor pool for all of the network event actors. - * @private - * @type object - * @see NetworkEventActor - */ - _networkEventActorsPool: null, - - /** - * Web Console-related preferences. - * @private - * @type object - */ - _prefs: null, - /** * Tells the current page location associated to the sandbox. When the page * location is changed, we recreate the sandbox. @@ -135,23 +108,6 @@ WebConsoleActor.prototype = */ consoleAPIListener: null, - /** - * The NetworkMonitor instance. - */ - networkMonitor: null, - - /** - * The ConsoleProgressListener instance. - */ - consoleProgressListener: null, - - /** - * Getter for the NetworkMonitor.saveRequestAndResponseBodies preference. - * @type boolean - */ - get saveRequestAndResponseBodies() - this._prefs["NetworkMonitor.saveRequestAndResponseBodies"], - actorPrefix: "console", grip: function WCA_grip() @@ -190,18 +146,8 @@ WebConsoleActor.prototype = this.consoleAPIListener.destroy(); this.consoleAPIListener = null; } - if (this.networkMonitor) { - this.networkMonitor.destroy(); - this.networkMonitor = null; - } - if (this.consoleProgressListener) { - this.consoleProgressListener.destroy(); - this.consoleProgressListener = null; - } this.conn.removeActorPool(this._objectActorsPool); - this.conn.removeActorPool(this._networkEventActorsPool); this._objectActorsPool = null; - this._networkEventActorsPool = null; this._sandboxLocation = this.sandbox = null; this.conn = this._browser = null; }, @@ -259,21 +205,6 @@ WebConsoleActor.prototype = this._objectActorsPool.removeActor(aActor.actorID); }, - /** - * Release a network event actor. - * - * @param object aActor - * The NetworkEventActor instance you want to release. - */ - releaseNetworkEvent: function WCA_releaseNetworkEvent(aActor) - { - this._networkEventActorsPool.removeActor(aActor.actorID); - }, - - ////////////////// - // Request handlers for known packet types. - ////////////////// - /** * Handler for the "startListeners" request. * @@ -305,30 +236,6 @@ WebConsoleActor.prototype = } startedListeners.push(listener); break; - case "NetworkActivity": - if (!this.networkMonitor) { - this.networkMonitor = - new NetworkMonitor(this.window, this); - this.networkMonitor.init(); - } - startedListeners.push(listener); - break; - case "FileActivity": - if (!this.consoleProgressListener) { - this.consoleProgressListener = - new ConsoleProgressListener(this._browser, this); - } - this.consoleProgressListener.startMonitor(this.consoleProgressListener. - MONITOR_FILE_ACTIVITY); - startedListeners.push(listener); - break; - case "LocationChange": - if (!this.consoleProgressListener) { - this.consoleProgressListener = - new ConsoleProgressListener(this._browser, this); - } - this.consoleProgressListener.startMonitor(this.consoleProgressListener. - MONITOR_LOCATION_CHANGE); } } return { @@ -352,9 +259,7 @@ WebConsoleActor.prototype = // If no specific listeners are requested to be detached, we stop all // listeners. - let toDetach = aRequest.listeners || - ["PageError", "ConsoleAPI", "NetworkActivity", - "FileActivity", "LocationChange"]; + let toDetach = aRequest.listeners || ["PageError", "ConsoleAPI"]; while (toDetach.length > 0) { let listener = toDetach.shift(); @@ -373,27 +278,6 @@ WebConsoleActor.prototype = } stoppedListeners.push(listener); break; - case "NetworkActivity": - if (this.networkMonitor) { - this.networkMonitor.destroy(); - this.networkMonitor = null; - } - stoppedListeners.push(listener); - break; - case "FileActivity": - if (this.consoleProgressListener) { - this.consoleProgressListener.stopMonitor(this.consoleProgressListener. - MONITOR_FILE_ACTIVITY); - } - stoppedListeners.push(listener); - break; - case "LocationChange": - if (this.consoleProgressListener) { - this.consoleProgressListener.stopMonitor(this.consoleProgressListener. - MONITOR_LOCATION_CHANGE); - } - stoppedListeners.push(listener); - break; } } @@ -525,24 +409,6 @@ WebConsoleActor.prototype = return {}; }, - /** - * The "setPreferences" request handler. - * - * @param object aRequest - * The request message - which preferences need to be updated. - */ - onSetPreferences: function WCA_onSetPreferences(aRequest) - { - for (let key in aRequest.preferences) { - this._prefs[key] = aRequest.preferences[key]; - } - return { updated: Object.keys(aRequest.preferences) }; - }, - - ////////////////// - // End of request handlers. - ////////////////// - /** * Create the JavaScript sandbox where user input is evaluated. * @private @@ -608,10 +474,6 @@ WebConsoleActor.prototype = return result; }, - ////////////////// - // Event handlers for various listeners. - ////////////////// - /** * Handler for page errors received from the PageErrorListener. This method * sends the nsIScriptError to the remote Web Console client. @@ -659,7 +521,6 @@ WebConsoleActor.prototype = * Handler for window.console API calls received from the ConsoleAPIListener. * This method sends the object to the remote Web Console client. * - * @see ConsoleAPIListener * @param object aMessage * The console API call we need to send to the remote client. */ @@ -673,88 +534,6 @@ WebConsoleActor.prototype = this.conn.send(packet); }, - /** - * Handler for network events. This method is invoked when a new network event - * is about to be recorded. - * - * @see NetworkEventActor - * @see NetworkMonitor from WebConsoleUtils.jsm - * - * @param object aEvent - * The initial network request event information. - * @return object - * A new NetworkEventActor is returned. This is used for tracking the - * network request and response. - */ - onNetworkEvent: function WCA_onNetworkEvent(aEvent) - { - let actor = new NetworkEventActor(aEvent, this); - this._networkEventActorsPool.addActor(actor); - - let packet = { - from: this.actorID, - type: "networkEvent", - eventActor: actor.grip(), - }; - - this.conn.send(packet); - - return actor; - }, - - /** - * Handler for file activity. This method sends the file request information - * to the remote Web Console client. - * - * @see ConsoleProgressListener - * @param string aFileURI - * The requested file URI. - */ - onFileActivity: function WCA_onFileActivity(aFileURI) - { - let packet = { - from: this.actorID, - type: "fileActivity", - uri: aFileURI, - }; - this.conn.send(packet); - }, - - /** - * Handler for location changes. This method sends the new browser location - * to the remote Web Console client. - * - * @see ConsoleProgressListener - * @param string aState - * Tells the location change state: - * - "start" means a load has begun. - * - "stop" means load completed. - * @param string aURI - * The new browser URI. - * @param string aTitle - * The new page title URI. - */ - onLocationChange: function WCA_onLocationChange(aState, aURI, aTitle) - { - // TODO: we should use tabNavigated, but that lives on the TabActor and in - // the Web Console we do not attach to the TabActor. Plus, the tabNavigated - // packet is only sent at the end of a page load - for the Web Console we - // need it as early as possible. Follow-up bug material? - let packet = { - from: this.actorID, - type: "locationChange", - uri: aURI, - title: aTitle, - state: aState, - nativeConsoleAPI: this.hasNativeConsoleAPI(), - }; - this.conn.send(packet); - }, - - ////////////////// - // End of event handlers for various listeners. - ////////////////// - /** * Prepare a message from the console API to be sent to the remote Web Console * instance. @@ -825,7 +604,6 @@ WebConsoleActor.prototype.requestTypes = evaluateJS: WebConsoleActor.prototype.onEvaluateJS, autocomplete: WebConsoleActor.prototype.onAutocomplete, clearMessagesCache: WebConsoleActor.prototype.onClearMessagesCache, - setPreferences: WebConsoleActor.prototype.onSetPreferences, }; /** @@ -900,375 +678,3 @@ WebConsoleObjectActor.prototype.requestTypes = "release": WebConsoleObjectActor.prototype.onRelease, }; - -/** - * Creates an actor for a network event. - * - * @constructor - * @param object aNetworkEvent - * The network event you want to use the actor for. - * @param object aWebConsoleActor - * The parent WebConsoleActor instance for this object. - */ -function NetworkEventActor(aNetworkEvent, aWebConsoleActor) -{ - this.parent = aWebConsoleActor; - this.conn = this.parent.conn; - - this._startedDateTime = aNetworkEvent.startedDateTime; - - this._request = { - method: aNetworkEvent.method, - url: aNetworkEvent.url, - httpVersion: aNetworkEvent.httpVersion, - headers: [], - cookies: [], - headersSize: aNetworkEvent.headersSize, - postData: {}, - }; - - this._response = { - headers: [], - cookies: [], - content: {}, - }; - - this._timings = {}; - - this._discardRequestBody = aNetworkEvent.discardRequestBody; - this._discardResponseBody = aNetworkEvent.discardResponseBody; -} - -NetworkEventActor.prototype = -{ - _request: null, - _response: null, - _timings: null, - - actorPrefix: "netEvent", - - /** - * Returns a grip for this actor for returning in a protocol message. - */ - grip: function NEA_grip() - { - return { - actor: this.actorID, - startedDateTime: this._startedDateTime, - url: this._request.url, - method: this._request.method, - }; - }, - - /** - * Releases this actor from the pool. - */ - release: function NEA_release() - { - this.parent.releaseNetworkEvent(this); - }, - - /** - * Handle a protocol request to release a grip. - */ - onRelease: function NEA_onRelease() - { - this.release(); - return {}; - }, - - /** - * The "getRequestHeaders" packet type handler. - * - * @return object - * The response packet - network request headers. - */ - onGetRequestHeaders: function NEA_onGetRequestHeaders() - { - return { - from: this.actorID, - headers: this._request.headers, - headersSize: this._request.headersSize, - }; - }, - - /** - * The "getRequestCookies" packet type handler. - * - * @return object - * The response packet - network request cookies. - */ - onGetRequestCookies: function NEA_onGetRequestCookies() - { - return { - from: this.actorID, - cookies: this._request.cookies, - }; - }, - - /** - * The "getRequestPostData" packet type handler. - * - * @return object - * The response packet - network POST data. - */ - onGetRequestPostData: function NEA_onGetRequestPostData() - { - return { - from: this.actorID, - postData: this._request.postData, - postDataDiscarded: this._discardRequestBody, - }; - }, - - /** - * The "getResponseHeaders" packet type handler. - * - * @return object - * The response packet - network response headers. - */ - onGetResponseHeaders: function NEA_onGetResponseHeaders() - { - return { - from: this.actorID, - headers: this._response.headers, - headersSize: this._response.headersSize, - }; - }, - - /** - * The "getResponseCookies" packet type handler. - * - * @return object - * The response packet - network response cookies. - */ - onGetResponseCookies: function NEA_onGetResponseCookies() - { - return { - from: this.actorID, - cookies: this._response.cookies, - }; - }, - - /** - * The "getResponseContent" packet type handler. - * - * @return object - * The response packet - network response content. - */ - onGetResponseContent: function NEA_onGetResponseContent() - { - return { - from: this.actorID, - content: this._response.content, - contentDiscarded: this._discardResponseBody, - }; - }, - - /** - * The "getEventTimings" packet type handler. - * - * @return object - * The response packet - network event timings. - */ - onGetEventTimings: function NEA_onGetEventTimings() - { - return { - from: this.actorID, - timings: this._timings, - totalTime: this._totalTime, - }; - }, - - /****************************************************************** - * Listeners for new network event data coming from NetworkMonitor. - ******************************************************************/ - - /** - * Add network request headers. - * - * @param array aHeaders - * The request headers array. - */ - addRequestHeaders: function NEA_addRequestHeaders(aHeaders) - { - this._request.headers = aHeaders; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "requestHeaders", - headers: aHeaders.length, - headersSize: this._request.headersSize, - }; - - this.conn.send(packet); - }, - - /** - * Add network request cookies. - * - * @param array aCookies - * The request cookies array. - */ - addRequestCookies: function NEA_addRequestCookies(aCookies) - { - this._request.cookies = aCookies; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "requestCookies", - cookies: aCookies.length, - }; - - this.conn.send(packet); - }, - - /** - * Add network request POST data. - * - * @param object aPostData - * The request POST data. - */ - addRequestPostData: function NEA_addRequestPostData(aPostData) - { - this._request.postData = aPostData; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "requestPostData", - dataSize: aPostData.text.length, - discardRequestBody: this._discardRequestBody, - }; - - this.conn.send(packet); - }, - - /** - * Add the initial network response information. - * - * @param object aInfo - * The response information. - */ - addResponseStart: function NEA_addResponseStart(aInfo) - { - this._response.httpVersion = aInfo.httpVersion; - this._response.status = aInfo.status; - this._response.statusText = aInfo.statusText; - this._response.headersSize = aInfo.headersSize; - this._discardResponseBody = aInfo.discardResponseBody; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "responseStart", - response: aInfo, - }; - - this.conn.send(packet); - }, - - /** - * Add network response headers. - * - * @param array aHeaders - * The response headers array. - */ - addResponseHeaders: function NEA_addResponseHeaders(aHeaders) - { - this._response.headers = aHeaders; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "responseHeaders", - headers: aHeaders.length, - headersSize: this._response.headersSize, - }; - - this.conn.send(packet); - }, - - /** - * Add network response cookies. - * - * @param array aCookies - * The response cookies array. - */ - addResponseCookies: function NEA_addResponseCookies(aCookies) - { - this._response.cookies = aCookies; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "responseCookies", - cookies: aCookies.length, - }; - - this.conn.send(packet); - }, - - /** - * Add network response content. - * - * @param object aContent - * The response content. - * @param boolean aDiscardedResponseBody - * Tells if the response content was recorded or not. - */ - addResponseContent: - function NEA_addResponseContent(aContent, aDiscardedResponseBody) - { - this._response.content = aContent; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "responseContent", - mimeType: aContent.mimeType, - contentSize: aContent.text.length, - discardResponseBody: aDiscardedResponseBody, - }; - - this.conn.send(packet); - }, - - /** - * Add network event timing information. - * - * @param number aTotal - * The total time of the network event. - * @param object aTimings - * Timing details about the network event. - */ - addEventTimings: function NEA_addEventTimings(aTotal, aTimings) - { - this._totalTime = aTotal; - this._timings = aTimings; - - let packet = { - from: this.actorID, - type: "networkEventUpdate", - updateType: "eventTimings", - totalTime: aTotal, - }; - - this.conn.send(packet); - }, -}; - -NetworkEventActor.prototype.requestTypes = -{ - "release": NetworkEventActor.prototype.onRelease, - "getRequestHeaders": NetworkEventActor.prototype.onGetRequestHeaders, - "getRequestCookies": NetworkEventActor.prototype.onGetRequestCookies, - "getRequestPostData": NetworkEventActor.prototype.onGetRequestPostData, - "getResponseHeaders": NetworkEventActor.prototype.onGetResponseHeaders, - "getResponseCookies": NetworkEventActor.prototype.onGetResponseCookies, - "getResponseContent": NetworkEventActor.prototype.onGetResponseContent, - "getEventTimings": NetworkEventActor.prototype.onGetEventTimings, -}; -