Title: [218750] trunk
Revision
218750
Author
[email protected]
Date
2017-06-23 10:25:43 -0700 (Fri, 23 Jun 2017)

Log Message

Add SPI to WKURLSchemeTask for redirection
https://bugs.webkit.org/show_bug.cgi?id=173730

Reviewed by Brady Eidson.

Source/WebCore:

* platform/network/CacheValidation.cpp:
(WebCore::computeFreshnessLifetimeForHTTPFamily):
Asserting that redirects are always http/https URLs is no longer valid.
If there's a custom scheme redirect, give it no freshness lifetime in the cache.

Source/WebKit2:

This is needed for testing an upcoming fix for redirect callbacks, and it might be
necessary for loading with custom schemes in general. Right now just responding with
 an HTTP 301/302/307/308 response code doesn't work because there is nothing that
synthesizes an NSURLRequest from the Location header like we do in 
SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest et al. for HSTS, 
and that would require using an NSHTTPURLResponse for non-HTTP responses, which is 
conceptually wrong.  Instead of waiting for a completion handler in the API, we are
following the pattern of WKNavigationDelegate.didReceiveServerRedirectForProvisionalNavigation
and allowing the SPI to indicate that a redirect has happened to update the state of
WebKit, but not allowing the SPI to wait for a processed request and slow down loading.

This adds WKURLSchemeTaskPrivate._didPerformRedirection which is covered by new API tests.

