Bug 1274032 - Show notification when opening RDM on non-remote tabs. r=gl draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 12 Aug 2016 17:09:29 -0500
changeset 403427 3fb483999b3ff45aa254b24eee33ec5e182c605f
parent 399408 0502bd9e025edde29777ba1de4280f9b52af4663
child 528908 4c48b686ffdc6e31d17fc47787108ed95a2ad16b
push id26915
push userbmo:jryans@gmail.com
push dateFri, 19 Aug 2016 20:17:15 +0000
reviewersgl
bugs1274032
milestone51.0a1
Bug 1274032 - Show notification when opening RDM on non-remote tabs. r=gl MozReview-Commit-ID: DGDuM6jobbG
devtools/client/locales/en-US/responsive.properties
devtools/client/responsive.html/manager.js
--- a/devtools/client/locales/en-US/responsive.properties
+++ b/devtools/client/locales/en-US/responsive.properties
@@ -48,8 +48,13 @@ responsive.disableTouch=Disable touch si
 # LOCALIZATION NOTE  (responsive.screenshot): tooltip of the screenshot button.
 responsive.screenshot=Take a screenshot of the viewport
 
 # LOCALIZATION NOTE (responsive.screenshotGeneratedFilename): The auto generated
 # filename.
 # The first argument (%1$S) is the date string in yyyy-mm-dd format and the
 # second argument (%2$S) is the time string in HH.MM.SS format.
 responsive.screenshotGeneratedFilename=Screen Shot %1$S at %2$S
+
+# LOCALIZATION NOTE (responsive.remoteOnly): Message displayed in the tab's
+# notification box if a user tries to open Responsive Design Mode in a
+# non-remote tab.
+responsive.remoteOnly=Responsive Design Mode is only available for remote browser tabs, such as those used for web content in multi-process Firefox.
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -7,16 +7,19 @@
 const promise = require("promise");
 const { Task } = require("devtools/shared/task");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { TouchEventSimulator } = require("devtools/shared/touch/simulator");
 const { getOwnerWindow } = require("sdk/tabs/utils");
 const { startup } = require("sdk/window/helpers");
 const message = require("./utils/message");
 const { swapToInnerBrowser } = require("./browser/swap");
+const { getStr } = require("./utils/l10n");
+const { TargetFactory } = require("devtools/client/framework/target");
+const { gDevTools } = require("devtools/client/framework/devtools");
 
 const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
 
 /**
  * ResponsiveUIManager is the external API for the browser UI, etc. to use when
  * opening and closing the responsive UI.
  *
  * While the HTML UI is in an experimental stage, the older ResponsiveUIManager
@@ -28,41 +31,48 @@ const ResponsiveUIManager = exports.Resp
 
   /**
    * Toggle the responsive UI for a tab.
    *
    * @param window
    *        The main browser chrome window.
    * @param tab
    *        The browser tab.
+   * @param options
+   *        Other options associated with toggling.  Currently includes:
+   *        - `command`: Whether initiated via GCLI command bar or toolbox button
    * @return Promise
    *         Resolved when the toggling has completed.  If the UI has opened,
    *         it is resolved to the ResponsiveUI instance for this tab.  If the
    *         the UI has closed, there is no resolution value.
    */
