Bug 1296870 - Do not clear output of BrowserConsole when receiving console.clear();r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Mon, 22 Aug 2016 23:51:01 +0200
changeset 404343 0f7c8a57b084e9731558ddea3fe3b8f03255c538
parent 404081 44bb26e3fb66f71161cac484360ba23bc5094031
child 529160 b98bc20635dc6a9ca4fae6f8ae970810120a9e85
push id27185
push userjdescottes@mozilla.com
push dateTue, 23 Aug 2016 08:49:34 +0000
reviewersbgrins
bugs1296870
milestone51.0a1
Bug 1296870 - Do not clear output of BrowserConsole when receiving console.clear();r=bgrins MozReview-Commit-ID: 2quJg454BxU
devtools/client/webconsole/hudservice.js
devtools/client/webconsole/jsterm.js
devtools/client/webconsole/test/browser.ini
devtools/client/webconsole/test/browser_console_clear_method.js
devtools/client/webconsole/webconsole.js
--- a/devtools/client/webconsole/hudservice.js
+++ b/devtools/client/webconsole/hudservice.js
@@ -606,17 +606,16 @@ WebConsole.prototype = {
     else {
       onDestroy();
     }
 
     return this._destroyer.promise;
   },
 };
 
-
 /**
  * A BrowserConsole instance is an interactive console initialized *per target*
  * that displays console log data as well as provides an interactive terminal to
  * manipulate the target's document content.
  *
  * This object only wraps the iframe that holds the Browser Console UI. This is
  * meant to be an integration point between the Firefox UI and the Browser Console
  * UI and features.
--- a/devtools/client/webconsole/jsterm.js
+++ b/devtools/client/webconsole/jsterm.js
@@ -259,17 +259,17 @@ JSTerm.prototype = {
       toolbox = { doc };
     }
     this.autocompletePopup = new AutocompletePopup(toolbox, autocompleteOptions);
 
     let inputContainer = doc.querySelector(".jsterm-input-container");
     this.completeNode = doc.querySelector(".jsterm-complete-node");
     this.inputNode = doc.querySelector(".jsterm-input-node");
 
-    if (this.hud.owner._browserConsole &&
+    if (this.hud.isBrowserConsole &&
         !Services.prefs.getBoolPref("devtools.chrome.enabled")) {
       inputContainer.style.display = "none";
     } else {
       let okstring = l10n.getStr("selfxss.okstring");
       let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
       this._onPaste = WebConsoleUtils.pasteHandlerGen(
         this.inputNode, doc.getElementById("webconsole-notificationbox"),
         msg, okstring);
@@ -762,17 +762,17 @@ JSTerm.prototype = {
 
     // We need to avoid pruning the object inspection starting point.
     // That one is pruned when the console message is removed.
     view.controller.releaseActors(actor => {
       return view._consoleLastObjectActor != actor;
     });
 
     if (options.objectActor &&
-        (!this.hud.owner._browserConsole ||
+        (!this.hud.isBrowserConsole ||
          Services.prefs.getBoolPref("devtools.chrome.enabled"))) {
       // Make sure eval works in the correct context.
       view.eval = this._variablesViewEvaluate.bind(this, options);
       view.switch = this._variablesViewSwitch.bind(this, options);
       view.delete = this._variablesViewDelete.bind(this, options);
     } else {
       view.eval = null;
       view.switch = null;
--- a/devtools/client/webconsole/test/browser.ini
+++ b/devtools/client/webconsole/test/browser.ini
@@ -155,16 +155,17 @@ subsuite = clipboard
 skip-if = (e10s && (os == 'win' || os == 'mac')) # Bug 1243976
 [browser_bug_865288_repeat_different_objects.js]
 [browser_bug_865871_variables_view_close_on_esc_key.js]
 [browser_bug_869003_inspect_cross_domain_object.js]
 [browser_bug_871156_ctrlw_close_tab.js]
 [browser_cached_messages.js]
 [browser_console.js]
 [browser_console_addonsdk_loader_exception.js]
+[browser_console_clear_method.js]
 [browser_console_clear_on_reload.js]
 [browser_console_click_focus.js]
 [browser_console_consolejsm_output.js]
 [browser_console_copy_command.js]
 subsuite = clipboard
 [browser_console_dead_objects.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_console_copy_entire_message_context_menu.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/browser_console_clear_method.js
@@ -0,0 +1,41 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Check that console.clear() does not clear the output of the browser console.
+
+"use strict";
+
+const TEST_URI = "data:text/html;charset=utf8,<p>Bug 1296870";
+
+add_task(function* () {
+  yield loadTab(TEST_URI);
+  let hud = yield HUDService.toggleBrowserConsole();
+
+  info("Log a new message from the content page");
+  ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
+    content.wrappedJSObject.console.log("msg");
+  });
+  yield waitForMessage("msg", hud);
+
+  info("Send a console.clear() from the content page");
+  ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
+    content.wrappedJSObject.console.clear();
+  });
+  yield waitForMessage("Console was cleared", hud);
+
+  info("Check that the messages logged after the first clear are still displayed");
+  isnot(hud.outputNode.textContent.indexOf("msg"), -1, "msg is in the output");
+});
+
+function waitForMessage(message, webconsole) {
+  return waitForMessages({
+    webconsole,
+    messages: [{
+      text: message,
+      category: CATEGORY_WEBDEV,
+      severity: SEVERITY_LOG,
+    }],
+  });
+}
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -201,16 +201,18 @@ const PREF_NEW_FRONTEND_ENABLED = "devto
  *
  * @constructor
  * @param object webConsoleOwner
  *        The WebConsole owner object.
  */
 function WebConsoleFrame(webConsoleOwner) {
   this.owner = webConsoleOwner;
   this.hudId = this.owner.hudId;
+  this.isBrowserConsole = this.owner._browserConsole;
+
   this.window = this.owner.iframeWindow;
 
   this._repeatNodes = {};
   this._outputQueue = [];
   this._itemDestroyQueue = [];
   this._pruneCategoriesQueue = {};
   this.filterPrefs = {};
 
@@ -428,17 +430,17 @@ WebConsoleFrame.prototype = {
    * Getter for the persistent logging preference.
    * @type boolean
    */
   get persistLog() {
     // For the browser console, we receive tab navigation
     // when the original top level window we attached to is closed,
     // but we don't want to reset console history and just switch to
     // the next available window.
-    return this.owner._browserConsole ||
+    return this.isBrowserConsole ||
            Services.prefs.getBoolPref(PREF_PERSISTLOG);
   },
 
   /**
    * Initialize the WebConsoleFrame instance.
    * @return object
    *         A promise object that resolves once the frame is ready to use.
    */
@@ -496,17 +498,17 @@ WebConsoleFrame.prototype = {
 
   /**
    * Find the Web Console UI elements and setup event listeners as needed.
    * @private
    */
   _initUI: function () {
     this.document = this.window.document;
     this.rootElement = this.document.documentElement;
-    this.NEW_CONSOLE_OUTPUT_ENABLED = !this.owner._browserConsole
+    this.NEW_CONSOLE_OUTPUT_ENABLED = !this.isBrowserConsole
       && !this.owner.target.chrome
       && Services.prefs.getBoolPref(PREF_NEW_FRONTEND_ENABLED);
 
     this._initDefaultFilterPrefs();
 
     // Register the controller to handle "select all" properly.
     this._commandController = new CommandController(this);
     this.window.controllers.insertControllerAt(0, this._commandController);
@@ -668,17 +670,17 @@ WebConsoleFrame.prototype = {
     if (system.constants.platform === "macosx") {
       clearShortcut = l10n.getStr("webconsole.clear.keyOSX");
     } else {
       clearShortcut = l10n.getStr("webconsole.clear.key");
     }
     shortcuts.on(clearShortcut,
                  () => this.jsterm.clearOutput(true));
 
-    if (this.owner._browserConsole) {
+    if (this.isBrowserConsole) {
       shortcuts.on(l10n.getStr("webconsole.close.key"),
                    this.window.close.bind(this.window));
 
       ZoomKeys.register(this.window);
     }
   },
 
   /**
@@ -780,17 +782,17 @@ WebConsoleFrame.prototype = {
         menuItem.setAttribute("checked", checked);
         someChecked = someChecked || checked;
       }, this);
 
       button.setAttribute("checked", someChecked);
       button.setAttribute("aria-pressed", someChecked);
     }, this);
 
-    if (!this.owner._browserConsole) {
+    if (!this.isBrowserConsole) {
       // The Browser Console displays nsIConsoleMessages which are messages that
       // end up in the JS category, but they are not errors or warnings, they
       // are just log messages. The Web Console does not show such messages.
       let jslog = this.document.querySelector("menuitem[prefKey=jslog]");
       jslog.hidden = true;
     }
 
     if (Services.appinfo.OS == "Darwin") {
@@ -2161,17 +2163,18 @@ WebConsoleFrame.prototype = {
     }
 
     let isFiltered = this.filterMessageNode(node);
 
     let isRepeated = this._filterRepeatedMessage(node);
 
     // If a clear message is processed while the webconsole is opened, the UI
     // should be cleared.
-    if (message && message.level == "clear") {
+    // Do not clear the output if the current frame is owned by a Browser Console.
+    if (message && message.level == "clear" && !this.isBrowserConsole) {
       // Do not clear the consoleStorage here as it has been cleared already
       // by the clear method, only clear the UI.
       this.jsterm.clearOutput(false);
     }
 
     let visible = !isRepeated && !isFiltered;
     if (!isRepeated) {
       this.outputNode.appendChild(node);
@@ -3211,17 +3214,17 @@ WebConsoleConnectionProxy.prototype = {
       return;
     }
 
     this.webConsoleClient = webConsoleClient;
     this._hasNativeConsoleAPI = response.nativeConsoleAPI;
 
     // There is no way to view response bodies from the Browser Console, so do
     // not waste the memory.
-    let saveBodies = !this.webConsoleFrame.owner._browserConsole;
+    let saveBodies = !this.webConsoleFrame.isBrowserConsole;
     this.webConsoleFrame.setSaveRequestAndResponseBodies(saveBodies);
 
     this.webConsoleClient.on("networkEvent", this._onNetworkEvent);
     this.webConsoleClient.on("networkEventUpdate", this._onNetworkEventUpdate);
 
     let msgs = ["PageError", "ConsoleAPI"];
     this.webConsoleClient.getCachedMessages(msgs, this._onCachedMessages);