Bug 1510408 - Closing devtools should stop recording. r=bhackett
authorJason Laster <jlaster@mozilla.com>
Fri, 30 Nov 2018 01:28:14 +0000
changeset 505498 7b419fe2aaef1c8c7e1ffdedb66c09187728cdb9
parent 505497 ae07b833833146811d507abd3166794be91b1fa4
child 505499 0a07b04b44833ef2e543458c5ae5a60a0a6f648d
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1510408
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1510408 - Closing devtools should stop recording. r=bhackett Differential Revision: https://phabricator.services.mozilla.com/D13145
devtools/client/debugger/new/test/mochitest/browser_dbg_rr_breakpoints-01.js
devtools/client/framework/components/ToolboxToolbar.js
devtools/client/framework/target.js
devtools/client/framework/toolbox.js
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg_rr_breakpoints-01.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg_rr_breakpoints-01.js
@@ -32,12 +32,12 @@ async function test() {
   await checkEvaluateInTopFrame(client, "number", 7);
   await resumeToLine(client, 21);
   await checkEvaluateInTopFrame(client, "number", 8);
   await resumeToLine(client, 21);
   await checkEvaluateInTopFrame(client, "number", 9);
   await resumeToLine(client, 21);
   await checkEvaluateInTopFrame(client, "number", 10);
 
-  await toolbox.destroy();
+  await toolbox.closeToolbox();
   await gBrowser.removeTab(tab);
   finish();
 }