* UIProcess/API/Cocoa/WKURLSchemeTask.mm:
(raiseExceptionIfNecessary):
(-[WKURLSchemeTaskImpl _didPerformRedirection:newRequest:completionHandler:]):
* UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h:
* UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h: Added.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::startURLSchemeTask):
(WebKit::WebPageProxy::stopURLSchemeTask):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/WebURLSchemeHandler.cpp:
(WebKit::WebURLSchemeHandler::startTask):
(WebKit::WebURLSchemeHandler::stopTask):
* UIProcess/WebURLSchemeHandler.h:
* UIProcess/WebURLSchemeTask.cpp:
(WebKit::WebURLSchemeTask::didReceiveResponse): Deleted.
(WebKit::WebURLSchemeTask::didReceiveData): Deleted.
(WebKit::WebURLSchemeTask::didComplete): Deleted.
* UIProcess/WebURLSchemeTask.h:
* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::urlSchemeTaskDidPerformRedirection):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp:
(WebKit::WebURLSchemeHandlerProxy::taskDidPerformRedirection):
* WebProcess/WebPage/WebURLSchemeHandlerProxy.h:
* WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:
(WebKit::WebURLSchemeTaskProxy::didPerformRedirection):
* WebProcess/WebPage/WebURLSchemeTaskProxy.h:

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm:
(-[SchemeHandler webView:startURLSchemeTask:]):
(-[SchemeHandler webView:stopURLSchemeTask:]):
(TEST):
(-[RedirectSchemeHandler webView:startURLSchemeTask:]):
(-[RedirectSchemeHandler webView:stopURLSchemeTask:]):
(-[RedirectSchemeHandler webView:didReceiveServerRedirectForProvisionalNavigation:]):
(-[RedirectSchemeHandler webView:decidePolicyForNavigationResponse:decisionHandler:]):
(-[RedirectSchemeHandler userContentController:didReceiveScriptMessage:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (218749 => 218750)


--- trunk/Source/WebCore/ChangeLog	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebCore/ChangeLog	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1,3 +1,15 @@
+2017-06-23  Alex Christensen  <[email protected]>
+
+        Add SPI to WKURLSchemeTask for redirection
+        https://bugs.webkit.org/show_bug.cgi?id=173730
+
+        Reviewed by Brady Eidson.
+
+        * platform/network/CacheValidation.cpp:
+        (WebCore::computeFreshnessLifetimeForHTTPFamily):
+        Asserting that redirects are always http/https URLs is no longer valid.
+        If there's a custom scheme redirect, give it no freshness lifetime in the cache.
+
 2017-06-23  Konstantin Tokarev  <[email protected]>
 
         Remove excessive headers from WebCore/{editing,fileapi,history,html,loader,page}

Modified: trunk/Source/WebCore/platform/network/CacheValidation.cpp (218749 => 218750)


--- trunk/Source/WebCore/platform/network/CacheValidation.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebCore/platform/network/CacheValidation.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -118,7 +118,8 @@
 {
     using namespace std::chrono;
 
-    ASSERT(response.url().protocolIsInHTTPFamily());
+    if (!response.url().protocolIsInHTTPFamily())
+        return 0us;
 
     // Freshness Lifetime:
     // http://tools.ietf.org/html/rfc7234#section-4.2.1

Modified: trunk/Source/WebKit2/ChangeLog (218749 => 218750)


--- trunk/Source/WebKit2/ChangeLog	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/ChangeLog	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1,3 +1,54 @@
+2017-06-23  Alex Christensen  <[email protected]>
+
+        Add SPI to WKURLSchemeTask for redirection
+        https://bugs.webkit.org/show_bug.cgi?id=173730
+
+        Reviewed by Brady Eidson.
+
+        This is needed for testing an upcoming fix for redirect callbacks, and it might be
+        necessary for loading with custom schemes in general. Right now just responding with
+         an HTTP 301/302/307/308 response code doesn't work because there is nothing that
+        synthesizes an NSURLRequest from the Location header like we do in 
+        SynchronousResourceHandleCFURLConnectionDelegate::willSendRequest et al. for HSTS, 
+        and that would require using an NSHTTPURLResponse for non-HTTP responses, which is 
+        conceptually wrong.  Instead of waiting for a completion handler in the API, we are
+        following the pattern of WKNavigationDelegate.didReceiveServerRedirectForProvisionalNavigation
+        and allowing the SPI to indicate that a redirect has happened to update the state of
+        WebKit, but not allowing the SPI to wait for a processed request and slow down loading.
+
+        This adds WKURLSchemeTaskPrivate._didPerformRedirection which is covered by new API tests.
+
+        * UIProcess/API/Cocoa/WKURLSchemeTask.mm:
+        (raiseExceptionIfNecessary):
+        (-[WKURLSchemeTaskImpl _didPerformRedirection:newRequest:completionHandler:]):
+        * UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h:
+        * UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h: Added.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::startURLSchemeTask):
+        (WebKit::WebPageProxy::stopURLSchemeTask):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/WebURLSchemeHandler.cpp:
+        (WebKit::WebURLSchemeHandler::startTask):
+        (WebKit::WebURLSchemeHandler::stopTask):
+        * UIProcess/WebURLSchemeHandler.h:
+        * UIProcess/WebURLSchemeTask.cpp:
+        (WebKit::WebURLSchemeTask::didReceiveResponse): Deleted.
+        (WebKit::WebURLSchemeTask::didReceiveData): Deleted.
+        (WebKit::WebURLSchemeTask::didComplete): Deleted.
+        * UIProcess/WebURLSchemeTask.h:
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::urlSchemeTaskDidPerformRedirection):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp:
+        (WebKit::WebURLSchemeHandlerProxy::taskDidPerformRedirection):
+        * WebProcess/WebPage/WebURLSchemeHandlerProxy.h:
+        * WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:
+        (WebKit::WebURLSchemeTaskProxy::didPerformRedirection):
+        * WebProcess/WebPage/WebURLSchemeTaskProxy.h:
+
 2017-06-23  Brent Fulgham  <[email protected]>
 
         [WK2][macOS] Support Mac Mini Flash Player Features

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTask.mm (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2017-06-23 17:25:43 UTC (rev 218750)
@@ -28,10 +28,11 @@
 
 #if WK_API_ENABLED
 
-#include "WebURLSchemeTask.h"
-#include <WebCore/ResourceError.h>
-#include <WebCore/ResourceResponse.h>
-#include <WebCore/SharedBuffer.h>
+#import "WebURLSchemeTask.h"
+#import <WebCore/ResourceError.h>
+#import <WebCore/ResourceResponse.h>
+#import <WebCore/SharedBuffer.h>
+#import <wtf/BlockPtr.h>
 
 using namespace WebCore;
 
@@ -52,6 +53,9 @@
     case WebKit::WebURLSchemeTask::ExceptionType::NoResponseSent:
         [NSException raise:NSInternalInconsistencyException format:@"No response has been sent for this task"];
         break;
+    case WebKit::WebURLSchemeTask::ExceptionType::RedirectAfterResponse:
+        [NSException raise:NSInternalInconsistencyException format:@"No redirects are allowed after the response"];
+        break;
     }
 }
 
@@ -86,6 +90,12 @@
     raiseExceptionIfNecessary(result);
 }
 
+- (void)_didPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request
+{
+    auto result = _urlSchemeTask->task().didPerformRedirection(response, request);
+    raiseExceptionIfNecessary(result);
+}
+
 #pragma mark WKObject protocol implementation
 
 - (API::Object&)_apiObject

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskInternal.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -23,7 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WKURLSchemeTask.h"
+#import "WKURLSchemeTaskPrivate.h"
 
 #if WK_API_ENABLED
 
@@ -30,7 +30,7 @@
 #import "APIURLSchemeTask.h"
 #import "WKObject.h"
 
