Revert "Backed out changeset edc506b37439 (bug 1495300) for failing at /browser_toolbox_options_disable_buttons.js on a CLOSED TREE"
authorJason Laster <jlaster@mozilla.com>
Fri, 05 Oct 2018 10:28:19 -0400
changeset 439787 e1fb734d457b2bbd0aadd9c981319809d4aae5fa
parent 439786 1638774724799ea8eb692868a2c501d088839a2c
child 439788 708061fd15ce14baa5d4f8f79be874a77119359a
push id108669
push userjlaster@mozilla.com
push dateFri, 05 Oct 2018 14:29:43 +0000
treeherdermozilla-inbound@e1fb734d457b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1495300
milestone64.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
Revert "Backed out changeset edc506b37439 (bug 1495300) for failing at /browser_toolbox_options_disable_buttons.js on a CLOSED TREE" This reverts commit f42585540c95dd9a2874a75f0a10125a313979f9.
browser/base/content/tabbrowser.js
devtools/client/definitions.js
devtools/client/framework/target.js
devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
devtools/client/jar.mn
devtools/client/locales/en-US/startup.properties
devtools/client/themes/images/command-replay.svg
devtools/client/themes/toolbox.css
devtools/client/webreplay/menu.js
modules/libpref/init/all.js
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1596,16 +1596,18 @@ window._gBrowser = {
     }
 
     if (recordExecution) {
       aBrowser.setAttribute("recordExecution", recordExecution);
 
       // Web Replay middleman processes need the default URL to be loaded in
       // order to set up their rendering state.
       aBrowser.setAttribute("nodefaultsrc", "false");
+    } else if (aBrowser.hasAttribute("recordExecution")) {
+      aBrowser.removeAttribute("recordExecution");
     }
 
     // NB: This works with the hack in the browser constructor that
     // turns this normal property into a field.
     if (sameProcessAsFrameLoader) {
       // Always set sameProcessAsFrameLoader when passed in explicitly.
       aBrowser.sameProcessAsFrameLoader = sameProcessAsFrameLoader;
     } else if (!aShouldBeRemote || oldRemoteType == remoteType) {
--- a/devtools/client/definitions.js
+++ b/devtools/client/definitions.js
@@ -21,16 +21,18 @@ loader.lazyGetter(this, "MemoryPanel", (
 loader.lazyGetter(this, "PerformancePanel", () => require("devtools/client/performance/panel").PerformancePanel);
 loader.lazyGetter(this, "NewPerformancePanel", () => require("devtools/client/performance-new/panel").PerformancePanel);
 loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/client/netmonitor/panel").NetMonitorPanel);
 loader.lazyGetter(this, "StoragePanel", () => require("devtools/client/storage/panel").StoragePanel);
 loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/client/scratchpad/panel").ScratchpadPanel);
 loader.lazyGetter(this, "DomPanel", () => require("devtools/client/dom/panel").DomPanel);
 loader.lazyGetter(this, "AccessibilityPanel", () => require("devtools/client/accessibility/panel").AccessibilityPanel);
 loader.lazyGetter(this, "ApplicationPanel", () => require("devtools/client/application/panel").ApplicationPanel);
+loader.lazyGetter(this, "reloadAndRecordTab", () => require("devtools/client/webreplay/menu.js").reloadAndRecordTab);
+loader.lazyGetter(this, "reloadAndStopRecordingTab", () => require("devtools/client/webreplay/menu.js").reloadAndStopRecordingTab);
 
 // Other dependencies
 loader.lazyRequireGetter(this, "AccessibilityStartup", "devtools/client/accessibility/accessibility-startup", true);
 loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
 loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
 loader.lazyRequireGetter(this, "getScreenshotFront", "resource://devtools/shared/fronts/screenshot", true);
 
 const {MultiLocalizationHelper} = require("devtools/shared/l10n");
@@ -529,16 +531,36 @@ exports.ToolboxButtons = [
   },
   { id: "command-button-scratchpad",
     description: l10n("toolbox.buttons.scratchpad"),
     isTargetSupported: target => target.isLocalTab,
     onClick(event, toolbox) {
       ScratchpadManager.openScratchpad();
     }
   },
+  {
+    id: "command-button-replay",
+    description: l10n("toolbox.buttons.replay"),
+    isTargetSupported: target =>
+      Services.prefs.getBoolPref("devtools.recordreplay.mvp.enabled")
+      && !target.canRewind
+      && target.isLocalTab,
+    onClick: () => reloadAndRecordTab(),
+    isChecked: () => false
+  },
+  {
+    id: "command-button-stop-replay",
+    description: l10n("toolbox.buttons.stopReplay"),
+    isTargetSupported: target =>
+      Services.prefs.getBoolPref("devtools.recordreplay.mvp.enabled")
+      && target.canRewind
+      && target.isLocalTab,
+    onClick: () => reloadAndStopRecordingTab(),
+    isChecked: () => true
+  },
   { id: "command-button-responsive",
     description: l10n("toolbox.buttons.responsive",
                       osString == "Darwin" ? "Cmd+Opt+M" : "Ctrl+Shift+M"),
     isTargetSupported: target => target.isLocalTab,
     onClick(event, toolbox) {
       const tab = toolbox.target.tab;
       const browserWindow = tab.ownerDocument.defaultView;
       ResponsiveUIManager.toggle(browserWindow, tab, { trigger: "toolbox" });
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -441,16 +441,20 @@ TabTarget.prototype = {
   get isLocalTab() {
     return !!this._tab;
   },
 
   get isMultiProcess() {
     return !this.window;
   },
 
+  get canRewind() {
+    return this.activeTab.traits.canRewind;
+  },
+
   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);
@@ -842,16 +846,20 @@ WorkerTarget.prototype = {
   get activeConsole() {
     return this.client._clients.get(this.form.consoleActor);
   },
 
   get client() {
     return this._workerClient.client;
   },
 
+  get canRewind() {
+    return false;
+  },
+
   destroy: function() {
     this._workerClient.detach();
   },
 
   hasActor: function(name) {
     // console is the only one actor implemented by WorkerTargetActor
     if (name == "console") {
       return true;
--- a/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
@@ -67,52 +67,54 @@ function testPreferenceAndUIStateIsConsi
   for (const tool of toolbox.toolbarButtons) {
     const isVisible = getBoolPref(tool.visibilityswitch);
 
     const button = toolboxButtonNodes.find(toolboxButton => toolboxButton.id === tool.id);
     is(!!button, isVisible,
       "Button visibility matches pref for " + tool.id);
 
     const check = checkNodes.filter(node => node.id === tool.id)[0];
-    is(check.checked, isVisible,
-      "Checkbox should be selected based on current pref for " + tool.id);
+    if (check) {
+      is(check.checked, isVisible,
+        "Checkbox should be selected based on current pref for " + tool.id);
+    }
   }
 }
 
 function testToggleToolboxButtons() {
   const checkNodes = [...panelWin.document.querySelectorAll(
     "#enabled-toolbox-buttons-box input[type=checkbox]")];
 
   const visibleToolbarButtons = toolbox.toolbarButtons.filter(tool => tool.isVisible);
 
   const toolbarButtonNodes = [...doc.querySelectorAll(".command-button")];
 
-  is(checkNodes.length, toolbox.toolbarButtons.length,
+  // NOTE: the web-replay buttons are not checkboxes
+  is(checkNodes.length + 2, toolbox.toolbarButtons.length,
     "All of the buttons are toggleable.");
   is(visibleToolbarButtons.length, toolbarButtonNodes.length,
     "All of the DOM buttons are toggleable.");
 
   for (const tool of toolbox.toolbarButtons) {
     const id = tool.id;
     const matchedCheckboxes = checkNodes.filter(node => node.id === id);
     const matchedButtons = toolbarButtonNodes.filter(button => button.id === id);
-    is(matchedCheckboxes.length, 1,
-      "There should be a single toggle checkbox for: " + id);
     if (tool.isVisible) {
+      is(matchedCheckboxes.length, 1,
+        "There should be a single toggle checkbox for: " + id);
+      is(matchedCheckboxes[0].nextSibling.textContent, tool.description,
+        "The label for checkbox matches the tool definition.");
       is(matchedButtons.length, 1,
         "There should be a DOM button for the visible: " + id);
       is(matchedButtons[0].getAttribute("title"), tool.description,
         "The tooltip for button matches the tool definition.");
     } else {
       is(matchedButtons.length, 0,
         "There should not be a DOM button for the invisible: " + id);
     }
-
-    is(matchedCheckboxes[0].nextSibling.textContent, tool.description,
-      "The label for checkbox matches the tool definition.");
   }
 
   // Store modified pref names so that they can be cleared on error.
   for (const tool of toolbox.toolbarButtons) {
     const pref = tool.visibilityswitch;
     modifiedPrefs.push(pref);
   }
 
@@ -132,17 +134,21 @@ function testToggleToolboxButtons() {
       "Clicking on the node should have toggled visibility preference for " +
       tool.visibilityswitch);
   }
 
   return promise.resolve();
 }
 
 function getBoolPref(key) {
-  return Services.prefs.getBoolPref(key);
+  try {
+    return Services.prefs.getBoolPref(key);
+  } catch (e) {
+    return false;
+  }
 }
 
 function cleanup() {
   toolbox.destroy().then(function() {
     gBrowser.removeCurrentTab();
     for (const pref of modifiedPrefs) {
       Services.prefs.clearUserPref(pref);
     }
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -139,16 +139,17 @@ devtools.jar:
     skin/images/filetypes/dir-open.svg (themes/images/filetypes/dir-open.svg)
     skin/images/filetypes/globe.svg (themes/images/filetypes/globe.svg)
     skin/images/alerticon-warning.png (themes/images/alerticon-warning.png)
     skin/images/alerticon-warning@2x.png (themes/images/alerticon-warning@2x.png)
     skin/rules.css (themes/rules.css)
     skin/images/command-paintflashing.svg (themes/images/command-paintflashing.svg)
     skin/images/command-screenshot.svg (themes/images/command-screenshot.svg)
     skin/images/command-responsivemode.svg (themes/images/command-responsivemode.svg)
+    skin/images/command-replay.svg (themes/images/command-replay.svg)
     skin/images/command-pick.svg (themes/images/command-pick.svg)
     skin/images/command-pick-accessibility.svg (themes/images/command-pick-accessibility.svg)
     skin/images/command-frames.svg (themes/images/command-frames.svg)
     skin/images/command-console.svg (themes/images/command-console.svg)
     skin/images/command-eyedropper.svg (themes/images/command-eyedropper.svg)
     skin/images/command-rulers.svg (themes/images/command-rulers.svg)
     skin/images/command-measure.svg (themes/images/command-measure.svg)
     skin/images/command-noautohide.svg (themes/images/command-noautohide.svg)
--- a/devtools/client/locales/en-US/startup.properties
+++ b/devtools/client/locales/en-US/startup.properties
@@ -283,16 +283,26 @@ application.panelLabel=Application Panel
 application.tooltip=Application Panel
 
 # LOCALIZATION NOTE (toolbox.buttons.responsive):
 # This is the tooltip of the button in the toolbox toolbar that toggles
 # the Responsive mode.
 # Keyboard shortcut will be shown inside brackets.
 toolbox.buttons.responsive = Responsive Design Mode (%S)
 
+# LOCALIZATION NOTE (toolbox.buttons.replay):
+# This is the tooltip of the button in the toolbox toolbar that enables
+# the web replay record feature.
+toolbox.buttons.replay = Enable WebReplay
+
+# LOCALIZATION NOTE (toolbox.buttons.stopReplay):
+# This is the tooltip of the button in the toolbox toolbar that dissables
+# the web replay feature.
+toolbox.buttons.stopReplay = Disable WebReplay
+
 # LOCALIZATION NOTE (toolbox.buttons.paintflashing):
 # This is the tooltip of the paintflashing button in the toolbox toolbar
 # that toggles paintflashing.
 toolbox.buttons.paintflashing = Toggle paint flashing
 
 # LOCALIZATION NOTE (toolbox.buttons.scratchpad):
 # This is the tooltip of the button in the toolbox toolbar that opens
 # the scratchpad window
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/command-replay.svg
@@ -0,0 +1,7 @@
+<!-- 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/. -->
+<svg width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="context-fill #0b0b0b">
+	<circle id="Oval" cx="10" cy="10" r="6"></circle>
+	<path d="M10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 Z M10,18 C14.418278,18 18,14.418278 18,10 C18,5.581722 14.418278,2 10,2 C5.581722,2 2,5.581722 2,10 C2,14.418278 5.581722,18 10,18 Z" id="Combined-Shape"></path>
+</svg>
\ No newline at end of file
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -12,16 +12,17 @@
   --more-button-image: url(chrome://devtools/skin/images/more.svg);
   --settings-image: url(chrome://devtools/skin/images/tool-options-photon.svg);
 
   --command-noautohide-image: url(images/command-noautohide.svg);
   --command-console-image: url(images/command-console.svg);
   --command-paintflashing-image: url(images/command-paintflashing.svg);
   --command-screenshot-image: url(images/command-screenshot.svg);
   --command-responsive-image: url(images/command-responsivemode.svg);
+  --command-replay-image: url(images/command-replay.svg);
   --command-scratchpad-image: url(images/tool-scratchpad.svg);
   --command-pick-image: url(images/command-pick.svg);
   --command-pick-accessibility-image: url(images/command-pick-accessibility.svg);
   --command-frames-image: url(images/command-frames.svg);
   --command-rulers-image: url(images/command-rulers.svg);
   --command-measure-image: url(images/command-measure.svg);
   --command-chevron-image: url(images/command-chevron.svg);
 }
@@ -286,16 +287,37 @@
   fill: var(--theme-toolbar-photon-icon-color);
   -moz-context-properties: fill;
 }
 
 #command-button-responsive.checked::before {
   fill: currentColor;
 }
 
+#command-button-stop-replay::before, #command-button-replay::before {
+  background-image: var(--command-replay-image);
+  fill: var(--theme-toolbar-photon-icon-color);
+  -moz-context-properties: fill;
+  background-repeat: no-repeat;
+  height: 16px;
+  background-size: contain;
+}
+
+#command-button-replay, #command-button-stop-replay {
+  background-color: transparent;
+}
+
+#command-button-replay:hover, #command-button-stop-replay:hover {
+  background: var(--toolbarbutton-background);
+}
+
+#command-button-stop-replay::before {
+  fill: currentColor;
+}
+
 #command-button-scratchpad::before {
   background-image: var(--command-scratchpad-image);
 }
 
 #command-button-pick::before {
   background-image: var(--command-pick-image);
 }
 
--- a/devtools/client/webreplay/menu.js
+++ b/devtools/client/webreplay/menu.js
@@ -28,16 +28,26 @@ function ReloadAndRecordTab() {
   const url = gBrowser.currentURI.spec;
   gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true,
                                    { recordExecution: "*", newFrameloader: true });
   gBrowser.loadURI(url, {
     triggeringPrincipal: gBrowser.selectedBrowser.contentPrincipal,
   });
 }
 
+function ReloadAndStopRecordingTab() {
+  const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
+  const url = gBrowser.currentURI.spec;
+  gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true,
+                                   { newFrameloader: true });
+  gBrowser.loadURI(url, {
+    triggeringPrincipal: gBrowser.selectedBrowser.contentPrincipal,
+  });
+}
+
 function SaveRecording() {
   const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
   const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
   const window = gBrowser.ownerGlobal;
   fp.init(window, null, Ci.nsIFilePicker.modeSave);
   fp.open(rv => {
     if (rv == Ci.nsIFilePicker.returnOK || rv == Ci.nsIFilePicker.returnReplace) {
       const tabParent = gBrowser.selectedTab.linkedBrowser.frameLoader.tabParent;
@@ -85,8 +95,11 @@ exports.addWebReplayMenu = function(doc)
     popup.appendChild(menuitem);
   }
 
   const mds = doc.getElementById("menu_devtools_separator");
   if (mds) {
     mds.parentNode.insertBefore(menu, mds);
   }
 };
+
+exports.reloadAndRecordTab = ReloadAndRecordTab;
+exports.reloadAndStopRecordingTab = ReloadAndStopRecordingTab;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1086,16 +1086,18 @@ pref("browser.dom.window.dump.enabled", 
 pref("toolkit.dump.emit", false);
 
 // Enable recording/replaying executions.
 #if defined(XP_MACOSX) && defined(NIGHTLY_BUILD)
 pref("devtools.recordreplay.enabled", true);
 pref("devtools.recordreplay.enableRewinding", true);
 #endif
 
+pref("devtools.recordreplay.mvp.enabled", false);
+
 // view source
 pref("view_source.syntax_highlight", true);
 pref("view_source.wrap_long_lines", false);
 pref("view_source.editor.path", "");
 // allows to add further arguments to the editor; use the %LINE% placeholder
 // for jumping to a specific line (e.g. "/line:%LINE%" or "--goto %LINE%")
 pref("view_source.editor.args", "");