Match Firefox restrictions to window.blur and window.focus
authorjochen@chromium.org <jochen@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 May 2012 13:28:13 +0000 (13:28 +0000)
committerjochen@chromium.org <jochen@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 May 2012 13:28:13 +0000 (13:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=86969

Reviewed by Adam Barth.

Source/WebCore:

Disallow window.blur altogether, and only allow window.focus to be
invoked from the context that created this very window.

There's a new setting (windowFocusRestricted) that defaults to true. If
false, the new restrictions are lifted. This can be used by ports that
would prefer to stick with the old behavior.

For tests, this setting is accessible in window.internals.settings

To temporarily allow window.focus(), an object of type
WindowFocusAllowedIndicator can be created. It is currently used to
enable window.focus() during dispatch of the click event for
notifications.

Tests: fast/dom/Window/mozilla-focus-blur.html
       fast/notifications/notifications-click-event-focus.html

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* notifications/Notification.cpp:
(WebCore::Notification::dispatchClickEvent):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::focus):
(WebCore::DOMWindow::blur):
* page/DOMWindow.h:
(DOMWindow):
* page/DOMWindow.idl:
* page/Settings.cpp:
(WebCore::Settings::Settings):
* page/Settings.h:
(Settings):
(WebCore::Settings::setWindowFocusRestricted):
(WebCore::Settings::windowFocusRestricted):
* page/WindowFocusAllowedIndicator.cpp: Added.
(WebCore):
(WebCore::WindowFocusAllowedIndicator::windowFocusAllowed):
(WebCore::WindowFocusAllowedIndicator::WindowFocusAllowedIndicator):
(WebCore::WindowFocusAllowedIndicator::~WindowFocusAllowedIndicator):
* page/WindowFocusAllowedIndicator.h: Added.
(WebCore):
(WindowFocusAllowedIndicator):
* testing/InternalSettings.cpp:
(WebCore::InternalSettings::InternalSettings):
(WebCore::InternalSettings::restoreTo):
(WebCore::InternalSettings::setWindowFocusRestricted):
(WebCore):
* testing/InternalSettings.h:
(InternalSettings):
* testing/InternalSettings.idl:

Source/WebKit/chromium:

Allow window.focus() during the dispatch of the click event on
notifications.

* src/WebNotification.cpp:
(WebKit::WebNotification::dispatchClickEvent):

LayoutTests:

* fast/dom/HTMLDocument/hasFocus.html:
* fast/dom/Window/mozilla-focus-blur-expected.txt: Added.
* fast/dom/Window/mozilla-focus-blur.html: Added.
* fast/notifications/notifications-click-event-focus-expected.txt: Added.
* fast/notifications/notifications-click-event-focus.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@118916 268f45cc-cd09-0410-ab3c-d52691b4dbfc

26 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/HTMLDocument/hasFocus.html
LayoutTests/fast/dom/Window/mozilla-focus-blur-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Window/mozilla-focus-blur.html [new file with mode: 0644]
LayoutTests/fast/notifications/notifications-click-event-focus-expected.txt [new file with mode: 0644]
LayoutTests/fast/notifications/notifications-click-event-focus.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/notifications/Notification.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/DOMWindow.h
Source/WebCore/page/DOMWindow.idl
Source/WebCore/page/Settings.cpp
Source/WebCore/page/Settings.h
Source/WebCore/page/WindowFocusAllowedIndicator.cpp [new file with mode: 0644]
Source/WebCore/page/WindowFocusAllowedIndicator.h [new file with mode: 0644]
Source/WebCore/testing/InternalSettings.cpp
Source/WebCore/testing/InternalSettings.h
Source/WebCore/testing/InternalSettings.idl
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebNotification.cpp

