Title: [283796] trunk
Revision
283796
Author
[email protected]
Date
2021-10-08 03:02:49 -0700 (Fri, 08 Oct 2021)

Log Message

Add support for processing push events without service worker clients
https://bugs.webkit.org/show_bug.cgi?id=231285

Reviewed by Chris Dumez.

Source/WebCore:

Covered by API test.

* workers/service/server/SWServer.cpp:
Add a timer to terminate service worker if a push message is not processed with a given number of seconds.
The timer value is the default termination delay or 1 second for testing.

Source/WebKit:

When firing a push event, ask UIProcess to take a background assertion for the process running the service worker.
We use a counter based approach to take/dispose of the backgorund assertion.

* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
* UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
* UIProcess/WebProcessProxy.cpp:
* UIProcess/WebProcessProxy.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (283795 => 283796)


--- trunk/Source/WebCore/ChangeLog	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebCore/ChangeLog	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1,3 +1,16 @@
+2021-10-08  Youenn Fablet  <[email protected]>
+
+        Add support for processing push events without service worker clients
+        https://bugs.webkit.org/show_bug.cgi?id=231285
+
+        Reviewed by Chris Dumez.
+
+        Covered by API test.
+
+        * workers/service/server/SWServer.cpp:
+        Add a timer to terminate service worker if a push message is not processed with a given number of seconds.
+        The timer value is the default termination delay or 1 second for testing.
+
 2021-10-08  Myles C. Maxfield  <[email protected]>
 
         font-families inside @font-palette-values need to be case insensitive

Modified: trunk/Source/WebCore/workers/service/server/SWServer.cpp (283795 => 283796)


--- trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1214,12 +1214,24 @@
             return;
         }
 
-        fireFunctionalEvent(*registration, [serviceWorkerIdentifier = worker->identifier(), data = "" callback = WTFMove(callback)](auto&& connectionOrStatus) mutable {
+        fireFunctionalEvent(*registration, [worker = Ref { *worker }, weakThis = WTFMove(weakThis), data = "" callback = WTFMove(callback)](auto&& connectionOrStatus) mutable {
             if (!connectionOrStatus.has_value()) {
                 callback(connectionOrStatus.error() == ShouldSkipEvent::Yes);
                 return;
             }
-            connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, WTFMove(callback));
+
+            auto serviceWorkerIdentifier = worker->identifier();
+            auto terminateWorkerTimer = makeUnique<Timer>([worker = WTFMove(worker)] {
+                RELEASE_LOG_ERROR(ServiceWorker, "Terminating service worker as processing push event took too much time");
+                worker->terminate();
+            });
+            terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : 2_s);
+            connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, [callback = WTFMove(callback), terminateWorkerTimer = WTFMove(terminateWorkerTimer)](bool succeeded) mutable {
+                if (terminateWorkerTimer->isActive())
+                    terminateWorkerTimer->stop();
+
+                callback(succeeded);
+            });
         });
     });
 }

Modified: trunk/Source/WebKit/ChangeLog (283795 => 283796)


--- trunk/Source/WebKit/ChangeLog	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/ChangeLog	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1,3 +1,25 @@
+2021-10-08  Youenn Fablet  <[email protected]>
+
+        Add support for processing push events without service worker clients
+        https://bugs.webkit.org/show_bug.cgi?id=231285
+
+        Reviewed by Chris Dumez.
+
+        When firing a push event, ask UIProcess to take a background assertion for the process running the service worker.
+        We use a counter based approach to take/dispose of the backgorund assertion.
+
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        * UIProcess/WebProcessProxy.cpp:
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2021-10-07  Simon Fraser  <[email protected]>
 
         Plumb "animated scroll did end" back from the scrolling tree

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp (283795 => 283796)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2021-10-08 10:02:49 UTC (rev 283796)
@@ -109,10 +109,17 @@
 
 void WebSWServerToContextConnection::firePushEvent(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, const std::optional<Vector<uint8_t>>& data, CompletionHandler<void(bool)>&& callback)
 {
+    if (!m_processingPushEventsCount++)
+        m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::StartServiceWorkerBackgroundProcessing { webProcessIdentifier() }, 0);
+
     std::optional<IPC::DataReference> ipcData;
     if (data)
         ipcData = IPC::DataReference { data->data(), data->size() };
