Bug 617872 - Focus manager allows F6 to focus elements inside non-focusable iframes/browsers. r=smaug, a=blocking
authorNeil Deakin <enndeakin@gmail.com>
Thu, 09 Dec 2010 13:20:00 -0800
changeset 60230 310cfcff5588ff5abc2d09ada42f8a084511530a
parent 60229 5e8b96f85355488871c18597d38635801dc2f8c8
child 60231 906f834203ffaae888029972aa28fbfc0c839f54
push id17890
push userjdolske@mozilla.com
push dateSat, 08 Jan 2011 01:44:53 +0000
treeherdermozilla-central@906f834203ff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, blocking
bugs617872
milestone2.0b9pre
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 617872 - Focus manager allows F6 to focus elements inside non-focusable iframes/browsers. r=smaug, a=blocking
browser/base/content/test/browser_tabfocus.js
dom/base/nsFocusManager.cpp
--- a/browser/base/content/test/browser_tabfocus.js
+++ b/browser/base/content/test/browser_tabfocus.js
@@ -118,16 +118,32 @@ function test() {
                      window, null, true,
                      "focusedWindow after switch to chrome with no focused element");
 
     // switch focus to another tab when neither have an active focus
     expectFocusShift(function () gBrowser.selectedTab = tab1,
                      browser1.contentWindow, null, true,
                      "focusedWindow after tab switch from no focus to no focus");
 
+    gURLBar.focus();
+    _browser_tabfocus_test_events = "";
+    _browser_tabfocus_test_lastfocus = gURLBar;
+    _browser_tabfocus_test_lastfocuswindow = window;
+
+    expectFocusShift(function () EventUtils.synthesizeKey("VK_F6", { }),
+                     browser1.contentWindow, browser1.contentDocument.documentElement,
+                     true, "switch document forward with f6");
+    EventUtils.synthesizeKey("VK_F6", { });
+    is(fm.focusedWindow, window, "switch document forward again with f6");
+
+    browser1.style.MozUserFocus = "ignore";
+    browser1.clientWidth;
+    EventUtils.synthesizeKey("VK_F6", { });
+    is(fm.focusedWindow, window, "switch document forward again with f6 when browser non-focusable");
+
     window.addEventListener("focus", _browser_tabfocus_test_eventOccured, true);
     window.addEventListener("blur", _browser_tabfocus_test_eventOccured, true);
 
     // next, check whether navigating forward, focusing the urlbar and then
     // navigating back maintains the focus in the urlbar.
     browser1.addEventListener("pageshow", _browser_tabfocus_navigation_test_eventOccured, true);
     button1.focus();
     browser1.contentWindow.location = testPage3;
@@ -202,17 +218,17 @@ function expectFocusShift(callback, expe
     if (expectedWindow && _browser_tabfocus_test_lastfocuswindow != expectedWindow) {
       if (expectedEvents)
         expectedEvents += " ";
       var windowid = expectedWindow.document.documentElement.id;
       expectedEvents += "focus: " + windowid + "-document " +
                         "focus: " + windowid + "-window";
     }
 
-    if (expectedElement) {
+    if (expectedElement && expectedElement != expectedElement.ownerDocument.documentElement) {
       if (expectedEvents)
         expectedEvents += " ";
       expectedEvents += "focus: " + getId(expectedElement);
     }
 
     _browser_tabfocus_test_lastfocus = expectedElement;
     _browser_tabfocus_test_lastfocuswindow = expectedWindow;
   }
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2873,18 +2873,25 @@ nsFocusManager::GetRootForFocus(nsPIDOMW
                                 PRBool aIsForDocNavigation,
                                 PRBool aCheckVisibility)
 {
   // the root element's canvas may be focused as long as the document is in a
   // a non-chrome shell and does not contain a frameset.
   if (aIsForDocNavigation) {
     nsCOMPtr<nsIContent> docContent =
       do_QueryInterface(aWindow->GetFrameElementInternal());
-    if (docContent && docContent->Tag() == nsGkAtoms::iframe)
-      return nsnull;
+    // document navigation skips iframes and frames that are specifically non-focusable
+    if (docContent) {
+      if (docContent->Tag() == nsGkAtoms::iframe)
+        return nsnull;
+
+      nsIFrame* frame = docContent->GetPrimaryFrame();
+      if (!frame || !frame->IsFocusable(nsnull, 0))
+        return nsnull;
+    }
   }
   else  {
     PRInt32 itemType;
     nsCOMPtr<nsIDocShellTreeItem> shellItem = do_QueryInterface(aWindow->GetDocShell());
     shellItem->GetItemType(&itemType);
 
     if (itemType == nsIDocShellTreeItem::typeChrome)
       return nsnull;