Bug 1495300 - Add a reload and record button. r=lsmyth
☠☠ backed out by a94aa2d9828f ☠ ☠
authorAnshul Malik <malikanshul29@gmail.com>
Thu, 04 Oct 2018 12:40:26 -0400
changeset 495470 edc506b37439bc118431d10e22159ffcf3c95ff1
parent 495469 1dda79799549eeee71c591c6f7fdda7bed1a3375
child 495471 3ff4a396300c717fe8d0e0288dee8cade03479d9
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsmyth
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
Bug 1495300 - Add a reload and record button. r=lsmyth Tags: #secure-revision Differential Revision: https://phabricator.services.mozilla.com/D7789
browser/base/content/tabbrowser.js
devtools/client/definitions.js
devtools/client/framework/target.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/jar.mn
+++ b/devtools/client/jar.mn
@@ -135,16 +135,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", "");