--- a/devtools/client/framework/components/ToolboxToolbar.js
+++ b/devtools/client/framework/components/ToolboxToolbar.js
@@ -400,19 +400,17 @@ class ToolboxToolbar extends Component {
     const closeButtonId = "toolbox-close";
 
     const closeButton = canCloseToolbox
       ? button({
         id: closeButtonId,
         onFocus: () => focusButton(closeButtonId),
         className: "devtools-button",
         title: L10N.getStr("toolbox.closebutton.tooltip"),
-        onClick: () => {
-          closeToolbox();
-        },
+        onClick: () => closeToolbox(),
         tabIndex: focusedButton === "toolbox-close" ? "0" : "-1",
       })
       : null;
 
     return div({id: "toolbox-controls"},
       meatballMenuButton,
       closeButton
     );
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const EventEmitter = require("devtools/shared/event-emitter");
+const Services = require("Services");
 
 loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
 loader.lazyRequireGetter(this, "DebuggerClient",
   "devtools/shared/client/debugger-client", true);
 loader.lazyRequireGetter(this, "gDevTools",
   "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
 
@@ -467,16 +468,22 @@ Target.prototype = {
   get isMultiProcess() {
     return !this.window;
   },
 
   get canRewind() {
     return this.activeTab && this.activeTab.traits.canRewind;
   },
 
+  isReplayEnabled() {
+    return Services.prefs.getBoolPref("devtools.recordreplay.mvp.enabled")
+      && this.canRewind
+      && this.isLocalTab;
+  },
+
   getExtensionPathName(url) {
     // Return the url if the target is not a webextension.
     if (!this.isWebExtension) {
       throw new Error("Target is not a WebExtension");
     }
 
     try {
       const parsedURL = new URL(url);
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -68,16 +68,21 @@ loader.lazyRequireGetter(this, "createEd
 loader.lazyGetter(this, "domNodeConstants", () => {
   return require("devtools/shared/dom-node-constants");
 });
 
 loader.lazyGetter(this, "registerHarOverlay", () => {
   return require("devtools/client/netmonitor/src/har/toolbox-overlay").register;
 });
 
+loader.lazyGetter(this, "reloadAndRecordTab",
+  () => require("devtools/client/webreplay/menu.js").reloadAndRecordTab);
+loader.lazyGetter(this, "reloadAndStopRecordingTab",
+  () => require("devtools/client/webreplay/menu.js").reloadAndStopRecordingTab);
+
 /**
  * A "Toolbox" is the component that holds all the tools for one specific
  * target. Visually, it's a document that includes the tools tabs and all
  * the iframes where the tool panels will be living in.
  *
  * @param {object} target
  *        The object the toolbox is debugging.
  * @param {string} selectedTool
@@ -124,16 +129,17 @@ function Toolbox(target, selectedTool, h
 
   this._toolRegistered = this._toolRegistered.bind(this);
   this._toolUnregistered = this._toolUnregistered.bind(this);
   this._onWillNavigate = this._onWillNavigate.bind(this);
   this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this.toggleNoAutohide = this.toggleNoAutohide.bind(this);
   this._updateFrames = this._updateFrames.bind(this);
   this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this);
+  this.closeToolbox = this.closeToolbox.bind(this);
   this.destroy = this.destroy.bind(this);
   this.highlighterUtils = getHighlighterUtils(this);
   this._highlighterReady = this._highlighterReady.bind(this);
   this._highlighterHidden = this._highlighterHidden.bind(this);
   this._applyCacheSettings = this._applyCacheSettings.bind(this);
   this._applyServiceWorkersTestingSettings =
     this._applyServiceWorkersTestingSettings.bind(this);
   this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
@@ -925,17 +931,17 @@ Toolbox.prototype = {
                  });
     this.shortcuts.on(L10N.getStr("toolbox.toggleHost.key"),
                  event => {
                    this.switchToPreviousHost();
                    event.preventDefault();
                  });
 
     // Close toolbox key-shortcut handler
-    const onClose = event => this.destroy();
+    const onClose = event => this.closeToolbox();
     this.shortcuts.on(L10N.getStr("toolbox.toggleToolboxF12.key"), onClose);
 
     // CmdOrCtrl+W is registered only when the toolbox is running in
     // detached window. In the other case the entire browser tab
     // is closed when the user uses this shortcut.
     if (this.hostType == "window") {
       this.shortcuts.on(L10N.getStr("toolbox.closeToolbox.key"), onClose);
     }
@@ -1145,17 +1151,17 @@ Toolbox.prototype = {
     // Ensure the toolbar doesn't try to render until the tool is ready.
     const element = this.React.createElement(this.ToolboxController, {
       L10N,
       currentToolId: this.currentToolId,
       selectTool: this.selectTool,
       toggleOptions: this.toggleOptions,
       toggleSplitConsole: this.toggleSplitConsole,
       toggleNoAutohide: this.toggleNoAutohide,
-      closeToolbox: this.destroy,
+      closeToolbox: this.closeToolbox,
       focusButton: this._onToolbarFocus,
       toolbox: this,
       showDebugTargetInfo: this._showDebugTargetInfo,
       deviceDescription: this._deviceDescription,
       onTabsOrderUpdated: this._onTabsOrderUpdated,
     });
 
     this.component = this.ReactDOM.render(element, this._componentMount);
@@ -2174,17 +2180,16 @@ Toolbox.prototype = {
   },
 
   /**
    * Tells the target tab to reload.
    */
   reloadTarget: function(force) {
     if (this.target.canRewind) {
       // Recording tabs need to be reloaded in a new content process.
-      const { reloadAndRecordTab } = require("devtools/client/webreplay/menu");
       reloadAndRecordTab();
     } else {
       this.target.activeTab.reload({ force: force });
     }
   },
 
   /**
    * Loads the tool next to the currently selected tool.
@@ -2796,16 +2801,24 @@ Toolbox.prototype = {
    * Get the toolbox's notification component
    *
    * @return The notification box component.
    */
   getNotificationBox: function() {
     return this.notificationBox;
   },
 
+  closeToolbox: async function() {
+    const shouldStopRecording = this.target.isReplayEnabled();
+    await this.destroy();
+    if (shouldStopRecording) {
+      reloadAndStopRecordingTab();
+    }
+  },
+
   /**
    * Remove all UI elements, detach from target and clear up
    */
   destroy: function() {
     // If several things call destroy then we give them all the same
     // destruction promise so we're sure to destroy only once
     if (this._destroyer) {
       return this._destroyer;