-@interface WKURLSchemeTaskImpl : NSObject <WKURLSchemeTask>
+@interface WKURLSchemeTaskImpl : NSObject <WKURLSchemeTaskPrivate>
 @end
 
 namespace WebKit {

Added: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h (0 => 218750)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h	                        (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKURLSchemeTask.h>
+
+#if WK_API_ENABLED
+
+WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@protocol WKURLSchemeTaskPrivate <WKURLSchemeTask>
+
+- (void)_didPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request;
+
+@end
+
+#endif
+

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -6879,20 +6879,20 @@
     return m_urlSchemeHandlersByScheme.get(scheme);
 }
 
-void WebPageProxy::startURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier, const WebCore::ResourceRequest& request)
+void WebPageProxy::startURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceRequest& request)
 {
     auto iterator = m_urlSchemeHandlersByIdentifier.find(handlerIdentifier);
     ASSERT(iterator != m_urlSchemeHandlersByIdentifier.end());
 
-    iterator->value->startTask(*this, resourceIdentifier, request);
+    iterator->value->startTask(*this, taskIdentifier, request);
 }
 
-void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier)
+void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
 {
     auto iterator = m_urlSchemeHandlersByIdentifier.find(handlerIdentifier);
     ASSERT(iterator != m_urlSchemeHandlersByIdentifier.end());
 
-    iterator->value->stopTask(*this, resourceIdentifier);
+    iterator->value->stopTask(*this, taskIdentifier);
 }
 
 void WebPageProxy::setAvoidsUnsafeArea(bool avoidsUnsafeArea)

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1607,8 +1607,8 @@
 #endif
 #endif
 
-    void startURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier, const WebCore::ResourceRequest&);
-    void stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t resourceIdentifier);
+    void startURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceRequest&);
+    void stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier);
 
     void handleAutoFillButtonClick(const UserData&);
 

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2017-06-23 17:25:43 UTC (rev 218750)
@@ -495,6 +495,6 @@
 
     SetIsUsingHighPerformanceWebGL(bool isUsingHighPerformanceWebGL)
 
-    StartURLSchemeTask(uint64_t loaderIdentifier, uint64_t resourceIdentifier, WebCore::ResourceRequest request)
-    StopURLSchemeTask(uint64_t loaderIdentifier, uint64_t resourceIdentifier)
+    StartURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceRequest request)
+    StopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
 }

Modified: trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.cpp (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -48,17 +48,17 @@
     ASSERT(m_tasks.isEmpty());
 }
 
-void WebURLSchemeHandler::startTask(WebPageProxy& page, uint64_t resourceIdentifier, const ResourceRequest& request)
+void WebURLSchemeHandler::startTask(WebPageProxy& page, uint64_t taskIdentifier, const ResourceRequest& request)
 {
-    auto result = m_tasks.add(resourceIdentifier, WebURLSchemeTask::create(*this, page, resourceIdentifier, request));
+    auto result = m_tasks.add(taskIdentifier, WebURLSchemeTask::create(*this, page, taskIdentifier, request));
     ASSERT(result.isNewEntry);
 
     platformStartTask(page, result.iterator->value);
 }
 
-void WebURLSchemeHandler::stopTask(WebPageProxy& page, uint64_t resourceIdentifier)
+void WebURLSchemeHandler::stopTask(WebPageProxy& page, uint64_t taskIdentifier)
 {
-    auto iterator = m_tasks.find(resourceIdentifier);
+    auto iterator = m_tasks.find(taskIdentifier);
     if (iterator == m_tasks.end())
         return;
 

Modified: trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.h (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebURLSchemeHandler.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -45,8 +45,8 @@
 
     uint64_t identifier() const { return m_identifier; }
 
-    void startTask(WebPageProxy&, uint64_t resourceIdentifier, const WebCore::ResourceRequest&);
-    void stopTask(WebPageProxy&, uint64_t resourceIdentifier);
+    void startTask(WebPageProxy&, uint64_t taskIdentifier, const WebCore::ResourceRequest&);
+    void stopTask(WebPageProxy&, uint64_t taskIdentifier);
 
 protected:
     WebURLSchemeHandler();

Modified: trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.cpp (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -48,54 +48,74 @@
 {
 }
 
-WebURLSchemeTask::ExceptionType WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response)
+auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) -> ExceptionType
 {
     if (m_stopped)
-        return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
+        return ExceptionType::TaskAlreadyStopped;
+    
+    if (m_completed)
+        return ExceptionType::CompleteAlreadyCalled;
+    
+    if (m_dataSent)
+        return ExceptionType::DataAlreadySent;
+    
+    if (m_responseSent)
+        return ExceptionType::RedirectAfterResponse;
+    
+    m_request = request;
+    m_page->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request));
 
