Title: [286751] trunk
Revision
286751
Author
achristen...@apple.com
Date
2021-12-08 16:19:46 -0800 (Wed, 08 Dec 2021)

Log Message

Add SPI to load a resource in the context of a page
https://bugs.webkit.org/show_bug.cgi?id=233908

Reviewed by Tim Horton.

Source/WebKit:

This is similar to startDownloadUsingRequest but you don't have to get the data from the disk.
This is similar to NSURLSession's dataTaskWithRequest:completionHandler: but using the same session as the page.
This is needed because LinkPresentation is currently using _getMainResourceDataWithCompletionHandler after loading
in a WKWebView made with _relatedWebView to get the content of a resource, and that's awful and limited to certain mime types.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::requestResource):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkSession.h:
(WebKit::NetworkSession::requestResource):
* NetworkProcess/cocoa/NetworkSessionCocoa.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(WebKit::NetworkSessionCocoa::requestResource):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _requestResource:completionHandler:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::requestResource):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::requestResource):
* UIProcess/WebPageProxy.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (286750 => 286751)


--- trunk/Source/WebKit/ChangeLog	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/ChangeLog	2021-12-09 00:19:46 UTC (rev 286751)
@@ -1,3 +1,34 @@
+2021-12-08  Alex Christensen  <achristen...@webkit.org>
+
+        Add SPI to load a resource in the context of a page
+        https://bugs.webkit.org/show_bug.cgi?id=233908
+
+        Reviewed by Tim Horton.
+
+        This is similar to startDownloadUsingRequest but you don't have to get the data from the disk.
+        This is similar to NSURLSession's dataTaskWithRequest:completionHandler: but using the same session as the page.
+        This is needed because LinkPresentation is currently using _getMainResourceDataWithCompletionHandler after loading
+        in a WKWebView made with _relatedWebView to get the content of a resource, and that's awful and limited to certain mime types.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::requestResource):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/NetworkSession.h:
+        (WebKit::NetworkSession::requestResource):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.h:
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (WebKit::NetworkSessionCocoa::requestResource):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _requestResource:completionHandler:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::requestResource):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::requestResource):
+        * UIProcess/WebPageProxy.h:
+
 2021-12-08  BJ Burg  <bb...@apple.com>
 
         Web Inspector: evaluateScriptForExtension() incorrectly unwraps internal errors, causing an ASSERT

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-12-09 00:19:46 UTC (rev 286751)
@@ -2169,6 +2169,15 @@
     }, destinationID);
 }
 
