Title: [225645] trunk
Revision
225645
Author
achristen...@apple.com
Date
2017-12-07 13:59:48 -0800 (Thu, 07 Dec 2017)

Log Message

Always synchronously continue with fragment navigations
https://bugs.webkit.org/show_bug.cgi?id=180544
<rdar://problem/34815986> and <rdar://problem/35126690>

Reviewed by Geoffrey Garen.

Source/WebCore:

Test: http/tests/dom/document-fragment.html

When a decidePolicyForNavigationAction completionHandler is called asynchronously,
the document's URL has not changed yet when _javascript_ execution continues.  This causes
significant web incompatibility because all browsers change the document's URL immediately
during fragment navigations.  In order to make WebKit applications more web compatible,
we now immediately continue to have the state consistent.  To keep compatibility with any
WebView, UIWebView, or WKWebView applications that use these delegate callbacks to update
state, we still call decidePolicyForNavigationAction.  This would break a theoretical app
that would cancel fragment navigations, but it fixes apps that continue fragment navigations
asynchronously.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::loadWithDocumentLoader):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/DecidePolicyForNavigationAction.mm:
(-[DecidePolicyForNavigationActionFragmentDelegate webView:decidePolicyForNavigationAction:decisionHandler:]):
(TEST):
Add a test that verifies that decidePolicyForNavigationAction is called for fragment navigations.

LayoutTests:

* http/tests/dom/document-fragment-expected.txt: Added.
* http/tests/dom/document-fragment.html: Added.
Add a test that verifies that the fragment of the document is set immediately during a fragment navigation,
even if decidePolicyForNavigationAction is called asynchronously.  Also verify the order of various events
associated with the navigation.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225644 => 225645)


--- trunk/LayoutTests/ChangeLog	2017-12-07 21:46:11 UTC (rev 225644)
+++ trunk/LayoutTests/ChangeLog	2017-12-07 21:59:48 UTC (rev 225645)
@@ -1,3 +1,17 @@
+2017-12-07  Alex Christensen  <achristen...@webkit.org>
+
+        Always synchronously continue with fragment navigations
+        https://bugs.webkit.org/show_bug.cgi?id=180544
+        <rdar://problem/34815986> and <rdar://problem/35126690>
+
+        Reviewed by Geoffrey Garen.
+
+        * http/tests/dom/document-fragment-expected.txt: Added.
+        * http/tests/dom/document-fragment.html: Added.
+        Add a test that verifies that the fragment of the document is set immediately during a fragment navigation,
+        even if decidePolicyForNavigationAction is called asynchronously.  Also verify the order of various events
+        associated with the navigation.
+
 2017-12-07  Youenn Fablet  <you...@apple.com>
 
         Activate IDB and WebSockets in service workers

Added: trunk/LayoutTests/http/tests/dom/document-fragment-expected.txt (0 => 225645)


--- trunk/LayoutTests/http/tests/dom/document-fragment-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/dom/document-fragment-expected.txt	2017-12-07 21:59:48 UTC (rev 225645)
@@ -0,0 +1,2 @@
+ALERT: continuing with correct fragment, promise, popstate, hashchange, timeout
+

Added: trunk/LayoutTests/http/tests/dom/document-fragment.html (0 => 225645)


