Title: [275447] trunk
Revision
275447
Author
[email protected]
Date
2021-04-02 15:39:22 -0700 (Fri, 02 Apr 2021)

Log Message

Add WKURLSchemeTask redirect API.
https://bugs.webkit.org/show_bug.cgi?id=224119

Reviewed by Alex Christensen.

Source/WebKit:

Covered by new API tests.

Instead of the existing "did do a redirect" SPI without completion handler, this one has
a completion handler with a new request for the task, proposed by WebKit.

* UIProcess/API/Cocoa/WKURLSchemeTask.h:
* UIProcess/API/Cocoa/WKURLSchemeTask.mm:
(raiseExceptionIfNecessary):
(-[WKURLSchemeTaskImpl willPerformRedirection:newRequest:completionHandler:]):

* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration setURLSchemeHandler:forURLScheme:]):

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setURLSchemeHandlerForScheme):

* UIProcess/WebURLSchemeTask.cpp:
(WebKit::WebURLSchemeTask::willPerformRedirection):
(WebKit::WebURLSchemeTask::didPerformRedirection):
(WebKit::WebURLSchemeTask::didReceiveResponse):
(WebKit::WebURLSchemeTask::didReceiveData):
(WebKit::WebURLSchemeTask::didComplete):
* UIProcess/WebURLSchemeTask.h:
(WebKit::WebURLSchemeTask::waitingForRedirectCompletionHandlerCallback const):