-    sendWithAsyncReply(Messages::WebSWContextManagerConnection::FirePushEvent(serviceWorkerIdentifier, ipcData), WTFMove(callback));
+    sendWithAsyncReply(Messages::WebSWContextManagerConnection::FirePushEvent(serviceWorkerIdentifier, ipcData), [weakThis = makeWeakPtr(this), callback = WTFMove(callback)](bool wasProcessed) mutable {
+        if (weakThis && !--weakThis->m_processingPushEventsCount)
+            weakThis->m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::EndServiceWorkerBackgroundProcessing { weakThis->webProcessIdentifier() }, 0);
+        callback(wasProcessed);
+    });
 }
 
 void WebSWServerToContextConnection::terminateWorker(ServiceWorkerIdentifier serviceWorkerIdentifier)

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h (283795 => 283796)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2021-10-08 10:02:49 UTC (rev 283796)
@@ -105,6 +105,7 @@
     HashMap<WebCore::FetchIdentifier, WeakPtr<ServiceWorkerFetchTask>> m_ongoingFetches;
     bool m_isThrottleable { true };
     WebPageProxyIdentifier m_webPageProxyID;
+    size_t m_processingPushEventsCount { 0 };
 }; // class WebSWServerToContextConnection
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2021-10-08 10:02:49 UTC (rev 283796)
@@ -753,6 +753,11 @@
     });
 }
 
+-(bool)_hasServiceWorkerBackgroundActivityForTesting
+{
+    return _websiteDataStore->hasServiceWorkerBackgroundActivityForTesting();
+}
+
 -(void)_processPushMessage:(NSData*) message registration:(NSURL *)registration completionHandler:(void(^)(bool wasProcessed))completionHandler
 {
 #if ENABLE(SERVICE_WORKER)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2021-10-08 10:02:49 UTC (rev 283796)
@@ -106,6 +106,7 @@
 + (BOOL)_defaultNetworkProcessExists WK_API_AVAILABLE(macos(12.0), ios(15.0));
 - (void)_countNonDefaultSessionSets:(void(^)(size_t))completionHandler;
 
+-(bool)_hasServiceWorkerBackgroundActivityForTesting WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 -(void)_processPushMessage:(NSData*)data registration:(NSURL *)registration completionHandler:(void(^)(bool))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @end

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1400,6 +1400,18 @@
 
     serviceWorkerProcess->unregisterServiceWorkerClientProcess(*webProcess);
 }
+
+void NetworkProcessProxy::startServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
+{
+    if (auto* serviceWorkerProcess = WebProcessProxy::processForIdentifier(serviceWorkerProcessIdentifier))
+        serviceWorkerProcess->startServiceWorkerBackgroundProcessing();
+}
+
+void NetworkProcessProxy::endServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
+{
+    if (auto* serviceWorkerProcess = WebProcessProxy::processForIdentifier(serviceWorkerProcessIdentifier))
+        serviceWorkerProcess->endServiceWorkerBackgroundProcessing();
+}
 #endif
 
 void NetworkProcessProxy::requestStorageSpace(PAL::SessionID sessionID, const WebCore::ClientOrigin& origin, uint64_t currentQuota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(std::optional<uint64_t> quota)>&& completionHandler)

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-10-08 10:02:49 UTC (rev 283796)
@@ -323,6 +323,8 @@
     void workerContextConnectionNoLongerNeeded(WebCore::ProcessIdentifier);
     void registerServiceWorkerClientProcess(WebCore::ProcessIdentifier webProcessIdentifier, WebCore::ProcessIdentifier serviceWorkerProcessIdentifier);
     void unregisterServiceWorkerClientProcess(WebCore::ProcessIdentifier webProcessIdentifier, WebCore::ProcessIdentifier serviceWorkerProcessIdentifier);
