<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214277] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214277">214277</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2017-03-22 14:14:23 -0700 (Wed, 22 Mar 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>WebKit should disallow beforeunload alerts from web pages users have never interacted with
https://bugs.webkit.org/show_bug.cgi?id=169936
<rdar://problem/23798897>
Reviewed by Brent Fulgham.
LayoutTests/imported/w3c:
* web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt:
* web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt:
Rebaseline now that the CONFIRM MESSAGE lines are now longer shown. This is because there is no user interaction
with the page.
Source/WebCore:
WebKit should disallow beforeunload alerts from web pages users have never interacted with.
This reduces the risk of annoyance to the user and is allowed by the specification:
- https://html.spec.whatwg.org/multipage/browsers.html#prompt-to-unload-a-document (Step 8):
which says:
"""
The user agent is encouraged to avoid asking the user for confirmation if it judges that doing
so would be annoying, deceptive, or pointless. A simple heuristic might be that if the user
has not interacted with the document, the user agent would not ask for confirmation before
unloading it.
"""
Firefox already implements this, Chrome does not.
Tests: fast/events/beforeunload-alert-no-user-interaction.html
fast/events/beforeunload-alert-user-interaction.html
fast/events/beforeunload-alert-user-interaction2.html
* loader/FrameLoader.cpp:
(WebCore::shouldAskForNavigationConfirmation):
(WebCore::FrameLoader::dispatchBeforeUnloadEvent):
LayoutTests:
* fast/events/before-unload-return-string-conversion-expected.txt:
* fast/events/before-unload-returnValue-expected.txt:
Rebaseline now that the CONFIRM MESSAGE is no longer shown. This is because there is
no user interaction with the page.
* fast/events/beforeunload-alert-no-user-interaction-expected.txt: Added.
* fast/events/beforeunload-alert-no-user-interaction.html: Added.
* fast/events/beforeunload-alert-user-interaction-expected.txt: Added.
* fast/events/beforeunload-alert-user-interaction.html: Added.
* fast/events/beforeunload-alert-user-interaction2-expected.txt: Added.
* fast/events/beforeunload-alert-user-interaction2.html: Added.
Add layout test coverage.
* fast/loader/form-submission-after-beforeunload-cancel.html:
* fast/loader/show-only-one-beforeunload-dialog.html:
* http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html:
* http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html:
Simulate user interaction with the page so that the CONFIRM MESSAGE log lines are still
shown.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadreturnstringconversionexpectedtxt">trunk/LayoutTests/fast/events/before-unload-return-string-conversion-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadreturnValueexpectedtxt">trunk/LayoutTests/fast/events/before-unload-returnValue-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastloaderformsubmissionafterbeforeunloadcancelhtml">trunk/LayoutTests/fast/loader/form-submission-after-beforeunload-cancel.html</a></li>
<li><a href="#trunkLayoutTestsfastloadershowonlyonebeforeunloaddialoghtml">trunk/LayoutTests/fast/loader/show-only-one-beforeunload-dialog.html</a></li>
<li><a href="#trunkLayoutTestshttptestsmisciframebeforeunloaddialogmatchingancestorsecurityoriginhtml">trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html</a></li>
<li><a href="#trunkLayoutTestshttptestsmisciframebeforeunloaddialognotmatchingancestorsecurityoriginhtml">trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestshtmlbrowsersbrowsingthewebunloadingdocumentsbeforeunloadcancelingexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestshtmlwebappapisscriptingeventscompileeventhandlersettingsobjectsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloaderFrameLoadercpp">trunk/Source/WebCore/loader/FrameLoader.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertnouserinteractionexpectedtxt">trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertnouserinteractionhtml">trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertuserinteractionexpectedtxt">trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertuserinteractionhtml">trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertuserinteraction2expectedtxt">trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsbeforeunloadalertuserinteraction2html">trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/ChangeLog        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2017-03-22 Chris Dumez <cdumez@apple.com>
+
+ WebKit should disallow beforeunload alerts from web pages users have never interacted with
+ https://bugs.webkit.org/show_bug.cgi?id=169936
+ <rdar://problem/23798897>
+
+ Reviewed by Brent Fulgham.
+
+ * fast/events/before-unload-return-string-conversion-expected.txt:
+ * fast/events/before-unload-returnValue-expected.txt:
+ Rebaseline now that the CONFIRM MESSAGE is no longer shown. This is because there is
+ no user interaction with the page.
+
+ * fast/events/beforeunload-alert-no-user-interaction-expected.txt: Added.
+ * fast/events/beforeunload-alert-no-user-interaction.html: Added.
+ * fast/events/beforeunload-alert-user-interaction-expected.txt: Added.
+ * fast/events/beforeunload-alert-user-interaction.html: Added.
+ * fast/events/beforeunload-alert-user-interaction2-expected.txt: Added.
+ * fast/events/beforeunload-alert-user-interaction2.html: Added.
+ Add layout test coverage.
+
+ * fast/loader/form-submission-after-beforeunload-cancel.html:
+ * fast/loader/show-only-one-beforeunload-dialog.html:
+ * http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html:
+ * http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html:
+ Simulate user interaction with the page so that the CONFIRM MESSAGE log lines are still
+ shown.
+
</ins><span class="cx"> 2017-03-22 Nan Wang <n_wang@apple.com>
</span><span class="cx">
</span><span class="cx"> AX: WebKit is returning the wrong rangeForLine
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadreturnstringconversionexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/before-unload-return-string-conversion-expected.txt (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/before-unload-return-string-conversion-expected.txt        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/fast/events/before-unload-return-string-conversion-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-CONFIRM NAVIGATION: PASS
</del><span class="cx"> Tests that the value returned from a beforeunload event handler gets converted to a string, even if the returnValue property was already set.
</span><span class="cx">
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadreturnValueexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/before-unload-returnValue-expected.txt (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/before-unload-returnValue-expected.txt        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/fast/events/before-unload-returnValue-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-CONFIRM NAVIGATION: This is beforeunload from the top level frame.
</del><span class="cx"> Tests the returnValue attribute of the BeforeUnloadEvent.
</span><span class="cx">
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertnouserinteractionexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction-expected.txt (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+Tests that the beforeunload alert is not shown when the user did not interact with the page. You should NOT see a 'CONFIRM NAVIGATION' message at the top.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertnouserinteractionhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction.html (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction.html         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-no-user-interaction.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test-pre.js"></script>
+<script>
+description("Tests that the beforeunload alert is not shown when the user did not interact with the page. You should 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 even though the user did not interact with the page.";
+ };
+ setTimeout(function() {
+ testFrame.src = "about:blank";
+ setTimeout(finishJSTest, 0);
+ }, 0);
+};
+</script>
+<iframe id="testFrame" src="resources/onclick.html"></iframe>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertuserinteractionexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction-expected.txt (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+CONFIRM NAVIGATION: PASS: a beforeunload alert was shown.
+Tests that the beforeunload alert is shown when the user interacted with the page. You should see a 'CONFIRM NAVIGATION' message at the top.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertuserinteractionhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction.html (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction.html         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test-pre.js"></script>
+<script>
+description("Tests that the beforeunload alert is shown when the user interacted with the page. You should 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.";
+ };
+ // Simulate a user interaction.
+ const testInput = document.getElementById("testInput");
+ testInput.focus();
+ if (window.eventSender)
+ eventSender.keyDown("a");
+ setTimeout(function() {
+ testFrame.src = "about:blank";
+ setTimeout(finishJSTest, 0);
+ }, 0);
+};
+</script>
+<iframe id="testFrame" src="resources/onclick.html"></iframe>
+<input id="testInput" type="text"></input>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertuserinteraction2expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2-expected.txt (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+CONFIRM NAVIGATION: PASS: a beforeunload alert was shown.
+Tests that the beforeunload alert is shown when the user interacted with the page. You should see a 'CONFIRM NAVIGATION' message at the top.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsbeforeunloadalertuserinteraction2html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2.html (0 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2.html         (rev 0)
+++ trunk/LayoutTests/fast/events/beforeunload-alert-user-interaction2.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../../resources/ui-helper.js"></script>
+<script>
+description("Tests that the beforeunload alert is shown when the user interacted with the page. You should 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.";
+ };
+ // Simulate a user interaction.
+ const testInput = document.getElementById("testInput");
+ UIHelper.activateAt(testInput.offsetLeft + 5, testInput.offsetTop + 5).then(function() {
+ setTimeout(function() {
+ testFrame.src = "about:blank";
+ setTimeout(finishJSTest, 0);
+ }, 0);
+ });
+};
+</script>
+<iframe id="testFrame" src="resources/onclick.html"></iframe>
+<input id="testInput" type="text"></input>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfastloaderformsubmissionafterbeforeunloadcancelhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/loader/form-submission-after-beforeunload-cancel.html (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/loader/form-submission-after-beforeunload-cancel.html        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/fast/loader/form-submission-after-beforeunload-cancel.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><ins>+<script src="../../resources/ui-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx"> if (window.testRunner) {
</span><span class="cx"> testRunner.waitUntilDone();
</span><span class="lines">@@ -7,6 +8,11 @@
</span><span class="cx">
</span><span class="cx"> _confirmationDialogDisplayedOnce = false;
</span><span class="cx">
</span><ins>+function submitForm()
+{
+ document.forms[0].submit();
+}
+
</ins><span class="cx"> window.addEventListener("beforeunload", function() {
</span><span class="cx">
</span><span class="cx"> if (window._confirmationDialogDisplayedOnce)
</span><span class="lines">@@ -34,10 +40,12 @@
</span><span class="cx"> <p>This tests that submitting a form a second time after canceling the first submission in a onbeforeunload handler is allowed. To test manually, follow the instructions in the JavaScript confirmation dialogs.</p>
</span><span class="cx">
</span><span class="cx"> <div id="console"></div>
</span><del>-
</del><ins>+<input id="testButton" type="button" value="Click to submit form" onclick="submitForm()">
</ins><span class="cx"> <form action="resources/pass-and-notify-done.html" method="POST">
</span><span class="cx"> </form>
</span><span class="cx">
</span><span class="cx"> <script>
</span><del>-document.forms[0].submit();
-</script>
</del><span class="cx">\ No newline at end of file
</span><ins>+// Simulate a user interaction with the page so that the beforeunload alert shows.
+const testButton = document.getElementById("testButton");
+UIHelper.activateAt(testButton.offsetLeft + 5, testButton.offsetTop + 5);
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsfastloadershowonlyonebeforeunloaddialoghtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/loader/show-only-one-beforeunload-dialog.html (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/loader/show-only-one-beforeunload-dialog.html        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/fast/loader/show-only-one-beforeunload-dialog.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><ins>+<script src="../../resources/ui-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx">
</span><span class="cx"> if (window.testRunner) {
</span><span class="lines">@@ -5,9 +6,16 @@
</span><span class="cx">         testRunner.waitUntilDone();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+function navigateFrame()
+{
+        window.location.href = 'resources/notify-done.html';
+}
+
</ins><span class="cx"> window.onload = function()
</span><span class="cx"> {
</span><del>-        window.setTimeout("window.location.href = 'resources/notify-done.html';", 0);
</del><ins>+        // Simulate a user interaction with the page so that the beforeunload alert shows.
+        const testButton = document.getElementById("testButton");
+        UIHelper.activateAt(testButton.offsetLeft + 5, testButton.offsetTop + 5);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> window.onbeforeunload = function()
</span><span class="lines">@@ -20,6 +28,7 @@
</span><span class="cx"> This page has multiple iframes, each trying to bring up a beforeunload dialog.<br>
</span><span class="cx"> This page also has a beforeunload dialog, itself.<br>
</span><span class="cx"> Only the dialog from this top-level frame should display, and none of the iframe ones should display.<br>
</span><ins>+<input id="testButton" type="button" value="Click to navigate" onclick="navigateFrame()"><br>
</ins><span class="cx"> <iframe src="resources/iframe-with-beforeunload.html"></iframe><br>
</span><span class="cx"> <iframe src="resources/iframe-with-beforeunload.html"></iframe><br>
</span><span class="cx"> </body>
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsmisciframebeforeunloaddialogmatchingancestorsecurityoriginhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-matching-ancestor-securityorigin.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><ins>+<script src="/js-test-resources/ui-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx">
</span><span class="cx"> if (window.testRunner) {
</span><span class="lines">@@ -5,9 +6,16 @@
</span><span class="cx">         testRunner.waitUntilDone();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+function navigateFrame()
+{
+        window.location.href = 'resources/notify-done.html';
+}
+
</ins><span class="cx"> window.onload = function()
</span><span class="cx"> {
</span><del>-        window.setTimeout("window.location.href = 'resources/notify-done.html';", 0);
</del><ins>+        // Simulate a user interaction with the page so that the beforeunload alert shows.
+        const testButton = document.getElementById("testButton");
+        UIHelper.activateAt(testButton.offsetLeft + 5, testButton.offsetTop + 5);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> </script>
</span><span class="lines">@@ -14,5 +22,6 @@
</span><span class="cx"> <body>
</span><span class="cx"> When viewed using the host 127.0.0.1, this page has an iframe whose security origin matches the main frame.<br>
</span><span class="cx"> The iframe has a beforeunload handler, and that handler should result in the display of the page dismissal dialog.<br>
</span><ins>+<input id="testButton" type="button" value="Click to navigate" onclick="navigateFrame()">
</ins><span class="cx"> <iframe src="http://127.0.0.1:8000/misc/resources/iframe-with-beforeunload.html"></iframe><br>
</span><span class="cx"> </body>
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsmisciframebeforeunloaddialognotmatchingancestorsecurityoriginhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/http/tests/misc/iframe-beforeunload-dialog-not-matching-ancestor-securityorigin.html        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><ins>+<script src="/js-test-resources/ui-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx">
</span><span class="cx"> if (window.testRunner) {
</span><span class="lines">@@ -5,9 +6,16 @@
</span><span class="cx">         testRunner.waitUntilDone();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+function navigateFrame()
+{
+        window.location.href = 'resources/notify-done.html';
+}
+
</ins><span class="cx"> window.onload = function()
</span><span class="cx"> {
</span><del>-        window.setTimeout("window.location.href = 'resources/notify-done.html';", 0);
</del><ins>+        // Simulate a user interaction with the page so that the beforeunload alert shows.
+        const testButton = document.getElementById("testButton");
+        UIHelper.activateAt(testButton.offsetLeft + 5, testButton.offsetTop + 5);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> </script>
</span><span class="lines">@@ -14,5 +22,6 @@
</span><span class="cx"> <body>
</span><span class="cx"> When viewed using the host 127.0.0.1, this page has an iframe whose security origin is different from the main frame.<br>
</span><span class="cx"> The iframe has a beforeunload handler, and that handler should not result in the display of the page dismissal dialog since the security origins differ.<br>
</span><ins>+<input id="testButton" type="button" value="Click to navigate" onclick="navigateFrame()"><br>
</ins><span class="cx"> <iframe src="http://localhost:8000/misc/resources/iframe-with-beforeunload.html"></iframe><br>
</span><span class="cx"> </body>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/imported/w3c/ChangeLog        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2017-03-22 Chris Dumez <cdumez@apple.com>
+
+ WebKit should disallow beforeunload alerts from web pages users have never interacted with
+ https://bugs.webkit.org/show_bug.cgi?id=169936
+ <rdar://problem/23798897>
+
+ Reviewed by Brent Fulgham.
+
+ * web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt:
+ * web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt:
+ Rebaseline now that the CONFIRM MESSAGE lines are now longer shown. This is because there is no user interaction
+ with the page.
+
</ins><span class="cx"> 2017-03-22 Romain Bellessort <romain.bellessort@crf.canon.fr>
</span><span class="cx">
</span><span class="cx"> [Readable Streams API] Implement ReadableStreamBYOBRequest respond() (readable stream state)
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestshtmlbrowsersbrowsingthewebunloadingdocumentsbeforeunloadcancelingexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,13 +1,3 @@
</span><del>-CONFIRM NAVIGATION:
-CONFIRM NAVIGATION: false
-CONFIRM NAVIGATION: true
-CONFIRM NAVIGATION: 0
-CONFIRM NAVIGATION: foo
-CONFIRM NAVIGATION: foo
-CONFIRM NAVIGATION: foo
-CONFIRM NAVIGATION: foo
-CONFIRM NAVIGATION: foo
-CONFIRM NAVIGATION: foo
</del><span class="cx">
</span><span class="cx"> PASS Returning a string must not cancel the event: CustomEvent, non-cancelable
</span><span class="cx"> PASS Returning a string must not cancel the event: CustomEvent, cancelable
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestshtmlwebappapisscriptingeventscompileeventhandlersettingsobjectsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-CONFIRM NAVIGATION: undefined
</del><span class="cx">
</span><span class="cx"> PASS The Function instance must be created in the Realm of the node document
</span><span class="cx"> FAIL The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document assert_equals: expected "/html/webappapis/scripting/events/resources/open-window.html" but got "/html/webappapis/scripting/events/open-window.html"
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -363,6 +363,7 @@
</span><span class="cx"> # This test relies on EventSender.keydown(), which is not supported on iOS
</span><span class="cx"> editing/caret/emoji.html [ Skip ]
</span><span class="cx"> webkit.org/b/155233 fast/events/max-tabindex-focus.html [ Skip ]
</span><ins>+fast/events/beforeunload-alert-user-interaction.html [ Skip ]
</ins><span class="cx"> fast/forms/validation-bubble-escape-key-dismiss.html [ Skip ]
</span><span class="cx"> fast/forms/validation-message-maxLength.html [ Skip ]
</span><span class="cx"> fast/shadow-dom/shadow-host-removal-crash.html [ Skip ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/Source/WebCore/ChangeLog        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2017-03-22 Chris Dumez <cdumez@apple.com>
+
+ WebKit should disallow beforeunload alerts from web pages users have never interacted with
+ https://bugs.webkit.org/show_bug.cgi?id=169936
+ <rdar://problem/23798897>
+
+ Reviewed by Brent Fulgham.
+
+ WebKit should disallow beforeunload alerts from web pages users have never interacted with.
+ This reduces the risk of annoyance to the user and is allowed by the specification:
+ - https://html.spec.whatwg.org/multipage/browsers.html#prompt-to-unload-a-document (Step 8):
+ which says:
+ """
+ The user agent is encouraged to avoid asking the user for confirmation if it judges that doing
+ so would be annoying, deceptive, or pointless. A simple heuristic might be that if the user
+ has not interacted with the document, the user agent would not ask for confirmation before
+ unloading it.
+ """
+
+ Firefox already implements this, Chrome does not.
+
+ Tests: fast/events/beforeunload-alert-no-user-interaction.html
+ fast/events/beforeunload-alert-user-interaction.html
+ fast/events/beforeunload-alert-user-interaction2.html
+
+ * loader/FrameLoader.cpp:
+ (WebCore::shouldAskForNavigationConfirmation):
+ (WebCore::FrameLoader::dispatchBeforeUnloadEvent):
+
</ins><span class="cx"> 2017-03-22 Brent Fulgham <bfulgham@apple.com>
</span><span class="cx">
</span><span class="cx"> ASan violation in IconLoader::stopLoading
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderFrameLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (214276 => 214277)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/FrameLoader.cpp        2017-03-22 20:46:31 UTC (rev 214276)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp        2017-03-22 21:14:23 UTC (rev 214277)
</span><span class="lines">@@ -3068,14 +3068,15 @@
</span><span class="cx"> m_frame.document()->removeAllEventListeners();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static bool shouldAskForNavigationConfirmation(const BeforeUnloadEvent& event)
</del><ins>+static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
</ins><span class="cx"> {
</span><ins>+ bool userDidInteractWithPage = document.topDocument().lastHandledUserGestureTimestamp() > 0;
</ins><span class="cx"> // Web pages can request we ask for confirmation before navigating by:
</span><span class="cx"> // - Cancelling the BeforeUnloadEvent (modern way)
</span><span class="cx"> // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.
</span><span class="cx"> // - Returning a non-empty string from the event handler, which is then set as returnValue
</span><span class="cx"> // attribute on the BeforeUnloadEvent.
</span><del>- return event.defaultPrevented() || !event.returnValue().isEmpty();
</del><ins>+ return userDidInteractWithPage && (event.defaultPrevented() || !event.returnValue().isEmpty());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
</span><span class="lines">@@ -3102,7 +3103,7 @@
</span><span class="cx"> if (!beforeUnloadEvent->defaultPrevented())
</span><span class="cx"> document->defaultEventHandler(beforeUnloadEvent.get());
</span><span class="cx">
</span><del>- if (!shouldAskForNavigationConfirmation(beforeUnloadEvent))
</del><ins>+ if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
</ins><span class="cx"> return true;
</span><span class="cx">
</span><span class="cx"> // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
</span></span></pre>
</div>
</div>
</body>
</html>