Bug 1438962 - Add diagnostics during Browser Toolbox startup. r=bgrins draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Wed, 21 Feb 2018 03:22:49 -0500
changeset 758031 2b72c22aa0bbb5efc780389fad8ada94d1ba6544
parent 758030 ead032c175f448b2f46b85be0347c70a6dd3fe6e
push id99921
push userbmo:jryans@gmail.com
push dateWed, 21 Feb 2018 19:42:05 +0000
reviewersbgrins
bugs1438962
milestone60.0a1
Bug 1438962 - Add diagnostics during Browser Toolbox startup. r=bgrins Track connection status at various points during Browser Toolbox startup. If connecting takes a long time or triggers an error, the status panel is revealed with the most recent message displayed. MozReview-Commit-ID: H8240rv3KRe
devtools/client/framework/toolbox-process-window.js
devtools/client/framework/toolbox-process-window.xul
devtools/client/locales/en-US/toolbox.dtd
--- a/devtools/client/framework/toolbox-process-window.js
+++ b/devtools/client/framework/toolbox-process-window.js
@@ -12,58 +12,76 @@ loader.require("devtools/client/framewor
 
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 var Services = require("Services");
 var { DebuggerClient } = require("devtools/shared/client/debugger-client");
 var { PrefsHelper } = require("devtools/client/shared/prefs");
 
+const STATUS_REVEAL_TIME = 5000;
+
 /**
  * Shortcuts for accessing various debugger preferences.
  */
 var Prefs = new PrefsHelper("devtools.debugger", {
   chromeDebuggingHost: ["Char", "chrome-debugging-host"],
   chromeDebuggingWebSocket: ["Bool", "chrome-debugging-websocket"],
 });
 
 var gToolbox, gClient;
 
+function appendStatusMessage(msg) {
+  let statusMessage = document.getElementById("status-message");
+  statusMessage.value += msg + "\n";
+  if (msg.stack) {
+    statusMessage.value += msg.stack + "\n";
+  }
+}
+
+function revealStatusMessage() {
+  let statusMessageContainer = document.getElementById("status-message-container");
+  statusMessageContainer.hidden = false;
+}
+
 var connect = async function () {
-  window.removeEventListener("load", connect);
-
   // Initiate the connection
   let env = Components.classes["@mozilla.org/process/environment;1"]
     .getService(Components.interfaces.nsIEnvironment);
   let port = env.get("MOZ_BROWSER_TOOLBOX_PORT");
   let addonID = env.get("MOZ_BROWSER_TOOLBOX_ADDONID");
 
   // A port needs to be passed in from the environment, for instance:
   //    MOZ_BROWSER_TOOLBOX_PORT=6080 ./mach run -chrome \
   //      chrome://devtools/content/framework/toolbox-process-window.xul
   if (!port) {
     throw new Error("Must pass a port in an env variable with MOZ_BROWSER_TOOLBOX_PORT");
   }
 
+  let host = Prefs.chromeDebuggingHost;
+  let webSocket = Prefs.chromeDebuggingWebSocket;
+  appendStatusMessage(`Connecting to ${host}:${port}, ws: ${webSocket}`);
   let transport = await DebuggerClient.socketConnect({
-    host: Prefs.chromeDebuggingHost,
+    host,
     port,
-    webSocket: Prefs.chromeDebuggingWebSocket,
+    webSocket,
   });
   gClient = new DebuggerClient(transport);
+  appendStatusMessage("Start protocol client for connection");
   await gClient.connect();
 
+  appendStatusMessage("Get root form for toolbox");
   if (addonID) {
     let { addons } = await gClient.listAddons();
     let addonActor = addons.filter(addon => addon.id === addonID).pop();
     let isTabActor = addonActor.isWebExtension;
-    openToolbox({form: addonActor, chrome: true, isTabActor});
+    await openToolbox({form: addonActor, chrome: true, isTabActor});
   } else {
     let response = await gClient.getProcess();
-    openToolbox({form: response.form, chrome: true});
+    await openToolbox({form: response.form, chrome: true});
   }
 };
 
 // Certain options should be toggled since we can assume chrome debugging here
 function setPrefDefaults() {
   Services.prefs.setBoolPref("devtools.inspector.showUserAgentStyles", true);
   Services.prefs.setBoolPref("devtools.performance.ui.show-platform-data", true);
   Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
@@ -76,49 +94,54 @@ function setPrefDefaults() {
   Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
   Services.prefs.setBoolPref("devtools.preference.new-panel-enabled", false);
   Services.prefs.setBoolPref("layout.css.emulate-moz-box-with-flex", false);
 }
 window.addEventListener("load", async function () {
   let cmdClose = document.getElementById("toolbox-cmd-close");
   cmdClose.addEventListener("command", onCloseCommand);
   setPrefDefaults();
+  // Reveal status message if connecting is slow or if an error occurs
+  let delayedStatusReveal = setTimeout(() => {
+    revealStatusMessage();
+  }, STATUS_REVEAL_TIME);
   try {
     await connect();
+    clearTimeout(delayedStatusReveal);
   } catch (e) {
-    let errorMessageContainer = document.getElementById("error-message-container");
-    let errorMessage = document.getElementById("error-message");
-    errorMessage.value = e.message || e;
-    errorMessageContainer.hidden = false;
+    appendStatusMessage(e);
+    revealStatusMessage();
     console.error(e);
   }
-});
+}, { once: true });
 
 function onCloseCommand(event) {
   window.close();
 }
 
 async function openToolbox({ form, chrome, isTabActor }) {
   let options = {
     form: form,
     client: gClient,
     chrome: chrome,
     isTabActor: isTabActor
   };
+  appendStatusMessage(`Create toolbox target: ${JSON.stringify(arguments, null, 2)}`);
   let target = await TargetFactory.forRemoteTab(options);
   let frame = document.getElementById("toolbox-iframe");
 
   // Remember the last panel that was used inside of this profile.
   // But if we are testing, then it should always open the debugger panel.
   let selectedTool =
     Services.prefs.getCharPref("devtools.browsertoolbox.panel",
       Services.prefs.getCharPref("devtools.toolbox.selectedTool",
                                   "jsdebugger"));
 
   options = { customIframe: frame };
+  appendStatusMessage(`Show toolbox with ${selectedTool} selected`);
   let toolbox = await gDevTools.showToolbox(
     target,
     selectedTool,
     Toolbox.HostType.CUSTOM,
     options
   );
   onNewToolbox(toolbox);
 }