* WebKit.xcodeproj/project.pbxproj:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::urlSchemeTaskWillPerformRedirection):
(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/WebKitCocoa/WKURLSchemeHandler-1.mm:
(-[TaskSchemeHandler webView:startURLSchemeTask:]):
(TEST):
(-[HTTPRedirectTest webView:startURLSchemeTask:]):
(-[HTTPRedirectTest webView:stopURLSchemeTask:]):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (275446 => 275447)


--- trunk/Source/WebKit/ChangeLog	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/ChangeLog	2021-04-02 22:39:22 UTC (rev 275447)
@@ -1,3 +1,51 @@
+2021-04-02  Brady Eidson  <[email protected]>
+
+        Add WKURLSchemeTask redirect API.
+        https://bugs.webkit.org/show_bug.cgi?id=224119
+
+        Reviewed by Alex Christensen.
+
+        Covered by new API tests.
+        
+        Instead of the existing "did do a redirect" SPI without completion handler, this one has
+        a completion handler with a new request for the task, proposed by WebKit.
+
+        * UIProcess/API/Cocoa/WKURLSchemeTask.h:
+        * UIProcess/API/Cocoa/WKURLSchemeTask.mm:
+        (raiseExceptionIfNecessary):
+        (-[WKURLSchemeTaskImpl willPerformRedirection:newRequest:completionHandler:]):
+
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+        (-[WKWebViewConfiguration setURLSchemeHandler:forURLScheme:]):
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::setURLSchemeHandlerForScheme):
+
+        * UIProcess/WebURLSchemeTask.cpp:
+        (WebKit::WebURLSchemeTask::willPerformRedirection):
+        (WebKit::WebURLSchemeTask::didPerformRedirection):
+        (WebKit::WebURLSchemeTask::didReceiveResponse):
+        (WebKit::WebURLSchemeTask::didReceiveData):
+        (WebKit::WebURLSchemeTask::didComplete):
+        * UIProcess/WebURLSchemeTask.h:
+        (WebKit::WebURLSchemeTask::waitingForRedirectCompletionHandlerCallback const):
+
+        * WebKit.xcodeproj/project.pbxproj:
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::urlSchemeTaskWillPerformRedirection):
+        (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:
+
 2021-04-02  Chris Dumez  <[email protected]>
 
         Introduce ScriptBuffer class to wrap SharedBuffer containing a script

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.h (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.h	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.h	2021-04-02 22:39:22 UTC (rev 275447)
@@ -36,6 +36,21 @@
  */
 @property (nonatomic, readonly, copy) NSURLRequest *request;
 
+/*! @abstract Indicate the task was redirected.
+ @param response The response causing a redirect to a new URL.
+ @param newRequest The new proposed request to handle the redirection.
+ @param completionHandler A completion handler called with the request you should use to commit to the redirection.
+ @discussion When performing a load of a URL over a network, the server might decide a different URL should be loaded instead.
+ A common example is an HTTP redirect.
+ When this happens, you should notify WebKit by sending the servers response and a proposed new request to the WKURLSchemeTask.
+ WebKit might decide that changes need to be make to the proposed request.
+ This is communicated through the completionHandler which tells you the request you should make to commit to the redirection.
+
+ An exception will be thrown if you make any other callbacks to the WKURLSchemeTask while this completionHandler is pending, other than didFailWithError:.
+ An exception will be thrown if your app has been told to stop loading this task via the registered WKURLSchemeHandler object.
+ */
+- (void)willPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 /*! @abstract Set the current response object for the task.
  @param response The response to use.
  @discussion This method must be called at least once for each URL scheme handler task.

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2021-04-02 22:39:22 UTC (rev 275447)
@@ -34,6 +34,7 @@
 #import <WebCore/ResourceResponse.h>
 #import <WebCore/SharedBuffer.h>
 #import <wtf/BlockPtr.h>
+#import <wtf/CompletionHandler.h>
 #import <wtf/MainThread.h>
 
 static WebKit::WebURLSchemeTask::ExceptionType getExceptionTypeFromMainRunLoop(Function<WebKit::WebURLSchemeTask::ExceptionType ()>&& function)
@@ -66,6 +67,9 @@
     case WebKit::WebURLSchemeTask::ExceptionType::RedirectAfterResponse:
         [NSException raise:NSInternalInconsistencyException format:@"No redirects are allowed after the response"];
         break;
+    case WebKit::WebURLSchemeTask::ExceptionType::WaitingForRedirectCompletionHandler:
+        [NSException raise:NSInternalInconsistencyException format:@"No callbacks are allowed while waiting for the redirection completion handler to be invoked"];
+        break;
     }
 }
 
@@ -92,6 +96,18 @@
     return _urlSchemeTask->task().nsRequest().cachePolicy == NSURLRequestReturnCacheDataDontLoad;
 }
 
+- (void)willPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler
+{
+    auto function = [protectedSelf = retainPtr(self), self, protectedResponse = retainPtr(response), response, protectedRequest = retainPtr(request), request, handler = makeBlockPtr(completionHandler)] () mutable {
+        return _urlSchemeTask->task().willPerformRedirection(response, request, [handler = WTFMove(handler)] (WebCore::ResourceRequest&& actualNewRequest) {
+            handler.get()(actualNewRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody));
+        });
+    };
+
+    auto result = getExceptionTypeFromMainRunLoop(WTFMove(function));
+    raiseExceptionIfNecessary(result);
+}
+
 - (void)didReceiveResponse:(NSURLResponse *)response
 {
     auto function = [protectedSelf = retainPtr(self), self, protectedResponse = retainPtr(response), response] {

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2021-04-02 22:39:22 UTC (rev 275447)
@@ -554,7 +554,7 @@
 
 - (void)setURLSchemeHandler:(id <WKURLSchemeHandler>)urlSchemeHandler forURLScheme:(NSString *)urlScheme
 {
-    if ([WKWebView handlesURLScheme:urlScheme])
+    if ([WKWebView handlesURLScheme:urlScheme] && [urlScheme caseInsensitiveCompare:@"http"] != NSOrderedSame && [urlScheme caseInsensitiveCompare:@"https"] != NSOrderedSame)
         [NSException raise:NSInvalidArgumentException format:@"'%@' is a URL scheme that WKWebView handles natively", urlScheme];
 
     auto canonicalScheme = WTF::URLParser::maybeCanonicalizeScheme(urlScheme);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-04-02 22:39:22 UTC (rev 275447)
@@ -9495,16 +9495,18 @@
 {
     auto canonicalizedScheme = WTF::URLParser::maybeCanonicalizeScheme(scheme);
     ASSERT(canonicalizedScheme);
-    ASSERT(!WTF::URLParser::isSpecialScheme(canonicalizedScheme.value()));
 
+    bool schemeIsInHTTPFamily = *canonicalizedScheme == "http" || *canonicalizedScheme == "https";
+    ASSERT_UNUSED(schemeIsInHTTPFamily, schemeIsInHTTPFamily || !WTF::URLParser::isSpecialScheme(canonicalizedScheme.value()));
+
     auto schemeResult = m_urlSchemeHandlersByScheme.add(canonicalizedScheme.value(), handler.get());
     ASSERT_UNUSED(schemeResult, schemeResult.isNewEntry);
 
-    auto identifier = handler->identifier();
-    auto identifierResult = m_urlSchemeHandlersByIdentifier.add(identifier, WTFMove(handler));
-    ASSERT_UNUSED(identifierResult, identifierResult.isNewEntry);
+    auto handlerIdentifier = handler->identifier();
+    auto handlerIdentifierResult = m_urlSchemeHandlersByIdentifier.add(handlerIdentifier, WTFMove(handler));
+    ASSERT_UNUSED(handlerIdentifierResult, handlerIdentifierResult.isNewEntry);
 
-    send(Messages::WebPage::RegisterURLSchemeHandler(identifier, canonicalizedScheme.value()));
+    send(Messages::WebPage::RegisterURLSchemeHandler(handlerIdentifier, canonicalizedScheme.value()));
 }
 
 WebURLSchemeHandler* WebPageProxy::urlSchemeHandlerForScheme(const String& scheme)

Modified: trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/WebURLSchemeTask.cpp	2021-04-02 22:39:22 UTC (rev 275447)
@@ -60,6 +60,50 @@
     ASSERT(RunLoop::isMain());
 }
 
+auto WebURLSchemeTask::willPerformRedirection(ResourceResponse&& response, ResourceRequest&& request,  Function<void(ResourceRequest&&)>&& completionHandler) -> ExceptionType
+{
+    ASSERT(RunLoop::isMain());
+
+    if (m_stopped)
+        return m_shouldSuppressTaskStoppedExceptions ? ExceptionType::None : ExceptionType::TaskAlreadyStopped;
+
+    if (m_completed)
+        return ExceptionType::CompleteAlreadyCalled;
+
+    if (m_dataSent)
+        return ExceptionType::DataAlreadySent;
+
+    if (m_responseSent)
+        return ExceptionType::RedirectAfterResponse;
+
+    if (m_waitingForRedirectCompletionHandlerCallback)
+        return ExceptionType::WaitingForRedirectCompletionHandler;
+
+    if (isSync())
+        m_syncResponse = response;
+
+    {
+        LockHolder locker(m_requestLock);
+        m_request = request;
+    }
+
+    auto* page = WebProcessProxy::webPage(m_pageProxyID);
+    if (!page)
+        return ExceptionType::None;
+
+    m_waitingForRedirectCompletionHandlerCallback = true;
+
+    Function<void(ResourceRequest&&)> innerCompletionHandler = [protectedThis = makeRef(*this), this, completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request) mutable {
+        m_waitingForRedirectCompletionHandlerCallback = false;
+        if (!m_stopped && !m_completed)
+            completionHandler(WTFMove(request));
+    };
+
+    page->sendWithAsyncReply(Messages::WebPage::URLSchemeTaskWillPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request), WTFMove(innerCompletionHandler));
+
+    return ExceptionType::None;
+}
+
 auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& response, WebCore::ResourceRequest&& request) -> ExceptionType
 {
     ASSERT(RunLoop::isMain());
@@ -66,16 +110,19 @@
 
     if (m_stopped)
         return m_shouldSuppressTaskStoppedExceptions ? ExceptionType::None : ExceptionType::TaskAlreadyStopped;
-    
+
     if (m_completed)
         return ExceptionType::CompleteAlreadyCalled;
-    
+
     if (m_dataSent)
         return ExceptionType::DataAlreadySent;
-    
+
     if (m_responseSent)
         return ExceptionType::RedirectAfterResponse;
-    
+
+    if (m_waitingForRedirectCompletionHandlerCallback)
+        return ExceptionType::WaitingForRedirectCompletionHandler;
+
     if (isSync())
         m_syncResponse = response;
 
@@ -102,6 +149,9 @@
     if (m_dataSent)
         return ExceptionType::DataAlreadySent;
 
+    if (m_waitingForRedirectCompletionHandlerCallback)
+        return ExceptionType::WaitingForRedirectCompletionHandler;
+
     m_responseSent = true;
 
     response.includeCertificateInfo();
@@ -126,6 +176,9 @@
     if (!m_responseSent)
         return ExceptionType::NoResponseSent;
 
+    if (m_waitingForRedirectCompletionHandlerCallback)
+        return ExceptionType::WaitingForRedirectCompletionHandler;
+
     m_dataSent = true;
 
     if (isSync()) {
@@ -153,6 +206,9 @@
     if (!m_responseSent && error.isNull())
         return ExceptionType::NoResponseSent;
 
+    if (m_waitingForRedirectCompletionHandlerCallback && error.isNull())
+        return ExceptionType::WaitingForRedirectCompletionHandler;
+
     m_completed = true;
     
     if (isSync()) {

Modified: trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h (275446 => 275447)


--- trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/UIProcess/WebURLSchemeTask.h	2021-04-02 22:39:22 UTC (rev 275447)
@@ -76,8 +76,10 @@
         RedirectAfterResponse,
         TaskAlreadyStopped,
         NoResponseSent,
+        WaitingForRedirectCompletionHandler,
         None,
     };
+    ExceptionType willPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&,  Function<void(WebCore::ResourceRequest&&)>&&);
     ExceptionType didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
     ExceptionType didReceiveResponse(const WebCore::ResourceResponse&);
     ExceptionType didReceiveData(Ref<WebCore::SharedBuffer>&&);
@@ -88,6 +90,8 @@
 
     void suppressTaskStoppedExceptions() { m_shouldSuppressTaskStoppedExceptions = true; }
 
+    bool waitingForRedirectCompletionHandlerCallback() const { return m_waitingForRedirectCompletionHandlerCallback; }
+
 private:
     WebURLSchemeTask(WebURLSchemeHandler&, WebPageProxy&, WebProcessProxy&, WebCore::PageIdentifier, URLSchemeTaskParameters&&, SyncLoadCompletionHandler&&);
 
@@ -110,6 +114,8 @@
     SyncLoadCompletionHandler m_syncCompletionHandler;
     WebCore::ResourceResponse m_syncResponse;
     RefPtr<WebCore::SharedBuffer> m_syncData;
+
+    bool m_waitingForRedirectCompletionHandlerCallback { false };
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (275446 => 275447)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-04-02 22:39:22 UTC (rev 275447)
@@ -1051,6 +1051,8 @@
 		517CF0E3163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */; };
 		517CF0E3163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0E1163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp */; };
 		517CF0E4163A486C00C2950E /* NetworkProcessConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */; };