index c955d90..c5d5ca6 100644 (file)
@@ -1,3 +1,16 @@
+2012-05-30  Jochen Eisinger  <jochen@chromium.org>
+
+        Match Firefox restrictions to window.blur and window.focus
+        https://bugs.webkit.org/show_bug.cgi?id=86969
+
+        Reviewed by Adam Barth.
+
+        * fast/dom/HTMLDocument/hasFocus.html:
+        * fast/dom/Window/mozilla-focus-blur-expected.txt: Added.
+        * fast/dom/Window/mozilla-focus-blur.html: Added.
+        * fast/notifications/notifications-click-event-focus-expected.txt: Added.
+        * fast/notifications/notifications-click-event-focus.html: Added.
+
 2012-05-30  Zan Dobersek  <zandobersek@gmail.com>
 
         Unreviewed GTK gardening, updating platform-specific baselines after r118902.
index 918149b..7ca7dae 100644 (file)
@@ -4,6 +4,10 @@
             var subFrameDocument;
             function test()
             {
+                if (window.internals)
+                    window.internals.settings.setWindowFocusRestricted(false);
+                else
+                    log("Could not lift restrictions on window.blur(), this part of the test will fail.\n")
                 if (window.layoutTestController) {
                     layoutTestController.dumpAsText();
                     layoutTestController.waitUntilDone();
diff --git a/LayoutTests/fast/dom/Window/mozilla-focus-blur-expected.txt b/LayoutTests/fast/dom/Window/mozilla-focus-blur-expected.txt
new file mode 100644 (file)
index 0000000..a59e640
--- /dev/null
@@ -0,0 +1,11 @@
+Check that window.blur() does nothing, and window.focus() only works if it is invoked from the window that opened the former. If the test passes, you should see a series of PASS messages with the last being 'All tests finished'.
+
+This test is adopted from mozilla's tests.
+
+PASS: The focus should not have been changed!
+PASS: The focus should not have been changed!
+PASS: The focus should not have been changed with URL=data:text/html,<script>opener.focus();opener.postMessage("", "*");</script>
+PASS: The focus should not have been changed with URL=data:text/html,<script>blur();opener.postMessage("", "*");</script>
+PASS: The last opened window should be able to get focus
+PASS: All tests finished
+
diff --git a/LayoutTests/fast/dom/Window/mozilla-focus-blur.html b/LayoutTests/fast/dom/Window/mozilla-focus-blur.html
new file mode 100644 (file)
index 0000000..d39b58d
--- /dev/null
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+    layoutTestController.setCanOpenWindows();
+}
+
+var originatingWindow = self;
+
+function log(passed, message) {
+    var log = document.getElementById('log');
+    var text = document.createTextNode((passed ? 'PASS: ' : 'FAIL: ') + message);
+    var br = document.createElement('br');
+    log.appendChild(text);
+    log.appendChild(br);
+}
+
+function focusShouldNotChange(action, nextTest) {
+    var w = window.open('about:blank', '', 'foo');
+    var fail = false;
+
+    function failHandler() { fail = true; }
+
+    originatingWindow.addEventListener('focus', failHandler, false);
+    w.addEventListener('blur', failHandler, false);
+
+    action(w);
+
+    originatingWindow.setTimeout(function () {
+        originatingWindow.removeEventListener('focus', failHandler, false);
+        w.removeEventListener('blur', failHandler, false);
+
+        log(!fail, 'The focus should not have been changed!');
+
+        // Cleaning and running next test.
+        w.close();
+        originatingWindow.setTimeout(nextTest, 0);
+    }, 0);
+}
+
+function focusShouldNotChange2(url, nextTest) {
+    var fail = false;
+    var w;
+    function failHandler() { fail = true; }
+
+    function msgHandler() {
+        originatingWindow.removeEventListener('message', msgHandler, false);
+        originatingWindow.removeEventListener('focus', failHandler, false);
+
+        log(!fail, 'The focus should not have been changed with URL=' + url);
+
+        // Cleaning and running next test.
+        w.close();
+        originatingWindow.setTimeout(nextTest, 0);
+    }
+    originatingWindow.addEventListener('message', msgHandler, false)
+
+    var w = window.open(url, '', 'foo');
+
+    originatingWindow.addEventListener('focus', failHandler, false);
+    w.addEventListener('blur', failHandler, false);
+}
+
+function test1() {
+    focusShouldNotChange(function (aW) { aW.blur(); }, test2);
+}
+
+function test2() {
+    focusShouldNotChange(function () { originatingWindow.focus(); }, test3);
+}
+
+function test3() {
+    focusShouldNotChange2('data:text/html,<script>opener.focus();opener.postMessage("", "*");<\/script>', test4);
+}
+
+function test4() {
+    focusShouldNotChange2('data:text/html,<script>blur();opener.postMessage("", "*");<\/script>', test5);
+}
+
+function test5()
+{
+    var w = window.open('about:blank', '', 'foo');
+    var fail = true;
+
+    function handler() { fail = false; }
+
+    w.addEventListener('focus', handler, false);
+
+    w.focus();
+
+    originatingWindow.setTimeout(function () {
+        w.removeEventListener('focus', handler, false);
+
+        log(!fail, 'The last opened window should be able to get focus');
+
+        w.close();
+        originatingWindow.setTimeout(finished, 0);
+    }, 0);
+}
+
+function finished() {
+    log(true, 'All tests finished');
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+</script>
+</head>
+<body onload='test1()'>
+<p>
+Check that window.blur() does nothing, and window.focus() only works if it is
+invoked from the window that opened the former. If the test passes, you should
+see a series of PASS messages with the last being 'All tests finished'.
+</p>
+<p>
+This test is adopted from <a href='http://mxr.mozilla.org/mozilla-aurora/source/dom/tests/mochitest/bugs/test_bug369306.html'>mozilla's tests</a>.
+</p>
+</div>
+<div id='log'></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/notifications/notifications-click-event-focus-expected.txt b/LayoutTests/fast/notifications/notifications-click-event-focus-expected.txt
new file mode 100644 (file)
index 0000000..35473a6
--- /dev/null
@@ -0,0 +1,9 @@
+DESKTOP NOTIFICATION: icon , title New E-mail, text Meet me tonight at 8!
+DESKTOP NOTIFICATION CLOSED: New E-mail
+Check that window.focus() is not restricted during notification click events.
+
+To exercise manually, disable pop-up blocking, grant notification permissions and load this page, then click on the notification. You should see two "PASS" messages and this window should be focused.
+
+PASS: click event fired.
+PASS: focus event fired.
+
diff --git a/LayoutTests/fast/notifications/notifications-click-event-focus.html b/LayoutTests/fast/notifications/notifications-click-event-focus.html
new file mode 100644 (file)
index 0000000..a834aa6
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script type="text/javascript">
+        function log(message)
+        {
+            document.getElementById("result").innerHTML += message + "<br>";
+        }
+
+        function runTests()
+        {
+            if (window.layoutTestController) {
+                layoutTestController.grantDesktopNotificationPermission("file://");
+                layoutTestController.dumpAsText();
+                layoutTestController.waitUntilDone();
+                layoutTestController.setCanOpenWindows();
+                layoutTestController.setCloseRemainingWindowsWhenComplete();
+            }
+
+            if (!window.webkitNotifications) {
+                log("FAIL: No webkitNotifications interface!");
+            }
+
+            // Open a new window, so we don't have the focus.
+            var W = window.open("about:blank");
+            W.focus();
+
+            window.onfocus = function() { log("PASS: focus event fired."); }
+
+            var N = window.webkitNotifications.createNotification("", "New E-mail", "Meet me tonight at 8!");
+            N.onclick = function() { log("PASS: click event fired."); window.focus(); N.cancel();  }
+            N.show();
+
+            if (window.layoutTestController) {
+                layoutTestController.simulateDesktopNotificationClick("New E-mail");
+                layoutTestController.notifyDone();
+            }
+        }
+    </script>
+</head>
+<body>
+<p>Check that window.focus() is not restricted during notification click events.</p>
+
+<p>To exercise manually, disable pop-up blocking, grant notification permissions and load this page, then click on the notification.  You should see two "PASS" messages and this window should be focused.</p>
+<div id="result"></div>
+
+<script type="text/javascript">
+runTests();
+</script>
+</body>
+</html>
index f738a3b..ef2d939 100644 (file)
@@ -1089,6 +1089,7 @@ SET(WebCore_SOURCES
     page/WebKitAnimation.cpp
     page/WebKitAnimationList.cpp
     page/WindowFeatures.cpp
+    page/WindowFocusAllowedIndicator.cpp
 
     page/animation/AnimationBase.cpp
     page/animation/AnimationController.cpp
index cf9db21..2bf19a1 100644 (file)
@@ -1,3 +1,64 @@
+2012-05-30  Jochen Eisinger  <jochen@chromium.org>
+
+        Match Firefox restrictions to window.blur and window.focus
+        https://bugs.webkit.org/show_bug.cgi?id=86969
+
+        Reviewed by Adam Barth.
+
+        Disallow window.blur altogether, and only allow window.focus to be
+        invoked from the context that created this very window.
+
+        There's a new setting (windowFocusRestricted) that defaults to true. If
+        false, the new restrictions are lifted. This can be used by ports that
+        would prefer to stick with the old behavior.
+
+        For tests, this setting is accessible in window.internals.settings
+
+        To temporarily allow window.focus(), an object of type
+        WindowFocusAllowedIndicator can be created. It is currently used to
+        enable window.focus() during dispatch of the click event for
+        notifications.
+
+        Tests: fast/dom/Window/mozilla-focus-blur.html
+               fast/notifications/notifications-click-event-focus.html
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * notifications/Notification.cpp:
+        (WebCore::Notification::dispatchClickEvent):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::focus):
+        (WebCore::DOMWindow::blur):
+        * page/DOMWindow.h:
+        (DOMWindow):
+        * page/DOMWindow.idl:
+        * page/Settings.cpp:
+        (WebCore::Settings::Settings):
+        * page/Settings.h:
+        (Settings):
+        (WebCore::Settings::setWindowFocusRestricted):
+        (WebCore::Settings::windowFocusRestricted):
+        * page/WindowFocusAllowedIndicator.cpp: Added.
+        (WebCore):
+        (WebCore::WindowFocusAllowedIndicator::windowFocusAllowed):
+        (WebCore::WindowFocusAllowedIndicator::WindowFocusAllowedIndicator):
+        (WebCore::WindowFocusAllowedIndicator::~WindowFocusAllowedIndicator):
+        * page/WindowFocusAllowedIndicator.h: Added.
+        (WebCore):
+        (WindowFocusAllowedIndicator):
+        * testing/InternalSettings.cpp:
+        (WebCore::InternalSettings::InternalSettings):
+        (WebCore::InternalSettings::restoreTo):
+        (WebCore::InternalSettings::setWindowFocusRestricted):
+        (WebCore):
+        * testing/InternalSettings.h:
+        (InternalSettings):
+        * testing/InternalSettings.idl:
+
 2012-05-30  Mariusz Grzegorczyk  <mariusz.g@samsung.com>, Ryuan Choi  <ryuan.choi@samsung.com>
 
         [EFL][WK2] Fix WebKit2-EFL build
index 2aff39e..37842af 100644 (file)
@@ -3077,6 +3077,8 @@ webcore_sources += \
        Source/WebCore/page/WebKitPoint.h \
        Source/WebCore/page/WindowFeatures.cpp \
        Source/WebCore/page/WindowFeatures.h \
+       Source/WebCore/page/WindowFocusAllowedIndicator.cpp \
+       Source/WebCore/page/WindowFocusAllowedIndicator.h \
        Source/WebCore/page/WorkerNavigator.cpp \
        Source/WebCore/page/WorkerNavigator.h \
        Source/WebCore/platform/animation/Animation.cpp \
index 5e6757f..59ef393 100644 (file)
@@ -1061,6 +1061,7 @@ SOURCES += \
     page/SuspendableTimer.cpp \
     page/UserContentURLPattern.cpp \
     page/WindowFeatures.cpp \
+    page/WindowFocusAllowedIndicator.cpp \
     plugins/PluginData.cpp \
     plugins/DOMPluginArray.cpp \
     plugins/DOMPlugin.cpp \
@@ -2192,6 +2193,7 @@ HEADERS += \
     page/WebKitAnimation.h \
     page/WebKitAnimationList.h \
     page/WindowFeatures.h \
+    page/WindowFocusAllowedIndicator.h \
     page/WorkerNavigator.h \
     platform/animation/Animation.h \
     platform/animation/AnimationList.h \
index cec1393..e3799b6 100644 (file)
             'page/UserStyleSheetTypes.h',
             'page/WebCoreKeyboardUIMode.h',
             'page/WindowFeatures.h',
+            'page/WindowFocusAllowedIndicator.h',
             'page/animation/AnimationController.h',
             'page/mac/WebCoreFrameView.h',
             'platform/Clock.h',
             'page/WebKitAnimationList.h',
             'page/WebKitPoint.h',
             'page/WindowFeatures.cpp',
+            'page/WindowFocusAllowedIndicator.cpp',
             'page/WorkerNavigator.cpp',
             'page/WorkerNavigator.h',
             'page/animation/AnimationBase.cpp',
index 40fe09a..40fc3c4 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\page\WindowFocusAllowedIndicator.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\page\WindowFocusAllowedIndicator.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\page\WorkerNavigator.cpp"
                                >
                        </File>
index 3f9ede4..2f240f5 100644 (file)
                BC82432A0D0CE8A200460C8F /* JSSQLTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8243260D0CE8A200460C8F /* JSSQLTransaction.h */; };
                BC8243E80D0CFD7500460C8F /* WindowFeatures.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8243E60D0CFD7500460C8F /* WindowFeatures.cpp */; };
                BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8243E70D0CFD7500460C8F /* WindowFeatures.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7E99AF510B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E99AF520B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp */; };
