Bug 125282 Webpage-JS can steal focus from URLbar / chrome r=enn, sr=smaug

This commit is contained in:
Masayuki Nakano 2009-08-02 10:51:17 +09:00
parent e103fbb15f
commit ded4cf29cb
3 changed files with 92 additions and 1 deletions

View File

@ -126,6 +126,7 @@ _BROWSER_FILES = \
browser_bug491431.js \
browser_bug304198.js \
browser_drag.js \
browser_bug125282.js \
$(NULL)
ifeq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))

View File

@ -0,0 +1,77 @@
function test() {
waitForExplicitFinish();
let fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
let tabs = [ gBrowser.mCurrentTab, gBrowser.addTab() ];
gBrowser.selectedTab = tabs[0];
let loadedCount;
// The first test set is checking the nsIDOMElement.focus can move focus at
// onload event.
let callback = doTest1;
load("data:text/html,<body onload=\"document.getElementById('input').focus()\"><input id='input'></body>");
function load(aURI) {
loadedCount = 0;
for (let i = 0; i < tabs.length; i++) {
tabs[i].linkedBrowser.addEventListener("load", onLoad, true);
tabs[i].linkedBrowser.loadURI(aURI);
}
}
function onLoad() {
if (++loadedCount == tabs.length) {
setTimeout(callback, 10);
}
}
function doTest1() {
tabs[0].linkedBrowser.removeEventListener("load", onLoad, true);
tabs[1].linkedBrowser.removeEventListener("load", onLoad, true);
let e = tabs[0].linkedBrowser.contentDocument.activeElement;
is(e.tagName, "INPUT", "the foreground tab's input element is not active");
is(fm.focusedElement, e, "the input element isn't focused");
e = tabs[1].linkedBrowser.contentDocument.activeElement;
is(e.tagName, "INPUT", "the background tab's input element is not active");
isnot(fm.focusedElement, e, "the input element is focused");
// The second test set is checking the nsIDOMElement.focus can NOT move
// if an element of chrome has focus.
callback = doTest2;
load("data:text/html,<body onload=\"setTimeout(function () { document.getElementById('input').focus(); }, 10);\"><input id='input'></body>");
BrowserSearch.searchBar.focus();
}
let canRetry = 10;
function doTest2() {
if (canRetry-- > 0 &&
(tabs[0].linkedBrowser.contentDocument.activeElement.tagName != "INPUT" ||
tabs[1].linkedBrowser.contentDocument.activeElement.tagName != "INPUT")) {
setTimeout(doTest2, 10); // retry
return;
}
tabs[0].linkedBrowser.removeEventListener("load", onLoad, true);
tabs[1].linkedBrowser.removeEventListener("load", onLoad, true);
let e = tabs[0].linkedBrowser.contentDocument.activeElement;
is(e.tagName, "INPUT", "the foreground tab's input element is not active");
isnot(fm.focusedElement, e, "the input element is focused");
e = tabs[1].linkedBrowser.contentDocument.activeElement;
is(e.tagName, "INPUT", "the background tab's input element is not active");
isnot(fm.focusedElement, e, "the input element is focused");
// cleaning-up...
tabs[0].linkedBrowser.loadURI("about:blank");
gBrowser.selectedTab = tabs[1];
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -1041,9 +1041,22 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, PRInt32 aFlags,
PRBool allowFrameSwitch = !(aFlags & FLAG_NOSWITCHFRAME) ||
IsSameOrAncestor(newWindow, mFocusedWindow);
PRBool canStealFocus = PR_TRUE;
// When an element already has focus but this focus changing isn't by the
// user input, we should check the permission.
if (mFocusedContent && !(aFlags & (FLAG_BYMOUSE | FLAG_BYKEY))) {
nsCOMPtr<nsIDOMNode> currentFocusedNode =
do_QueryInterface(mFocusedContent);
// If the caller cannot access the current focused node, the caller should
// not be able to steal focus from it. E.g., When the current focused node
// is in chrome, any web contents should not be able to steal the focus.
canStealFocus = nsContentUtils::CanCallerAccess(currentFocusedNode);
}
// if the element is in the active window, frame switching is allowed and
// the content is in a visible window, fire blur and focus events.
if (isElementInActiveWindow && allowFrameSwitch && IsWindowVisible(newWindow)) {
if (isElementInActiveWindow && allowFrameSwitch &&
IsWindowVisible(newWindow) && canStealFocus) {
// return if blurring fails or the focus changes during the blur
if (mFocusedWindow) {
// if the focus is being moved to another element in the same document,