Add SPI to notify WKNavigationDelegate about client redirects
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2017 00:39:09 +0000 (00:39 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2017 00:39:09 +0000 (00:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174680
rdar://problem/33184886

Patch by David Quesada <david_quesada@apple.com> on 2017-07-20
Reviewed by Brady Eidson.

Source/WebCore:

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::performClientRedirect):
* loader/FrameLoader.h:
Add a convenience method for NavigationScheduler that handles a FrameLoadRequest
as a client redirect. Currently this means loading the request and informing the
client about it.

* loader/FrameLoaderClient.h:
Add FrameLoaderClient::dispatchDidPerformClientRedirect() to inform the client when
a client redirect occurs.

* loader/NavigationScheduler.cpp:
Removed ScheduledURLNavigation::fire(). This class was never instantiated directly,
and all subclasses override fire(), so this was unused code.
For ScheduledRedirects and ScheduledLocationChange, use FrameLoader's new method to
load the request as a client redirect.

Source/WebKit:

* UIProcess/API/APINavigationClient.h:
(API::NavigationClient::didPerformClientRedirectForNavigation):
Add a new virtual method for navigation clients to implement if they want to be informed
when the page is initiating a navigation that is a client redirect.

* UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
Declare the new WKNavigationDelegate method -_webView:didPerformClientRedirectForNavigation:

* UIProcess/Cocoa/NavigationState.h:
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::setNavigationDelegate):
(WebKit::NavigationState::NavigationClient::didPerformClientRedirectForNavigation):
Add a new method to NavigationState method to tell the WKNavigationDelegate when a
client redirect happens.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didPerformClientRedirectForLoadForFrame):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
Allow the WebPageProxy to receive a message from the web process when a client redirect happens.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDidPerformClientRedirect):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
Send this new message to the UI process on client redirects.

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/Navigation.mm:
(-[DidPerformClientRedirectNavigationDelegate _webView:didPerformClientRedirectForNavigation:]):
(TEST):
Add API test for -[id<WKNavigationDelegatePrivate> _webView:didPerformClientRedirectForNavigation:].

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

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/loader/NavigationScheduler.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/APINavigationClient.h
Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h
Source/WebKit/UIProcess/Cocoa/NavigationState.h
Source/WebKit/UIProcess/Cocoa/NavigationState.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Navigation.mm

index 285aaf6..6c2a475 100644 (file)
@@ -1,3 +1,28 @@
+2017-07-20  David Quesada  <david_quesada@apple.com>
+
+        Add SPI to notify WKNavigationDelegate about client redirects
+        https://bugs.webkit.org/show_bug.cgi?id=174680
+        rdar://problem/33184886
+
+        Reviewed by Brady Eidson.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::performClientRedirect):
+        * loader/FrameLoader.h:
+        Add a convenience method for NavigationScheduler that handles a FrameLoadRequest
+        as a client redirect. Currently this means loading the request and informing the
+        client about it.
+
+        * loader/FrameLoaderClient.h:
+        Add FrameLoaderClient::dispatchDidPerformClientRedirect() to inform the client when
+        a client redirect occurs.
+
+        * loader/NavigationScheduler.cpp:
+        Removed ScheduledURLNavigation::fire(). This class was never instantiated directly,
+        and all subclasses override fire(), so this was unused code.
+        For ScheduledRedirects and ScheduledLocationChange, use FrameLoader's new method to
+        load the request as a client redirect.
+
 2017-07-20  Chris Dumez  <cdumez@apple.com>
 
         Drop legacy XPathException type
index 04cdb5a..861466f 100644 (file)
@@ -2049,6 +2049,12 @@ void FrameLoader::clientRedirected(const URL& url, double seconds, double fireDa
     m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
 }
 
+void FrameLoader::performClientRedirect(FrameLoadRequest&& frameLoadRequest)
+{
+    changeLocation(WTFMove(frameLoadRequest));
+    m_client.dispatchDidPerformClientRedirect();
+}
+
 bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
 {
     // This function implements the rule: "Don't reload if navigating by fragment within
index 0e12704..f9f52b5 100644 (file)
@@ -263,6 +263,7 @@ public:
     bool allAncestorsAreComplete() const; // including this
     void clientRedirected(const URL&, double delay, double fireDate, LockBackForwardList);
     void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress);
+    void performClientRedirect(FrameLoadRequest&&);
 
     // FIXME: This is public because this asynchronous callback from the FrameLoaderClient
     // uses the policy machinery (and therefore is called via the PolicyChecker).  Once we
index 5174705..3bb6df5 100644 (file)
@@ -151,6 +151,7 @@ public:
     virtual void dispatchDidChangeProvisionalURL() { }
     virtual void dispatchDidCancelClientRedirect() = 0;
     virtual void dispatchWillPerformClientRedirect(const URL&, double interval, double fireDate) = 0;