--- a/devtools/client/framework/toolbox-process-window.xul
+++ b/devtools/client/framework/toolbox-process-window.xul
@@ -32,16 +32,16 @@
          command="toolbox-cmd-close"
          modifiers="accel"/>
   </keyset>
 
   <!-- This will be used by the Web Console to hold any popups it may create,
        for example when viewing network request details. -->
   <popupset id="mainPopupSet"></popupset>
 
-  <vbox id="error-message-container" hidden="true" flex="1">
-    <box>&browserToolboxErrorMessage;</box>
-    <textbox multiline="true" id="error-message" flex="1"></textbox>
+  <vbox id="status-message-container" hidden="true" flex="1">
+    <box>&browserToolboxStatusMessage;</box>
+    <textbox multiline="true" id="status-message" flex="1"></textbox>
   </vbox>
 
   <tooltip id="aHTMLTooltip" page="true"/>
   <iframe id="toolbox-iframe" flex="1" tooltip="aHTMLTooltip"></iframe>
 </window>
--- a/devtools/client/locales/en-US/toolbox.dtd
+++ b/devtools/client/locales/en-US/toolbox.dtd
@@ -5,19 +5,20 @@
 <!-- LOCALIZATION NOTE : FILE This file contains the Toolbox strings -->
 <!-- LOCALIZATION NOTE : FILE Do not translate key -->
 
 <!ENTITY closeCmd.key  "W">
 <!ENTITY toggleToolbox.key  "I">
 <!ENTITY toggleToolboxF12.keycode          "VK_F12">
 <!ENTITY toggleToolboxF12.keytext          "F12">
 
-<!-- LOCALIZATION NOTE (browserToolboxErrorMessage): This is the label
-  -  shown next to error details when the Browser Toolbox is unable to open. -->
-<!ENTITY browserToolboxErrorMessage          "Error opening Browser Toolbox:">
+<!-- LOCALIZATION NOTE (browserToolboxStatusMessage): This is the label
+  -  shown next to status details when the Browser Toolbox fails to connect or
+  -  appears to be taking a while to do so. -->
+<!ENTITY browserToolboxStatusMessage "Browser Toolbox connection status:">
 
 <!-- LOCALIZATION NOTE (options.context.advancedSettings): This is the label for
   -  the heading of the advanced settings group in the options panel. -->
 <!ENTITY options.context.advancedSettings "Advanced settings">
 
 <!-- LOCALIZATION NOTE (options.context.inspector): This is the label for
   -  the heading of the Inspector group in the options panel. -->
 <!ENTITY options.context.inspector "Inspector">