+    return ExceptionType::None;
+}
+
+auto WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response) -> ExceptionType
+{
+    if (m_stopped)
+        return ExceptionType::TaskAlreadyStopped;
+
     if (m_completed)
-        return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
+        return ExceptionType::CompleteAlreadyCalled;
 
     if (m_dataSent)
-        return WebURLSchemeTask::ExceptionType::DataAlreadySent;
+        return ExceptionType::DataAlreadySent;
 
     m_responseSent = true;
 
     response.includeCertificateInfo();
     m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveResponse(m_urlSchemeHandler->identifier(), m_identifier, response));
-    return WebURLSchemeTask::ExceptionType::None;
+    return ExceptionType::None;
 }
 
-WebURLSchemeTask::ExceptionType WebURLSchemeTask::didReceiveData(Ref<SharedBuffer> buffer)
+auto WebURLSchemeTask::didReceiveData(Ref<SharedBuffer> buffer) -> ExceptionType
 {
     if (m_stopped)
-        return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
+        return ExceptionType::TaskAlreadyStopped;
 
     if (m_completed)
-        return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
+        return ExceptionType::CompleteAlreadyCalled;
 
     if (!m_responseSent)
-        return WebURLSchemeTask::ExceptionType::NoResponseSent;
+        return ExceptionType::NoResponseSent;
 
     m_dataSent = true;
     m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveData(m_urlSchemeHandler->identifier(), m_identifier, IPC::SharedBufferDataReference(buffer.ptr())));
-    return WebURLSchemeTask::ExceptionType::None;
+    return ExceptionType::None;
 }
 
-WebURLSchemeTask::ExceptionType WebURLSchemeTask::didComplete(const ResourceError& error)
+auto WebURLSchemeTask::didComplete(const ResourceError& error) -> ExceptionType
 {
     if (m_stopped)
-        return WebURLSchemeTask::ExceptionType::TaskAlreadyStopped;
+        return ExceptionType::TaskAlreadyStopped;
 
     if (m_completed)
-        return WebURLSchemeTask::ExceptionType::CompleteAlreadyCalled;
+        return ExceptionType::CompleteAlreadyCalled;
 
     if (!m_responseSent && error.isNull())
-        return WebURLSchemeTask::ExceptionType::NoResponseSent;
+        return ExceptionType::NoResponseSent;
 
     m_completed = true;
     m_page->send(Messages::WebPage::URLSchemeTaskDidComplete(m_urlSchemeHandler->identifier(), m_identifier, error));
-    return WebURLSchemeTask::ExceptionType::None;
+    return ExceptionType::None;
 }
 
 void WebURLSchemeTask::pageDestroyed()

Modified: trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.h (218749 => 218750)


--- trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/UIProcess/WebURLSchemeTask.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -52,10 +52,12 @@
     enum class ExceptionType {
         DataAlreadySent,
         CompleteAlreadyCalled,
+        RedirectAfterResponse,
         TaskAlreadyStopped,
         NoResponseSent,
         None,
     };
+    ExceptionType didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
     ExceptionType didReceiveResponse(const WebCore::ResourceResponse&);
     ExceptionType didReceiveData(Ref<WebCore::SharedBuffer>);
     ExceptionType didComplete(const WebCore::ResourceError&);

Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (218749 => 218750)


--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1160,6 +1160,7 @@
 		5C20CB9D1BB0DCFA00895BB1 /* NetworkSessionCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C20CB9B1BB0DCD200895BB1 /* NetworkSessionCocoa.mm */; };
 		5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C20CB9E1BB0DD1800895BB1 /* NetworkSession.h */; };
 		5C298DA01C3DF02100470AFE /* PendingDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C298D9E1C3DEF2900470AFE /* PendingDownload.h */; };
+		5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5C7706741D1138380012700F /* WebSocketProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C7706731D111D8B0012700F /* WebSocketProvider.cpp */; };
 		5C85C7881C3F23CE0061A4FA /* PendingDownload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */; };
 		5C9E56821DF7F1AB00C9EE33 /* WKWebsitePolicies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C9E56801DF7F05500C9EE33 /* WKWebsitePolicies.cpp */; };
@@ -3443,6 +3444,7 @@
 		5C20CB9B1BB0DCD200895BB1 /* NetworkSessionCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkSessionCocoa.mm; path = NetworkProcess/cocoa/NetworkSessionCocoa.mm; sourceTree = "<group>"; };
 		5C20CB9E1BB0DD1800895BB1 /* NetworkSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkSession.h; path = NetworkProcess/NetworkSession.h; sourceTree = "<group>"; };
 		5C298D9E1C3DEF2900470AFE /* PendingDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PendingDownload.h; path = NetworkProcess/Downloads/PendingDownload.h; sourceTree = "<group>"; };
+		5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKURLSchemeTaskPrivate.h; sourceTree = "<group>"; };
 		5C7706731D111D8B0012700F /* WebSocketProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebSocketProvider.cpp; path = Network/WebSocketProvider.cpp; sourceTree = "<group>"; };
 		5C7C88DC1D0F41A0009D2F6D /* WebSocketProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebSocketProvider.h; path = Network/WebSocketProvider.h; sourceTree = "<group>"; };
 		5C85C7861C3F23C50061A4FA /* PendingDownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PendingDownload.cpp; path = NetworkProcess/Downloads/PendingDownload.cpp; sourceTree = "<group>"; };
@@ -5718,6 +5720,7 @@
 				51D1242F1E6DDDD7002B2820 /* WKURLSchemeTask.h */,
 				51D124301E6DDDD7002B2820 /* WKURLSchemeTask.mm */,
 				51D124371E6DFD2A002B2820 /* WKURLSchemeTaskInternal.h */,
