Bug 1522400: Set proper context menu items on about:devtools-toolbox page. r=jdescottes,mconley
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 13 Feb 2019 01:50:20 +0000
changeset 458837 1731ef0126f9a6d43f864a72b7773b547b74f290
parent 458836 86b52991b24a456913f4e91826a3db61d7852e69
child 458838 e32e036906b9573147bc59a533b4af0f4e3e6988
push id35548
push useropoprus@mozilla.com
push dateWed, 13 Feb 2019 09:48:26 +0000
treeherdermozilla-central@93e37c529818 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, mconley
bugs1522400
milestone67.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 1522400: Set proper context menu items on about:devtools-toolbox page. r=jdescottes,mconley Depends on D17458 Differential Revision: https://phabricator.services.mozilla.com/D17459
browser/actors/ContextMenuChild.jsm
browser/base/content/nsContextMenu.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_devtoolstoolbox_contextmenu.js
--- a/browser/actors/ContextMenuChild.jsm
+++ b/browser/actors/ContextMenuChild.jsm
@@ -701,16 +701,26 @@ class ContextMenuChild extends ActorChil
 
     if (node.nodeType == node.DOCUMENT_NODE ||
         // Don't display for XUL element unless <label class="text-link">
         (node.namespaceURI == XUL_NS && !this._isXULTextLinkLabel(node))) {
       context.shouldDisplay = false;
       return;
     }
 
+    const isAboutDevtoolsToolbox =
+          this.content.document.documentURI.startsWith("about:devtools-toolbox");
+    const editFlags = SpellCheckHelper.isEditable(node, this.content);
+
+    if (isAboutDevtoolsToolbox && (editFlags & SpellCheckHelper.TEXTINPUT) === 0) {
+      // Don't display for about:devtools-toolbox page unless the source was text input.
+      context.shouldDisplay = false;
+      return;
+    }
+
     // Initialize context to be sent to nsContextMenu
     // Keep this consistent with the similar code in nsContextMenu's setContext
     context.bgImageURL          = "";
     context.imageDescURL        = "";
     context.imageInfo           = null;
     context.mediaURL            = "";
     context.webExtBrowserType   = "";
 
@@ -759,26 +769,35 @@ class ContextMenuChild extends ActorChil
     context.frameOuterWindowID = WebNavigationFrames.getFrameId(context.target.ownerGlobal);
 
     // Check if we are in a synthetic document (stand alone image, video, etc.).
     context.inSyntheticDoc = context.target.ownerDocument.mozSyntheticDocument;
 
     context.shouldInitInlineSpellCheckerUINoChildren = false;
     context.shouldInitInlineSpellCheckerUIWithChildren = false;
 
-    let editFlags = SpellCheckHelper.isEditable(context.target, this.content);
     this._setContextForNodesNoChildren(editFlags);
     this._setContextForNodesWithChildren(editFlags);
 
     this.lastMenuTarget = {
       // Remember the node for extensions.
       targetRef: Cu.getWeakReference(node),
       // The timestamp is used to verify that the target wasn't changed since the observed menu event.
       timeStamp: context.timeStamp,
     };
+
+    if (isAboutDevtoolsToolbox) {
+      // Setup the menu items on text input in about:devtools-toolbox.
+      context.inAboutDevtoolsToolbox = true;
+      context.canSpellCheck = false;
+      context.inTabBrowser = false;
+      context.inFrame = false;
+      context.inSrcdocFrame = false;
+      context.onSpellcheckable = false;
+    }
   }
 
   /**
    * Sets up the parts of the context menu for when when nodes have no children.
    *
    * @param {Integer} editFlags The edit flags for the node. See SpellCheckHelper
    *                            for the details.
    */
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -220,16 +220,18 @@ nsContextMenu.prototype = {
 
     this.target = this.isRemote ? context.target : document.popupNode;
     this.targetAsCPOW = context.targetAsCPOW;
 
     this.principal = context.principal;
     this.frameOuterWindowID = context.frameOuterWindowID;
 
     this.inSyntheticDoc = context.inSyntheticDoc;
+    this.inAboutDevtoolsToolbox = context.inAboutDevtoolsToolbox;
+
 
     // Everything after this isn't sent directly from ContextMenu
     this.ownerDoc = this.target.ownerDocument;
 
     // Remember the CSS selectors corresponding to clicked node. gContextMenuContentData
     // can be null if the menu was triggered by tests in which case use an empty array.
     this.targetSelectors = gContextMenuContentData
                            ? gContextMenuContentData.popupNodeSelectors
@@ -418,33 +420,24 @@ nsContextMenu.prototype = {
     let mediaIsBlob = this.mediaURL.startsWith("blob:");
     this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL || mediaIsBlob);
     this.setItemAttr("context-sendaudio", "disabled", !this.mediaURL || mediaIsBlob);
   },
 
   initViewItems: function CM_initViewItems() {
     // View source is always OK, unless in directory listing.
     this.showItem("context-viewpartialsource-selection",
-                  this.isContentSelected);
-
-    const {gBrowser} = this.browser.ownerGlobal;
-    // Hide menu that opens devtools when the window is showing `about:devtools-toolbox`.
-    // This is to avoid displaying multiple devtools at the same time. See bug 1495944.
-    const isAboutDevtoolsToolbox = gBrowser &&
-                                   gBrowser.currentURI &&
-                                   gBrowser.currentURI.scheme === "about" &&
-                                   gBrowser.currentURI.filePath === "devtools-toolbox";
+                  !this.inAboutDevtoolsToolbox && this.isContentSelected);
 
     var shouldShow = !(this.isContentSelected ||
                        this.onImage || this.onCanvas ||
                        this.onVideo || this.onAudio ||
                        this.onLink || this.onTextInput);
 
