Title: [227317] branches/safari-605-branch

Diff

Modified: branches/safari-605-branch/Source/WebCore/ChangeLog (227316 => 227317)


--- branches/safari-605-branch/Source/WebCore/ChangeLog	2018-01-22 17:57:48 UTC (rev 227316)
+++ branches/safari-605-branch/Source/WebCore/ChangeLog	2018-01-22 17:57:50 UTC (rev 227317)
@@ -1,5 +1,38 @@
 2018-01-22  Jason Marcell  <jmarc...@apple.com>
 
+        Cherry-pick r227220. rdar://problem/36722596
+
+    2018-01-19  Chris Dumez  <cdu...@apple.com>
+
+            Service worker registrations restored from disk may not be reused when the JS calls register() again
+            https://bugs.webkit.org/show_bug.cgi?id=181810
+            <rdar://problem/36591711>
+
+            Reviewed by Youenn Fablet.
+
+            The issue was that when restoring a registration from disk, we would not set its active worker right
+            away. We only set it later in installContextData(). installContextData() is only called after we’ve
+            launched the service worker process and established a connection to it.
+
+            However, we would start processing jobs (such as registrations) before we’ve established the connection
+            to the service worker process. SWServerJobQueue::runRegisterJob(), in order to reuse an existing
+            registration checks the registration’s active worker has the right script URL. The issue was that when
+            this code would execute, we may not have set the registration’s active service worker yet, in which case,
+            we would update the existing registration instead of reusing it as-is.
+
+            To address the issue, we now delay the processing of jobs until the connection to the service worker
+            process has been established and we've installed all pending contexts via installContextData().
+
+            Changed is covered by new API test.
+
+            * workers/service/server/SWServer.cpp:
+            (WebCore::SWServer::Connection::scheduleJobInServer):
+            (WebCore::SWServer::scheduleJob):
+            (WebCore::SWServer::serverToContextConnectionCreated):
+            * workers/service/server/SWServer.h:
+
+2018-01-22  Jason Marcell  <jmarc...@apple.com>
+
         Cherry-pick r227219. rdar://problem/36722501
 
     2018-01-19  James Craig  <jcr...@apple.com>

Modified: branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.cpp (227316 => 227317)


--- branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.cpp	2018-01-22 17:57:48 UTC (rev 227316)
+++ branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.cpp	2018-01-22 17:57:50 UTC (rev 227317)
@@ -209,12 +209,12 @@
     m_registrationStore.flushChanges(WTFMove(completionHandler));
 }
 
-void SWServer::Connection::scheduleJobInServer(const ServiceWorkerJobData& jobData)
+void SWServer::Connection::scheduleJobInServer(ServiceWorkerJobData&& jobData)
 {
     LOG(ServiceWorker, "Scheduling ServiceWorker job %s in server", jobData.identifier().loggingString().utf8().data());
     ASSERT(identifier() == jobData.connectionIdentifier());
 
-    m_server.scheduleJob(jobData);
+    m_server.scheduleJob(WTFMove(jobData));
 }
 
 void SWServer::Connection::finishFetchingScriptInServer(const ServiceWorkerFetchResult& result)
@@ -256,10 +256,15 @@
 }
 
 // https://w3c.github.io/ServiceWorker/#schedule-job-algorithm
-void SWServer::scheduleJob(const ServiceWorkerJobData& jobData)
+void SWServer::scheduleJob(ServiceWorkerJobData&& jobData)
 {
     ASSERT(m_connections.contains(jobData.connectionIdentifier()));
 
+    if (!SWServerToContextConnection::globalServerToContextConnection()) {
+        m_pendingJobs.append(WTFMove(jobData));
+        return;
+    }
+
     // FIXME: Per the spec, check if this job is equivalent to the last job on the queue.
     // If it is, stack it along with that job.
 
@@ -471,6 +476,10 @@
         for (auto& callback : item.value)
             callback(success, *connection);
     }