+    virtual void dispatchDidPerformClientRedirect() { }
     virtual void dispatchDidChangeMainDocument() { }
     virtual void dispatchDidNavigateWithinPage() { }
     virtual void dispatchDidChangeLocationWithinPage() = 0;
index 57b75be..86e73b2 100644 (file)
@@ -127,16 +127,6 @@ protected:
     {
     }
 
-    void fire(Frame& frame) override
-    {
-        UserGestureIndicator gestureIndicator { userGestureToForward() };
-
-        ResourceRequest resourceRequest { m_url, m_referrer, UseProtocolCachePolicy };
-        FrameLoadRequest frameLoadRequest { m_initiatingDocument.get(), *m_securityOrigin, resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), initiatedByMainFrame() };
-
-        frame.loader().changeLocation(WTFMove(frameLoadRequest));
-    }
-
     void didStartTimer(Frame& frame, Timer& timer) override
     {
         if (m_haveToldClient)
@@ -195,7 +185,7 @@ public:
         ResourceRequest resourceRequest { url(), referrer(), refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy };
         FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), initiatedByMainFrame() };
 
-        frame.loader().changeLocation(WTFMove(frameLoadRequest));
+        frame.loader().performClientRedirect(WTFMove(frameLoadRequest));
     }
 };
 
@@ -211,7 +201,7 @@ public:
         ResourceRequest resourceRequest { url(), referrer(), UseProtocolCachePolicy };
         FrameLoadRequest frameLoadRequest { initiatingDocument(), *securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, shouldOpenExternalURLs(), initiatedByMainFrame() };
 
-        frame.loader().changeLocation(WTFMove(frameLoadRequest));
+        frame.loader().performClientRedirect(WTFMove(frameLoadRequest));
     }
 };
 
index 8cd56b6..ff11514 100644 (file)
@@ -1,3 +1,37 @@
+2017-07-20  David Quesada  <david_quesada@apple.com>
+
+        Add SPI to notify WKNavigationDelegate about client redirects
+        https://bugs.webkit.org/show_bug.cgi?id=174680
+        rdar://problem/33184886
+
+        Reviewed by Brady Eidson.
+
+        * UIProcess/API/APINavigationClient.h:
+        (API::NavigationClient::didPerformClientRedirectForNavigation):
+        Add a new virtual method for navigation clients to implement if they want to be informed
+        when the page is initiating a navigation that is a client redirect.
+
+        * UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
+        Declare the new WKNavigationDelegate method -_webView:didPerformClientRedirectForNavigation:
+
+        * UIProcess/Cocoa/NavigationState.h:
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::setNavigationDelegate):
+        (WebKit::NavigationState::NavigationClient::didPerformClientRedirectForNavigation):
+        Add a new method to NavigationState method to tell the WKNavigationDelegate when a
+        client redirect happens.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didPerformClientRedirectForLoadForFrame):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        Allow the WebPageProxy to receive a message from the web process when a client redirect happens.
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDidPerformClientRedirect):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+        Send this new message to the UI process on client redirects.
+
 2017-07-20  Chris Dumez  <cdumez@apple.com>
 
         Drop legacy XPathException type
index e459487..c3262db 100644 (file)
@@ -69,6 +69,7 @@ public:
 
     virtual void didStartProvisionalNavigation(WebKit::WebPageProxy&, API::Navigation*, API::Object*) { }
     virtual void didReceiveServerRedirectForProvisionalNavigation(WebKit::WebPageProxy&, API::Navigation*, API::Object*) { }
+    virtual void didPerformClientRedirectForNavigation(WebKit::WebPageProxy&, API::Navigation*) { }
     virtual void didFailProvisionalNavigationWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, API::Navigation*, const WebCore::ResourceError&, API::Object*) { }
     virtual void didFailProvisionalLoadInSubframeWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, const WebCore::SecurityOriginData&, API::Navigation*, const WebCore::ResourceError&, API::Object*) { }
     virtual void didCommitNavigation(WebKit::WebPageProxy&, API::Navigation*, API::Object*) { }
index 93d3183..717b55a 100644 (file)
@@ -44,6 +44,8 @@ static const WKNavigationResponsePolicy _WKNavigationResponsePolicyBecomeDownloa
 
 - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didFailProvisionalLoadInSubframe:(WKFrameInfo *)subframe withError:(NSError *)error;
 
+- (void)_webView:(WKWebView *)webView didPerformClientRedirectForNavigation:(WKNavigation *)navigation;
+
 - (void)_webView:(WKWebView *)webView navigationDidFinishDocumentLoad:(WKNavigation *)navigation;
 - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didSameDocumentNavigation:(_WKSameDocumentNavigationType)navigationType;
 
index 7a9c3c5..fa04098 100644 (file)
@@ -91,6 +91,7 @@ private:
     private:
         void didStartProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
         void didReceiveServerRedirectForProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