-  toggle(window, tab) {
+  toggle(window, tab, options) {
     let action = this.isActiveForTab(tab) ? "close" : "open";
-    let completed = this[action + "IfNeeded"](window, tab);
+    let completed = this[action + "IfNeeded"](window, tab, options);
     completed.catch(console.error);
     return completed;
   },
 
   /**
    * Opens the responsive UI, if not already open.
    *
    * @param window
    *        The main browser chrome window.
    * @param tab
    *        The browser tab.
+   * @param options
+   *        Other options associated with opening.  Currently includes:
+   *        - `command`: Whether initiated via GCLI command bar or toolbox button
    * @return Promise
    *         Resolved to the ResponsiveUI instance for this tab when opening is
    *         complete.
    */
-  openIfNeeded: Task.async(function* (window, tab) {
+  openIfNeeded: Task.async(function* (window, tab, options) {
     if (!tab.linkedBrowser.isRemoteBrowser) {
+      this.showRemoteOnlyNotification(window, tab, options);
       return promise.reject(new Error("RDM only available for remote tabs."));
     }
     if (!this.isActiveForTab(tab)) {
       this.initMenuCheckListenerFor(window);
 
       let ui = new ResponsiveUI(window, tab);
       this.activeTabs.set(tab, ui);
       yield this.setMenuCheckFor(tab, window);
@@ -75,18 +85,20 @@ const ResponsiveUIManager = exports.Resp
 
   /**
    * Closes the responsive UI, if not already closed.
    *
    * @param window
    *        The main browser chrome window.
    * @param tab
    *        The browser tab.
-   * @param object
-   *        Close options, which currently includes a `reason` string.
+   * @param options
+   *        Other options associated with closing.  Currently includes:
+   *        - `command`: Whether initiated via GCLI command bar or toolbox button
+   *        - `reason`: String detailing the specific cause for closing
    * @return Promise
    *         Resolved (with no value) when closing is complete.
    */
   closeIfNeeded: Task.async(function* (window, tab, options) {
     if (this.isActiveForTab(tab)) {
       let ui = this.activeTabs.get(tab);
       let destroyed = yield ui.destroy(options);
       if (!destroyed) {
@@ -148,27 +160,27 @@ const ResponsiveUIManager = exports.Resp
    *        The GCLI command name.
    * @param args
    *        The GCLI command arguments.
    */
   handleGcliCommand(window, tab, command, args) {
     let completed;
     switch (command) {
       case "resize to":
-        completed = this.openIfNeeded(window, tab);
+        completed = this.openIfNeeded(window, tab, { command: true });
         this.activeTabs.get(tab).setViewportSize(args.width, args.height);
         break;
       case "resize on":
-        completed = this.openIfNeeded(window, tab);
+        completed = this.openIfNeeded(window, tab, { command: true });
         break;
       case "resize off":
-        completed = this.closeIfNeeded(window, tab);
+        completed = this.closeIfNeeded(window, tab, { command: true });
         break;
       case "resize toggle":
-        completed = this.toggle(window, tab);
+        completed = this.toggle(window, tab, { command: true });
         break;
       default:
     }
     completed.catch(e => console.error(e));
   },
 
   handleMenuCheck({target}) {
     ResponsiveUIManager.setMenuCheckFor(target);
@@ -188,17 +200,46 @@ const ResponsiveUIManager = exports.Resp
 
   setMenuCheckFor: Task.async(function* (tab, window = getOwnerWindow(tab)) {
     yield startup(window);
 
     let menu = window.document.getElementById("menu_responsiveUI");
     if (menu) {
       menu.setAttribute("checked", this.isActiveForTab(tab));
     }
-  })
+  }),
+
+  showRemoteOnlyNotification(window, tab, { command } = {}) {
+    // Default to using the browser's per-tab notification box
+    let nbox = window.gBrowser.getNotificationBox(tab.linkedBrowser);
+
+    // If opening was initiated by GCLI command bar or toolbox button, check for an open
+    // toolbox for the tab.  If one exists, use the toolbox's notification box so that the
+    // message is placed closer to the action taken by the user.
+    if (command) {
+      let target = TargetFactory.forTab(tab);
+      let toolbox = gDevTools.getToolbox(target);
+      if (toolbox) {
+        nbox = toolbox.notificationBox;
+      }
+    }
+
+    let value = "devtools-responsive-remote-only";
+    if (nbox.getNotificationWithValue(value)) {
+      // Notification already displayed
+      return;
+    }
+
+    nbox.appendNotification(
+       getStr("responsive.remoteOnly"),
+       value,
+       null,
+       nbox.PRIORITY_CRITICAL_MEDIUM,
+       []);
+  },
 };
 
 // GCLI commands in ../responsivedesign/resize-commands.js listen for events
 // from this object to know when the UI for a tab has opened or closed.
 EventEmitter.decorate(ResponsiveUIManager);
 
 /**
  * ResponsiveUI manages the responsive design tool for a specific tab.  The