+
+    auto pendingJobs = WTFMove(m_pendingJobs);
+    for (auto& jobData : pendingJobs)
+        scheduleJob(WTFMove(jobData));
 }
 
 void SWServer::installContextData(const ServiceWorkerContextData& data)

Modified: branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.h (227316 => 227317)


--- branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.h	2018-01-22 17:57:48 UTC (rev 227316)
+++ branches/safari-605-branch/Source/WebCore/workers/service/server/SWServer.h	2018-01-22 17:57:50 UTC (rev 227317)
@@ -94,7 +94,7 @@
         WEBCORE_EXPORT explicit Connection(SWServer&);
         SWServer& server() { return m_server; }
 
-        WEBCORE_EXPORT void scheduleJobInServer(const ServiceWorkerJobData&);
+        WEBCORE_EXPORT void scheduleJobInServer(ServiceWorkerJobData&&);
         WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerFetchResult&);
         WEBCORE_EXPORT void addServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
         WEBCORE_EXPORT void removeServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
@@ -131,7 +131,7 @@
     void removeRegistration(const ServiceWorkerRegistrationKey&);
     WEBCORE_EXPORT Vector<ServiceWorkerRegistrationData> getRegistrations(const SecurityOriginData& topOrigin, const URL& clientURL);
 
-    void scheduleJob(const ServiceWorkerJobData&);
+    void scheduleJob(ServiceWorkerJobData&&);
     void rejectJob(const ServiceWorkerJobData&, const ExceptionData&);
     void resolveRegistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved);
     void resolveUnregistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationKey&, bool unregistrationResult);
@@ -238,7 +238,8 @@
     bool m_mainThreadReplyScheduled { false };
     UniqueRef<SWOriginStore> m_originStore;
     RegistrationStore m_registrationStore;
-    Deque<ServiceWorkerContextData> m_pendingContextDatas;
+    Vector<ServiceWorkerContextData> m_pendingContextDatas;
+    Vector<ServiceWorkerJobData> m_pendingJobs;
     HashMap<ServiceWorkerIdentifier, Vector<RunServiceWorkerCallback>> m_serviceWorkerRunRequests;
     PAL::SessionID m_sessionID;
     bool m_importCompleted { false };

Modified: branches/safari-605-branch/Tools/ChangeLog (227316 => 227317)


--- branches/safari-605-branch/Tools/ChangeLog	2018-01-22 17:57:48 UTC (rev 227316)
+++ branches/safari-605-branch/Tools/ChangeLog	2018-01-22 17:57:50 UTC (rev 227317)
@@ -1,5 +1,23 @@
 2018-01-22  Jason Marcell  <jmarc...@apple.com>
 
+        Cherry-pick r227220. rdar://problem/36722596
+
+    2018-01-19  Chris Dumez  <cdu...@apple.com>
+
+            Service worker registrations restored from disk may not be reused when the JS calls register() again
+            https://bugs.webkit.org/show_bug.cgi?id=181810
+            <rdar://problem/36591711>
+
+            Reviewed by Youenn Fablet.
+
+            Add API test coverage.
+
+            * TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
+            (-[SWMessageHandlerForRestoreFromDiskTest initWithExpectedMessage:]):
+            (-[SWMessageHandlerForRestoreFromDiskTest userContentController:didReceiveScriptMessage:]):
+
+2018-01-22  Jason Marcell  <jmarc...@apple.com>
+
         Cherry-pick r227153. rdar://problem/36722558
 
     2018-01-18  Chris Dumez  <cdu...@apple.com>

Modified: branches/safari-605-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm (227316 => 227317)


--- branches/safari-605-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm	2018-01-22 17:57:48 UTC (rev 227316)
+++ branches/safari-605-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm	2018-01-22 17:57:50 UTC (rev 227317)
@@ -75,6 +75,31 @@
 }
 @end
 