+		5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 51832475261599CC003F239E /* NetworkURLSchemeHandler.h */; };
+		5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 5183247A26168675003F239E /* NetworkURLSchemeTask.h */; };
 		5183722223CE97410003CF83 /* APIContentWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 5183722023CE973A0003CF83 /* APIContentWorld.h */; };
 		51871B5C127CB89D00F76232 /* WebContextMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 51871B5A127CB89D00F76232 /* WebContextMenu.h */; };
 		518ACAEA12AEE6BB00B04B83 /* WKProtectionSpaceTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 518ACAE912AEE6BB00B04B83 /* WKProtectionSpaceTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4031,6 +4033,12 @@
 		517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkProcessConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/NetworkProcessConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		517CF0E1163A486C00C2950F /* CacheStorageEngineConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CacheStorageEngineConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/CacheStorageEngineConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkProcessConnectionMessages.h; path = DerivedSources/WebKit2/NetworkProcessConnectionMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
+		51832475261599CC003F239E /* NetworkURLSchemeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkURLSchemeHandler.h; sourceTree = "<group>"; };
+		51832476261599CC003F239E /* NetworkURLSchemeHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkURLSchemeHandler.cpp; sourceTree = "<group>"; };
+		518324782615B00D003F239E /* NetworkSchemeURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSchemeURLProtocol.h; sourceTree = "<group>"; };
+		518324792615B00D003F239E /* NetworkSchemeURLProtocol.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkSchemeURLProtocol.mm; sourceTree = "<group>"; };
+		5183247A26168675003F239E /* NetworkURLSchemeTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkURLSchemeTask.h; sourceTree = "<group>"; };
+		5183247B26168675003F239E /* NetworkURLSchemeTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkURLSchemeTask.cpp; sourceTree = "<group>"; };
 		5183722023CE973A0003CF83 /* APIContentWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIContentWorld.h; sourceTree = "<group>"; };
 		5183722123CE973A0003CF83 /* APIContentWorld.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIContentWorld.cpp; sourceTree = "<group>"; };
 		5183B3931379F85C00E8754E /* Shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shim.xcconfig; sourceTree = "<group>"; };
@@ -8523,6 +8531,10 @@
 				5C0B177E1E7C886700E9123C /* NetworkSocketStream.h */,
 				5C0B177F1E7C886700E9123C /* NetworkSocketStream.messages.in */,
 				5C9EF2E721F058F9003BDC56 /* NetworkStorageSessionProvider.h */,