+				5C62FDF81EFC263C00CE072E /* WKURLSchemeTaskPrivate.h */,
 				1AFA3AC718E61C61003CCBAE /* WKUserContentController.h */,
 				1AFA3AC618E61C61003CCBAE /* WKUserContentController.mm */,
 				1AAF08A3192682DA00B6390C /* WKUserContentControllerInternal.h */,
@@ -8944,6 +8947,7 @@
 				37F623B812A57B6200E3FDF6 /* WKFindOptions.h in Headers */,
 				C54256B518BEC18C00DE4179 /* WKFormInputControl.h in Headers */,
 				C54256B718BEC18C00DE4179 /* WKFormPeripheral.h in Headers */,
+				5C62FDF91EFC271C00CE072E /* WKURLSchemeTaskPrivate.h in Headers */,
 				C54256B818BEC18C00DE4179 /* WKFormPopover.h in Headers */,
 				C54256BA18BEC18C00DE4179 /* WKFormSelectControl.h in Headers */,
 				0F08CF521D63C13A00B48DF1 /* WKFormSelectPicker.h in Headers */,

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -5905,7 +5905,7 @@
 
 void WebPage::registerURLSchemeHandler(uint64_t handlerIdentifier, const String& scheme)
 {
-    auto schemeResult = m_schemeToURLSchemeHandlerProxyMap.add(scheme, std::make_unique<WebURLSchemeHandlerProxy>(*this, handlerIdentifier));
+    auto schemeResult = m_schemeToURLSchemeHandlerProxyMap.add(scheme, WebURLSchemeHandlerProxy::create(*this, handlerIdentifier));
     ASSERT(schemeResult.isNewEntry);
 
     auto identifierResult = m_identifierToURLSchemeHandlerProxyMap.add(handlerIdentifier, schemeResult.iterator->value.get());
@@ -5912,6 +5912,14 @@
     ASSERT_UNUSED(identifierResult, identifierResult.isNewEntry);
 }
 
+void WebPage::urlSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, ResourceResponse&& response, ResourceRequest&& request)
+{
+    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
+    ASSERT(handler);
+    
+    handler->taskDidPerformRedirection(taskIdentifier, WTFMove(response), WTFMove(request));
+}
+    
 void WebPage::urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceResponse& response)
 {
     auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1276,6 +1276,7 @@
 
     void registerURLSchemeHandler(uint64_t identifier, const String& scheme);
 
+    void urlSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
     void urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceResponse&);
     void urlSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, const IPC::DataReference&);
     void urlSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceError&);
@@ -1568,7 +1569,7 @@
     const String m_overrideContentSecurityPolicy;
     const std::optional<double> m_cpuLimit;
 
-    HashMap<String, std::unique_ptr<WebURLSchemeHandlerProxy>> m_schemeToURLSchemeHandlerProxyMap;
+    HashMap<String, RefPtr<WebURLSchemeHandlerProxy>> m_schemeToURLSchemeHandlerProxyMap;
     HashMap<uint64_t, WebURLSchemeHandlerProxy*> m_identifierToURLSchemeHandlerProxyMap;
 };
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in	2017-06-23 17:25:43 UTC (rev 218750)
@@ -475,7 +475,8 @@
 
     RegisterURLSchemeHandler(uint64_t identifier, String scheme)
 
-    URLSchemeTaskDidReceiveResponse(uint64_t providerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response)
-    URLSchemeTaskDidReceiveData(uint64_t providerIdentifier, uint64_t taskIdentifier, IPC::DataReference data)
-    URLSchemeTaskDidComplete(uint64_t providerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
+    URLSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response, WebCore::ResourceRequest request)
+    URLSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response)
+    URLSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, IPC::DataReference data)
+    URLSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
 }

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -48,7 +48,7 @@
 
 void WebURLSchemeHandlerProxy::startNewTask(ResourceLoader& loader)
 {
-    auto result = m_tasks.add(loader.identifier(), std::make_unique<WebURLSchemeTaskProxy>(*this, loader));
+    auto result = m_tasks.add(loader.identifier(), WebURLSchemeTaskProxy::create(*this, loader));
     ASSERT(result.isNewEntry);
 
     WebProcess::singleton().webLoaderStrategy().addURLSchemeTaskProxy(*result.iterator->value);
@@ -55,6 +55,14 @@
     result.iterator->value->startLoading();
 }
 