+@interface SWMessageHandlerForRestoreFromDiskTest : NSObject <WKScriptMessageHandler> {
+    NSString *_expectedMessage;
+}
+- (instancetype)initWithExpectedMessage:(NSString *)expectedMessage;
+@end
+
+@implementation SWMessageHandlerForRestoreFromDiskTest
+
+- (instancetype)initWithExpectedMessage:(NSString *)expectedMessage
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _expectedMessage = expectedMessage;
+
+    return self;
+}
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    EXPECT_TRUE([[message body] isEqualToString:_expectedMessage]);
+    done = true;
+}
+@end
+
 @interface SWSchemes : NSObject <WKURLSchemeHandler> {
 @public
     HashMap<String, ResourceInfo> resources;
@@ -200,6 +225,62 @@
 </body>
 )SWRESOURCE";
 
+static const char* mainRegisteringWorkerBytes = R"SWRESOURCE(
+<script>
+try {
+function log(msg)
+{
+    window.webkit.messageHandlers.sw.postMessage(msg);
+}
+
+navigator.serviceWorker.register('/sw.js').then(function(reg) {
+    if (reg.active) {
+        log("FAIL: Registration already has an active worker");
+        return;
+    }
+    worker = reg.installing;
+    worker.addEventListener('statechange', function() {
+        if (worker.state == 'activated')
+            log("PASS: Registration was successful and service worker was activated");
+    });
+}).catch(function(error) {
+    log("Registration failed with: " + error);
+});
+} catch(e) {
+    log("Exception: " + e);
+}
+</script>
+)SWRESOURCE";
+
+static const char* mainRegisteringAlreadyExistingWorkerBytes = R"SWRESOURCE(
+<script>
+try {
+function log(msg)
+{
+    window.webkit.messageHandlers.sw.postMessage(msg);
+}
+
+navigator.serviceWorker.register('/sw.js').then(function(reg) {
+    if (reg.installing) {
+        log("FAIL: Registration had an installing worker");
+        return;
+    }
+    if (reg.active) {
+        if (reg.active.state == "activated")
+            log("PASS: Registration already has an active worker");
+        else
+            log("FAIL: Registration has an active worker but its state is not activated");
+    } else
+        log("FAIL: Registration does not have an active worker");
+}).catch(function(error) {
+    log("Registration failed with: " + error);
+});
+} catch(e) {
+    log("Exception: " + e);
+}
+</script>
+)SWRESOURCE";
+
 TEST(ServiceWorkers, Basic)
 {
     ASSERT(mainBytes);
@@ -246,6 +327,65 @@
     done = false;
 }
 
+TEST(ServiceWorkers, RestoreFromDisk)
+{
+    ASSERT(mainRegisteringWorkerBytes);
+    ASSERT(scriptBytes);
+    ASSERT(mainRegisteringAlreadyExistingWorkerBytes);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    // Start with a clean slate data store
+    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    RetainPtr<SWMessageHandlerForRestoreFromDiskTest> messageHandler = adoptNS([[SWMessageHandlerForRestoreFromDiskTest alloc] initWithExpectedMessage:@"PASS: Registration was successful and service worker was activated"]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    RetainPtr<SWSchemes> handler = adoptNS([[SWSchemes alloc] init]);
+    handler->resources.set("sw://host/main.html", ResourceInfo { @"text/html", mainRegisteringWorkerBytes });
+    handler->resources.set("sw://host/sw.js", ResourceInfo { @"application/_javascript_", scriptBytes });
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"SW"];
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+
+    webView = nullptr;
+    configuration = nullptr;
+    messageHandler = nullptr;
+    handler = nullptr;
+
+    done = false;
+
+    configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    messageHandler = adoptNS([[SWMessageHandlerForRestoreFromDiskTest alloc] initWithExpectedMessage:@"PASS: Registration already has an active worker"]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    handler = adoptNS([[SWSchemes alloc] init]);
+    handler->resources.set("sw://host/main.html", ResourceInfo { @"text/html", mainRegisteringAlreadyExistingWorkerBytes });
+    handler->resources.set("sw://host/sw.js", ResourceInfo { @"application/_javascript_", scriptBytes });
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"SW"];
+
+    webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+}
+
 TEST(ServiceWorkers, FetchAfterRestoreFromDisk)
 {
     ASSERT(mainForFetchTestBytes);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to