Bug 1425552 - Move clearOutput and clearPrivateMessages from the jsterm and onto the WebConsoleFrame;r=nchevobbe draft
authorBrian Grinstead <bgrinstead@mozilla.com>
Sat, 02 Jun 2018 16:44:08 -0700
changeset 803318 1a331fb42429206688ac5c980a2915c1c7d48157
parent 803317 1f62ecdf59b6ecaa3c0fdda39bb296ec092a156b
push id112068
push userbgrinstead@mozilla.com
push dateSun, 03 Jun 2018 03:45:36 +0000
reviewersnchevobbe
bugs1425552
milestone62.0a1
Bug 1425552 - Move clearOutput and clearPrivateMessages from the jsterm and onto the WebConsoleFrame;r=nchevobbe MozReview-Commit-ID: 9lJW7qt64DT
devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
devtools/client/shared/webpack/shims/jsterm-stub.js
devtools/client/webconsole/components/JSTerm.js
devtools/client/webconsole/console-commands.js
devtools/client/webconsole/test/mochitest/browser_console.js
devtools/client/webconsole/test/mochitest/browser_console_consolejsm_output.js
devtools/client/webconsole/test/mochitest/browser_console_webconsole_private_browsing.js
devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
devtools/client/webconsole/test/mochitest/browser_jsterm_dollar.js
devtools/client/webconsole/test/mochitest/browser_jsterm_error_docs.js
devtools/client/webconsole/test/mochitest/browser_jsterm_helper_help.js
devtools/client/webconsole/test/mochitest/browser_jsterm_hide_when_devtools_chrome_enabled_false.js
devtools/client/webconsole/test/mochitest/browser_jsterm_history.js
devtools/client/webconsole/test/mochitest/browser_jsterm_selfxss.js
devtools/client/webconsole/test/mochitest/browser_webconsole_cd_iframe.js
devtools/client/webconsole/test/mochitest/browser_webconsole_console_logging_workers_api.js
devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_entire_message.js
devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_link_location.js
devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_open_url.js
devtools/client/webconsole/test/mochitest/browser_webconsole_csp_violation.js
devtools/client/webconsole/test/mochitest/browser_webconsole_cspro.js
devtools/client/webconsole/test/mochitest/browser_webconsole_execution_scope.js
devtools/client/webconsole/test/mochitest/browser_webconsole_file_uri.js
devtools/client/webconsole/test/mochitest/browser_webconsole_highlighter_console_helper.js
devtools/client/webconsole/test/mochitest/browser_webconsole_hpkp_invalid-headers.js
devtools/client/webconsole/test/mochitest/browser_webconsole_hsts_invalid-headers.js
devtools/client/webconsole/test/mochitest/browser_webconsole_input_focus.js
devtools/client/webconsole/test/mochitest/browser_webconsole_js_input_expansion.js
devtools/client/webconsole/test/mochitest/browser_webconsole_loglimit.js
devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
devtools/client/webconsole/test/mochitest/browser_webconsole_output_order.js
devtools/client/webconsole/test/mochitest/browser_webconsole_reopen_closed_tab.js
devtools/client/webconsole/test/mochitest/browser_webconsole_sandbox_update_after_navigation.js
devtools/client/webconsole/test/mochitest/browser_webconsole_script_errordoc_urls.js
devtools/client/webconsole/test/mochitest/browser_webconsole_select_all.js
devtools/client/webconsole/test/mochitest/browser_webconsole_show_subresource_security_errors.js
devtools/client/webconsole/test/mochitest/browser_webconsole_time_methods.js
devtools/client/webconsole/test/mochitest/head.js
devtools/client/webconsole/webconsole-connection-proxy.js
devtools/client/webconsole/webconsole-frame.js
--- a/devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_wrong_window_focus.js
@@ -24,17 +24,17 @@ function test() {
       const sw = gScratchpadWindow;
       const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
       const {TargetFactory} = require("devtools/client/framework/target");
 
       openScratchpad(function() {
         const target = TargetFactory.forTab(gBrowser.selectedTab);
         gDevTools.showToolbox(target, "webconsole").then((toolbox) => {
           const hud = toolbox.getCurrentPanel().hud;
-          hud.jsterm.clearOutput(true);
+          hud.ui.clearOutput(true);
           testFocus(sw, hud);
         });
       });
     });
   });
 
   gBrowser.loadURI("data:text/html;charset=utf8,<p>test window focus for Scratchpad.");
 }