+void WebURLSchemeHandlerProxy::taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& newRequest)
+{
+    auto* task = m_tasks.get(taskIdentifier);
+    if (!task)
+        return;
+    
+    task->didPerformRedirection(WTFMove(redirectResponse), WTFMove(newRequest));
+}
 
 void WebURLSchemeHandlerProxy::taskDidReceiveResponse(uint64_t taskIdentifier, const ResourceResponse& response)
 {

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.h (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeHandlerProxy.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -27,11 +27,13 @@
 
 #include "WebURLSchemeTaskProxy.h"
 #include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
 
 namespace WebCore {
 class ResourceError;
 class ResourceLoader;
 class ResourceResponse;
+class ResourceRequest;
 }
 
 namespace WebKit {
@@ -38,10 +40,12 @@
 
 class WebPage;
 
-class WebURLSchemeHandlerProxy {
-    WTF_MAKE_NONCOPYABLE(WebURLSchemeHandlerProxy);
+class WebURLSchemeHandlerProxy : public RefCounted<WebURLSchemeHandlerProxy> {
 public:
-    WebURLSchemeHandlerProxy(WebPage&, uint64_t identifier);
+    static Ref<WebURLSchemeHandlerProxy> create(WebPage& page, uint64_t identifier)
+    {
+        return adoptRef(*new WebURLSchemeHandlerProxy(page, identifier));
+    }
     ~WebURLSchemeHandlerProxy();
 
     void startNewTask(WebCore::ResourceLoader&);
@@ -49,6 +53,7 @@
     uint64_t identifier() const { return m_identifier; }
     WebPage& page() { return m_webPage; }
 
+    void taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
     void taskDidReceiveResponse(uint64_t taskIdentifier, const WebCore::ResourceResponse&);
     void taskDidReceiveData(uint64_t taskIdentifier, size_t, const uint8_t* data);
     void taskDidComplete(uint64_t taskIdentifier, const WebCore::ResourceError&);
@@ -55,10 +60,11 @@
     void taskDidStopLoading(WebURLSchemeTaskProxy&);
 
 private:
+    WebURLSchemeHandlerProxy(WebPage&, uint64_t identifier);
     WebPage& m_webPage;
     uint64_t m_identifier { 0 };
 
-    HashMap<unsigned long, std::unique_ptr<WebURLSchemeTaskProxy>> m_tasks;
+    HashMap<uint64_t, RefPtr<WebURLSchemeTaskProxy>> m_tasks;
 }; // class WebURLSchemeHandlerProxy
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp	2017-06-23 17:25:43 UTC (rev 218750)
@@ -62,9 +62,32 @@
     // This line will result in this being deleted.
     m_urlSchemeHandler.taskDidStopLoading(*this);
 }
+    
+void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request)
+{
+    if (!hasLoader())
+        return;
+    
+    auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) {
+        m_waitingForRedirectCompletionHandler = false;
+        // We do not inform the UIProcess of WebKit's new request with the given suggested request.
+        // We do want to know if WebKit would have generated a request that differs from the suggested request, though.
+        if (request.url() != originalRequest.url())
+            WTFLogAlways("Redirected scheme task would have been sent to a different URL.");
+    };
+    
+    if (m_waitingForRedirectCompletionHandler)
+        WTFLogAlways("Received redirect during previous redirect processing.");
+    m_waitingForRedirectCompletionHandler = true;
 
+    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
+}
+
 void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response)
 {
+    if (m_waitingForRedirectCompletionHandler)
+        WTFLogAlways("Received response during redirect processing.");
+    
     if (!hasLoader())
         return;
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.h (218749 => 218750)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.h	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebURLSchemeTaskProxy.h	2017-06-23 17:25:43 UTC (rev 218750)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include <WebCore/ResourceRequest.h>
+#include <wtf/RefCounted.h>
 
 namespace WebCore {
 class ResourceError;
@@ -37,16 +38,19 @@
 
 class WebURLSchemeHandlerProxy;
 
-class WebURLSchemeTaskProxy {
-    WTF_MAKE_NONCOPYABLE(WebURLSchemeTaskProxy);
+class WebURLSchemeTaskProxy : public RefCounted<WebURLSchemeTaskProxy> {
 public:
-    WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy&, WebCore::ResourceLoader&);
-
+    static Ref<WebURLSchemeTaskProxy> create(WebURLSchemeHandlerProxy& handler, WebCore::ResourceLoader& loader)
+    {
+        return adoptRef(*new WebURLSchemeTaskProxy(handler, loader));
+    }
+    
     const WebCore::ResourceRequest& request() const { return m_request; }
 
     void startLoading();
     void stopLoading();
 
+    void didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
     void didReceiveResponse(const WebCore::ResourceResponse&);
     void didReceiveData(size_t, const uint8_t* data);
     void didComplete(const WebCore::ResourceError&);
@@ -54,6 +58,7 @@
     unsigned long identifier() const { return m_identifier; }
 
 private:
+    WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy&, WebCore::ResourceLoader&);
     bool hasLoader();
 
     WebURLSchemeHandlerProxy& m_urlSchemeHandler;
@@ -60,6 +65,7 @@
     RefPtr<WebCore::ResourceLoader> m_coreLoader;
     WebCore::ResourceRequest m_request;
     unsigned long m_identifier;
+    bool m_waitingForRedirectCompletionHandler { };
 };
 
 } // namespace WebKit