+    void startServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier);
+    void endServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier);
 #endif
 
     void terminateWebProcess(WebCore::ProcessIdentifier);

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2021-10-08 10:02:49 UTC (rev 283796)
@@ -57,6 +57,8 @@
     WorkerContextConnectionNoLongerNeeded(WebCore::ProcessIdentifier identifier)
     RegisterServiceWorkerClientProcess(WebCore::ProcessIdentifier webProcessIdentifier, WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
     UnregisterServiceWorkerClientProcess(WebCore::ProcessIdentifier webProcessIdentifier, WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
+    StartServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
+    EndServiceWorkerBackgroundProcessing(WebCore::ProcessIdentifier serviceWorkerProcessIdentifier)
 #endif
 
     SetWebProcessHasUploads(WebCore::ProcessIdentifier processID, bool hasUpload)

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1938,6 +1938,14 @@
             m_serviceWorkerInformation->activity = m_throttler.backgroundActivity("Service Worker for background view(s)"_s);
         return;
     }
+
+    if (m_hasServiceWorkerBackgroundProcessing) {
+        WEBPROCESSPROXY_RELEASE_LOG(ProcessSuspension, "Service Worker for background processing");
+        if (!ProcessThrottler::isValidBackgroundActivity(m_serviceWorkerInformation->activity))
+            m_serviceWorkerInformation->activity = m_throttler.backgroundActivity("Service Worker for background processing"_s);
+        return;
+    }
+
     m_serviceWorkerInformation->activity = nullptr;
 }
 
@@ -1970,6 +1978,26 @@
 {
     return m_serviceWorkerInformation ? ProcessThrottler::isValidBackgroundActivity(m_serviceWorkerInformation->activity) : false;
 }
+
+void WebProcessProxy::startServiceWorkerBackgroundProcessing()
+{
+    if (!m_serviceWorkerInformation)
+        return;
+
+    WEBPROCESSPROXY_RELEASE_LOG(ProcessSuspension, "startServiceWorkerBackgroundProcessing");
+    m_hasServiceWorkerBackgroundProcessing = true;
+    updateServiceWorkerProcessAssertion();
+}
+
+void WebProcessProxy::endServiceWorkerBackgroundProcessing()
+{
+    if (!m_serviceWorkerInformation)
+        return;
+
+    WEBPROCESSPROXY_RELEASE_LOG(ProcessSuspension, "endServiceWorkerBackgroundProcessing");
+    m_hasServiceWorkerBackgroundProcessing = false;
+    updateServiceWorkerProcessAssertion();
+}
 #endif // ENABLE(SERVICE_WORKER)
 
 void WebProcessProxy::disableServiceWorkers()

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-10-08 10:02:49 UTC (rev 283796)
@@ -366,6 +366,8 @@
     void unregisterServiceWorkerClientProcess(WebProcessProxy&);
     bool hasServiceWorkerForegroundActivityForTesting() const;
     bool hasServiceWorkerBackgroundActivityForTesting() const;
+    void startServiceWorkerBackgroundProcessing();
+    void endServiceWorkerBackgroundProcessing();
 #endif
     void setAssertionTypeForTesting(ProcessAssertionType type) { didSetAssertionType(type); }
 
@@ -657,6 +659,7 @@
         WeakHashSet<WebProcessProxy> clientProcesses;
     };
     std::optional<ServiceWorkerInformation> m_serviceWorkerInformation;
+    bool m_hasServiceWorkerBackgroundProcessing { false };
 
     HashMap<WebCore::SleepDisablerIdentifier, std::unique_ptr<WebCore::SleepDisabler>> m_sleepDisablers;
 

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1007,6 +1007,11 @@
     networkProcess().sendSync(Messages::NetworkProcess::ResetServiceWorkerFetchTimeoutForTesting(), Messages::NetworkProcess::ResetServiceWorkerFetchTimeoutForTesting::Reply(), 0);
 }
 
