Bug 1369072 - part3: nsXBLPrototypeHandler::DispatchXBLCommand() should use controller of visible window r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 07 Sep 2017 22:54:49 +0900
changeset 429177 ef1641e40903ff5e6cff94f2a1d1a3188598e563
parent 429176 1c3ac6cb53ea9c76c89d8e5d1cb1ee19703e1180
child 429178 5534f9aff56be5ff944631f028951378bbbfaaf1
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1369072
milestone57.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 1369072 - part3: nsXBLPrototypeHandler::DispatchXBLCommand() should use controller of visible window r=smaug With previous change, KeyboardEvent is dispatched even when invisible window has focus. However, nsRootWindow::GetControllerForCommand() returns controller for focused window even when the window is invisible because it uses nsFocusManager::GetFocusedDescendant() to retrieve focused window. Perhaps, we can assume that users won't expect to do something with invisible window when they type some keys. Then, nsRootWindow::GetControllerForCommand() should return controller for visible ancestor window if focused window is invisible. This patch makes nsFocusManager::GetFocusedDescendant() can return only visible descendants. However, it already has a bool argument. Therefore, it should have a flag instead of adding new flag. Most changes of this patch is replacing its callers. Then, nsRootWindow::GetControllerForCommand() and nsRootWindow::GetControllers() should have a bool flag if it should return controller(s) for visible window. This patch adds a bool flag for it. Fortunately, the interface isn't scriptable. Finally, this patch makes nsXBLPrototypeHandler::DispatchXBLCommand() and EventStateManager::DoContentCommandEvent() retrieve controller for visible window since they are always handles user input. MozReview-Commit-ID: GygttTHuKRm
docshell/base/nsDocShell.cpp
dom/base/Element.cpp
dom/base/Selection.cpp
dom/base/nsDocument.cpp
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsPIWindowRoot.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
dom/commandhandler/nsCommandManager.cpp
dom/events/ContentEventHandler.cpp
dom/events/EventStateManager.cpp
dom/html/nsHTMLDocument.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/xbl/nsXBLPrototypeHandler.cpp
dom/xul/nsXULCommandDispatcher.cpp
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorEventListener.cpp
editor/libeditor/HTMLEditor.cpp
layout/base/PresShell.cpp
layout/printing/nsPrintEngine.cpp
toolkit/components/find/nsWebBrowserFind.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13673,17 +13673,18 @@ nsDocShell::EnsureFind()
   // set that up each time.
 
   nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
   NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED);
 
   // default to our window
   nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
   nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