Modified: trunk/Tools/ChangeLog (218749 => 218750)


--- trunk/Tools/ChangeLog	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Tools/ChangeLog	2017-06-23 17:25:43 UTC (rev 218750)
@@ -1,3 +1,20 @@
+2017-06-23  Alex Christensen  <[email protected]>
+
+        Add SPI to WKURLSchemeTask for redirection
+        https://bugs.webkit.org/show_bug.cgi?id=173730
+
+        Reviewed by Brady Eidson.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm:
+        (-[SchemeHandler webView:startURLSchemeTask:]):
+        (-[SchemeHandler webView:stopURLSchemeTask:]):
+        (TEST):
+        (-[RedirectSchemeHandler webView:startURLSchemeTask:]):
+        (-[RedirectSchemeHandler webView:stopURLSchemeTask:]):
+        (-[RedirectSchemeHandler webView:didReceiveServerRedirectForProvisionalNavigation:]):
+        (-[RedirectSchemeHandler webView:decidePolicyForNavigationResponse:decisionHandler:]):
+        (-[RedirectSchemeHandler userContentController:didReceiveScriptMessage:]):
+
 2017-06-23  Carlos Garcia Campos  <[email protected]>
 
         [WPE] Use JSC API to send script messages from web extension in tests

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm (218749 => 218750)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm	2017-06-23 17:21:48 UTC (rev 218749)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKURLSchemeHandler-1.mm	2017-06-23 17:25:43 UTC (rev 218750)
@@ -28,14 +28,15 @@
 #import "PlatformUtilities.h"
 #import "Test.h"
 #import <WebKit/WKURLSchemeHandler.h>
-#import <WebKit/WKURLSchemeTask.h>
+#import <WebKit/WKURLSchemeTaskPrivate.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WebKit.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/Vector.h>
 
 #if WK_API_ENABLED
 
-static bool receivedScriptMessage;
+static bool done;
 
 @interface SchemeHandler : NSObject <WKURLSchemeHandler>
 @property (readonly) NSMutableArray<NSURL *> *startedURLs;
@@ -76,7 +77,7 @@
     // Always fail the image load.
     if ([task.request.URL.absoluteString isEqualToString:@"testing:image"]) {
         [task didFailWithError:[NSError errorWithDomain:@"TestWebKitAPI" code:1 userInfo:nil]];
-        receivedScriptMessage = true;
+        done = true;
         return;
     }
 
@@ -90,7 +91,7 @@
 {
     [_stoppedURLs addObject:task.request.URL];
 
-    receivedScriptMessage = true;
+    done = true;
 }
 
 @end
@@ -102,7 +103,7 @@
 
 TEST(URLSchemeHandler, Basic)
 {
-    receivedScriptMessage = false;
+    done = false;
 
     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
 
@@ -114,7 +115,7 @@
     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:main"]];
     [webView loadRequest:request];
 
-    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    TestWebKitAPI::Util::run(&done);
 
     EXPECT_EQ([handler.get().startedURLs count], 2u);
     EXPECT_TRUE([[handler.get().startedURLs objectAtIndex:0] isEqual:[NSURL URLWithString:@"testing:main"]]);
@@ -127,7 +128,7 @@
     // Since there's no MIMEType, and no NavigationDelegate to tell WebKit to do the load anyways, WebKit will ignore (silently fail) the load.
     // This test makes sure that is communicated back to the URLSchemeHandler.
 
-    receivedScriptMessage = false;
+    done = false;
 
     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
 
@@ -139,7 +140,7 @@
     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:main"]];
     [webView loadRequest:request];
 
-    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    TestWebKitAPI::Util::run(&done);
 
     EXPECT_EQ([handler.get().startedURLs count], 1u);
     EXPECT_TRUE([[handler.get().startedURLs objectAtIndex:0] isEqual:[NSURL URLWithString:@"testing:main"]]);
@@ -191,5 +192,166 @@
     }
 }
 