+				51832476261599CC003F239E /* NetworkURLSchemeHandler.cpp */,
+				51832475261599CC003F239E /* NetworkURLSchemeHandler.h */,
+				5183247B26168675003F239E /* NetworkURLSchemeTask.cpp */,
+				5183247A26168675003F239E /* NetworkURLSchemeTask.h */,
 				462107D71F38DBD300DD7810 /* PingLoad.cpp */,
 				5CE85B1F1C88E6430070BFCE /* PingLoad.h */,
 				83A0ED331F747CC7003299EB /* PreconnectTask.cpp */,
@@ -9257,6 +9269,8 @@
 				7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */,
 				532159501DBAE6D70054AA3C /* NetworkSessionCocoa.h */,
 				5C20CB9B1BB0DCD200895BB1 /* NetworkSessionCocoa.mm */,
+				518324782615B00D003F239E /* NetworkSchemeURLProtocol.h */,
+				518324792615B00D003F239E /* NetworkSchemeURLProtocol.mm */,
 				41287D4C225C05C5009A3E26 /* WebSocketTaskCocoa.h */,
 				41287D4B225C05C4009A3E26 /* WebSocketTaskCocoa.mm */,
 			);
@@ -11661,6 +11675,7 @@
 				317FE7C51C487A6C00A0CA89 /* APIExperimentalFeature.h in Headers */,
 				00B9661618E24CBA00CE1F88 /* APIFindClient.h in Headers */,
 				2DD67A2E1BD819730053B251 /* APIFindMatchesClient.h in Headers */,