+void NetworkProcess::requestResource(WebPageProxyIdentifier pageID, PAL::SessionID sessionID, WebCore::ResourceRequest&& request, IPC::FormDataReference&& httpBody, CompletionHandler<void(IPC::DataReference, WebCore::ResourceResponse, WebCore::ResourceError)>&& completionHandler)
+{
+    request.setHTTPBody(httpBody.takeData());
+    if (auto* networkSession = m_networkSessions.get(sessionID))
+        networkSession->requestResource(pageID, WTFMove(request), WTFMove(completionHandler));
+    else
+        completionHandler({ }, { }, { });
+}
+
 void NetworkProcess::setCacheModelSynchronouslyForTesting(CacheModel cacheModel, CompletionHandler<void()>&& completionHandler)
 {
     setCacheModel(cacheModel);

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -455,6 +455,7 @@
     void publishDownloadProgress(DownloadID, const URL&, SandboxExtension::Handle&&);
 #endif
     void continueWillSendRequest(DownloadID, WebCore::ResourceRequest&&);
+    void requestResource(WebPageProxyIdentifier, PAL::SessionID, WebCore::ResourceRequest&&, IPC::FormDataReference&&, CompletionHandler<void(IPC::DataReference, WebCore::ResourceResponse, WebCore::ResourceError)>&&);
     void applicationDidEnterBackground();
     void applicationWillEnterForeground();
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-12-09 00:19:46 UTC (rev 286751)
@@ -53,6 +53,7 @@
 #if PLATFORM(COCOA)
     PublishDownloadProgress(WebKit::DownloadID downloadID, URL url, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
 #endif
+    RequestResource(WebKit::WebPageProxyIdentifier pageID, PAL::SessionID sessionID, WebCore::ResourceRequest request, IPC::FormDataReference requestBody) -> (IPC::DataReference data, WebCore::ResourceResponse response, WebCore::ResourceError error) Async
     ApplicationDidEnterBackground()
     ApplicationWillEnterForeground()
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.h (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "AppPrivacyReport.h"
+#include "DataReference.h"
 #include "NavigatingToAppBoundDomain.h"
 #include "NetworkNotificationManager.h"
 #include "NetworkResourceLoadIdentifier.h"
@@ -193,6 +194,7 @@
 
     virtual void removeNetworkWebsiteData(std::optional<WallTime>, std::optional<HashSet<WebCore::RegistrableDomain>>&&, CompletionHandler<void()>&& completionHandler) { completionHandler(); }
 
+    virtual void requestResource(WebPageProxyIdentifier, WebCore::ResourceRequest&&, CompletionHandler<void(const IPC::DataReference&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&&) { }
     virtual void addWebPageNetworkParameters(WebPageProxyIdentifier, WebPageNetworkParameters&&) { }
     virtual void removeWebPageNetworkParameters(WebPageProxyIdentifier) { }
     virtual size_t countNonDefaultSessionSets() const { return 0; }

Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -162,6 +162,7 @@
     void removeWebSocketTask(SessionSet&, WebSocketTask&) final;
 #endif
 
+    void requestResource(WebPageProxyIdentifier, WebCore::ResourceRequest&&, CompletionHandler<void(const IPC::DataReference&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&&) final;
     void addWebPageNetworkParameters(WebPageProxyIdentifier, WebPageNetworkParameters&&) final;
     void removeWebPageNetworkParameters(WebPageProxyIdentifier) final;
     size_t countNonDefaultSessionSets() const final;

Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (286750 => 286751)


--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2021-12-09 00:19:46 UTC (rev 286751)
@@ -1773,6 +1773,16 @@
     m_attributedBundleIdentifierFromPageIdentifiers.add(pageID, parameters.attributedBundleIdentifier());
 }
 
+void NetworkSessionCocoa::requestResource(WebPageProxyIdentifier pageID, WebCore::ResourceRequest&& request, CompletionHandler<void(const IPC::DataReference&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&& completionHandler)
+{
+    auto session = sessionWrapperForTask(pageID, request, WebCore::StoredCredentialsPolicy::Use, std::nullopt).session;
+    auto nsRequest = request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
+    auto completionBlock = makeBlockPtr([completionHandler = WTFMove(completionHandler)] (NSData *data, NSURLResponse *response, NSError *error) mutable {
+        completionHandler(IPC::DataReference { static_cast<const uint8_t*>(data.bytes), data.length }, WebCore::ResourceResponse { response }, WebCore::ResourceError { error });
+    });
+    [[session dataTaskWithRequest:nsRequest completionHandler:completionBlock.get()] resume];
+}
+
 void NetworkSessionCocoa::removeWebPageNetworkParameters(WebPageProxyIdentifier pageID)
 {
     m_perPageSessionSets.remove(pageID);

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-12-09 00:19:46 UTC (rev 286751)
@@ -2217,6 +2217,15 @@
 #endif
 }
 
+- (void)_requestResource:(NSURLRequest *)request completionHandler:(void(^)(NSData *, NSURLResponse *, NSError *))completionHandler
+{
+    _page->requestResource(request, [completionHandler = makeBlockPtr(completionHandler)] (Ref<WebCore::SharedBuffer>&& buffer, WebCore::ResourceResponse&& response, WebCore::ResourceError&& error) {
+        if (error.isNull())
+            return completionHandler(buffer->createNSData().get(), response.nsURLResponse(), nil);
+        completionHandler(nil, nil, error.nsError());
+    });
+}
+
 - (void)_takeFindStringFromSelection:(id)sender
 {
     THROW_IF_SUSPENDED;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -422,6 +422,8 @@
 
 - (void)_startImageAnalysis:(NSString *)identifier WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+- (void)_requestResource:(NSURLRequest *)request completionHandler:(void(^)(NSData *, NSURLResponse *, NSError *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 #if TARGET_OS_IPHONE

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-12-09 00:19:46 UTC (rev 286751)
@@ -335,6 +335,14 @@
     return m_downloadProxyMap->createDownloadProxy(dataStore, processPool, resourceRequest, frameInfo, originatingPage);
 }
 
+void NetworkProcessProxy::requestResource(WebPageProxyIdentifier pageID, PAL::SessionID sessionID, WebCore::ResourceRequest&& request, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&& completionHandler)
+{
+    sendWithAsyncReply(Messages::NetworkProcess::RequestResource(pageID, sessionID, request, IPC::FormDataReference(request.httpBody())), [completionHandler = WTFMove(completionHandler)] (IPC::DataReference&& data, WebCore::ResourceResponse&& response, WebCore::ResourceError&& error) mutable {
+        auto buffer = SharedBuffer::create(data.data(), data.size());
+        completionHandler(WTFMove(buffer), WTFMove(response), WTFMove(error));
+    });
+}
+
 void NetworkProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void(WebsiteData)>&& completionHandler)
 {
     sendWithAsyncReply(Messages::NetworkProcess::FetchWebsiteData(sessionID, dataTypes, fetchOptions), WTFMove(completionHandler));

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -122,6 +122,7 @@
     void getNetworkProcessConnection(WebProcessProxy&, Messages::WebProcessProxy::GetNetworkProcessConnectionDelayedReply&&);
 
     DownloadProxy& createDownloadProxy(WebsiteDataStore&, WebProcessPool&, const WebCore::ResourceRequest&, const FrameInfoData&, WebPageProxy* originatingPage);
+    void requestResource(WebPageProxyIdentifier, PAL::SessionID, WebCore::ResourceRequest&&, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&&);
 
     void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, CompletionHandler<void(WebsiteData)>&&);
     void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-12-09 00:19:46 UTC (rev 286751)
@@ -6372,6 +6372,11 @@
     download.setDidStartCallback(WTFMove(completionHandler));
 }
 
+void WebPageProxy::requestResource(WebCore::ResourceRequest&& request, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&& completionHandler)
+{
+    websiteDataStore().networkProcess().requestResource(identifier(), sessionID(), WTFMove(request), WTFMove(completionHandler));
+}
+
 void WebPageProxy::didChangeContentSize(const IntSize& size)
 {
     pageClient().didChangeContentSize(size);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (286750 => 286751)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -1373,6 +1373,7 @@
     void handleDownloadRequest(DownloadProxy&);
     void resumeDownload(const API::Data& resumeData, const String& path, CompletionHandler<void(DownloadProxy*)>&&);
     void downloadRequest(WebCore::ResourceRequest&&, CompletionHandler<void(DownloadProxy*)>&&);
+    void requestResource(WebCore::ResourceRequest&&, CompletionHandler<void(Ref<WebCore::SharedBuffer>&&, WebCore::ResourceResponse&&, WebCore::ResourceError&&)>&&);
 
     void advanceToNextMisspelling(bool startBeforeSelection);
     void changeSpellingToWord(const String& word);

Modified: trunk/Tools/ChangeLog (286750 => 286751)


--- trunk/Tools/ChangeLog	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Tools/ChangeLog	2021-12-09 00:19:46 UTC (rev 286751)
@@ -1,3 +1,13 @@
+2021-12-08  Alex Christensen  <achristen...@webkit.org>
+
+        Add SPI to load a resource in the context of a page
+        https://bugs.webkit.org/show_bug.cgi?id=233908
+
+        Reviewed by Tim Horton.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm:
+        (TEST):
+
 2021-12-08  J Pascoe  <j_pas...@apple.com>
 
         [WebAuthn] Consider support for the displayName for FIDO authenticator

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm (286750 => 286751)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/NetworkProcess.mm	2021-12-09 00:19:46 UTC (rev 286751)
@@ -344,3 +344,50 @@
     EXPECT_EQ(webPID1, [webView1 _webProcessIdentifier]);
     EXPECT_EQ(webPID2, [webView2 _webProcessIdentifier]);
 }
+
+TEST(NetworkProcess, LoadResource)
+{
+    using namespace TestWebKitAPI;
+    auto html = "<script>document.cookie='testkey=value'</script>";
+    auto secondResponse = "second response";
+    Vector<char> secondRequest;
+    auto server = HTTPServer([&](const Connection& connection) {
+        connection.receiveHTTPRequest([&, connection](Vector<char>&& request) {
+            connection.send(HTTPResponse(html).serialize(), [&, connection] {
+                connection.receiveHTTPRequest([&, connection](Vector<char>&& request) {
+                    secondRequest = WTFMove(request);
+                    connection.send(HTTPResponse(secondResponse).serialize());
+                });
+            });
+        });
+    });
+    auto webView = adoptNS([TestWKWebView new]);
+    [webView synchronouslyLoadRequest:server.request()];
+
+    __block bool done = false;
+    RetainPtr<NSMutableURLRequest> postRequest = adoptNS([server.request() mutableCopy]);
+    [postRequest setMainDocumentURL:postRequest.get().URL];
+    [postRequest setHTTPMethod:@"POST"];
+    auto requestBody = "request body";
+    [postRequest setHTTPBody:[NSData dataWithBytes:requestBody length:strlen(requestBody)]];
+    [webView _requestResource:postRequest.get() completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_WK_STREQ(response.URL.absoluteString, postRequest.get().URL.absoluteString);
+        EXPECT_EQ(data.length, strlen(secondResponse));
+        EXPECT_TRUE(!memcmp(data.bytes, secondResponse, data.length));
+        done = true;
+    }];
+    Util::run(&done);
+    EXPECT_TRUE(strnstr(secondRequest.data(), "Cookie: testkey=value\r\n", secondRequest.size()));
+    EXPECT_WK_STREQ(HTTPServer::parseBody(secondRequest), requestBody);
+
+    done = false;
+    [webView _requestResource:[NSURLRequest requestWithURL:[NSURL URLWithString:@"blob:blank"]] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
+        EXPECT_WK_STREQ(error.domain, NSURLErrorDomain);
+        EXPECT_EQ(error.code, NSURLErrorUnsupportedURL);
+        EXPECT_NULL(data);
+        EXPECT_NULL(response);
+        done = true;
+    }];
+    Util::run(&done);
+}

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h (286750 => 286751)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2021-12-09 00:19:46 UTC (rev 286751)
@@ -59,7 +59,7 @@
     static void respondWithOK(Connection);
     static void respondWithChallengeThenOK(Connection);
     static String parsePath(const Vector<char>& request);
-
+    static String parseBody(const Vector<char>&);
     static Vector<uint8_t> testPrivateKey();
     static Vector<uint8_t> testCertificate();
 

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm (286750 => 286751)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-12-09 00:16:51 UTC (rev 286750)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-12-09 00:19:46 UTC (rev 286751)
@@ -324,6 +324,14 @@
     return String(request.data() + pathPrefixLength, pathLength);
 }
 
+String HTTPServer::parseBody(const Vector<char>& request)
+{
+    const char* headerEndBytes = "\r\n\r\n";
+    const char* headerEnd = strnstr(request.data(), headerEndBytes, request.size()) + strlen(headerEndBytes);
+    size_t headerLength = headerEnd - request.data();
+    return String(headerEnd, request.size() - headerLength);
+}
+
 void HTTPServer::respondToRequests(Connection connection, Ref<RequestData> requestData)
 {
     connection.receiveHTTPRequest([connection, requestData] (Vector<char>&& request) mutable {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to