+static bool receivedRedirect;
+static bool responsePolicyDecided;
 
+@interface RedirectSchemeHandler : NSObject <WKURLSchemeHandler, WKNavigationDelegate, WKScriptMessageHandler>
+@end
+
+@implementation RedirectSchemeHandler { }
+
+- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+    ASSERT_STREQ(task.request.URL.absoluteString.UTF8String, "testing:///initial");
+    NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil] autorelease];
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///redirected"]];
+    [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:response newRequest:request];
+    ASSERT_FALSE(receivedRedirect);
+    ASSERT_STREQ(task.request.URL.absoluteString.UTF8String, "testing:///redirected");
+    NSString *html = @"<script>window.webkit.messageHandlers.testHandler.postMessage('Document URL: ' + document.URL);</script>";
+    [task didReceiveResponse:[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil]];
+    [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
+    [task didFinish];
+}
+
+- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+    ASSERT_TRUE(false);
+}
+
+- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation
+{
+    ASSERT_FALSE(receivedRedirect);
+    receivedRedirect = true;
+}
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+    ASSERT_TRUE(receivedRedirect);
+    ASSERT_STREQ(navigationResponse.response.URL.absoluteString.UTF8String, "testing:///redirected");
+    ASSERT_FALSE(responsePolicyDecided);
+    responsePolicyDecided = true;
+    decisionHandler(WKNavigationResponsePolicyAllow);
+}
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    EXPECT_WK_STREQ(@"Document URL: testing:///redirected", [message body]);
+    done = true;
+}
+@end
+
+TEST(URLSchemeHandler, Redirection)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[RedirectSchemeHandler alloc] init]);
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
+    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView setNavigationDelegate:handler.get()];
+    
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///initial"]];
+    [webView loadRequest:request];
+    
+    TestWebKitAPI::Util::run(&done);
+    
+    EXPECT_TRUE(responsePolicyDecided);
+    EXPECT_STREQ(webView.get().URL.absoluteString.UTF8String, "testing:///redirected");
+}
+
+enum class Command {
+    Redirect,
+    Response,
+    Data,
+    Finish,
+    Error,
+};
+
+@interface TaskSchemeHandler : NSObject <WKURLSchemeHandler>
+- (instancetype)initWithCommands:(Vector<Command>&&)commandVector expectedException:(bool)expected;
+@end
+
+@implementation TaskSchemeHandler {
+    Vector<Command> commands;
+    bool expectedException;
+}
+
+- (instancetype)initWithCommands:(Vector<Command>&&)commandVector expectedException:(bool)expected
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    
+    self->commands = WTFMove(commandVector);
+    self->expectedException = expected;
+    
+    return self;
+}
+
+- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+    bool caughtException = false;
+    @try {
+        for (auto command : commands) {
+            switch (command) {
+            case Command::Redirect:
+                [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:[[[NSURLResponse alloc] init] autorelease] newRequest:[[[NSURLRequest alloc] init] autorelease]];
+                break;
+            case Command::Response:
+                [task didReceiveResponse:[[[NSURLResponse alloc] init] autorelease]];
+                break;
+            case Command::Data:
+                [task didReceiveData:[[[NSData alloc] init] autorelease]];
+                break;
+            case Command::Finish:
+                [task didFinish];
+                break;
+            case Command::Error:
+                [task didFailWithError:[[[NSError alloc] init] autorelease]];
+                break;
+            }
+        }
+    }
+    @catch(NSException *exception)
+    {
+        caughtException = true;
+    }
+    ASSERT_EQ(caughtException, expectedException);
+    done = true;
+}
+
+- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+}
+@end
+
+enum class ShouldRaiseException { No, Yes };
+
+static void checkCallSequence(Vector<Command>&& commands, ShouldRaiseException shouldRaiseException)
+{
+    done = false;
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[TaskSchemeHandler alloc] initWithCommands:WTFMove(commands) expectedException:shouldRaiseException == ShouldRaiseException::Yes]);
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:///initial"]]];
+    TestWebKitAPI::Util::run(&done);
+}
+
+TEST(URLSchemeHandler, Exceptions)
+{
+    checkCallSequence({Command::Response, Command::Data, Command::Finish}, ShouldRaiseException::No);
+    checkCallSequence({Command::Response, Command::Redirect}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Redirect, Command::Response}, ShouldRaiseException::No);
+    checkCallSequence({Command::Data, Command::Finish}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Error}, ShouldRaiseException::No);
+    checkCallSequence({Command::Error, Command::Error}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Error, Command::Data}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Response, Command::Finish, Command::Data}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Response, Command::Finish, Command::Redirect}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Response, Command::Finish, Command::Response}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Response, Command::Finish, Command::Finish}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::Response, Command::Finish, Command::Error}, ShouldRaiseException::Yes);
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to