-    var showInspect = this.inTabBrowser &&
-                      !isAboutDevtoolsToolbox &&
+    var showInspect = this.inTabBrowser && !this.inAboutDevtoolsToolbox &&
                       Services.prefs.getBoolPref("devtools.inspector.enabled", true) &&
                       !Services.prefs.getBoolPref("devtools.policy.disabled", false);
 
     var showInspectA11Y = showInspect &&
                           // Only when accessibility service started.
                           Services.appinfo.accessibilityEnabled &&
                           this.inTabBrowser &&
                           Services.prefs.getBoolPref("devtools.enabled", true) &&
@@ -522,17 +515,18 @@ nsContextMenu.prototype = {
                     this.onCanvas || this.inWebExtBrowser));
 
     this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
                                            !this.onMozExtLink) || this.onPlainTextLink);
     this.showItem("context-keywordfield",
                   this.onTextInput && this.onKeywordField);
     this.showItem("frame", this.inFrame);
 
-    let showSearchSelect = (this.isTextSelected || this.onLink) && !this.onImage;
+    let showSearchSelect = !this.inAboutDevtoolsToolbox &&
+                           (this.isTextSelected || this.onLink) && !this.onImage;
     this.showItem("context-searchselect", showSearchSelect);
     if (showSearchSelect) {
       this.formatSearchContextItem();
     }
 
     // srcdoc cannot be opened separately due to concerns about web
     // content with about:srcdoc in location bar masquerading as trusted
     // chrome/addon content.
@@ -623,17 +617,18 @@ nsContextMenu.prototype = {
                   this.isContentSelected || this.onTextInput);
     this.showItem("context-paste", this.onTextInput);
     this.showItem("context-delete", this.onTextInput);
     this.showItem("context-sep-paste", this.onTextInput);
     this.showItem("context-selectall", !(this.onLink || this.onImage ||
                                          this.onVideo || this.onAudio ||
                                          this.inSyntheticDoc) ||
                                        this.isDesignMode);
-    this.showItem("context-sep-selectall", this.isContentSelected );
+    this.showItem("context-sep-selectall",
+                  !this.inAboutDevtoolsToolbox && this.isContentSelected);
 
     // XXX dr
     // ------
     // nsDocumentViewer.cpp has code to determine whether we're
     // on a link or an image. we really ought to be using that...
 
     // Copy email link depends on whether we're on an email link.
     this.showItem("context-copyemail", this.onMailtoLink);
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_devtoolstoolbox_contextmenu.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_devtoolstoolbox_contextmenu.js
@@ -27,25 +27,43 @@ add_task(async function() {
   info("Check whether the menu item which opens devtools is enabled");
   await assertContextMenu(rootDocument, devtoolsBrowser, "#mount", true);
 
   await closeAboutDevtoolsToolbox(devtoolsTab, window);
   await removeTab(tab);
 });
 
 async function assertContextMenu(rootDocument, browser, targetSelector, shouldBeEnabled) {
+  if (shouldBeEnabled) {
+    await assertContextMenuEnabled(rootDocument, browser, targetSelector);
+  } else {
+    await assertContextMenuDisabled(rootDocument, browser, targetSelector);
+  }
+}
+
+async function assertContextMenuDisabled(rootDocument, browser, targetSelector) {
+  const contextMenu = rootDocument.getElementById("contentAreaContextMenu");
+  let isPopupShown = false;
+  const listener = () => {
+    isPopupShown = true;
+  };
+  contextMenu.addEventListener("popupshown", listener);
+  BrowserTestUtils.synthesizeMouseAtCenter(targetSelector,
+                                           { type: "contextmenu" }, browser);
+  await wait(1000);
+  ok(!isPopupShown, `Context menu should not be shown`);
+  contextMenu.removeEventListener("popupshown", listener);
+}
+
+async function assertContextMenuEnabled(rootDocument, browser, targetSelector) {
   // Show content context menu.
   const contextMenu = rootDocument.getElementById("contentAreaContextMenu");
   const popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
   BrowserTestUtils.synthesizeMouseAtCenter(targetSelector,
                                            { type: "contextmenu" }, browser);
   await popupShownPromise;
-
-  // Check hidden attribute of #context-inspect.
-  const inspectMenuItem = rootDocument.getElementById("context-inspect");
-  is(inspectMenuItem.hidden, !shouldBeEnabled,
-     '"hidden" attribute of #context-inspect should be correct');
+  ok(true, `Context menu should be shown`);
 
   // Hide content context menu.
   const popupHiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
   contextMenu.hidePopup();
   await popupHiddenPromise;
 }