--- a/devtools/client/shared/webpack/shims/jsterm-stub.js
+++ b/devtools/client/shared/webpack/shims/jsterm-stub.js
@@ -17,17 +17,16 @@ function JSTerm(webConsoleFrame) {
 JSTerm.prototype = {
   SELECTED_FRAME: -1,
 
   get webConsoleClient() {
     return this.hud.webConsoleClient;
   },
 
   openVariablesView() { },
-  clearOutput() { },
 
   init() {
     this.doc = this.hud.window.document;
     this.root = this.doc.createElement("div");
     this.root.className = "jsterm-input-container";
     this.inputNode = this.doc.createElement("input");
     this.inputNode.className = "jsterm-input-node jsterm-input-node-html";
     this.root.appendChild(this.inputNode);
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -283,17 +283,17 @@ class JSTerm extends Component {
     }
     const result = response.result;
     const helperResult = response.helperResult;
     const helperHasRawOutput = !!(helperResult || {}).rawOutput;
 
     if (helperResult && helperResult.type) {
       switch (helperResult.type) {
         case "clearOutput":
-          this.clearOutput();
+          this.hud.clearOutput();
           break;
         case "clearHistory":
           this.props.clearHistory();
           break;
         case "inspectObject":
           this.inspectObjectActor(helperResult.object);
           break;
         case "error":
@@ -480,50 +480,16 @@ class JSTerm extends Component {
     } else {
       grip = state.frames[frame];
     }
 
     return grip ? grip.actor : null;
   }
 
   /**
-   * Clear the Web Console output.
-   *
-   * This method emits the "messages-cleared" notification.
-   *
-   * @param boolean clearStorage
-   *        True if you want to clear the console messages storage associated to
-   *        this Web Console.
-   */
-  clearOutput(clearStorage) {
-    if (this.hud && this.hud.consoleOutput) {
-      this.hud.consoleOutput.dispatchMessagesClear();
-    }
-
-    this.webConsoleClient.clearNetworkRequests();
-    if (clearStorage) {
-      this.webConsoleClient.clearMessagesCache();
-    }
-    this.focus();
-    this.emit("messages-cleared");
-  }
-
-  /**
-   * Remove all of the private messages from the Web Console output.
-   *
-   * This method emits the "private-messages-cleared" notification.
-   */
-  clearPrivateMessages() {
-    if (this.hud && this.hud.consoleOutput) {
-      this.hud.consoleOutput.dispatchPrivateMessagesClear();
-      this.emit("private-messages-cleared");
-    }
-  }
-
-  /**
    * Updates the size of the input field (command line) to fit its contents.
    *
    * @returns void
    */
   resizeInput() {
     if (this.props.codeMirrorEnabled) {
       return;
     }
--- a/devtools/client/webconsole/console-commands.js
+++ b/devtools/client/webconsole/console-commands.js
@@ -68,18 +68,18 @@ exports.items = [
         return null;
       }
 
       const panel = toolbox.getPanel("webconsole");
       if (panel == null) {
         return null;
       }
 
-      const onceMessagesCleared = panel.hud.jsterm.once("messages-cleared");
-      panel.hud.jsterm.clearOutput();
+      const onceMessagesCleared = panel.hud.once("messages-cleared");
+      panel.hud.ui.clearOutput();
       return onceMessagesCleared;
     }
   },
   {
     item: "command",
     runAt: "client",
     name: "console close",
     description: l10n.lookup("consolecloseDesc"),
--- a/devtools/client/webconsole/test/mochitest/browser_console.js
+++ b/devtools/client/webconsole/test/mochitest/browser_console.js
@@ -39,17 +39,17 @@ add_task(async function() {
   });
 
   await testMessages(hud);
   await testCPOWInspection(hud);
   await resetFilters(hud);
 });
 
 async function testMessages(hud) {
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 
   expectUncaughtException();
 
   executeSoon(() => {
     // eslint-disable-next-line no-undef
     foobarException();
   });
 
--- a/devtools/client/webconsole/test/mochitest/browser_console_consolejsm_output.js
+++ b/devtools/client/webconsole/test/mochitest/browser_console_consolejsm_output.js
@@ -14,17 +14,17 @@ add_task(async function testCategoryLogs
 
   const {console} = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
   console.log("bug861338-log-cached");
 
   const hud = await HUDService.toggleBrowserConsole();
 
   await checkMessageExists(hud, "bug861338-log-cached");
 
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 
   function testTrace() {
     console.trace();
   }
 
   console.time("foobarTimer");
   const foobar = { bug851231prop: "bug851231value" };
 
@@ -43,17 +43,17 @@ add_task(async function testCategoryLogs
   await checkMessageExists(hud, "bug851231-info");
   await checkMessageExists(hud, "bug851231-warn");
   await checkMessageExists(hud, "bug851231-error");
   await checkMessageExists(hud, "bug851231-debug");
   await checkMessageExists(hud, "XULDocument");
   await checkMessageExists(hud, "console.trace()");
   await checkMessageExists(hud, "foobarTimer");
 
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
   await HUDService.toggleBrowserConsole();
 });
 
 add_task(async function testFilter() {
   const consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
   const storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
   storage.clearEvents();
 
@@ -74,17 +74,17 @@ add_task(async function testFilter() {
   console2.error(shouldBeVisible);
 
   await checkMessageExists(hud, shouldBeVisible);
   // Here we can safely assert that the log message is not visible, since the
   // error message was logged after and is visible.
   await checkMessageHidden(hud, shouldBeHidden);
 
   await resetFilters(hud);
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
   await HUDService.toggleBrowserConsole();
 });
 
 // Test that console.profile / profileEnd trigger the right events
 add_task(async function testProfile() {
   const consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
   const storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
   const { console } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
--- a/devtools/client/webconsole/test/mochitest/browser_console_webconsole_private_browsing.js
+++ b/devtools/client/webconsole/test/mochitest/browser_console_webconsole_private_browsing.js
@@ -80,17 +80,17 @@ add_task(async function() {
     waitForMessage(hud, PRIVATE_EXCEPTION, ".error");
   logPrivateMessages(privateBrowser.selectedBrowser);
 
   await onBrowserConsolePrivateLogMessage;
   await onBrowserConsolePrivateErrorMessage;
   ok(true, "Messages are displayed as expected");
 
   info("close the private window and check if private messages are removed");
-  const onPrivateMessagesCleared = hud.jsterm.once("private-messages-cleared");
+  const onPrivateMessagesCleared = hud.ui.once("private-messages-cleared");
   privateWindow.BrowserTryToCloseWindow();
   await onPrivateMessagesCleared;
 
   ok(findMessage(hud, NON_PRIVATE_MESSAGE),
     "non-private messages are still shown after private window closed");
   assertNoPrivateMessages(hud);
 
   info("close the browser console");
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
@@ -5,17 +5,17 @@
 
 // Tests that code completion works properly.
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf8,<p>test code completion";
 
 add_task(async function() {
-  const {jsterm} = await openNewTabAndConsole(TEST_URI);
+  const {jsterm, ui} = await openNewTabAndConsole(TEST_URI);
   const input = jsterm.inputNode;
 
   // Test typing 'docu'.
   await jstermSetValueAndComplete(jsterm, "docu");
   is(input.value, "docu", "'docu' completion (input.value)");
   is(jsterm.completeNode.value, "    ment", "'docu' completion (completeNode)");
 
   // Test typing 'docu' and press tab.
@@ -45,17 +45,17 @@ add_task(async function() {
      "'document.getElem' another tab completion");
 
   // Test pressing shift_tab.
   await jstermComplete(jsterm, jsterm.COMPLETE_BACKWARD);
   is(input.value, "document.getElem", "'document.getElem' untab completion");
   is(jsterm.completeNode.value, "                entsByTagNameNS",
      "'document.getElem' completion");
 
-  jsterm.clearOutput();
+  ui.clearOutput();
 
   await jstermSetValueAndComplete(jsterm, "docu");
   is(jsterm.completeNode.value, "    ment", "'docu' completion");
 
   await jsterm.execute();
   is(jsterm.completeNode.value, "", "clear completion on execute()");
 
   // Test multi-line completion works
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_dollar.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_dollar.js
@@ -13,19 +13,19 @@ const TEST_URI = "http://example.com/bro
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
   await test$(hud);
   await test$$(hud);
 });
 
 async function test$(hud) {
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
   const msg = await hud.jsterm.execute("$(document.body)");
   ok(msg.textContent.includes("<p>"), "jsterm output is correct for $()");
 }
 
 async function test$$(hud) {
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
   hud.jsterm.setInputValue();
   const msg = await hud.jsterm.execute("$$(document)");
   ok(msg.textContent.includes("621644"), "jsterm output is correct for $$()");
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_error_docs.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_error_docs.js
@@ -17,17 +17,17 @@ add_task(async function() {
     "JSMSG_BAD_ARRAY_LENGTH": "([]).length = -1",
     "JSMSG_NEGATIVE_REPETITION_COUNT": "'abc'.repeat(-1);",
     "JSMSG_PRECISION_RANGE": "77.1234.toExponential(-1);",
   };
 
   for (const [errorMessageName, expression] of Object.entries(ErrorDocStatements)) {
     const title = ErrorDocs.GetURL({ errorMessageName }).split("?")[0];
 
-    jsterm.clearOutput();
+    hud.ui.clearOutput();
     const onMessage = waitForMessage(hud, "RangeError:");
     jsterm.execute(expression);
     const {node} = await onMessage;
     const learnMoreLink = node.querySelector(".learn-more-link");
     ok(learnMoreLink, `There is a [Learn More] link for "${errorMessageName}" error`);
     is(learnMoreLink.title, title, `The link has the expected "${title}" title`);
   }
 });
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_helper_help.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_helper_help.js
@@ -13,17 +13,17 @@ add_task(async function() {
   let openedLinks = 0;
   const oldOpenLink = hud.openLink;
   hud.openLink = (url) => {
     if (url == HELP_URL) {
       openedLinks++;
     }
   };
 
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
   await jsterm.execute("help()");
   await jsterm.execute("help");
   await jsterm.execute("?");
 
   const messages = Array.from(jsterm.outputNode.querySelectorAll(".message"));
   ok(messages.every(msg => msg.classList.contains("command")),
     "There is no results shown for the help commands");
   is(openedLinks, 3, "correct number of pages opened by the help calls");
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_hide_when_devtools_chrome_enabled_false.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_hide_when_devtools_chrome_enabled_false.js
@@ -60,17 +60,17 @@ add_task(async function() {
  * currently in use.
  */
 async function getObjectInspector(hud) {
   const { ui, jsterm } = hud;
 
   // Filter out other messages to ensure ours stays visible.
   ui.filterBox.value = "browser_console_hide_jsterm_test";
 
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
   jsterm.execute("new Object({ browser_console_hide_jsterm_test: true })");
 
   const message = await waitFor(
     () => findMessage(hud, "Object { browser_console_hide_jsterm_test: true }")
   );
 
   const objInspector = message.querySelector(".tree");
   return objInspector;
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_history.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_history.js
@@ -11,19 +11,19 @@ const TEST_URI = "data:text/html;charset
 const COMMANDS = ["document", "window", "window.location"];
 
 const {
   HISTORY_BACK,
   HISTORY_FORWARD,
 } = require("devtools/client/webconsole/constants");
 
 add_task(async function() {
-  const { jsterm } = await openNewTabAndConsole(TEST_URI);
+  const { jsterm, ui } = await openNewTabAndConsole(TEST_URI);
   const { inputNode } = jsterm;
-  jsterm.clearOutput();
+  ui.clearOutput();
 
   for (const command of COMMANDS) {
     info(`Executing command ${command}`);
     jsterm.setInputValue(command);
     await jsterm.execute();
   }
 
   for (let x = COMMANDS.length - 1; x != -1; x--) {
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_selfxss.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_selfxss.js
@@ -14,18 +14,18 @@ XPCOMUtils.defineLazyServiceGetter(
   "nsIClipboardHelper"
 );
 const WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
 const stringToCopy = "foobazbarBug642615";
 
 add_task(async function() {
   await pushPref("devtools.selfxss.count", 0);
 
-  const {jsterm} = await openNewTabAndConsole(TEST_URI);
-  jsterm.clearOutput();
+  const {jsterm, ui} = await openNewTabAndConsole(TEST_URI);
+  ui.clearOutput();
   ok(!jsterm.completeNode.value, "no completeNode.value");
 
   jsterm.setInputValue("doc");
 
   info("wait for completion value after typing 'docu'");
   let onAutocompleteUpdated = jsterm.once("autocomplete-updated");
   EventUtils.sendString("u");
   await onAutocompleteUpdated;
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_cd_iframe.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_cd_iframe.js
@@ -62,10 +62,10 @@ async function executeWindowTest(hud, if
   hud.jsterm.execute(`document.title`);
   hud.jsterm.execute(`"p: " + document.querySelector("p").textContent`);
   hud.jsterm.execute(`"obj: " + window.foobar`);
 
   const messages = await onMessages;
   ok(messages, `Expected evaluation result messages are shown in ${iframeRole} iframe`);
 
   // Clear the output so we don't pollute the next assertions.
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 }
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_console_logging_workers_api.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_console_logging_workers_api.js
@@ -15,12 +15,12 @@ add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
   const message = await waitFor(() => findMessage(hud, "foo-bar-shared-worker"));
   is(
     message.querySelector(".message-body").textContent,
     `foo-bar-shared-worker Object { foo: "bar" }`,
     "log from SharedWorker is displayed as expected"
   );
 
-  const onMessagesCleared = hud.jsterm.once("messages-cleared");
-  hud.jsterm.clearOutput(true);
+  const onMessagesCleared = hud.ui.once("messages-cleared");
+  hud.ui.clearOutput(true);
   await onMessagesCleared;
 });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_entire_message.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_entire_message.js
@@ -30,17 +30,17 @@ const TEST_URI = `data:text/html;charset
 
 add_task(async function() {
   const observer = new PrefObserver("");
   let onPrefUpdated = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
   Services.prefs.setBoolPref(PREF_MESSAGE_TIMESTAMP, true);
   await onPrefUpdated;
 
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   info("Call the log function defined in the test page");
   await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.wrappedJSObject.logStuff();
   });
 
   info("Test copy menu item for the simple log");
   let message = await waitFor(() => findMessage(hud, "simple text message"));
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_link_location.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_copy_link_location.js
@@ -13,17 +13,17 @@ const TEST_URI = "http://example.com/bro
                  Date.now();
 const CONTEXT_MENU_ID = "#console-menu-copy-url";
 
 add_task(async function() {
   // Enable net messages in the console for this test.
   await pushPref("devtools.webconsole.filter.net", true);
 
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   info("Test Copy URL menu item for text log");
 
   info("Logging a text message in the content window");
   const onLogMessage = waitForMessage(hud, "simple text message");
   await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.wrappedJSObject.console.log("simple text message");
   });
@@ -31,17 +31,17 @@ add_task(async function() {
   ok(message, "Text log found in the console");
 
   info("Open and check the context menu for the logged text message");
   let menuPopup = await openContextMenu(hud, message.node);
   let copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
   ok(!copyURLItem, "Copy URL menu item is hidden for a simple text message");
 
   await hideContextMenu(hud);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   info("Test Copy URL menu item for network log");
 
   info("Reload the content window to produce a network log");
   const onNetworkMessage = waitForMessage(hud, "test-console.html");
   await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.wrappedJSObject.location.reload();
   });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_open_url.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_context_menu_open_url.js
@@ -11,34 +11,34 @@
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/test-console.html";
 
 add_task(async function() {
   // Enable net messages in the console for this test.
   await pushPref("devtools.webconsole.filter.net", true);
 
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   info("Test Open URL menu item for text log");
 
   info("Logging a text message in the content window");
   await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.wrappedJSObject.console.log("simple text message");
   });
   let message = await waitFor(() => findMessage(hud, "simple text message"));
   ok(message, "Text log found in the console");
 
   info("Open and check the context menu for the logged text message");
   let menuPopup = await openContextMenu(hud, message);
   let openUrlItem = menuPopup.querySelector("#console-menu-open-url");
   ok(!openUrlItem, "Open URL menu item is not available");
 
   await hideContextMenu(hud);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   info("Test Open URL menu item for network log");
 
   info("Reload the content window to produce a network log");
   await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.wrappedJSObject.location.reload();
   });
   message = await waitFor(() => findMessage(hud, "test-console.html"));
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_csp_violation.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_csp_violation.js
@@ -12,16 +12,16 @@ const TEST_URI = "data:text/html;charset
 const TEST_VIOLATION = "https://example.com/browser/devtools/client/webconsole/" +
                        "test/mochitest/test-csp-violation.html";
 const CSP_VIOLATION_MSG = "Content Security Policy: The page\u2019s settings " +
                           "blocked the loading of a resource at " +
                           "http://some.example.com/test.png (\u201cimg-src\u201d).";
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const onRepeatedMessage = waitForRepeatedMessage(hud, CSP_VIOLATION_MSG, 2);
   await loadDocument(TEST_VIOLATION);
   await onRepeatedMessage;
 
   ok(true, "Received expected messages");
 });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_cspro.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_cspro.js
@@ -35,10 +35,10 @@ add_task(async function() {
 
   info("Load a page with CSP warnings.");
   loadDocument(TEST_VIOLATION);
 
   await onCspViolationMessage;
   await onCspReportMessage;
   ok(true, "Confirmed that CSP and CSP-Report-Only log different messages to console");
 
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_execution_scope.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_execution_scope.js
@@ -8,17 +8,17 @@
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/test-console.html";
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
   const {jsterm} = hud;
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const onInputMessage = waitForMessage(hud, "window.location.href;", ".message.command");
   const onEvaluationResultMessage = waitForMessage(hud, TEST_URI, ".message.result");
   jsterm.execute("window.location.href;");
 
   let message = await onInputMessage;
   ok(message, "Input message is displayed with the expected class");
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_file_uri.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_file_uri.js
@@ -28,17 +28,17 @@ add_task(async function() {
 
   // Open tab with correct remote type so we don't switch processes when we load
   // the file:// URI, otherwise we won't get the same web console.
   const remoteType = E10SUtils.getRemoteTypeForURI(uri.spec,
                                                  gMultiProcessBrowser);
   const { browser } = await loadTab("about:blank", remoteType);
 
   hud = await openConsole();
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const loaded = loadBrowser(browser);
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, uri.spec);
   await loaded;
 
   await testMessages();
 
   Services.prefs.clearUserPref(PREF);
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_highlighter_console_helper.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_highlighter_console_helper.js
@@ -43,24 +43,24 @@ add_task(async function() {
 
   await onPickerStopped;
   await onInspectorUpdated;
 
   info("Picker mode stopped, <h1> selected, now switching to the console");
   const hud = await openConsole();
   const {jsterm} = hud;
 
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const onEvaluationResult = waitForMessage(hud, "<h1>");
   jsterm.execute("$0");
   await onEvaluationResult;
   ok(true, "correct output for $0");
 
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const newH1Content = "newH1Content";
   const onAssignmentResult = waitForMessage(hud, "<h1>");
   jsterm.execute(`$0.textContent = "${newH1Content}";$0`);
   await onAssignmentResult;
 
   ok(true, "correct output for $0 after setting $0.textContent");
   const {textContent} = await testActor.getNodeInfo("h1");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_hpkp_invalid-headers.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_hpkp_invalid-headers.js
@@ -87,17 +87,17 @@ add_task(async function() {
     name: "Non-built-in root error displayed successfully",
     text: "Public-Key-Pins: The certificate used by the site was not issued " +
           "by a certificate in the default root certificate store. To " +
           "prevent accidental breakage, the specified header was ignored."
   }, hud);
 });
 
 async function navigateAndCheckForWarningMessage({name, text, url}, hud) {
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 
   const onMessage = waitForMessage(hud, text, ".message.warning");
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   const {node} = await onMessage;
   ok(node, name);
 
   const learnMoreNode = node.querySelector(".learn-more-link");
   ok(learnMoreNode, `There is a "Learn more" link`);
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_hsts_invalid-headers.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_hsts_invalid-headers.js
@@ -53,17 +53,17 @@ add_task(async function() {
     url: SJS_URL + "?multipleMaxAge",
     name: "Multiple max-age error displayed successfully",
     text: "Strict-Transport-Security: The site specified a header that " +
           "included multiple \u2018max-age\u2019 directives."
   }, hud);
 });
 
 async function navigateAndCheckWarningMessage({url, name, text}, hud) {
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 
   const onMessage = waitForMessage(hud, text, ".message.warning");
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   const {node} = await onMessage;
   ok(node, name);
 
   const learnMoreNode = node.querySelector(".learn-more-link");
   ok(learnMoreNode, `There is a "Learn more" link`);
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_input_focus.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_input_focus.js
@@ -15,17 +15,17 @@ const TEST_URI =
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
 
   const inputNode = hud.jsterm.inputNode;
   info("Focus after console is opened");
   ok(hasFocus(inputNode), "input node is focused after console is opened");
 
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
   ok(hasFocus(inputNode), "input node is focused after output is cleared");
 
   info("Focus during message logging");
   ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
     content.wrappedJSObject.console.log("console message 2");
   });
   const msg = await waitFor(() => findMessage(hud, "console message 2"));
   ok(hasFocus(inputNode, "input node is focused, first time"));
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_js_input_expansion.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_js_input_expansion.js
@@ -6,18 +6,18 @@
 // Tests that the input box expands as the user types long lines.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/test-console.html";
 
 add_task(async function() {
-  const { jsterm } = await openNewTabAndConsole(TEST_URI);
-  jsterm.clearOutput();
+  const { jsterm, ui } = await openNewTabAndConsole(TEST_URI);
+  ui.clearOutput();
 
   const { inputNode } = jsterm;
   const getInputHeight = () => inputNode.clientHeight;
 
   info("Get the initial (empty) height of the input");
   const emptyHeight = getInputHeight();
 
   info("Set some multiline text in the input");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_loglimit.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_loglimit.js
@@ -8,17 +8,17 @@
 // Test that messages are properly updated when the log limit is reached.
 
 const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
                  "Old messages are removed after passing devtools.hud.loglimit";
 
 add_task(async function() {
   await pushPref("devtools.hud.loglimit", 140);
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   let onMessage = waitForMessage(hud, "test message [149]");
   ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
     for (let i = 0; i < 150; i++) {
       content.console.log(`test message [${i}]`);
     }
   });
   await onMessage;
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_network_messages_expand.js
@@ -99,17 +99,17 @@ async function openRequestAfterUpdates(t
 
   await payload;
   await testNetworkMessage(toolbox, messageNode);
 }
 
 async function openRequestBeforeUpdates(target, hud, tab) {
   const toolbox = gDevTools.getToolbox(target);
 
-  hud.jsterm.clearOutput(true);
+  hud.ui.clearOutput(true);
 
   const xhrUrl = TEST_PATH + "sjs_slow-response-test-server.sjs";
   const message = waitForMessage(hud, xhrUrl);
 
   // Fire an XHR POST request.
   ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
     content.wrappedJSObject.testXhrPostSlowResponse();
   });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_output_order.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_output_order.js
@@ -8,17 +8,17 @@
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/test-console.html";
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   const messages = ["console.log('foo', 'bar');", "foo bar", "undefined"];
   const onMessages = waitForMessages({
     hud,
     messages: messages.map(text => ({text}))
   });
 
   hud.jsterm.execute("console.log('foo', 'bar');");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_reopen_closed_tab.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_reopen_closed_tab.js
@@ -15,17 +15,17 @@ add_task(async function() {
   // If we persist log, the test might be successful even if only the first
   // error log is shown.
   pushPref("devtools.webconsole.persistlog", false);
 
   info("Open console and refresh tab.");
 
   expectUncaughtExceptionNoE10s();
   let hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 
   expectUncaughtExceptionNoE10s();
   await refreshTab();
   await waitForError(hud);
 
   // Close and reopen
   await closeConsole();
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_sandbox_update_after_navigation.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_sandbox_update_after_navigation.js
@@ -41,28 +41,28 @@ add_task(async function() {
   onMessages = waitForMessages({
     hud,
     messages: [
       { text: "window.location.href" },
       { text: TEST_URI2 },
     ],
   });
 
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
   hud.jsterm.execute("window.location.href");
 
   info("wait for window.location.href after page navigation");
   await onMessages;
 
   ok(!findMessage(hud, "Permission denied"), "no permission denied errors");
 
   // Navigation clears messages. Wait for that clear to happen before
   // continuing the test or it might destroy messages we wait later on (Bug
   // 1270234).
-  const cleared = hud.jsterm.once("messages-cleared");
+  const cleared = hud.ui.once("messages-cleared");
 
   gBrowser.goBack();
 
   info("Waiting for messages-cleared event due to navigation");
   await cleared;
 
   info("Messages cleared after navigation; checking location");
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_script_errordoc_urls.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_script_errordoc_urls.js
@@ -61,10 +61,10 @@ async function testScriptError(hud, test
   // but have the URL in the title attribute.
   const hrefs = new Set();
   for (const link of hud.ui.outputNode.querySelectorAll("a")) {
     hrefs.add(link.title);
   }
 
   ok(hrefs.has(url), `Expected a link to ${url}.`);
 
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
 }
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_select_all.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_select_all.js
@@ -18,17 +18,17 @@ add_task(async function testSelectAll() 
   testBrowserMenuSelectAll(hud);
   await testContextMenuSelectAll(hud);
 });
 
 async function testSelectionWhenMovingBetweenBoxes(hud) {
   const jsterm = hud.jsterm;
 
   // Fill the console with some output.
-  jsterm.clearOutput();
+  hud.ui.clearOutput();
   await jsterm.execute("1 + 2");
   await waitFor(() => findMessage(hud, "3"));
   await jsterm.execute("3 + 4");
   await waitFor(() => findMessage(hud, "7"));
   await jsterm.execute("5 + 6");
   await waitFor(() => findMessage(hud, "11"));
 }
 
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_show_subresource_security_errors.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_show_subresource_security_errors.js
@@ -10,15 +10,15 @@
 const TEST_URI = "data:text/html;charset=utf-8,Web Console subresource STS " +
                  "warning test";
 const TEST_DOC = "https://example.com/browser/devtools/client/webconsole/" +
                  "test/mochitest/test-subresource-security-error.html";
 const SAMPLE_MSG = "specified a header that could not be parsed successfully.";
 
 add_task(async function() {
   const hud = await openNewTabAndConsole(TEST_URI);
-  hud.jsterm.clearOutput();
+  hud.ui.clearOutput();
   await loadDocument(TEST_DOC);
 
   await waitFor(() => findMessage(hud, SAMPLE_MSG, ".message.warn"));
 
   ok(true, "non-toplevel security warning message was displayed");
 });
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_time_methods.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_time_methods.js
@@ -50,17 +50,17 @@ add_task(async function() {
   // We use this await to 'sync' until the message appears, as the console API
   // guarantees us that the smoke signal will be printed after the message for
   // console.time("bTimer") (if there were any)
   await waitFor(() => findMessage(hud2, "smoke signal"));
 
   is(findMessage(hud2, "bTimer started"), null, "No message is printed to "
     + "the console when the timer starts");
 
-  hud2.jsterm.clearOutput();
+  hud2.ui.clearOutput();
 
   // Calling console.time('bTimer') on a page, then navigating to another page
   // and calling console.timeEnd('bTimer') on the new console front-end should
   // result on a warning message: 'Timer "bTimer" does not exist',
   // as the timers in different pages are not related
   await BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_URI4);
 
   const error2 =
--- a/devtools/client/webconsole/test/mochitest/head.js
+++ b/devtools/client/webconsole/test/mochitest/head.js
@@ -41,17 +41,17 @@ registerCleanupFunction(async function()
   // filter prefs has been pushed for the test
   await SpecialPowers.flushPrefEnv();
   Services.prefs.getChildList("devtools.webconsole.filter").forEach(pref => {
     Services.prefs.clearUserPref(pref);
   });
   const browserConsole = HUDService.getBrowserConsole();
   if (browserConsole) {
     if (browserConsole.jsterm) {
-      browserConsole.jsterm.clearOutput(true);
+      browserConsole.jsterm.hud.clearOutput(true);
     }
     await HUDService.toggleBrowserConsole();
   }
 });
 
 /**
  * Add a new tab and open the toolbox in it, and select the webconsole.
  *
--- a/devtools/client/webconsole/webconsole-connection-proxy.js
+++ b/devtools/client/webconsole/webconsole-connection-proxy.js
@@ -382,17 +382,17 @@ WebConsoleConnectionProxy.prototype = {
    * @private
    * @param string type
    *        Message type.
    * @param object packet
    *        The message received from the server.
    */
   _onLastPrivateContextExited: function(type, packet) {
     if (this.webConsoleFrame && packet.from == this._consoleActor) {
-      this.webConsoleFrame.jsterm.clearPrivateMessages();
+      this.webConsoleFrame.clearPrivateMessages();
     }
   },
 
   /**
    * The "navigate" event handlers. We redirect any message to the UI for displaying.
    *
    * @private
    * @param object packet
--- a/devtools/client/webconsole/webconsole-frame.js
+++ b/devtools/client/webconsole/webconsole-frame.js
@@ -118,16 +118,49 @@ WebConsoleFrame.prototype = {
       this.proxy = null;
     } else {
       onDestroy();
     }
 
     return this._destroyer.promise;
   },
 
+  /**
+   * Clear the Web Console output.
+   *
+   * This method emits the "messages-cleared" notification.
+   *
+   * @param boolean clearStorage
+   *        True if you want to clear the console messages storage associated to
+   *        this Web Console.
+   */
+  clearOutput(clearStorage) {
+    if (this.consoleOutput) {
+      this.consoleOutput.dispatchMessagesClear();
+    }
+    this.webConsoleClient.clearNetworkRequests();
+    if (clearStorage) {
+      this.webConsoleClient.clearMessagesCache();
+    }
+    this.jsterm.focus();
+    this.emit("messages-cleared");
+  },
+
+  /**
+   * Remove all of the private messages from the Web Console output.
+   *
+   * This method emits the "private-messages-cleared" notification.
+   */
+  clearPrivateMessages() {
+    if (this.consoleOutput) {
+      this.consoleOutput.dispatchPrivateMessagesClear();
+      this.emit("private-messages-cleared");
+    }
+  },
+
   _onUpdateListeners() {
 
   },
 
   logWarningAboutReplacedAPI() {
     this.owner.target.logWarningInPage(l10n.getStr("ConsoleAPIDisabled"),
       "ConsoleAPIDisabled");
   },
@@ -233,17 +266,17 @@ WebConsoleFrame.prototype = {
 
     let clearShortcut;
     if (AppConstants.platform === "macosx") {
       clearShortcut = l10n.getStr("webconsole.clear.keyOSX");
     } else {
       clearShortcut = l10n.getStr("webconsole.clear.key");
     }
 
-    shortcuts.on(clearShortcut, () => this.jsterm.clearOutput(true));
+    shortcuts.on(clearShortcut, () => this.clearOutput(true));
 
     if (this.isBrowserConsole) {
       // Make sure keyboard shortcuts work immediately after opening
       // the Browser Console (Bug 1461366).
       this.window.focus();
 
       shortcuts.on(l10n.getStr("webconsole.close.key"),
                    this.window.top.close.bind(this.window.top));
@@ -333,17 +366,17 @@ WebConsoleFrame.prototype = {
   },
 
   handleTabWillNavigate: function(packet) {
     if (this.persistLog) {
       // Add a _type to hit convertCachedPacket.
       packet._type = true;
       this.consoleOutput.dispatchMessageAdd(packet);
     } else {
-      this.jsterm.clearOutput(false);
+      this.clearOutput(false);
     }
 
     if (packet.url) {
       this.onLocationChange(packet.url, packet.title);
     }
   }
 };