+               7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E99AF540B13846468FB01A5 /* WindowFocusAllowedIndicator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC85F23D151915E000BC17BE /* RenderNamedFlowThread.h in Headers */ = {isa = PBXBuildFile; fileRef = BC85F23C151915E000BC17BE /* RenderNamedFlowThread.h */; };
                BC8AE34E12EA096A00EB3AE6 /* ScrollableArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8AE34C12EA096A00EB3AE6 /* ScrollableArea.cpp */; };
                BC8AE34F12EA096A00EB3AE6 /* ScrollableArea.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8AE34D12EA096A00EB3AE6 /* ScrollableArea.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC8243260D0CE8A200460C8F /* JSSQLTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLTransaction.h; sourceTree = "<group>"; };
                BC8243E60D0CFD7500460C8F /* WindowFeatures.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowFeatures.cpp; sourceTree = "<group>"; };
                BC8243E70D0CFD7500460C8F /* WindowFeatures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowFeatures.h; sourceTree = "<group>"; };
+               7E99AF520B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowFocusAllowedIndicator.cpp; sourceTree = "<group>"; };
+               7E99AF540B13846468FB01A5 /* WindowFocusAllowedIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowFocusAllowedIndicator.h; sourceTree = "<group>"; };
                BC85F23C151915E000BC17BE /* RenderNamedFlowThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderNamedFlowThread.h; sourceTree = "<group>"; };
                BC85F23E1519187300BC17BE /* RenderNamedFlowThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderNamedFlowThread.cpp; sourceTree = "<group>"; };
                BC8AE34C12EA096A00EB3AE6 /* ScrollableArea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollableArea.cpp; sourceTree = "<group>"; };
                                494BD7940F55C8EE00747828 /* WebKitPoint.idl */,
                                BC8243E60D0CFD7500460C8F /* WindowFeatures.cpp */,
                                BC8243E70D0CFD7500460C8F /* WindowFeatures.h */,