+				5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */,
 				37E25D6E18FDE5D6005D3A00 /* APIFormClient.h in Headers */,
 				1AC1337218566C7C00F3EC05 /* APIFrameHandle.h in Headers */,
 				2DF9EEE61A781FB400B6CFBE /* APIFrameInfo.h in Headers */,
@@ -12811,6 +12826,7 @@
 				0FCB4E6818BBE3D9000FCFC9 /* WKTextInputWindowController.h in Headers */,
 				CE21215F240EE571006ED443 /* WKTextPlaceholder.h in Headers */,
 				CE45945C240F88550078019F /* WKTextSelectionRect.h in Headers */,
+				5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */,
 				2EB6FC01203021960017E619 /* WKTimePickerViewController.h in Headers */,
 				71A676A622C62325007D6295 /* WKTouchActionGestureRecognizer.h in Headers */,
 				BC407608124FF0270068F20A /* WKType.h in Headers */,

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-04-02 22:39:22 UTC (rev 275447)
@@ -6731,12 +6731,21 @@
     m_identifierToURLSchemeHandlerProxyMap.add(handlerIdentifier, schemeResult.iterator->value.get());
 }
 
+void WebPage::urlSchemeTaskWillPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, ResourceResponse&& response, ResourceRequest&& request, CompletionHandler<void(WebCore::ResourceRequest&&)>&& completionHandler)
+{
+    auto* handler = m_identifierToURLSchemeHandlerProxyMap.get(handlerIdentifier);
+    ASSERT(handler);
+
+    auto actualNewRequest = request;
+    handler->taskDidPerformRedirection(taskIdentifier, WTFMove(response), WTFMove(request), WTFMove(completionHandler));
+}
+
 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));
+
+    handler->taskDidPerformRedirection(taskIdentifier, WTFMove(response), WTFMove(request), [] (ResourceRequest&&) {});
 }
     
 void WebPage::urlSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, const ResourceResponse& response)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-04-02 22:39:22 UTC (rev 275447)
@@ -1807,6 +1807,7 @@
 
     void registerURLSchemeHandler(uint64_t identifier, const String& scheme);
 
+    void urlSchemeTaskWillPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, CompletionHandler<void(WebCore::ResourceRequest&&)>&&);
     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&);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2021-04-02 22:39:22 UTC (rev 275447)
@@ -559,7 +559,8 @@
 
     RegisterURLSchemeHandler(uint64_t identifier, String scheme)
 