+bool WebsiteDataStore::hasServiceWorkerBackgroundActivityForTesting() const
+{
+    return WTF::anyOf(WebProcessPool::allProcessPools(), [](auto& pool) { return pool->hasServiceWorkerBackgroundActivityForTesting(); });
+}
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
 void WebsiteDataStore::setMaxStatisticsEntries(size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
 {

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (283795 => 283796)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2021-10-08 10:02:49 UTC (rev 283796)
@@ -173,6 +173,7 @@
     void setCacheModelSynchronouslyForTesting(CacheModel);
     void setServiceWorkerTimeoutForTesting(Seconds);
     void resetServiceWorkerTimeoutForTesting();
+    bool hasServiceWorkerBackgroundActivityForTesting() const;
 
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
     void fetchDataForRegistrableDomains(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Vector<WebCore::RegistrableDomain>&&, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&&);

Modified: trunk/Tools/ChangeLog (283795 => 283796)


--- trunk/Tools/ChangeLog	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Tools/ChangeLog	2021-10-08 10:02:49 UTC (rev 283796)
@@ -1,3 +1,12 @@
+2021-10-08  Youenn Fablet  <[email protected]>
+
+        Add support for processing push events without service worker clients
+        https://bugs.webkit.org/show_bug.cgi?id=231285
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm:
+
 2021-10-07  Jonathan Bedard  <[email protected]>
 
         [webkitscmpy] Library should own contributors.json loading

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm (283795 => 283796)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	2021-10-08 08:25:52 UTC (rev 283795)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	2021-10-08 10:02:49 UTC (rev 283796)
@@ -29,7 +29,9 @@
 #import "PlatformUtilities.h"
 #import "Test.h"
 #import "TestWKWebView.h"
+#import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
 
 static bool done;
 static String expectedMessage;
@@ -105,6 +107,18 @@
 
 static bool pushMessageProcessed = false;
 static bool pushMessageSuccessful = false;
+
+static bool waitUntilEvaluatesToTrue(const Function<bool()>& f)
+{
+    unsigned timeout = 0;
+    do {
+        if (f())
+            return true;
+        TestWebKitAPI::Util::sleep(0.1);
+    } while (++timeout < 100);
+    return false;
+}
+
 TEST(PushAPI, firePushEvent)
 {
     TestWebKitAPI::HTTPServer server({
@@ -157,3 +171,177 @@
 
     clearWebsiteDataStore([configuration websiteDataStore]);
 }
+
+static const char* waitOneSecondScriptBytes = R"SWRESOURCE(
+let port;
+self.addEventListener("message", (event) => {
+    port = event.data.port;
+    port.postMessage("Ready");
+});
+self.addEventListener("push", (event) => {
+    if (!event.data)
+        return;
+    const value = event.data.text();
+    if (value === 'Sweet Potatoes')
+        event.waitUntil(new Promise(resolve => setTimeout(resolve, 1000)));
+    else if (value === 'Rotten Potatoes')
+        event.waitUntil(new Promise((resolve, reject) => setTimeout(reject, 1000)));
+    else if (value === 'Timeless Potatoes')
+        event.waitUntil(new Promise(resolve => { }));
+});
+)SWRESOURCE";
+
+static void terminateNetworkProcessWhileRegistrationIsStored(WKWebViewConfiguration *configuration)
+{
+    auto path = configuration.websiteDataStore._configuration._serviceWorkerRegistrationDirectory.path;
+    NSURL* directory = [NSURL fileURLWithPath:path isDirectory:YES];
+    NSURL *swDBPath = [directory URLByAppendingPathComponent:@"ServiceWorkerRegistrations-7.sqlite3"];
+    unsigned timeout = 0;
+    while (![[NSFileManager defaultManager] fileExistsAtPath:swDBPath.path] && ++timeout < 100)
+        TestWebKitAPI::Util::sleep(0.1);
+    // Let's close the SQL database.
+    [configuration.websiteDataStore _sendNetworkProcessWillSuspendImminently];
+    [configuration.websiteDataStore _terminateNetworkProcess];
+}
+
+TEST(PushAPI, firePushEventWithNoPagesSuccessful)
+{
+    TestWebKitAPI::HTTPServer server({
+        { "/", { mainBytes } },
+        { "/sw.js", { {{ "Content-Type", "application/_javascript_" }}, waitOneSecondScriptBytes } }
+    }, TestWebKitAPI::HTTPServer::Protocol::Http);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    clearWebsiteDataStore([configuration websiteDataStore]);
+
+    auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    expectedMessage = "Ready";
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadRequest:server.request()];
+
+    TestWebKitAPI::Util::run(&done);
+
+    [webView _close];
+    webView = nullptr;
+
+    terminateNetworkProcessWhileRegistrationIsStored(configuration.get());
+
+    // Push event for service worker without any related page, should succeed.
+    pushMessageProcessed = false;
+    pushMessageSuccessful = false;
+    NSString *message = @"Sweet Potatoes";
+    [[configuration websiteDataStore] _processPushMessage:[message dataUsingEncoding:NSUTF8StringEncoding] registration:[server.request() URL] completionHandler:^(bool result) {
+        pushMessageSuccessful = result;
+        pushMessageProcessed = true;
+    }];
+
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return [[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    TestWebKitAPI::Util::run(&pushMessageProcessed);
+    EXPECT_TRUE(pushMessageSuccessful);
+
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return ![[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    clearWebsiteDataStore([configuration websiteDataStore]);
+}
+
+TEST(PushAPI, firePushEventWithNoPagesFail)
+{
+    TestWebKitAPI::HTTPServer server({
+        { "/", { mainBytes } },
+        { "/sw.js", { {{ "Content-Type", "application/_javascript_" }}, waitOneSecondScriptBytes } }
+    }, TestWebKitAPI::HTTPServer::Protocol::Http);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    clearWebsiteDataStore([configuration websiteDataStore]);
+
+    auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    expectedMessage = "Ready";
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadRequest:server.request()];
+
+    TestWebKitAPI::Util::run(&done);
+
+    [webView _close];
+    webView = nullptr;
+
+    terminateNetworkProcessWhileRegistrationIsStored(configuration.get());
+
+    // Push event for service worker without any related page, should fail.
+    pushMessageProcessed = false;
+    pushMessageSuccessful = false;
+    NSString *message = @"Rotten Potatoes";
+    [[configuration websiteDataStore] _processPushMessage:[message dataUsingEncoding:NSUTF8StringEncoding] registration:[server.request() URL] completionHandler:^(bool result) {
+        pushMessageSuccessful = result;
+        pushMessageProcessed = true;
+    }];
+
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return [[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    TestWebKitAPI::Util::run(&pushMessageProcessed);
+    EXPECT_FALSE(pushMessageSuccessful);
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return ![[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    clearWebsiteDataStore([configuration websiteDataStore]);
+}
+
+TEST(PushAPI, firePushEventWithNoPagesTimeout)
+{
+    TestWebKitAPI::HTTPServer server({
+        { "/", { mainBytes } },
+        { "/sw.js", { {{ "Content-Type", "application/_javascript_" }}, waitOneSecondScriptBytes } }
+    }, TestWebKitAPI::HTTPServer::Protocol::Http);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    // Disable service worker delay for the purpose of testing, push event should timeout after 1 second.
+    auto dataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
+    auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]);
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    configuration.get().websiteDataStore = dataStore.get();
+    clearWebsiteDataStore([configuration websiteDataStore]);
+
+    auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    expectedMessage = "Ready";
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadRequest:server.request()];
+
+    TestWebKitAPI::Util::run(&done);
+
+    [webView _close];
+    webView = nullptr;
+
+    [dataStoreConfiguration setServiceWorkerProcessTerminationDelayEnabled:NO];
+    dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]);
+    configuration.get().websiteDataStore = dataStore.get();
+
+    terminateNetworkProcessWhileRegistrationIsStored(configuration.get());
+
+    // Push event for service worker without any related page, should timeout so fail.
+    pushMessageProcessed = false;
+    pushMessageSuccessful = false;
+    NSString *message = @"Timeless Potatoes";
+    [[configuration websiteDataStore] _processPushMessage:[message dataUsingEncoding:NSUTF8StringEncoding] registration:[server.request() URL] completionHandler:^(bool result) {
+        pushMessageSuccessful = result;
+        pushMessageProcessed = true;
+    }];
+
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return [[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    TestWebKitAPI::Util::run(&pushMessageProcessed);
+    EXPECT_FALSE(pushMessageSuccessful);
+    EXPECT_TRUE(waitUntilEvaluatesToTrue([&] { return ![[configuration websiteDataStore] _hasServiceWorkerBackgroundActivityForTesting]; }));
+
+    clearWebsiteDataStore([configuration websiteDataStore]);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to