+                               7E99AF520B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp */,
+                               7E99AF540B13846468FB01A5 /* WindowFocusAllowedIndicator.h */,
                                E1271A130EEEC80400F61213 /* WorkerNavigator.cpp */,
                                E1271A0A0EEEC77A00F61213 /* WorkerNavigator.h */,
                                E1271A510EEECD1C00F61213 /* WorkerNavigator.idl */,
                                939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
                                4123E569127B3041000FEEA7 /* WindowEventContext.h in Headers */,
                                BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
+                               7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */,
                                E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */,
                                501BAAA913950E2C00F7ACEB /* WindRule.h in Headers */,
                                379919971200DDF400EA041C /* WOFFFileFormat.h in Headers */,
                                939B02EE0EA2DBC400C54570 /* WidthIterator.cpp in Sources */,
                                4123E56A127B3041000FEEA7 /* WindowEventContext.cpp in Sources */,
                                BC8243E80D0CFD7500460C8F /* WindowFeatures.cpp in Sources */,
+                               7E99AF510B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp in Sources */,
                                379919961200DDF400EA041C /* WOFFFileFormat.cpp in Sources */,
                                2E4346450F546A8200B0F1BA /* Worker.cpp in Sources */,
                                F3820896147D35F90010BC06 /* WorkerConsoleAgent.cpp in Sources */,
