Title: [216360] releases/WebKitGTK/webkit-2.16
Revision
216360
Author
carlo...@webkit.org
Date
2017-05-08 01:02:08 -0700 (Mon, 08 May 2017)

Log Message

Merge r215404 - CMD+R / CMD+Q is considered as user interaction and beforeunload alert is shown
https://bugs.webkit.org/show_bug.cgi?id=169995
<rdar://problem/23798897>

Reviewed by Sam Weinig.

Source/WebCore:

Any key event was considered as user interaction with the page, which meant that they
would allow beforeunload alerts to be shown even when they do not represent actual
user interaction (e.g CMD+R / CMD+Q / CMD+T keyboard shortcuts).

To address the issue, we now only treat as user interaction with the page key events
that are actually handled by the page (i.e. handled by JS, typed into a field, ...).

Tests: fast/events/beforeunload-alert-handled-keydown.html
       fast/events/beforeunload-alert-unhandled-keydown.html

* dom/Document.h:
(WebCore::Document::setUserDidInteractWithPage):
(WebCore::Document::userDidInteractWithPage):
* dom/UserGestureIndicator.cpp:
(WebCore::UserGestureIndicator::UserGestureIndicator):
* loader/FrameLoader.cpp:
(WebCore::shouldAskForNavigationConfirmation):
* page/EventHandler.cpp:
(WebCore::EventHandler::keyEvent):
(WebCore::EventHandler::internalKeyEvent):
* page/EventHandler.h:

LayoutTests:

Add layout test coverage.

