webkitRequestPointerLock and webkitExitPointerLock limited to the same document of...
authorscheib@chromium.org <scheib@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Aug 2012 05:10:30 +0000 (05:10 +0000)
committerscheib@chromium.org <scheib@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Aug 2012 05:10:30 +0000 (05:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=91284

Reviewed by Adrienne Walker.

Previously, cross-talk between documents was possible, e.g. allowing one
document.webkitExitPointerLock to exit the lock from another document.
This change brings Pointer Lock closer to the Fullscreen API behavior,
and stops the pointer lock target from being transferable between
documents.

Source/WebCore:

Test: http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html

* dom/Document.cpp:
(WebCore::Document::webkitExitPointerLock):
* page/PointerLockController.cpp:
(WebCore::PointerLockController::requestPointerLock):

LayoutTests:

* http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt: Added.
* http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html: Added.
* http/tests/resources/pointer-lock/iframe-common.js:
(document.onwebkitpointerlockchange):
(document.onwebkitpointerlockerror):
* pointer-lock/pointerlockchange-pointerlockerror-events-expected.txt:
* pointer-lock/pointerlockchange-pointerlockerror-events.html:

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

LayoutTests/ChangeLog
LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html [new file with mode: 0644]
LayoutTests/http/tests/resources/pointer-lock/iframe-common.js
LayoutTests/pointer-lock/pointerlockchange-pointerlockerror-events-expected.txt
LayoutTests/pointer-lock/pointerlockchange-pointerlockerror-events.html
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/page/PointerLockController.cpp

index 10f7e5e..bc7e17c 100644 (file)
@@ -1,3 +1,24 @@
+2012-07-31  Vincent Scheib  <scheib@chromium.org>
+
+        webkitRequestPointerLock and webkitExitPointerLock limited to the same document of an active Pointer lock.
+        https://bugs.webkit.org/show_bug.cgi?id=91284
+
+        Reviewed by Adrienne Walker.
+
+        Previously, cross-talk between documents was possible, e.g. allowing one
+        document.webkitExitPointerLock to exit the lock from another document.
+        This change brings Pointer Lock closer to the Fullscreen API behavior,
+        and stops the pointer lock target from being transferable between
+        documents.
+
+        * http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt: Added.
+        * http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html: Added.
+        * http/tests/resources/pointer-lock/iframe-common.js:
+        (document.onwebkitpointerlockchange):
+        (document.onwebkitpointerlockerror):
+        * pointer-lock/pointerlockchange-pointerlockerror-events-expected.txt:
+        * pointer-lock/pointerlockchange-pointerlockerror-events.html:
+
 2012-07-31  Ami Fischman  <fischman@chromium.org>
 
         [Chromium][Mac] Assertion failure in null_audio_sink.cc running WebGL video layout test on 10.5 debug bots
diff --git a/LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt b/LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt
new file mode 100644 (file)
index 0000000..e81ddc4
--- /dev/null
@@ -0,0 +1,13 @@
+Test iframe from same origin can not transfer pointer lock across documents.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+     Lock targetDiv1.
+PASS onwebkitpointerlockchange received after: Lock targetDiv1.
+PASS document.webkitPointerLockElement is targetDiv1
+PASS message is "inner-iframe.html onwebkitpointerlockerror"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html b/LayoutTests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html
new file mode 100644 (file)
index 0000000..f82ac2b
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+<script src="../resources/pointer-lock/pointer-lock-test-harness.js"></script>
+</head>
+<body>
+<div>
+  <div id="target1"></div>
+  <iframe src="../resources/pointer-lock/inner-iframe.html" onload="doNextStepWithUserGesture()"></iframe>
+</div>
+<script>
+    description("Test iframe from same origin can not transfer pointer lock across documents.")
+    window.jsTestIsAsync = true;
+
+    targetDiv1 = document.getElementById("target1");
+    iframe = document.getElementsByTagName("iframe")[0];
+
+    todo = [
+      function () {
+          expectOnlyChangeEvent("Lock targetDiv1.");
+          targetDiv1.webkitRequestPointerLock();
+          // doNextStep called by event handler.
+      },
+      function () {
+          shouldBe("document.webkitPointerLockElement", "targetDiv1");
+          doNextStep();
+      },
+      function () {
+          iframe.contentWindow.postMessage(["eval", 'document.body.webkitRequestPointerLock()'], "*");
+          window.onmessage = function (messageEvent) {
+              message = messageEvent.data;
+              shouldBeEqualToString("message", "inner-iframe.html onwebkitpointerlockerror");
+              window.onmessage = null;
+              doNextStep();
+          }
+      },
+      function () {
+          iframe.contentWindow.postMessage(["eval", 'document.webkitExitPointerLock()'], "*");
+          window.onmessage = function (messageEvent) {
+              testFailed("webkitExitPointerLock from a document that doesn't have a lock caused an event " + messageEvent.data);
+              finishJSTest();
+          }
+          doNextStep();
+      },
+    ];
+    // doNextStep() called by iframe onload handler.
+</script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
index c22c21e..524331f 100644 (file)
@@ -11,3 +11,10 @@ window.onmessage = function (messageEvent) {
     }
 }
 