-  nsFocusManager::GetFocusedDescendant(ourWindow, true,
+  nsFocusManager::GetFocusedDescendant(ourWindow,
+                                       nsFocusManager::eIncludeAllDescendants,
                                        getter_AddRefs(windowToSearch));
 
   nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
   if (!findInFrames) {
     return NS_ERROR_NO_INTERFACE;
   }
 
   rv = findInFrames->SetRootSearchFrame(ourWindow);
@@ -13988,17 +13989,18 @@ nsDocShell::GetControllerForCommand(cons
   NS_ENSURE_ARG_POINTER(aResult);
   *aResult = nullptr;
 
   NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
-  return root->GetControllerForCommand(aCommand, aResult);
+  return root->GetControllerForCommand(aCommand, false /* for any window */,
+                                       aResult);
 }
 
 NS_IMETHODIMP
 nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult)
 {
   NS_ENSURE_ARG_POINTER(aResult);
   *aResult = false;
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2153,17 +2153,19 @@ Element::ShouldBlur(nsIContent *aContent
     return false;
 
   nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
   if (!window)
     return false;
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
   nsIContent* contentToBlur =
-    nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame));
+    nsFocusManager::GetFocusedDescendant(window,
+                                         nsFocusManager::eOnlyCurrentWindow,
+                                         getter_AddRefs(focusedFrame));
   if (contentToBlur == aContent)
     return true;
 
   // if focus on this element would get redirected, then check the redirected
   // content as well when blurring.
   return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
 }
 
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -3827,17 +3827,19 @@ Selection::NotifySelectionListeners()
     // If the document is in design mode or doesn't have contenteditable
     // element, we don't need to move focus.
     if (window && document && !document->HasFlag(NODE_IS_EDITABLE) &&
         GetHTMLEditor()) {
       RefPtr<Element> newEditingHost = GetCommonEditingHostForAllRanges();
       nsFocusManager* fm = nsFocusManager::GetFocusManager();
       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
       nsIContent* focusedContent =
-        fm->GetFocusedDescendant(window, false, getter_AddRefs(focusedWindow));
+        nsFocusManager::GetFocusedDescendant(window,
+                                             nsFocusManager::eOnlyCurrentWindow,
+                                             getter_AddRefs(focusedWindow));
       nsCOMPtr<Element> focusedElement = do_QueryInterface(focusedContent);
       // When all selected ranges are in an editing host, it should take focus.
       // But otherwise, we shouldn't move focus since Chromium doesn't move
       // focus but only selection range is updated.
       if (newEditingHost && newEditingHost != focusedElement) {
         MOZ_ASSERT(!newEditingHost->IsInNativeAnonymousSubtree());
         nsCOMPtr<nsIDOMElement> domElementToFocus =
           do_QueryInterface(newEditingHost->AsDOMNode());
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3599,17 +3599,18 @@ nsDocument::GetActiveElement(nsIDOMEleme
 
 Element*
 nsIDocument::GetActiveElement()
 {
   // Get the focused element.
   if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
     nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
     nsIContent* focusedContent =
-      nsFocusManager::GetFocusedDescendant(window, false,
+      nsFocusManager::GetFocusedDescendant(window,
+                                           nsFocusManager::eOnlyCurrentWindow,
                                            getter_AddRefs(focusedWindow));
     // be safe and make sure the element is from this document
     if (focusedContent && focusedContent->OwnerDoc() == this) {
       if (focusedContent->ChromeOnlyAccess()) {
         focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent();
       }
       if (focusedContent) {
         return focusedContent->AsElement();
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -294,32 +294,54 @@ static nsPIDOMWindowOuter*
 GetCurrentWindow(nsIContent* aContent)
 {
   nsIDocument* doc = aContent->GetComposedDoc();
   return doc ? doc->GetWindow() : nullptr;
 }
 
 // static
 nsIContent*
-nsFocusManager::GetFocusedDescendant(nsPIDOMWindowOuter* aWindow, bool aDeep,
+nsFocusManager::GetFocusedDescendant(nsPIDOMWindowOuter* aWindow,
+                                     SearchRange aSearchRange,
                                      nsPIDOMWindowOuter** aFocusedWindow)
 {
   NS_ENSURE_TRUE(aWindow, nullptr);
 
   *aFocusedWindow = nullptr;
 
   nsIContent* currentContent = nullptr;
   nsPIDOMWindowOuter* window = aWindow;
-  while (window) {
+  for (;;) {
     *aFocusedWindow = window;
     currentContent = window->GetFocusedNode();
-    if (!currentContent || !aDeep)
+    if (!currentContent || aSearchRange == eOnlyCurrentWindow) {
       break;
+    }
 
     window = GetContentWindow(currentContent);
+    if (!window) {
+      break;
+    }
+
+    if (aSearchRange == eIncludeAllDescendants) {
+      continue;
+    }
+
+    MOZ_ASSERT(aSearchRange == eIncludeVisibleDescendants);
+
+    // If the child window doesn't have PresShell, it means the window is
+    // invisible.
+    nsIDocShell* docShell = window->GetDocShell();
+    if (!docShell) {
+      break;
+    }
+    nsIPresShell* presShell = docShell->GetPresShell();
+    if (!presShell) {
+      break;
+    }
   }
 
   NS_IF_ADDREF(*aFocusedWindow);
 
   return currentContent;
 }
 
 // static
@@ -623,17 +645,20 @@ nsFocusManager::GetFocusedElementForWind
   if (aFocusedWindow)
     *aFocusedWindow = nullptr;
 
   NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
   nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
   nsCOMPtr<nsIContent> focusedContent =
-    GetFocusedDescendant(window, aDeep, getter_AddRefs(focusedWindow));
+    GetFocusedDescendant(window,
+                         aDeep ? nsFocusManager::eIncludeAllDescendants :
+                                 nsFocusManager::eOnlyCurrentWindow,
+                         getter_AddRefs(focusedWindow));
   if (focusedContent)
     CallQueryInterface(focusedContent, aElement);
 
   if (aFocusedWindow)
     NS_IF_ADDREF(*aFocusedWindow = focusedWindow);
 
   return NS_OK;
 }
@@ -733,17 +758,18 @@ nsFocusManager::WindowRaised(mozIDOMWind
   // is called.
   if (XRE_IsParentProcess()) {
     ActivateOrDeactivate(window, true);
   }
 
   // retrieve the last focused element within the window that was raised
   nsCOMPtr<nsPIDOMWindowOuter> currentWindow;
   nsCOMPtr<nsIContent> currentFocus =
-    GetFocusedDescendant(window, true, getter_AddRefs(currentWindow));
+    GetFocusedDescendant(window, eIncludeAllDescendants,
+                         getter_AddRefs(currentWindow));
 
   NS_ASSERTION(currentWindow, "window raised with no window current");
   if (!currentWindow)
     return NS_OK;
 
   // If there is no nsIXULWindow, then this is an embedded or child process window.
   // Pass false for aWindowRaised so that commands get updated.
   nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(baseWindow));
@@ -905,17 +931,18 @@ nsFocusManager::WindowShown(mozIDOMWindo
   }
 
   if (mFocusedWindow != window)
     return NS_OK;
 
   if (aNeedsFocus) {
     nsCOMPtr<nsPIDOMWindowOuter> currentWindow;
     nsCOMPtr<nsIContent> currentFocus =
-      GetFocusedDescendant(window, true, getter_AddRefs(currentWindow));
+      GetFocusedDescendant(window, eIncludeAllDescendants,
+                           getter_AddRefs(currentWindow));
     if (currentWindow)
       Focus(currentWindow, currentFocus, 0, true, false, false, true);
   }
   else {
     // Sometimes, an element in a window can be focused before the window is
     // visible, which would mean that the widget may not be properly focused.
     // When the window becomes visible, make sure the right widget is focused.
     EnsureCurrentWidgetFocused();
@@ -1208,17 +1235,18 @@ nsFocusManager::SetFocusInner(nsIContent
 
   // check if the element to focus is a frame (iframe) containing a child
   // document. Frames are never directly focused; instead focusing a frame
   // means focus what is inside the frame. To do this, the descendant content
   // within the frame is retrieved and that will be focused instead.
   nsCOMPtr<nsPIDOMWindowOuter> newWindow;
   nsCOMPtr<nsPIDOMWindowOuter> subWindow = GetContentWindow(contentToFocus);
   if (subWindow) {
-    contentToFocus = GetFocusedDescendant(subWindow, true, getter_AddRefs(newWindow));
+    contentToFocus = GetFocusedDescendant(subWindow, eIncludeAllDescendants,
+                                          getter_AddRefs(newWindow));
     // since a window is being refocused, clear aFocusChanged so that the
     // caret position isn't updated.
     aFocusChanged = false;
   }
 
   // unless it was set above, retrieve the window for the element to focus
   if (!newWindow)
     newWindow = GetCurrentWindow(contentToFocus);
@@ -2285,17 +2313,18 @@ nsFocusManager::RaiseWindow(nsPIDOMWindo
 
 #if defined(XP_WIN)
   // Windows would rather we focus the child widget, otherwise, the toplevel
   // widget will always end up being focused. Fortunately, focusing the child
   // widget will also have the effect of raising the window this widget is in.
   // But on other platforms, we can just focus the toplevel widget to raise
   // the window.
   nsCOMPtr<nsPIDOMWindowOuter> childWindow;
-  GetFocusedDescendant(aWindow, true, getter_AddRefs(childWindow));
+  GetFocusedDescendant(aWindow, eIncludeAllDescendants,
+                       getter_AddRefs(childWindow));
   if (!childWindow)
     childWindow = aWindow;
 
   nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
   if (!docShell)
     return;
 
   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
@@ -2649,17 +2678,18 @@ nsFocusManager::DetermineElementToMoveFo
   bool mayFocusRoot = (aStartContent != nullptr);
 
   nsCOMPtr<nsIContent> startContent = aStartContent;
   if (!startContent && aType != MOVEFOCUS_CARET) {
     if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC) {
       // When moving between documents, make sure to get the right
       // starting content in a descendant.
       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-      startContent = GetFocusedDescendant(aWindow, true, getter_AddRefs(focusedWindow));
+      startContent = GetFocusedDescendant(aWindow, eIncludeAllDescendants,
+                                          getter_AddRefs(focusedWindow));
     }
     else if (aType != MOVEFOCUS_LASTDOC) {
       // Otherwise, start at the focused node. If MOVEFOCUS_LASTDOC is used,
       // then we are document-navigating backwards from chrome to the content
       // process, and we don't want to use this so that we start from the end
       // of the document.
       startContent = aWindow->GetFocusedNode();
     }
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -129,17 +129,27 @@ public:
    * active window. This will traverse down the frame hierarchy, starting at
    * the given window aWindow. Sets aFocusedWindow to the window with the
    * document containing aFocusedContent. If no element is focused,
    * aFocusedWindow may be still be set -- this means that the document is
    * focused but no element within it is focused.
    *
    * aWindow and aFocusedWindow must both be non-null.
    */
-  static nsIContent* GetFocusedDescendant(nsPIDOMWindowOuter* aWindow, bool aDeep,
+  enum SearchRange
+  {
+    // Return focused content in aWindow.  So, aFocusedWindow is always aWindow.
+    eOnlyCurrentWindow,
+    // Return focused content in aWindow or one of all sub windows.
+    eIncludeAllDescendants,
+    // Return focused content in aWindow or one of visible sub windows.
+    eIncludeVisibleDescendants,
+  };
+  static nsIContent* GetFocusedDescendant(nsPIDOMWindowOuter* aWindow,
+                                          SearchRange aSearchRange,
                                           nsPIDOMWindowOuter** aFocusedWindow);
 
   /**
    * Returns the content node that focus will be redirected to if aContent was
    * focused. This is used for the special case of certain XUL elements such
    * as textboxes or input number which redirect focus to an anonymous child.
    *
    * aContent must be non-null.
--- a/dom/base/nsPIWindowRoot.h
+++ b/dom/base/nsPIWindowRoot.h
@@ -31,19 +31,30 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWINDOWROOT_IID)
 
   virtual nsPIDOMWindowOuter* GetWindow()=0;
 
   // get and set the node that is the context of a popup menu
   virtual nsIDOMNode* GetPopupNode() = 0;
   virtual void SetPopupNode(nsIDOMNode* aNode) = 0;
 
+  /**
+   * @param aForVisibleWindow   true if caller needs controller which is
+   *                            associated with visible window.
+   */
   virtual nsresult GetControllerForCommand(const char *aCommand,
+                                           bool aForVisibleWindow,
                                            nsIController** aResult) = 0;
-  virtual nsresult GetControllers(nsIControllers** aResult) = 0;
+
+  /**
+   * @param aForVisibleWindow   true if caller needs controllers which are
+   *                            associated with visible window.
+   */
+  virtual nsresult GetControllers(bool aForVisibleWindow,
+                                  nsIControllers** aResult) = 0;
 
   virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
                                           nsTArray<nsCString>& aDisabledCommands) = 0;
 
   virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) = 0;
   virtual mozilla::dom::EventTarget* GetParentTarget() = 0;
 
   // Stores a weak reference to the browser.
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -202,27 +202,32 @@ nsWindowRoot::GetOwnerGlobal() const
 
 nsPIDOMWindowOuter*
 nsWindowRoot::GetWindow()
 {
   return mWindow;
 }
 
 nsresult
-nsWindowRoot::GetControllers(nsIControllers** aResult)
+nsWindowRoot::GetControllers(bool aForVisibleWindow,
+                             nsIControllers** aResult)
 {
   *aResult = nullptr;
 
   // XXX: we should fix this so there's a generic interface that
   // describes controllers, so this code would have no special
   // knowledge of what object might have controllers.
 
+  nsFocusManager::SearchRange searchRange =
+    aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants :
+                        nsFocusManager::eIncludeAllDescendants;
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
   nsIContent* focusedContent =
-    nsFocusManager::GetFocusedDescendant(mWindow, true, getter_AddRefs(focusedWindow));
+    nsFocusManager::GetFocusedDescendant(mWindow, searchRange,
+                                         getter_AddRefs(focusedWindow));
   if (focusedContent) {
 #ifdef MOZ_XUL
     RefPtr<nsXULElement> xulElement = nsXULElement::FromContent(focusedContent);
     if (xulElement) {
       ErrorResult rv;
       *aResult = xulElement->GetControllers(rv);
       NS_IF_ADDREF(*aResult);
       return rv.StealNSResult();
@@ -245,37 +250,42 @@ nsWindowRoot::GetControllers(nsIControll
   else {
     return focusedWindow->GetControllers(aResult);
   }
 
   return NS_OK;
 }
 
 nsresult
-nsWindowRoot::GetControllerForCommand(const char * aCommand,
+nsWindowRoot::GetControllerForCommand(const char* aCommand,
+                                      bool aForVisibleWindow,
                                       nsIController** _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   {
     nsCOMPtr<nsIControllers> controllers;
-    GetControllers(getter_AddRefs(controllers));
+    GetControllers(aForVisibleWindow, getter_AddRefs(controllers));
     if (controllers) {
       nsCOMPtr<nsIController> controller;
       controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
       if (controller) {
         controller.forget(_retval);
         return NS_OK;
       }
     }
   }
 
+  nsFocusManager::SearchRange searchRange =
+    aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants :
+                        nsFocusManager::eIncludeAllDescendants;
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsFocusManager::GetFocusedDescendant(mWindow, true, getter_AddRefs(focusedWindow));
+  nsFocusManager::GetFocusedDescendant(mWindow, searchRange,
+                                       getter_AddRefs(focusedWindow));
   while (focusedWindow) {
     nsCOMPtr<nsIControllers> controllers;
     focusedWindow->GetControllers(getter_AddRefs(controllers));
     if (controllers) {
       nsCOMPtr<nsIController> controller;
       controllers->GetControllerForCommand(aCommand,
                                            getter_AddRefs(controller));
       if (controller) {
@@ -335,24 +345,26 @@ nsWindowRoot::GetEnabledDisabledCommands
 
 void
 nsWindowRoot::GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
                                          nsTArray<nsCString>& aDisabledCommands)
 {
   nsTHashtable<nsCharPtrHashKey> commandsHandled;
 
   nsCOMPtr<nsIControllers> controllers;
-  GetControllers(getter_AddRefs(controllers));
+  GetControllers(false, getter_AddRefs(controllers));
   if (controllers) {
     GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
                                              aEnabledCommands, aDisabledCommands);
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsFocusManager::GetFocusedDescendant(mWindow, true, getter_AddRefs(focusedWindow));
+  nsFocusManager::GetFocusedDescendant(mWindow,
+                                       nsFocusManager::eIncludeAllDescendants,
+                                       getter_AddRefs(focusedWindow));
   while (focusedWindow) {
     focusedWindow->GetControllers(getter_AddRefs(controllers));
     if (controllers) {
       GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
                                                aEnabledCommands, aDisabledCommands);
     }
 
     nsGlobalWindow* win = nsGlobalWindow::Cast(focusedWindow);
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -38,18 +38,20 @@ public:
                                 const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) override;
 
   // nsPIWindowRoot
 
   virtual nsPIDOMWindowOuter* GetWindow() override;
 
-  virtual nsresult GetControllers(nsIControllers** aResult) override;
+  virtual nsresult GetControllers(bool aForVisibleWindow,
+                                  nsIControllers** aResult) override;
   virtual nsresult GetControllerForCommand(const char * aCommand,
+                                           bool aForVisibleWindow,
                                            nsIController** _retval) override;
 
   virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
                                           nsTArray<nsCString>& aDisabledCommands) override;
 
   virtual nsIDOMNode* GetPopupNode() override;
   virtual void SetPopupNode(nsIDOMNode* aNode) override;
 
--- a/dom/commandhandler/nsCommandManager.cpp
+++ b/dom/commandhandler/nsCommandManager.cpp
@@ -251,10 +251,11 @@ nsCommandManager::GetControllerForComman
   }
 
   auto* window = nsPIDOMWindowOuter::From(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
   nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
   // no target window; send command to focus controller
-  return root->GetControllerForCommand(aCommand, aResult);
+  return root->GetControllerForCommand(aCommand, false /* for any window */,
+                                       aResult);
 }
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -510,18 +510,20 @@ nsIContent*
 ContentEventHandler::GetFocusedContent()
 {
   nsIDocument* doc = mPresShell->GetDocument();
   if (!doc) {
     return nullptr;
   }
   nsCOMPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  return nsFocusManager::GetFocusedDescendant(window, true,
-                                              getter_AddRefs(focusedWindow));
+  return nsFocusManager::GetFocusedDescendant(
+                           window,
+                           nsFocusManager::eIncludeAllDescendants,
+                           getter_AddRefs(focusedWindow));
 }
 
 bool
 ContentEventHandler::IsPlugin(nsIContent* aContent)
 {
   return aContent &&
          aContent->GetDesiredIMEState().mEnabled == IMEState::PLUGIN;
 }
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -5167,18 +5167,20 @@ nsIContent*
 EventStateManager::GetFocusedContent()
 {
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   EnsureDocument(mPresContext);
   if (!fm || !mDocument)
     return nullptr;
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  return nsFocusManager::GetFocusedDescendant(mDocument->GetWindow(), false,
-                                              getter_AddRefs(focusedWindow));
+  return nsFocusManager::GetFocusedDescendant(
+                           mDocument->GetWindow(),
+                           nsFocusManager::eOnlyCurrentWindow,
+                           getter_AddRefs(focusedWindow));
 }
 
 //-------------------------------------------------------
 // Return true if the docshell is visible
 
 bool
 EventStateManager::IsShellVisible(nsIDocShell* aShell)
 {
@@ -5231,18 +5233,21 @@ EventStateManager::DoContentCommandEvent
       cmd = "cmd_pasteTransferable";
       break;
     case eContentCommandLookUpDictionary:
       cmd = "cmd_lookUpDictionary";
       break;
     default:
       return NS_ERROR_NOT_IMPLEMENTED;
   }
+  // If user tries to do something, user must try to do it in visible window.
+  // So, let's retrieve controller of visible window.
   nsCOMPtr<nsIController> controller;
-  nsresult rv = root->GetControllerForCommand(cmd, getter_AddRefs(controller));
+  nsresult rv = root->GetControllerForCommand(cmd, true,
+                                              getter_AddRefs(controller));
   NS_ENSURE_SUCCESS(rv, rv);
   if (!controller) {
     // When GetControllerForCommand succeeded but there is no controller, the
     // command isn't supported.
     aEvent->mIsEnabled = false;
   } else {
     bool canDoIt;
     rv = controller->IsCommandEnabled(cmd, &canDoIt);
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2817,17 +2817,18 @@ nsHTMLDocument::EditingStateChanged()
     presShell->RestyleForCSSRuleChanges();
 
     // Adjust focused element with new style but blur event shouldn't be fired
     // until mEditingState is modified with newState.
     nsAutoScriptBlocker scriptBlocker;
     if (designMode) {
       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
       nsIContent* focusedContent =
-        nsFocusManager::GetFocusedDescendant(window, false,
+        nsFocusManager::GetFocusedDescendant(window,
+                                             nsFocusManager::eOnlyCurrentWindow,
                                              getter_AddRefs(focusedWindow));
       if (focusedContent) {
         nsIFrame* focusedFrame = focusedContent->GetPrimaryFrame();
         bool clearFocus = focusedFrame ? !focusedFrame->IsFocusable() :
                                          !focusedContent->IsFocusable();
         if (clearFocus) {
           nsFocusManager* fm = nsFocusManager::GetFocusManager();
           if (fm) {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1821,17 +1821,20 @@ ContentIsFocusedWithinWindow(nsIContent*
   }
 
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (!fm) {
     return false;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
-  nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame));
+  nsCOMPtr<nsIContent> focusedContent =
+    nsFocusManager::GetFocusedDescendant(rootWindow,
+                                         nsFocusManager::eIncludeAllDescendants,
+                                         getter_AddRefs(focusedFrame));
   return (focusedContent.get() == aContent);
 }
 
 static NPCocoaEventType
 CocoaEventTypeForEvent(const WidgetGUIEvent& anEvent, nsIFrame* aObjectFrame)
 {
   const NPCocoaEvent* event = static_cast<const NPCocoaEvent*>(anEvent.mPluginEvent);
   if (event) {
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -511,20 +511,24 @@ nsXBLPrototypeHandler::DispatchXBLComman
       if (!privateWindow)
         return NS_ERROR_FAILURE;
     }
 
     windowRoot = privateWindow->GetTopWindowRoot();
   }
 
   NS_LossyConvertUTF16toASCII command(mHandlerText);
-  if (windowRoot)
-    windowRoot->GetControllerForCommand(command.get(), getter_AddRefs(controller));
-  else
+  if (windowRoot) {
+    // If user tries to do something, user must try to do it in visible window.
+    // So, let's retrieve controller of visible window.
+    windowRoot->GetControllerForCommand(command.get(), true,
+                                        getter_AddRefs(controller));
+  } else {
     controller = GetController(aTarget); // We're attached to the receiver possibly.
+  }
 
   // We are the default action for this command.
   // Stop any other default action from executing.
   aEvent->PreventDefault();
 
   if (mEventName == nsGkAtoms::keypress &&
       mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
       mMisc == 1) {
@@ -536,17 +540,20 @@ nsXBLPrototypeHandler::DispatchXBLComman
       windowToCheck = windowRoot->GetWindow();
     else
       windowToCheck = privateWindow->GetPrivateRoot();
 
     nsCOMPtr<nsIContent> focusedContent;
     if (windowToCheck) {
       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
       focusedContent =
-        nsFocusManager::GetFocusedDescendant(windowToCheck, true, getter_AddRefs(focusedWindow));
+        nsFocusManager::GetFocusedDescendant(
+                          windowToCheck,
+                          nsFocusManager::eIncludeAllDescendants,
+                          getter_AddRefs(focusedWindow));
     }
 
     // If the focus is in an editable region, don't scroll.
     if (focusedContent && focusedContent->IsEditable()) {
       return NS_OK;
     }
 
     // If the focus is in a form control, don't scroll.
--- a/dom/xul/nsXULCommandDispatcher.cpp
+++ b/dom/xul/nsXULCommandDispatcher.cpp
@@ -105,17 +105,20 @@ nsXULCommandDispatcher::GetRootFocusedCo
   *aWindow = nullptr;
 
   if (!mDocument) {
     return nullptr;
   }
 
   if (nsCOMPtr<nsPIDOMWindowOuter> win = mDocument->GetWindow()) {
     if (nsCOMPtr<nsPIDOMWindowOuter> rootWindow = win->GetPrivateRoot()) {
-      return nsFocusManager::GetFocusedDescendant(rootWindow, true, aWindow);
+      return nsFocusManager::GetFocusedDescendant(
+                               rootWindow,
+                               nsFocusManager::eIncludeAllDescendants,
+                               aWindow);
     }
   }
 
   return nullptr;
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetFocusedElement(nsIDOMElement** aElement)
@@ -433,26 +436,27 @@ nsXULCommandDispatcher::Matches(const ns
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetControllers(nsIControllers** aResult)
 {
   nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
-  return root->GetControllers(aResult);
+  return root->GetControllers(false /* for any window */, aResult);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetControllerForCommand(const char *aCommand, nsIController** _retval)
 {
   nsCOMPtr<nsPIWindowRoot> root = GetWindowRoot();
   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
-  return root->GetControllerForCommand(aCommand, _retval);
+  return root->GetControllerForCommand(aCommand, false /* for any window */,
+                                       _retval);
 }
 
 NS_IMETHODIMP
 nsXULCommandDispatcher::GetSuppressFocusScroll(bool* aSuppressFocusScroll)
 {
   *aSuppressFocusScroll = false;
   return NS_OK;
 }
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -5205,17 +5205,18 @@ EditorBase::IsActiveInDOMWindow()
 
   nsCOMPtr<nsIDocument> document = GetDocument();
   if (NS_WARN_IF(!document)) {
     return false;
   }
   nsPIDOMWindowOuter* ourWindow = document->GetWindow();
   nsCOMPtr<nsPIDOMWindowOuter> win;
   nsIContent* content =
-    nsFocusManager::GetFocusedDescendant(ourWindow, false,
+    nsFocusManager::GetFocusedDescendant(ourWindow,
+                                         nsFocusManager::eOnlyCurrentWindow,
                                          getter_AddRefs(win));
   return SameCOMIdentity(content, piTarget);
 }
 
 bool
 EditorBase::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
 {
   // If the event is trusted, the event should always cause input.
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -76,17 +76,18 @@ DoCommandCallback(Command aCommand, void
   nsCOMPtr<nsPIWindowRoot> root = win->GetTopWindowRoot();
   if (!root) {
     return;
   }
 
   const char* commandStr = WidgetKeyboardEvent::GetCommandStr(aCommand);
 
   nsCOMPtr<nsIController> controller;
-  root->GetControllerForCommand(commandStr, getter_AddRefs(controller));
+  root->GetControllerForCommand(commandStr, false /* for any window */,
+                                getter_AddRefs(controller));
   if (!controller) {
     return;
   }
 
   bool commandEnabled;
   nsresult rv = controller->IsCommandEnabled(commandStr, &commandEnabled);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (commandEnabled) {
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -4914,17 +4914,18 @@ HTMLEditor::IsActiveInDOMWindow()
   // If we're in designMode, we're always active in the DOM window.
   if (inDesignMode) {
     return true;
   }
 
   nsPIDOMWindowOuter* ourWindow = document->GetWindow();
   nsCOMPtr<nsPIDOMWindowOuter> win;
   nsIContent* content =
-    nsFocusManager::GetFocusedDescendant(ourWindow, false,
+    nsFocusManager::GetFocusedDescendant(ourWindow,
+                                         nsFocusManager::eOnlyCurrentWindow,
                                          getter_AddRefs(win));
   if (!content) {
     return false;
   }
 
   // We're HTML editor for contenteditable
 
   // If the active content isn't editable, or it has independent selection,
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1629,17 +1629,18 @@ PresShell::GetSelectionControllerForFocu
 {
   if (aFocusedContent) {
     *aFocusedContent = nullptr;
   }
 
   if (mDocument) {
     nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
     nsCOMPtr<nsIContent> focusedContent =
-      nsFocusManager::GetFocusedDescendant(mDocument->GetWindow(), false,
+      nsFocusManager::GetFocusedDescendant(mDocument->GetWindow(),
+                                           nsFocusManager::eOnlyCurrentWindow,
                                            getter_AddRefs(focusedWindow));
     if (focusedContent) {
       nsIFrame* frame = focusedContent->GetPrimaryFrame();
       if (frame) {
         nsCOMPtr<nsISelectionController> selectionController;
         frame->GetSelectionController(mPresContext,
                                       getter_AddRefs(selectionController));
         if (selectionController) {
@@ -6790,17 +6791,18 @@ PresShell::GetRootWindow()
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 PresShell::GetFocusedDOMWindowInOurWindow()
 {
   nsCOMPtr<nsPIDOMWindowOuter> rootWindow = GetRootWindow();
   NS_ENSURE_TRUE(rootWindow, nullptr);
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsFocusManager::GetFocusedDescendant(rootWindow, true,
+  nsFocusManager::GetFocusedDescendant(rootWindow,
+                                       nsFocusManager::eIncludeAllDescendants,
                                        getter_AddRefs(focusedWindow));
   return focusedWindow.forget();
 }
 
 already_AddRefed<nsIContent>
 nsIPresShell::GetFocusedContentInOurWindow() const
 {
   nsCOMPtr<nsIContent> focusedContent;
@@ -7793,17 +7795,18 @@ PresShell::HandleEvent(nsIFrame* aFrame,
 
     // key and IME related events go to the focused frame in this DOM window.
     if (aEvent->IsTargetedAtFocusedContent()) {
       mCurrentEventContent = nullptr;
 
       nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
       nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
       nsCOMPtr<nsIContent> eventTarget =
-        nsFocusManager::GetFocusedDescendant(window, false,
+        nsFocusManager::GetFocusedDescendant(window,
+                                             nsFocusManager::eOnlyCurrentWindow,
                                              getter_AddRefs(focusedWindow));
 
       // otherwise, if there is no focused content or the focused content has
       // no frame, just use the root content. This ensures that key events
       // still get sent to the window properly if nothing is focused or if a
       // frame goes away while it is focused.
       if (!eventTarget || !eventTarget->GetPrimaryFrame()) {
         eventTarget = mDocument->GetUnfocusedKeyEventTarget();
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -3188,17 +3188,18 @@ nsPrintEngine::FindFocusedDOMWindow()
 
   nsPIDOMWindowOuter* window = mDocument->GetWindow();
   NS_ENSURE_TRUE(window, nullptr);
 
   nsCOMPtr<nsPIDOMWindowOuter> rootWindow = window->GetPrivateRoot();
   NS_ENSURE_TRUE(rootWindow, nullptr);
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsFocusManager::GetFocusedDescendant(rootWindow, true,
+  nsFocusManager::GetFocusedDescendant(rootWindow,
+                                       nsFocusManager::eIncludeAllDescendants,
                                        getter_AddRefs(focusedWindow));
   NS_ENSURE_TRUE(focusedWindow, nullptr);
 
   if (IsWindowsInOurSubTree(focusedWindow)) {
     return focusedWindow.forget();
   }
 
   return nullptr;
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -793,18 +793,20 @@ nsWebBrowserFind::GetFrameSelection(nsPI
     return nullptr;
   }
 
   // text input controls have their independent selection controllers that we
   // must use when they have focus.
   nsPresContext* presContext = presShell->GetPresContext();
 
   nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-  nsCOMPtr<nsIContent> focusedContent = nsFocusManager::GetFocusedDescendant(
-    aWindow, false, getter_AddRefs(focusedWindow));
+  nsCOMPtr<nsIContent> focusedContent =
+    nsFocusManager::GetFocusedDescendant(aWindow,
+                                         nsFocusManager::eOnlyCurrentWindow,
+                                         getter_AddRefs(focusedWindow));
 
   nsIFrame* frame =
     focusedContent ? focusedContent->GetPrimaryFrame() : nullptr;
 
   nsCOMPtr<nsISelectionController> selCon;
   nsCOMPtr<nsISelection> sel;
   if (frame) {
     frame->GetSelectionController(presContext, getter_AddRefs(selCon));