-    URLSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response, WebCore::ResourceRequest request)
+    URLSchemeTaskWillPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response, WebCore::ResourceRequest proposedRequest) -> (WebCore::ResourceRequest actualRequest) Async
+    URLSchemeTaskDidPerformRedirection(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response, WebCore::ResourceRequest proposedRequest)
     URLSchemeTaskDidReceiveResponse(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceResponse response)
     URLSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, IPC::SharedBufferDataReference data)
     URLSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.cpp	2021-04-02 22:39:22 UTC (rev 275447)
@@ -78,13 +78,13 @@
         m_tasks.begin()->value->stopLoading();
 }
 
-void WebURLSchemeHandlerProxy::taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& newRequest)
+void WebURLSchemeHandlerProxy::taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& newRequest, CompletionHandler<void(WebCore::ResourceRequest&&)>&& completionHandler)
 {
     auto* task = m_tasks.get(taskIdentifier);
     if (!task)
         return;
     
-    task->didPerformRedirection(WTFMove(redirectResponse), WTFMove(newRequest));
+    task->didPerformRedirection(WTFMove(redirectResponse), WTFMove(newRequest), WTFMove(completionHandler));
 }
 
 void WebURLSchemeHandlerProxy::taskDidReceiveResponse(uint64_t taskIdentifier, const ResourceResponse& response)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.h (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.h	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeHandlerProxy.h	2021-04-02 22:39:22 UTC (rev 275447)
@@ -57,7 +57,7 @@
     uint64_t identifier() const { return m_identifier; }
     WebPage& page() { return m_webPage; }
 
-    void taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
+    void taskDidPerformRedirection(uint64_t taskIdentifier, WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, CompletionHandler<void(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&);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp	2021-04-02 22:39:22 UTC (rev 275447)
@@ -68,31 +68,31 @@
     m_urlSchemeHandler.taskDidStopLoading(*this);
 }
     
-void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request)
+void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request, CompletionHandler<void(WebCore::ResourceRequest&&)>&& completionHandler)
 {
-    if (!hasLoader())
+    if (!hasLoader()) {
+        completionHandler({ });
         return;
-    
-    auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) {
-        m_waitingForCompletionHandler = 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())
-            RELEASE_LOG(Loading, "Redirected scheme task would have been sent to a different URL.");
+    }
 
-        processNextPendingTask();
-    };
-    
     if (m_waitingForCompletionHandler) {
         RELEASE_LOG(Loading, "Received redirect during previous redirect processing, queuing it.");
-        queueTask([this, protectedThis = makeRef(*this), redirectResponse = WTFMove(redirectResponse), request = WTFMove(request)]() mutable {
-            didPerformRedirection(WTFMove(redirectResponse), WTFMove(request));
+        queueTask([this, protectedThis = makeRef(*this), redirectResponse = WTFMove(redirectResponse), request = WTFMove(request), completionHandler = WTFMove(completionHandler)]() mutable {
+            didPerformRedirection(WTFMove(redirectResponse), WTFMove(request), WTFMove(completionHandler));
         });
         return;
     }
     m_waitingForCompletionHandler = true;
 
-    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
+    auto innerCompletionHandler = [this, protectedThis = makeRef(*this), originalRequest = request, completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request) mutable {
+        m_waitingForCompletionHandler = false;
+
+        completionHandler(WTFMove(request));
+
+        processNextPendingTask();
+    };
+
+    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(innerCompletionHandler));
 }
 
 void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.h (275446 => 275447)


--- trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.h	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.h	2021-04-02 22:39:22 UTC (rev 275447)
@@ -52,7 +52,7 @@
     void startLoading();
     void stopLoading();
 
-    void didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&);
+    void didPerformRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, CompletionHandler<void(WebCore::ResourceRequest&&)>&&);
     void didReceiveResponse(const WebCore::ResourceResponse&);
     void didReceiveData(size_t, const uint8_t* data);
     void didComplete(const WebCore::ResourceError&);

Modified: trunk/Tools/ChangeLog (275446 => 275447)