+document.onwebkitpointerlockchange = function () {
+    parent.postMessage(thisFileName() + " onwebkitpointerlockchange, document.webkitPointerLockElement = " + document.webkitPointerLockElement, "*");
+}
+
+document.onwebkitpointerlockerror = function () {
+    parent.postMessage(thisFileName() + " onwebkitpointerlockerror", "*");
+}
index c5b13e0..f75145e 100644 (file)
@@ -14,19 +14,19 @@ PASS onwebkitpointerlockchange received after: Lock targetDiv1 again.
 PASS onwebkitpointerlockchange received after: Lock targetDiv2.
      Lock targetDiv2 again.
 PASS onwebkitpointerlockchange received after: Lock targetDiv2 again.
+     Unlock targetDiv2.
+PASS onwebkitpointerlockchange received after: Unlock targetDiv2.
      Lock targetIframe1.
      Lock targetIframe1 (handler for iframe1).
 PASS onwebkitpointerlockchange received after: Lock targetIframe1 (handler for iframe1).
-PASS onwebkitpointerlockchange received after: Lock targetIframe1.
      Lock targetIframe2.
      Lock targetIframe2 (handler for iframe1).
      Lock targetIframe2 (handler for iframe2).
-PASS onwebkitpointerlockchange received after: Lock targetIframe2 (handler for iframe2).
-PASS onwebkitpointerlockchange received after: Lock targetIframe2 (handler for iframe1).
+PASS onwebkitpointerlockerror received after: Lock targetIframe2 (handler for iframe2).
      Unlock targetIframe2.
      Unlock targetIframe2 (handler for iframe1).
      Unlock targetIframe2 (handler for iframe2).
-PASS onwebkitpointerlockchange received after: Unlock targetIframe2 (handler for iframe2).
+PASS onwebkitpointerlockchange received after: Unlock targetIframe2 (handler for iframe1).
 PASS testRunner.setPointerLockWillFailSynchronously is defined.
      Lock with synchronous failure.
 PASS onwebkitpointerlockerror received after: Lock with synchronous failure.