+        void didPerformClientRedirectForNavigation(WebPageProxy&, API::Navigation*) override;
         void didFailProvisionalNavigationWithError(WebPageProxy&, WebFrameProxy&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
         void didFailProvisionalLoadInSubframeWithError(WebPageProxy&, WebFrameProxy&, const WebCore::SecurityOriginData&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
         void didCommitNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
@@ -172,6 +173,7 @@ private:
         bool webViewDidReceiveServerRedirectForProvisionalNavigation : 1;
         bool webViewDidFailProvisionalNavigationWithError : 1;
         bool webViewNavigationDidFailProvisionalLoadInSubframeWithError : 1;
+        bool webViewDidPerformClientRedirectForNavigation : 1;
         bool webViewDidCommitNavigation : 1;
         bool webViewNavigationDidFinishDocumentLoad : 1;
         bool webViewDidFinishNavigation : 1;
index 6e75953..198d20a 100644 (file)
@@ -150,6 +150,7 @@ void NavigationState::setNavigationDelegate(id <WKNavigationDelegate> delegate)
     m_navigationDelegateMethods.webViewDidFailNavigationWithError = [delegate respondsToSelector:@selector(webView:didFailNavigation:withError:)];
 
     m_navigationDelegateMethods.webViewNavigationDidFailProvisionalLoadInSubframeWithError = [delegate respondsToSelector:@selector(_webView:navigation:didFailProvisionalLoadInSubframe:withError:)];
+    m_navigationDelegateMethods.webViewDidPerformClientRedirectForNavigation = [delegate respondsToSelector:@selector(_webView:didPerformClientRedirectForNavigation:)];
     m_navigationDelegateMethods.webViewNavigationDidFinishDocumentLoad = [delegate respondsToSelector:@selector(_webView:navigationDidFinishDocumentLoad:)];
     m_navigationDelegateMethods.webViewNavigationDidSameDocumentNavigation = [delegate respondsToSelector:@selector(_webView:navigation:didSameDocumentNavigation:)];
     m_navigationDelegateMethods.webViewRenderingProgressDidChange = [delegate respondsToSelector:@selector(_webView:renderingProgressDidChange:)];
@@ -488,6 +489,23 @@ void NavigationState::NavigationClient::didReceiveServerRedirectForProvisionalNa
     [navigationDelegate webView:m_navigationState.m_webView didReceiveServerRedirectForProvisionalNavigation:wkNavigation];
 }
 
+void NavigationState::NavigationClient::didPerformClientRedirectForNavigation(WebPageProxy& page, API::Navigation* navigation)
+{
+    if (!m_navigationState.m_navigationDelegateMethods.webViewDidPerformClientRedirectForNavigation)
+        return;
+
+    auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
+    if (!navigationDelegate)
+        return;
+
+    // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
+    WKNavigation *wkNavigation = nil;
+    if (navigation)
+        wkNavigation = wrapper(*navigation);
+
+    [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView didPerformClientRedirectForNavigation:wkNavigation];
+}
+
 static RetainPtr<NSError> createErrorWithRecoveryAttempter(WKWebView *webView, WebFrameProxy& webFrameProxy, NSError *originalError)
 {
     RefPtr<API::FrameHandle> frameHandle = API::FrameHandle::create(webFrameProxy.frameID());
index 524c152..bbd398b 100644 (file)
@@ -3189,6 +3189,24 @@ void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t f
         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
 }
 
+void WebPageProxy::didPerformClientRedirectForLoadForFrame(uint64_t frameID, uint64_t navigationID)
+{
+    PageClientProtector protector(m_pageClient);
+
+    WebFrameProxy* frame = m_process->webFrame(frameID);
+    MESSAGE_CHECK(frame);
+
+    // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
+    RefPtr<API::Navigation> navigation;
+    if (frame->isMainFrame() && navigationID)
+        navigation = &navigationState().navigation(navigationID);
+
+    if (m_navigationClient) {
+        if (frame->isMainFrame())
+            m_navigationClient->didPerformClientRedirectForNavigation(*this, navigation.get());
+    }
+}
+
 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, const String& url)
 {
     PageClientProtector protector(m_pageClient);
index 2df2e4d..8122023 100644 (file)
@@ -1249,6 +1249,7 @@ private:
 
     void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, const String& unreachableURL, const UserData&);
     void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String&, const UserData&);
+    void didPerformClientRedirectForLoadForFrame(uint64_t frameID, uint64_t navigationID);
     void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, const String& url);
     void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
     void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, std::optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
index bb0e444..da12f0e 100644 (file)
@@ -118,6 +118,7 @@ messages -> WebPageProxy {
     # Frame load messages
     DidStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, String url, String unreachableURL, WebKit::UserData userData)
     DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, String url, WebKit::UserData userData)