--- trunk/Tools/ChangeLog	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Tools/ChangeLog	2021-04-02 22:39:22 UTC (rev 275447)
@@ -1,3 +1,16 @@
+2021-04-02  Brady Eidson  <[email protected]>
+
+        Add WKURLSchemeTask redirect API.
+        https://bugs.webkit.org/show_bug.cgi?id=224119
+
+        Reviewed by Alex Christensen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
+        (-[TaskSchemeHandler webView:startURLSchemeTask:]):
+        (TEST):
+        (-[HTTPRedirectTest webView:startURLSchemeTask:]):
+        (-[HTTPRedirectTest webView:stopURLSchemeTask:]):
+
 2021-04-02  Jonathan Bedard  <[email protected]>
 
         [check-webkit-style] Check python files in LayoutTests

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm (275446 => 275447)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm	2021-04-02 22:33:42 UTC (rev 275446)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm	2021-04-02 22:39:22 UTC (rev 275447)
@@ -224,8 +224,6 @@
     @"data",
     @"file",
     @"ftp",
-    @"http",
-    @"https",
     @"_javascript_",
     @"webkit-fake-url",
     @"ws",
@@ -346,6 +344,7 @@
 
 enum class Command {
     Redirect,
+    APIRedirect,
     Response,
     Data,
     Finish,
@@ -382,6 +381,9 @@
             case Command::Redirect:
                 [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:adoptNS([[NSURLResponse alloc] init]).get() newRequest:adoptNS([[NSURLRequest alloc] init]).get()];
                 break;
+            case Command::APIRedirect:
+                [(id<WKURLSchemeTaskPrivate>)task willPerformRedirection:adoptNS([[NSURLResponse alloc] init]).get() newRequest:adoptNS([[NSURLRequest alloc] init]).get() completionHandler:^(NSURLRequest*) { }];
+                break;
             case Command::Response:
                 [task didReceiveResponse:adoptNS([[NSURLResponse alloc] init]).get()];
                 break;
@@ -437,6 +439,11 @@
     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);
+    checkCallSequence({Command::APIRedirect, Command::Redirect}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::APIRedirect, Command::Response}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::APIRedirect, Command::Data}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::APIRedirect, Command::Finish}, ShouldRaiseException::Yes);
+    checkCallSequence({Command::APIRedirect, Command::Error}, ShouldRaiseException::No);
 }
 
 struct SchemeResourceInfo {
@@ -1433,3 +1440,62 @@
     TestWebKitAPI::Util::run(&receivedScriptMessage);
     EXPECT_WK_STREQ(@"secure", [lastScriptMessage body]);
 }
+
+@interface HTTPRedirectTest : NSObject <WKURLSchemeHandler> {
+}
+@end
+
+@implementation HTTPRedirectTest
+
+- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+    auto redirectResponse = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil]);
+    auto redirectRequest = adoptNS([[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://bar.com/anothertest.html"]]);
+
+    [task willPerformRedirection:redirectResponse.get() newRequest:redirectRequest.get() completionHandler:^(NSURLRequest *proposedRequest) {
+        NSString *html = @"<script>window.webkit.messageHandlers.testHandler.postMessage('Document URL: ' + document.URL);</script>";
+        auto finalResponse = adoptNS([[NSURLResponse alloc] initWithURL:proposedRequest.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil]);
+
+        [task didReceiveResponse:finalResponse.get()];
+        [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
+        [task didFinish];
+    }];
+}
+
+- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+}
+
+@end
+
+TEST(URLSchemeHandler, HTTPWithRedirect)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto schemeHandler = adoptNS([TestURLSchemeHandler new]);
+    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+        auto redirectResponse = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil]);
+        auto redirectRequest = adoptNS([[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://bar.com/anothertest.html"]]);
+
+        [task willPerformRedirection:redirectResponse.get() newRequest:redirectRequest.get() completionHandler:^(NSURLRequest *proposedRequest) {
+            NSString *html = @"<script>window.webkit.messageHandlers.testHandler.postMessage('Document URL: ' + document.URL);</script>";
+            auto finalResponse = adoptNS([[NSURLResponse alloc] initWithURL:proposedRequest.URL MIMEType:@"text/html" expectedContentLength:html.length textEncodingName:nil]);
+
+            [task didReceiveResponse:finalResponse.get()];
+            [task didReceiveData:[html dataUsingEncoding:NSUTF8StringEncoding]];
+            [task didFinish];
+        }];
+    }];
+
+    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"http"];
+    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"https"];
+
+    auto messageHandler = adoptNS([[URLSchemeHandlerMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    receivedScriptMessage = false;
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://foo.com/test.html"]]];
+    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    EXPECT_WK_STREQ(@"Document URL: https://bar.com/anothertest.html", [lastScriptMessage body]);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to