index f795559..b652fe0 100644 (file)
             targetDiv2.webkitRequestPointerLock();
         },
         function () {
+            expectOnlyChangeEvent("Unlock targetDiv2.");
+            document.webkitExitPointerLock();
+        },
+        function () {
             targetIframe1.src = "about:blank";
             targetIframe1.onload = function () { doNextStep(); }
         },
             targetIframe2.onload = function () { doNextStep(); }
         },
         function () {
-            expectOnlyChangeEvent("Lock targetIframe1.");
+            expectNoEvents("Lock targetIframe1.");
             expectOnlyChangeEvent("Lock targetIframe1 (handler for iframe1).", targetIframe1.contentDocument);
             targetIframe1.contentDocument.body.webkitRequestPointerLock();
         },
         function () {
-            // Absorb an extra doNextStep() from previous event handlers.
-        },
-        function () {
             expectNoEvents("Lock targetIframe2.");
-            expectOnlyChangeEvent("Lock targetIframe2 (handler for iframe1).", targetIframe1.contentDocument);
-            expectOnlyChangeEvent("Lock targetIframe2 (handler for iframe2).", targetIframe2.contentDocument);
+            expectNoEvents("Lock targetIframe2 (handler for iframe1).", targetIframe1.contentDocument);
+            expectOnlyErrorEvent("Lock targetIframe2 (handler for iframe2).", targetIframe2.contentDocument);
             targetIframe2.contentDocument.body.webkitRequestPointerLock();
         },
         function () {
-            // Absorb an extra doNextStep() from previous event handlers.
-        },
-        function () {
             expectNoEvents("Unlock targetIframe2.");
-            expectNoEvents("Unlock targetIframe2 (handler for iframe1).", targetIframe1.contentDocument);
-            expectOnlyChangeEvent("Unlock targetIframe2 (handler for iframe2).", targetIframe2.contentDocument);
-            document.webkitExitPointerLock();
+            expectOnlyChangeEvent("Unlock targetIframe2 (handler for iframe1).", targetIframe1.contentDocument);
+            expectNoEvents("Unlock targetIframe2 (handler for iframe2).", targetIframe2.contentDocument);
+            targetIframe1.contentDocument.webkitExitPointerLock();
         },
         function () {
             shouldBeDefined("testRunner.setPointerLockWillFailSynchronously");
index 2b432cc..0d185d3 100644 (file)
@@ -1,3 +1,23 @@
+2012-07-31  Vincent Scheib  <scheib@chromium.org>
+
+        webkitRequestPointerLock and webkitExitPointerLock limited to the same document of an active Pointer lock.
+        https://bugs.webkit.org/show_bug.cgi?id=91284
+
+        Reviewed by Adrienne Walker.
+
+        Previously, cross-talk between documents was possible, e.g. allowing one
+        document.webkitExitPointerLock to exit the lock from another document.
+        This change brings Pointer Lock closer to the Fullscreen API behavior,
+        and stops the pointer lock target from being transferable between
+        documents.
+
+        Test: http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::webkitExitPointerLock):
+        * page/PointerLockController.cpp:
+        (WebCore::PointerLockController::requestPointerLock):
+
 2012-07-31  Keishi Hattori  <keishi@webkit.org>
 
         ColorInputType::typeMismatchFor is returning the opposite bool
index 169d8a5..52b44e7 100644 (file)
@@ -5829,8 +5829,13 @@ void Document::addDocumentToFullScreenChangeEventQueue(Document* doc)
 #if ENABLE(POINTER_LOCK)
 void Document::webkitExitPointerLock()
 {
-    if (page())
-        page()->pointerLockController()->requestPointerUnlock();
+    if (!page())
+        return;
+    if (Element* target = page()->pointerLockController()->element()) {
+        if (target->document() != this)
+            return;
+    }
+    page()->pointerLockController()->requestPointerUnlock();
 }
 
 Element* Document::webkitPointerLockElement() const
index abbfc80..f49668d 100644 (file)
@@ -54,6 +54,11 @@ void PointerLockController::requestPointerLock(Element* target, PassRefPtr<VoidC
     }
 
     if (m_element) {
+        if (m_element->document() != target->document()) {
+            enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
+            return;
+        }
+
         // FIXME: Keep enqueueEvent usage. (https://bugs.webkit.org/show_bug.cgi?id=84402)
         enqueueEvent(eventNames().webkitpointerlockchangeEvent, target);
         if (m_element->document() != target->document())