+    DidPerformClientRedirectForLoadForFrame(uint64_t frameID, uint64_t navigationID)
     DidChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, String url)
     DidFailProvisionalLoadForFrame(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, String provisionalURL, WebCore::ResourceError error, WebKit::UserData userData)
     DidCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, String mimeType, bool hasCustomContentProvider, uint32_t loadType, WebCore::CertificateInfo certificateInfo, bool containsPluginDocument, std::optional<WebCore::HasInsecureContent> forcedHasInsecureContent, WebKit::UserData userData)
index 2cfcfce..5c24d02 100644 (file)
@@ -290,6 +290,18 @@ void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
     webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), url, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
 }
 
+void WebFrameLoaderClient::dispatchDidPerformClientRedirect()
+{
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+
+    auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
+    // Notify the UIProcess.
+    webPage->send(Messages::WebPageProxy::DidPerformClientRedirectForLoadForFrame(m_frame->frameID(), navigationID));
+}
+
 void WebFrameLoaderClient::dispatchDidChangeProvisionalURL()
 {
     WebPage* webPage = m_frame->page();
index 655b0bd..25a8e6a 100644 (file)
@@ -88,6 +88,7 @@ private:
 
     void dispatchDidDispatchOnloadEvents() final;
     void dispatchDidReceiveServerRedirectForProvisionalLoad() final;
+    void dispatchDidPerformClientRedirect() final;
     void dispatchDidChangeProvisionalURL() final;
     void dispatchDidCancelClientRedirect() final;
     void dispatchWillPerformClientRedirect(const WebCore::URL&, double interval, double fireDate) final;
index 147f5ff..9de471e 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-20  David Quesada  <david_quesada@apple.com>
+
+        Add SPI to notify WKNavigationDelegate about client redirects
+        https://bugs.webkit.org/show_bug.cgi?id=174680
+        rdar://problem/33184886
+
+        Reviewed by Brady Eidson.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/Navigation.mm:
+        (-[DidPerformClientRedirectNavigationDelegate _webView:didPerformClientRedirectForNavigation:]):
+        (TEST):
+        Add API test for -[id<WKNavigationDelegatePrivate> _webView:didPerformClientRedirectForNavigation:].
+
 2017-07-20  Brady Eidson  <beidson@apple.com>
 
         Test WebKit2CustomProtocolsTest.ProcessPoolDestroyedDuringLoading added in r219664 fails on El Capitan.
index d5c8fd7..91de61d 100644 (file)
@@ -25,8 +25,8 @@
 
 #include "config.h"
 
+#import <WebKit/WKNavigationDelegatePrivate.h>
 #import <WebKit/WKNavigationPrivate.h>
-#import <WebKit/WKNavigationDelegate.h>
 #import <WebKit/WKWebView.h>
 #import <wtf/RetainPtr.h>
 #import "PlatformUtilities.h"
@@ -36,6 +36,7 @@
 
 static bool isDone;
 static RetainPtr<WKNavigation> currentNavigation;
+static RetainPtr<NSURL> redirectURL;
 
 @interface NavigationDelegate : NSObject <WKNavigationDelegate>
 @end
@@ -187,4 +188,40 @@ TEST(WKNavigation, DecidePolicyForPageCacheNavigation)
     ASSERT_TRUE([delegate decidedPolicyForBackForwardNavigation]);
 }
 
+@interface DidPerformClientRedirectNavigationDelegate : NSObject<WKNavigationDelegatePrivate>
+@end
+
+@implementation DidPerformClientRedirectNavigationDelegate
+- (void)_webView:(WKWebView *)webView didPerformClientRedirectForNavigation:(WKNavigation *)navigation
+{
+    isDone = true;
+    redirectURL = webView.URL;
+}
+@end
+
+TEST(WKNavigation, DidPerformClientRedirect)
+{
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+    RetainPtr<DidPerformClientRedirectNavigationDelegate> delegate = adoptNS([[DidPerformClientRedirectNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"data:text/html,%3Cmeta%20http-equiv=%22refresh%22%20content=%220;URL=data:text/html,Page1%22%3E"]];
+
+    isDone = false;
+    redirectURL = nil;
+    [webView loadRequest:request];
+    TestWebKitAPI::Util::run(&isDone);
+
+    ASSERT_STREQ(redirectURL.get().absoluteString.UTF8String, "data:text/html,Page1");
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"data:text/html,%3Cscript%3Ewindow.location=%22data:text/html,Page2%22;%3C/script%3E"]];
+    isDone = false;
+    redirectURL = nil;
+    [webView loadRequest:request];
+    TestWebKitAPI::Util::run(&isDone);
+
+    ASSERT_STREQ(redirectURL.get().absoluteString.UTF8String, "data:text/html,Page2");
+}
+
 #endif