index 37f3b3e..348992a 100644 (file)
@@ -48,6 +48,7 @@
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
 #include "ThreadableLoader.h"
+#include "WindowFocusAllowedIndicator.h"
 #include "WorkerContext.h"
 
 namespace WebCore {
@@ -222,6 +223,7 @@ void Notification::dispatchShowEvent()
 
 void Notification::dispatchClickEvent()
 {
+    WindowFocusAllowedIndicator windowFocusAllowed;
     dispatchEvent(Event::create(eventNames().clickEvent, false, false));
 }
 
index 400270b..86c1212 100644 (file)
@@ -95,6 +95,7 @@
 #include "SuddenTermination.h"
 #include "WebKitPoint.h"
 #include "WindowFeatures.h"
+#include "WindowFocusAllowedIndicator.h"
 #include <algorithm>
 #include <wtf/CurrentTime.h>
 #include <wtf/MainThread.h>
@@ -899,7 +900,7 @@ Element* DOMWindow::frameElement() const
     return m_frame->ownerElement();
 }
 
-void DOMWindow::focus()
+void DOMWindow::focus(ScriptExecutionContext* context)
 {
     if (!m_frame)
         return;
@@ -908,8 +909,16 @@ void DOMWindow::focus()
     if (!page)
         return;
 
+    bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed() || !m_frame->settings()->windowFocusRestricted();
+    if (context) {
+        ASSERT(isMainThread());
+        Document* activeDocument = static_cast<Document*>(context);
+        if (opener() && activeDocument->domWindow() == opener())
+            allowFocus = true;
+    }
+
     // If we're a top level window, bring the window to the front.
-    if (m_frame == page->mainFrame())
+    if (m_frame == page->mainFrame() && allowFocus)
         page->chrome()->focus();
 
     if (!m_frame)
@@ -920,6 +929,7 @@ void DOMWindow::focus()
 
 void DOMWindow::blur()
 {
+
     if (!m_frame)
         return;
 
@@ -927,6 +937,9 @@ void DOMWindow::blur()
     if (!page)
         return;
 
+    if (m_frame->settings()->windowFocusRestricted())
+        return;
+
     if (m_frame != page->mainFrame())
         return;
 
index 4ac8162..728c315 100644 (file)
@@ -144,7 +144,7 @@ namespace WebCore {
 
         Element* frameElement() const;
 
-        void focus();
+        void focus(ScriptExecutionContext* = 0);
         void blur();
         void close(ScriptExecutionContext* = 0);
         void print();
index 8fc1490..f0656d8 100644 (file)
@@ -64,7 +64,7 @@ module window {
 
         readonly attribute [CheckSecurityForNode] Element frameElement;
 
-        [DoNotCheckSecurity] void focus();
+        [DoNotCheckSecurity, CallWith=ScriptExecutionContext] void focus();
         [DoNotCheckSecurity] void blur();
         [DoNotCheckSecurity, CallWith=ScriptExecutionContext] void close();
 
index 858d994..8b7b1d7 100644 (file)
@@ -274,6 +274,7 @@ Settings::Settings(Page* page)
     , m_needsDidFinishLoadOrderQuirk(false)
     , m_fixedPositionCreatesStackingContext(false)
     , m_syncXHRInDocumentsEnabled(true)
+    , m_windowFocusRestricted(true)
     , m_loadsImagesAutomaticallyTimer(this, &Settings::loadsImagesAutomaticallyTimerFired)
     , m_incrementalRenderingSuppressionTimeoutInSeconds(defaultIncrementalRenderingSuppressionTimeoutInSeconds)
 {
index da045c9..fb1cd3f 100644 (file)
@@ -587,6 +587,12 @@ namespace WebCore {
         void setSyncXHRInDocumentsEnabled(bool enabled) { m_syncXHRInDocumentsEnabled = enabled; }
         bool syncXHRInDocumentsEnabled() const { return m_syncXHRInDocumentsEnabled; }
 
+        // When enabled, window.blur() does not change focus, and
+        // window.focus() only changes focus when invoked from the context that
+        // created the window.
+        void setWindowFocusRestricted(bool restricted) { m_windowFocusRestricted = restricted; }
+        bool windowFocusRestricted() const { return m_windowFocusRestricted; }
+
 #if USE(JSC)
         static void setShouldRespectPriorityInCSSAttributeSetters(bool);
         static bool shouldRespectPriorityInCSSAttributeSetters();
@@ -762,6 +768,8 @@ namespace WebCore {
         bool m_fixedPositionCreatesStackingContext : 1;
         bool m_syncXHRInDocumentsEnabled : 1;
 
+        bool m_windowFocusRestricted : 1;
+
         Timer<Settings> m_loadsImagesAutomaticallyTimer;
         void loadsImagesAutomaticallyTimerFired(Timer<Settings>*);
         
diff --git a/Source/WebCore/page/WindowFocusAllowedIndicator.cpp b/Source/WebCore/page/WindowFocusAllowedIndicator.cpp
new file mode 100644 (file)
index 0000000..f44de6a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WindowFocusAllowedIndicator.h"
+
+namespace WebCore {
+
+static bool s_windowFocusAllowed = false;
+
+bool WindowFocusAllowedIndicator::windowFocusAllowed()
+{
+    return s_windowFocusAllowed;
+}
+
+WindowFocusAllowedIndicator::WindowFocusAllowedIndicator()
+    : m_previousWindowFocusAllowed(s_windowFocusAllowed)
+{
+    s_windowFocusAllowed = true;
+}
+
+WindowFocusAllowedIndicator::~WindowFocusAllowedIndicator()
+{
+    s_windowFocusAllowed = m_previousWindowFocusAllowed;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/page/WindowFocusAllowedIndicator.h b/Source/WebCore/page/WindowFocusAllowedIndicator.h
new file mode 100644 (file)
index 0000000..86598d7
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WindowFocusAllowedIndicator_h
+#define WindowFocusAllowedIndicator_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class WindowFocusAllowedIndicator {
+    WTF_MAKE_NONCOPYABLE(WindowFocusAllowedIndicator);
+public:
+    WindowFocusAllowedIndicator();
+    ~WindowFocusAllowedIndicator();
+
+    static bool windowFocusAllowed();
+
+private:
+    bool m_previousWindowFocusAllowed;
+};
+
+} // namespace WebCore
+
+#endif // WindowFocusAllowedIndicator_h
index d648668..2f42794 100644 (file)
@@ -104,6 +104,7 @@ InternalSettings::InternalSettings(Frame* frame)
 #if ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
     , m_originalJavaScriptProfilingEnabled(page() && page()->inspectorController() && page()->inspectorController()->profilerEnabled())
 #endif
+    , m_originalWindowFocusRestricted(settings()->windowFocusRestricted())
 {
 }
 
@@ -122,6 +123,7 @@ void InternalSettings::restoreTo(Settings* settings)
     if (page() && page()->inspectorController())
         page()->inspectorController()->setProfilerEnabled(m_originalJavaScriptProfilingEnabled);
 #endif
+    settings->setWindowFocusRestricted(m_originalWindowFocusRestricted);
 }
 
 Settings* InternalSettings::settings() const
@@ -383,4 +385,10 @@ void InternalSettings::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode
 #endif
 }
 
+void InternalSettings::setWindowFocusRestricted(bool restricted, ExceptionCode& ec)
+{
+    InternalSettingsGuardForSettings();
+    settings()->setWindowFocusRestricted(restricted);
+}
+
 }
index 111c180..86cd135 100644 (file)
@@ -78,6 +78,7 @@ public:
     void setEditingBehavior(const String&, ExceptionCode&);
     void setFixedPositionCreatesStackingContext(bool, ExceptionCode&);
     void setSyncXHRInDocumentsEnabled(bool, ExceptionCode&);
+    void setWindowFocusRestricted(bool, ExceptionCode&);
 
     void restoreTo(Settings*);
 
@@ -102,6 +103,7 @@ private:
 #if ENABLE(INSPECTOR) && ENABLE(JAVASCRIPT_DEBUGGER)
     bool m_originalJavaScriptProfilingEnabled;
 #endif
+    bool m_originalWindowFocusRestricted;
 };
 
 } // namespace WebCore
index 350101e..b6a14e7 100644 (file)
@@ -57,6 +57,7 @@ module window {
         void setFixedPositionCreatesStackingContext(in boolean creates) raises(DOMException);
         void setSyncXHRInDocumentsEnabled(in boolean enabled) raises(DOMException);
         void setJavaScriptProfilingEnabled(in boolean creates) raises(DOMException);
+        void setWindowFocusRestricted(in boolean restricted) raises(DOMException);
     };
 }
 
index deac720..3db98f7 100644 (file)
@@ -1,3 +1,16 @@
+2012-05-30  Jochen Eisinger  <jochen@chromium.org>
+
+        Match Firefox restrictions to window.blur and window.focus
+        https://bugs.webkit.org/show_bug.cgi?id=86969
+
+        Reviewed by Adam Barth.
+
+        Allow window.focus() during the dispatch of the click event on
+        notifications.
+
+        * src/WebNotification.cpp:
+        (WebKit::WebNotification::dispatchClickEvent):
+
 2012-05-29  Mark Pilgrim  <pilgrim@chromium.org>
 
         [Chromium] Move fileExists to Platform.h
index f6e981d..54209fd 100644 (file)
@@ -36,6 +36,7 @@
 #include "Event.h"
 #include "Notification.h"
 #include "UserGestureIndicator.h"
+#include "WindowFocusAllowedIndicator.h"
 
 #include "platform/WebString.h"
 #include "WebTextDirection.h"
@@ -136,8 +137,8 @@ void WebNotification::dispatchCloseEvent(bool /* byUser */)
 
 void WebNotification::dispatchClickEvent()
 {
-    // Make sure clicks on notifications are treated as user gestures.
     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
+    WindowFocusAllowedIndicator windowFocusAllowed;
     dispatchEvent(eventNames().clickEvent);
 }