Bug 1369072 - part3: nsXBLPrototypeHandler::DispatchXBLCommand() should use controller of visible window r?smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 07 Sep 2017 22:54:49 +0900
changeset 661334 20a2132b22ac3eeda72b2080eea9a8971c8f19ec
parent 661242 c8a85f8076e25ee0dfaa794251532e105f8dd83f
child 661346 5828c45fa89db416539a925b2cee3d555dbd1b05
push id78715
push usermasayuki@d-toybox.com
push dateFri, 08 Sep 2017 09:33:48 +0000
reviewerssmaug
bugs1369072
milestone57.0a1
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));