--- trunk/LayoutTests/http/tests/dom/document-fragment.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/dom/document-fragment.html	2017-12-07 21:59:48 UTC (rev 225645)
@@ -0,0 +1,27 @@
+<script>
+
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+    if (testRunner.setShouldDecideNavigationPolicyAfterDelay)
+        testRunner.setShouldDecideNavigationPolicyAfterDelay(true);
+}
+
+var events = [];
+function eventHappened(eventName) {
+    events.push(eventName);
+    if (events.length == 5) {
+        alert(events[0] + ", " + events[1] + ", " + events[2] + ", " + events[3] + ", " + events[4]);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+}
+
+window._onhashchange_ = ()=>{ eventHappened("hashchange") }
+window._onpopstate_ = ()=>{ eventHappened("popstate") };
+window.location.href = ""
+Promise.resolve().then(()=>{ eventHappened("promise") });
+setTimeout(()=>{ eventHappened("timeout") }, 0)
+eventHappened("continuing with " + (document.URL.endsWith("#fragment") ? "correct fragment" : "incorrect fragment"));
+
+</script>

Modified: trunk/Source/WebCore/ChangeLog (225644 => 225645)


--- trunk/Source/WebCore/ChangeLog	2017-12-07 21:46:11 UTC (rev 225644)
+++ trunk/Source/WebCore/ChangeLog	2017-12-07 21:59:48 UTC (rev 225645)
@@ -1,3 +1,27 @@
+2017-12-07  Alex Christensen  <achristen...@webkit.org>
+
+        Always synchronously continue with fragment navigations
+        https://bugs.webkit.org/show_bug.cgi?id=180544
+        <rdar://problem/34815986> and <rdar://problem/35126690>
+
+        Reviewed by Geoffrey Garen.
+
+        Test: http/tests/dom/document-fragment.html
+
+        When a decidePolicyForNavigationAction completionHandler is called asynchronously,
+        the document's URL has not changed yet when _javascript_ execution continues.  This causes
+        significant web incompatibility because all browsers change the document's URL immediately
+        during fragment navigations.  In order to make WebKit applications more web compatible,
+        we now immediately continue to have the state consistent.  To keep compatibility with any
+        WebView, UIWebView, or WKWebView applications that use these delegate callbacks to update
+        state, we still call decidePolicyForNavigationAction.  This would break a theoretical app
+        that would cancel fragment navigations, but it fixes apps that continue fragment navigations
+        asynchronously.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadURL):
+        (WebCore::FrameLoader::loadWithDocumentLoader):
+
 2017-12-07  Youenn Fablet  <you...@apple.com>
 
         Activate IDB and WebSockets in service workers

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (225644 => 225645)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2017-12-07 21:46:11 UTC (rev 225644)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2017-12-07 21:59:48 UTC (rev 225645)
@@ -1315,9 +1315,8 @@
         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
         policyChecker().stopCheck();
         policyChecker().setLoadType(newLoadType);
-        policyChecker().checkNavigationPolicy(WTFMove(request), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) {
-            continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
-        });
+        continueFragmentScrollAfterNavigationPolicy(request, true);
+        policyChecker().checkNavigationPolicy(WTFMove(request), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [] (const ResourceRequest&, FormState*, bool) { });
         return;
     }
 
@@ -1475,9 +1474,8 @@
         oldDocumentLoader->setTriggeringAction(action);
         oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
         policyChecker().stopCheck();
-        policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) {
-            continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
-        });
+        continueFragmentScrollAfterNavigationPolicy(loader->request(), true);
+        policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, oldDocumentLoader.get(), formState, [] (const ResourceRequest&, FormState*, bool) { });
         return;
     }
 

Modified: trunk/Tools/ChangeLog (225644 => 225645)


--- trunk/Tools/ChangeLog	2017-12-07 21:46:11 UTC (rev 225644)
+++ trunk/Tools/ChangeLog	2017-12-07 21:59:48 UTC (rev 225645)
@@ -1,3 +1,16 @@
+2017-12-07  Alex Christensen  <achristen...@webkit.org>
+
+        Always synchronously continue with fragment navigations
+        https://bugs.webkit.org/show_bug.cgi?id=180544
+        <rdar://problem/34815986> and <rdar://problem/35126690>
+
+        Reviewed by Geoffrey Garen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/DecidePolicyForNavigationAction.mm:
+        (-[DecidePolicyForNavigationActionFragmentDelegate webView:decidePolicyForNavigationAction:decisionHandler:]):
+        (TEST):
+        Add a test that verifies that decidePolicyForNavigationAction is called for fragment navigations.
+
 2017-12-07  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [Cocoa] Add SPI to disallow user-installed fonts

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DecidePolicyForNavigationAction.mm (225644 => 225645)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DecidePolicyForNavigationAction.mm	2017-12-07 21:46:11 UTC (rev 225644)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DecidePolicyForNavigationAction.mm	2017-12-07 21:59:48 UTC (rev 225645)
@@ -526,6 +526,41 @@
     action = ""
 }
 
+static size_t calls;
+static bool done;
+
+@interface DecidePolicyForNavigationActionFragmentDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation DecidePolicyForNavigationActionFragmentDelegate
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+    decisionHandler(WKNavigationActionPolicyAllow);
+    const char* url = ""
+    switch (calls++) {
+    case 0:
+        EXPECT_STREQ(url, "http://webkit.org/");
+        return;
+    case 1:
+        EXPECT_STREQ(url, "http://webkit.org/#fragment");
+        done = true;
+        return;
+    }
+    ASSERT_NOT_REACHED();
+}
+
+@end
+
+TEST(WebKit, DecidePolicyForNavigationActionFragment)
+{
+    auto webView = adoptNS([[WKWebView alloc] init]);
+    auto delegate = adoptNS([[DecidePolicyForNavigationActionFragmentDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+    [webView loadHTMLString:@"<script>window.location.href='';</script>" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
+    TestWebKitAPI::Util::run(&done);
+}
+
 #endif
 
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to