* fast/events/beforeunload-alert-handled-keydown-expected.txt: Added.
* fast/events/beforeunload-alert-handled-keydown.html: Added.
* fast/events/beforeunload-alert-unhandled-keydown-expected.txt: Added.
* fast/events/beforeunload-alert-unhandled-keydown.html: Added.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog	2017-05-08 08:02:08 UTC (rev 216360)
@@ -1,3 +1,18 @@
+2017-04-16  Chris Dumez  <cdu...@apple.com>
+
+        CMD+R / CMD+Q is considered as user interaction and beforeunload alert is shown
+        https://bugs.webkit.org/show_bug.cgi?id=169995
+        <rdar://problem/23798897>
+
+        Reviewed by Sam Weinig.
+
+        Add layout test coverage.
+
+        * fast/events/beforeunload-alert-handled-keydown-expected.txt: Added.
+        * fast/events/beforeunload-alert-handled-keydown.html: Added.
+        * fast/events/beforeunload-alert-unhandled-keydown-expected.txt: Added.
+        * fast/events/beforeunload-alert-unhandled-keydown.html: Added.
+
 2017-04-14  Zalan Bujtas  <za...@apple.com>
 
         text-align start / end failure in table cells

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown-expected.txt (0 => 216360)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown-expected.txt	2017-05-08 08:02:08 UTC (rev 216360)
@@ -0,0 +1,12 @@
+CONFIRM NAVIGATION: PASS: a beforeunload alert was shown.
+Tests that the beforeunload alert is shown when the user has typed a character into a field. This test passes if you see a 'CONFIRM NAVIGATION' message at the top.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Simulate user typing letter 'a' into the field.
+PASS testInput.value is "a"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown.html (0 => 216360)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-handled-keydown.html	2017-05-08 08:02:08 UTC (rev 216360)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests that the beforeunload alert is shown when the user has typed a character into a field. This test passes if you see a 'CONFIRM NAVIGATION' message at the top.");
+jsTestIsAsync = true;
+
+_onload_ = function() {
+    const testFrame = document.getElementById("testFrame");
+    testFrame.contentWindow._onbeforeunload_ = function(e) {
+        return "PASS: a beforeunload alert was shown.";
+    };
+
+    debug("Simulate user typing letter 'a' into the field.");
+    testInput = document.getElementById("testInput");
+    testInput.focus();
+    if (window.eventSender)
+        eventSender.keyDown("a");
+
+    setTimeout(function() {
+        shouldBeEqualToString("testInput.value", "a");
+        testFrame.src = ""
+        setTimeout(finishJSTest, 0);
+    }, 0);
+};
+</script>
+<iframe id="testFrame" src=""
+<input id="testInput" type="text"></input>
+<script src=""
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown-expected.txt (0 => 216360)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown-expected.txt	2017-05-08 08:02:08 UTC (rev 216360)
@@ -0,0 +1,10 @@
+Tests that the beforeunload alert is not shown in case of unhandled keypress. This test passes if you do NOT see a 'CONFIRM NAVIGATION' message at the top.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Simulate an unhandled user key press.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown.html (0 => 216360)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/fast/events/beforeunload-alert-unhandled-keydown.html	2017-05-08 08:02:08 UTC (rev 216360)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests that the beforeunload alert is not shown in case of unhandled keypress. This test passes if you do NOT see a 'CONFIRM NAVIGATION' message at the top.");
+jsTestIsAsync = true;
+
+_onload_ = function() {
+    const testFrame = document.getElementById("testFrame");
+    testFrame.contentWindow._onbeforeunload_ = function(e) {
+        return "FAIL: a beforeunload alert was shown.";
+    };
+
+    debug("Simulate an unhandled user key press.");
+    if (window.eventSender)
+        eventSender.keyDown("a", ["metaKey"]);
+
+    setTimeout(function() {
+        testFrame.src = ""
+        setTimeout(finishJSTest, 0);
+    }, 0);
+};
+</script>
+<iframe id="testFrame" src=""
+<script src=""
+</body>
+</html>

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog	2017-05-08 08:02:08 UTC (rev 216360)
@@ -1,3 +1,33 @@
+2017-04-16  Chris Dumez  <cdu...@apple.com>
+
+        CMD+R / CMD+Q is considered as user interaction and beforeunload alert is shown
+        https://bugs.webkit.org/show_bug.cgi?id=169995
+        <rdar://problem/23798897>
+
+        Reviewed by Sam Weinig.
+
+        Any key event was considered as user interaction with the page, which meant that they
+        would allow beforeunload alerts to be shown even when they do not represent actual
+        user interaction (e.g CMD+R / CMD+Q / CMD+T keyboard shortcuts).
+
+        To address the issue, we now only treat as user interaction with the page key events
+        that are actually handled by the page (i.e. handled by JS, typed into a field, ...).
+
+        Tests: fast/events/beforeunload-alert-handled-keydown.html
+               fast/events/beforeunload-alert-unhandled-keydown.html
+
+        * dom/Document.h:
+        (WebCore::Document::setUserDidInteractWithPage):
+        (WebCore::Document::userDidInteractWithPage):
+        * dom/UserGestureIndicator.cpp:
+        (WebCore::UserGestureIndicator::UserGestureIndicator):
+        * loader/FrameLoader.cpp:
+        (WebCore::shouldAskForNavigationConfirmation):
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::keyEvent):
+        (WebCore::EventHandler::internalKeyEvent):
+        * page/EventHandler.h:
+
 2017-04-05  Miguel Gomez  <mago...@igalia.com>
 
         [GTK+] PNG animations that should run once are not played at all

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.h (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.h	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.h	2017-05-08 08:02:08 UTC (rev 216360)
@@ -1154,6 +1154,9 @@
     bool hasTouchEventHandlers() const { return false; }
 #endif
 
+    void setUserDidInteractWithPage(bool userDidInteractWithPage) { ASSERT(&topDocument() == this); m_userDidInteractWithPage = userDidInteractWithPage; }
+    bool userDidInteractWithPage() const { ASSERT(&topDocument() == this); return m_userDidInteractWithPage; }
+
     // Used for testing. Count handlers in the main document, and one per frame which contains handlers.
     WEBCORE_EXPORT unsigned wheelEventHandlerCount() const;
     WEBCORE_EXPORT unsigned touchEventHandlerCount() const;
@@ -1735,6 +1738,7 @@
     RefPtr<MediaSession> m_defaultMediaSession;
 #endif
     bool m_areDeviceMotionAndOrientationUpdatesSuspended { false };
+    bool m_userDidInteractWithPage { false };
 
 #if ENABLE(MEDIA_STREAM)
     bool m_hasHadActiveMediaStreamTrack { false };

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/UserGestureIndicator.cpp (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/UserGestureIndicator.cpp	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/UserGestureIndicator.cpp	2017-05-08 08:02:08 UTC (rev 216360)
@@ -54,8 +54,10 @@
     if (state)
         currentToken() = UserGestureToken::create(state.value());
 
-    if (document && currentToken()->processingUserGesture())
+    if (document && currentToken()->processingUserGesture()) {
         document->topDocument().updateLastHandledUserGestureTimestamp();
+        document->topDocument().setUserDidInteractWithPage(true);
+    }
 }
 
 UserGestureIndicator::UserGestureIndicator(RefPtr<UserGestureToken> token)

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/FrameLoader.cpp (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/FrameLoader.cpp	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/FrameLoader.cpp	2017-05-08 08:02:08 UTC (rev 216360)
@@ -2988,7 +2988,7 @@
 
 static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
 {
-    bool userDidInteractWithPage = document.topDocument().lastHandledUserGestureTimestamp() > 0;
+    bool userDidInteractWithPage = document.topDocument().userDidInteractWithPage();
     // Web pages can request we ask for confirmation before navigating by:
     // - Cancelling the BeforeUnloadEvent (modern way)
     // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.cpp (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.cpp	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.cpp	2017-05-08 08:02:08 UTC (rev 216360)
@@ -3093,8 +3093,21 @@
 }
 #endif
 
-bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
+bool EventHandler::keyEvent(const PlatformKeyboardEvent& keyEvent)
 {
+    Document* topDocument = m_frame.document() ? &m_frame.document()->topDocument() : nullptr;
+    bool savedUserDidInteractWithPage = topDocument ? topDocument->userDidInteractWithPage() : false;
+    bool wasHandled = internalKeyEvent(keyEvent);
+
+    // If the key event was not handled, do not treat it as user interaction with the page.
+    if (topDocument && !wasHandled)
+        topDocument->setUserDidInteractWithPage(savedUserDidInteractWithPage);
+
+    return wasHandled;
+}
+
+bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent)
+{
     Ref<Frame> protectedFrame(m_frame);
     RefPtr<FrameView> protector(m_frame.view());
 

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.h (216359 => 216360)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.h	2017-05-08 07:56:02 UTC (rev 216359)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/page/EventHandler.h	2017-05-08 08:02:08 UTC (rev 216360)
@@ -347,6 +347,8 @@
 
     WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
 
+    bool internalKeyEvent(const PlatformKeyboardEvent&);
+
     std::optional<Cursor> selectCursor(const HitTestResult&, bool shiftKey);
     void updateCursor(FrameView&, const HitTestResult&, bool shiftKey);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to