Title: [225455] trunk
Revision
225455
Author
[email protected]
Date
2017-12-02 18:32:42 -0800 (Sat, 02 Dec 2017)

Log Message

Support serviceWorkerRegistration.update() inside service workers
https://bugs.webkit.org/show_bug.cgi?id=180215

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Rebaseline WPT test that no longer times out. The test still fails even
though we support update(). The issue is that the second frame load
uses the new worker (because of the update()) instead of the old one.
The test seems to expect that the new service worker is still in
waiting state at the point the second frame is loaded. However, for us
it is already activated.

* web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https-expected.txt:

Source/WebCore:

Support serviceWorkerRegistration.update() inside service workers. The code paths
for job scheduling and resolution have been made thread safe by hopping to the right
thread when necessary. In particular, ServiceWorkerContainer always makes sure to to
a callOnMainThread() before calling methods on the SWClientConnection. Also, the
SWClientConnection relies on a new postTaskTo() method before calling methods on the
job.

Test: http/tests/workers/service/self_registration_update.html

* workers/service/SWClientConnection.cpp:
(WebCore::SWClientConnection::scheduleJob):
(WebCore::SWClientConnection::finishedFetchingScript):
(WebCore::SWClientConnection::failedFetchingScript):
(WebCore::SWClientConnection::jobRejectedInServer):
(WebCore::SWClientConnection::registrationJobResolvedInServer):
(WebCore::SWClientConnection::unregistrationJobResolvedInServer):
(WebCore::SWClientConnection::startScriptFetchForServer):
(WebCore::SWClientConnection::postMessageToServiceWorkerClient):
(WebCore::SWClientConnection::updateRegistrationState):
(WebCore::SWClientConnection::updateWorkerState):
(WebCore::SWClientConnection::fireUpdateFoundEvent):
(WebCore::SWClientConnection::notifyClientsOfControllerChange):
(WebCore::SWClientConnection::clearPendingJobs):
(WebCore::SWClientConnection::postTaskTo):
* workers/service/SWClientConnection.h:
* workers/service/ServiceWorkerContainer.cpp:
(WebCore::ServiceWorkerContainer::scheduleJob):
(WebCore::ServiceWorkerContainer::jobFailedWithException):
(WebCore::ServiceWorkerContainer::scheduleTaskToFireUpdateFoundEvent):
(WebCore::ServiceWorkerContainer::jobResolvedWithRegistration):
(WebCore::ServiceWorkerContainer::jobResolvedWithUnregistrationResult):
(WebCore::ServiceWorkerContainer::startScriptFetchForJob):
(WebCore::ServiceWorkerContainer::jobFinishedLoadingScript):
(WebCore::ServiceWorkerContainer::jobFailedLoadingScript):
(WebCore::ServiceWorkerContainer::jobDidFinish):
(WebCore::ServiceWorkerContainer::addRegistration):
(WebCore::ServiceWorkerContainer::removeRegistration):
(WebCore::ServiceWorkerContainer::scheduleTaskToFireControllerChangeEvent):
(WebCore::ServiceWorkerContainer::contextIdentifier):
* workers/service/ServiceWorkerContainer.h:
* workers/service/ServiceWorkerJob.cpp:
(WebCore::ServiceWorkerJob::ServiceWorkerJob):
* workers/service/ServiceWorkerJob.h:
(WebCore::ServiceWorkerJob::contextIdentifier):
* workers/service/ServiceWorkerJobClient.h:
* workers/service/ServiceWorkerRegistration.cpp:
(WebCore::ServiceWorkerRegistration::update):
* workers/service/ServiceWorkerTypes.h:

LayoutTests:

Add layout test coverage and unskip WPT test that no longer times out.

* TestExpectations:
* http/tests/workers/service/resources/self_registration_update-worker.js: Added.
* http/tests/workers/service/self_registration_update-expected.txt: Added.
* http/tests/workers/service/self_registration_update.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225454 => 225455)


--- trunk/LayoutTests/ChangeLog	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/LayoutTests/ChangeLog	2017-12-03 02:32:42 UTC (rev 225455)
@@ -1,3 +1,17 @@
+2017-12-02  Chris Dumez  <[email protected]>
+
+        Support serviceWorkerRegistration.update() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180215
+
+        Reviewed by Darin Adler.
+
+        Add layout test coverage and unskip WPT test that no longer times out.
+
+        * TestExpectations:
+        * http/tests/workers/service/resources/self_registration_update-worker.js: Added.
+        * http/tests/workers/service/self_registration_update-expected.txt: Added.
+        * http/tests/workers/service/self_registration_update.html: Added.
+
 2017-12-02  Youenn Fablet  <[email protected]>
 
         Implement https://w3c.github.io/ServiceWorker/#clients-getall

Modified: trunk/LayoutTests/TestExpectations (225454 => 225455)


--- trunk/LayoutTests/TestExpectations	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/LayoutTests/TestExpectations	2017-12-03 02:32:42 UTC (rev 225455)
@@ -147,7 +147,6 @@
 imported/w3c/web-platform-tests/fetch/api/abort/general-serviceworker.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/extendable-message-event.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html [ Skip ]
-imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-on-evaluation.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/detached-context.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/extendable-event-waituntil.https.html [ Skip ]

Added: trunk/LayoutTests/http/tests/workers/service/resources/self_registration_update-worker.js (0 => 225455)


--- trunk/LayoutTests/http/tests/workers/service/resources/self_registration_update-worker.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/resources/self_registration_update-worker.js	2017-12-03 02:32:42 UTC (rev 225455)
@@ -0,0 +1,4 @@
+self.addEventListener("message", (event) => {
+    self.registration.update();
+});
+

Added: trunk/LayoutTests/http/tests/workers/service/self_registration_update-expected.txt (0 => 225455)


--- trunk/LayoutTests/http/tests/workers/service/self_registration_update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/self_registration_update-expected.txt	2017-12-03 02:32:42 UTC (rev 225455)
@@ -0,0 +1,7 @@
+* Add basic testing for ServiceWorkerGlobalScope.registration.update()
+
+PASS: registration was successfuly updated by the service worker
+PASS: service worker became redundant
+PASS: Old worker is still the registration's active worker
+PASS: New worker should be the registration's waiting worker
+

Added: trunk/LayoutTests/http/tests/workers/service/self_registration_update.html (0 => 225455)


--- trunk/LayoutTests/http/tests/workers/service/self_registration_update.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/self_registration_update.html	2017-12-03 02:32:42 UTC (rev 225455)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+log("* Add basic testing for ServiceWorkerGlobalScope.registration.update()");
+log("");
+
+navigator.serviceWorker.register("resources/self_registration_update-worker.js", { }).then(function(_registration) {
+    registration = _registration;
+    worker = registration.installing;
+
+    waitForState(worker, "activated").then(function() {
+        registration.addEventListener("updatefound", function() {
+            log("PASS: registration was successfuly updated by the service worker");
+            waitForState(worker, "redundant").then(function() {
+                log("PASS: service worker became redundant");
+                if (registration.active === worker)
+                    log("PASS: Old worker is still the registration's active worker");
+                else
+                    log("FAIL: Old worker is still the registration's active worker");
+
+                if (!self.registration.waiting || self.registration.waiting === worker)
+                    log("FAIL: New worker should be the registration's waiting worker");
+                else
+                    log("PASS: New worker should be the registration's waiting worker");
+                finishSWTest();
+            });
+        });
+        worker.postMessage("update");
+    });
+});
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (225454 => 225455)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-12-03 02:32:42 UTC (rev 225455)
@@ -1,3 +1,19 @@
+2017-12-02  Chris Dumez  <[email protected]>
+
+        Support serviceWorkerRegistration.update() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180215
+
+        Reviewed by Darin Adler.
+
+        Rebaseline WPT test that no longer times out. The test still fails even
+        though we support update(). The issue is that the second frame load
+        uses the new worker (because of the update()) instead of the old one.
+        The test seems to expect that the new service worker is still in
+        waiting state at the point the second frame is loaded. However, for us
+        it is already activated.
+
+        * web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https-expected.txt:
+
 2017-12-02  Youenn Fablet  <[email protected]>
 
         Implement https://w3c.github.io/ServiceWorker/#clients-getall

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https-expected.txt (225454 => 225455)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https-expected.txt	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https-expected.txt	2017-12-03 02:32:42 UTC (rev 225455)
@@ -1,6 +1,4 @@
 
 
-Harness Error (TIMEOUT), message = null
+FAIL Update a registration on ServiceWorkerGlobalScope assert_equals: events seen by the worker expected "updatefound,activate,fetch,message,updatefound,fetch" but got "updatefound,activate,fetch"
 
-TIMEOUT Update a registration on ServiceWorkerGlobalScope Test timed out
-

Modified: trunk/Source/WebCore/ChangeLog (225454 => 225455)


--- trunk/Source/WebCore/ChangeLog	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/ChangeLog	2017-12-03 02:32:42 UTC (rev 225455)
@@ -1,3 +1,59 @@
+2017-12-02  Chris Dumez  <[email protected]>
+
+        Support serviceWorkerRegistration.update() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180215
+
+        Reviewed by Darin Adler.
+
+        Support serviceWorkerRegistration.update() inside service workers. The code paths
+        for job scheduling and resolution have been made thread safe by hopping to the right
+        thread when necessary. In particular, ServiceWorkerContainer always makes sure to to
+        a callOnMainThread() before calling methods on the SWClientConnection. Also, the
+        SWClientConnection relies on a new postTaskTo() method before calling methods on the
+        job.
+
+        Test: http/tests/workers/service/self_registration_update.html
+
+        * workers/service/SWClientConnection.cpp:
+        (WebCore::SWClientConnection::scheduleJob):
+        (WebCore::SWClientConnection::finishedFetchingScript):
+        (WebCore::SWClientConnection::failedFetchingScript):
+        (WebCore::SWClientConnection::jobRejectedInServer):
+        (WebCore::SWClientConnection::registrationJobResolvedInServer):
+        (WebCore::SWClientConnection::unregistrationJobResolvedInServer):
+        (WebCore::SWClientConnection::startScriptFetchForServer):
+        (WebCore::SWClientConnection::postMessageToServiceWorkerClient):
+        (WebCore::SWClientConnection::updateRegistrationState):
+        (WebCore::SWClientConnection::updateWorkerState):
+        (WebCore::SWClientConnection::fireUpdateFoundEvent):
+        (WebCore::SWClientConnection::notifyClientsOfControllerChange):
+        (WebCore::SWClientConnection::clearPendingJobs):
+        (WebCore::SWClientConnection::postTaskTo):
+        * workers/service/SWClientConnection.h:
+        * workers/service/ServiceWorkerContainer.cpp:
+        (WebCore::ServiceWorkerContainer::scheduleJob):
+        (WebCore::ServiceWorkerContainer::jobFailedWithException):
+        (WebCore::ServiceWorkerContainer::scheduleTaskToFireUpdateFoundEvent):
+        (WebCore::ServiceWorkerContainer::jobResolvedWithRegistration):
+        (WebCore::ServiceWorkerContainer::jobResolvedWithUnregistrationResult):
+        (WebCore::ServiceWorkerContainer::startScriptFetchForJob):
+        (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript):
+        (WebCore::ServiceWorkerContainer::jobFailedLoadingScript):
+        (WebCore::ServiceWorkerContainer::jobDidFinish):
+        (WebCore::ServiceWorkerContainer::addRegistration):
+        (WebCore::ServiceWorkerContainer::removeRegistration):
+        (WebCore::ServiceWorkerContainer::scheduleTaskToFireControllerChangeEvent):
+        (WebCore::ServiceWorkerContainer::contextIdentifier):
+        * workers/service/ServiceWorkerContainer.h:
+        * workers/service/ServiceWorkerJob.cpp:
+        (WebCore::ServiceWorkerJob::ServiceWorkerJob):
+        * workers/service/ServiceWorkerJob.h:
+        (WebCore::ServiceWorkerJob::contextIdentifier):
+        * workers/service/ServiceWorkerJobClient.h:
+        * workers/service/ServiceWorkerRegistration.cpp:
+        (WebCore::ServiceWorkerRegistration::update):
+        * workers/service/ServiceWorkerTypes.h:
+
 2017-12-02  Simon Fraser  <[email protected]>
 
         Make IOSurface::Locker and use it in ImageBufferDataCG

Modified: trunk/Source/WebCore/workers/service/SWClientConnection.cpp (225454 => 225455)


--- trunk/Source/WebCore/workers/service/SWClientConnection.cpp	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.cpp	2017-12-03 02:32:42 UTC (rev 225455)
@@ -47,6 +47,8 @@
 
 void SWClientConnection::scheduleJob(ServiceWorkerJob& job)
 {
+    ASSERT(isMainThread());
+
     auto addResult = m_scheduledJobs.add(job.identifier(), &job);
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
 
@@ -55,6 +57,7 @@
 
 void SWClientConnection::finishedFetchingScript(ServiceWorkerJob& job, const String& script)
 {
+    ASSERT(isMainThread());
     ASSERT(m_scheduledJobs.get(job.identifier()) == &job);
 
     finishFetchingScriptInServer({ job.data().identifier(), job.data().registrationKey(), script, { } });
@@ -62,6 +65,7 @@
 
 void SWClientConnection::failedFetchingScript(ServiceWorkerJob& job, const ResourceError& error)
 {
+    ASSERT(isMainThread());
     ASSERT(m_scheduledJobs.get(job.identifier()) == &job);
 
     finishFetchingScriptInServer({ job.data().identifier(), job.data().registrationKey(), { }, error });
@@ -69,6 +73,8 @@
 
 void SWClientConnection::jobRejectedInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ExceptionData& exceptionData)
 {
+    ASSERT(isMainThread());
+
     auto job = m_scheduledJobs.take(jobDataIdentifier.jobIdentifier);
     if (!job) {
         LOG_ERROR("Job %s rejected from server, but was not found", jobDataIdentifier.loggingString().utf8().data());
@@ -75,11 +81,15 @@
         return;
     }
 
-    job->failedWithException(exceptionData.toException());
+    postTaskTo(job->contextIdentifier(), [job, exceptionData = exceptionData.isolatedCopy()] {
+        job->failedWithException(exceptionData.toException());
+    });
 }
 
 void SWClientConnection::registrationJobResolvedInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, ServiceWorkerRegistrationData&& registrationData, ShouldNotifyWhenResolved shouldNotifyWhenResolved)
 {
+    ASSERT(isMainThread());
+
     auto job = m_scheduledJobs.take(jobDataIdentifier.jobIdentifier);
     if (!job) {
         LOG_ERROR("Job %s resolved in server, but was not found", jobDataIdentifier.loggingString().utf8().data());
@@ -86,12 +96,15 @@
         return;
     }
 
-    auto key = registrationData.key;
-    job->resolvedWithRegistration(WTFMove(registrationData), shouldNotifyWhenResolved);
+    postTaskTo(job->contextIdentifier(), [job, registrationData = registrationData.isolatedCopy(), shouldNotifyWhenResolved]() mutable {
+        job->resolvedWithRegistration(WTFMove(registrationData), shouldNotifyWhenResolved);
+    });
 }
 
 void SWClientConnection::unregistrationJobResolvedInServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, bool unregistrationResult)
 {
+    ASSERT(isMainThread());
+
     auto job = m_scheduledJobs.take(jobDataIdentifier.jobIdentifier);
     if (!job) {
         LOG_ERROR("Job %s resolved in server, but was not found", jobDataIdentifier.loggingString().utf8().data());
@@ -98,11 +111,15 @@
         return;
     }
 
-    job->resolvedWithUnregistrationResult(unregistrationResult);
+    postTaskTo(job->contextIdentifier(), [job, unregistrationResult] {
+        job->resolvedWithUnregistrationResult(unregistrationResult);
+    });
 }
 
 void SWClientConnection::startScriptFetchForServer(const ServiceWorkerJobDataIdentifier& jobDataIdentifier)
 {
+    ASSERT(isMainThread());
+
     auto job = m_scheduledJobs.get(jobDataIdentifier.jobIdentifier);
     if (!job) {
         LOG_ERROR("Job %s instructed to start fetch from server, but job was not found", jobDataIdentifier.loggingString().utf8().data());
@@ -114,11 +131,15 @@
         return;
     }
 
-    job->startScriptFetch();
+    postTaskTo(job->contextIdentifier(), [job] {
+        job->startScriptFetch();
+    });
 }
 
 void SWClientConnection::postMessageToServiceWorkerClient(DocumentIdentifier destinationContextIdentifier, Ref<SerializedScriptValue>&& message, ServiceWorkerData&& sourceData, const String& sourceOrigin)
 {
+    ASSERT(isMainThread());
+
     // FIXME: destinationContextIdentifier can only identify a Document at the moment.
     auto* destinationDocument = Document::allDocumentsMap().get(destinationContextIdentifier);
     if (!destinationDocument)
@@ -137,6 +158,8 @@
 
 void SWClientConnection::updateRegistrationState(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
 {
+    ASSERT(isMainThread());
+
     SWContextManager::singleton().forEachServiceWorkerThread([identifier, state, &serviceWorkerData] (auto& workerThread) {
         workerThread.thread().runLoop().postTask([identifier, state, serviceWorkerData = crossThreadCopy(serviceWorkerData)](ScriptExecutionContext& context) mutable {
             if (auto* container = context.serviceWorkerContainer())
@@ -152,6 +175,8 @@
 
 void SWClientConnection::updateWorkerState(ServiceWorkerIdentifier identifier, ServiceWorkerState state)
 {
+    ASSERT(isMainThread());
+
     SWContextManager::singleton().forEachServiceWorkerThread([identifier, state] (auto& workerThread) {
         workerThread.thread().runLoop().postTask([identifier, state](ScriptExecutionContext& context) {
             if (auto* serviceWorker = context.serviceWorker(identifier))
@@ -167,6 +192,8 @@
 
 void SWClientConnection::fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier identifier)
 {
+    ASSERT(isMainThread());
+
     SWContextManager::singleton().forEachServiceWorkerThread([identifier] (auto& workerThread) {
         workerThread.thread().runLoop().postTask([identifier](ScriptExecutionContext& context) {
             if (auto* container = context.serviceWorkerContainer())
@@ -182,6 +209,7 @@
 
 void SWClientConnection::notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, ServiceWorkerData&& newController)
 {
+    ASSERT(isMainThread());
     ASSERT(!contextIdentifiers.isEmpty());
 
     for (auto& clientIdentifier : contextIdentifiers) {
@@ -200,11 +228,34 @@
 
 void SWClientConnection::clearPendingJobs()
 {
+    ASSERT(isMainThread());
+
     auto jobs = WTFMove(m_scheduledJobs);
-    for (auto& job : jobs.values())
-        job->failedWithException(Exception { TypeError, ASCIILiteral("Internal error") });
+    for (auto& job : jobs.values()) {
+        postTaskTo(job->contextIdentifier(), [job] {
+            job->failedWithException(Exception { TypeError, ASCIILiteral("Internal error") });
+        });
+    }
 }
 
+void SWClientConnection::postTaskTo(const DocumentOrWorkerIdentifier& contextIdentifier, WTF::Function<void()>&& task)
+{
+    ASSERT(isMainThread());
+
+    switchOn(contextIdentifier, [&](DocumentIdentifier identifier) {
+        auto* document = Document::allDocumentsMap().get(identifier);
+        if (!document)
+            return;
+        document->postTask([task = WTFMove(task)](ScriptExecutionContext&) {
+            task();
+        });
+    }, [&](ServiceWorkerIdentifier identifier) {
+        SWContextManager::singleton().postTaskToServiceWorker(identifier, [task = WTFMove(task)](ServiceWorkerGlobalScope&) {
+            task();
+        });
+    });
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

Modified: trunk/Source/WebCore/workers/service/SWClientConnection.h (225454 => 225455)


--- trunk/Source/WebCore/workers/service/SWClientConnection.h	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.h	2017-12-03 02:32:42 UTC (rev 225455)
@@ -95,6 +95,7 @@
     WEBCORE_EXPORT void notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, ServiceWorkerData&& newController);
 
     WEBCORE_EXPORT void clearPendingJobs();
+    WEBCORE_EXPORT void postTaskTo(const DocumentOrWorkerIdentifier&, WTF::Function<void()>&&);
 
 private:
     virtual void scheduleJobInServer(const ServiceWorkerJobData&) = 0;

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2017-12-03 02:32:42 UTC (rev 225455)
@@ -28,6 +28,7 @@
 
 #if ENABLE(SERVICE_WORKER)
 
+#include "Document.h"
 #include "Event.h"
 #include "EventNames.h"
 #include "Exception.h"
@@ -40,9 +41,11 @@
 #include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
 #include "ServiceWorker.h"
+#include "ServiceWorkerGlobalScope.h"
 #include "ServiceWorkerJob.h"
 #include "ServiceWorkerJobData.h"
 #include "ServiceWorkerProvider.h"
+#include "ServiceWorkerThread.h"
 #include "URL.h"
 #include <wtf/RunLoop.h>
 #include <wtf/Scope.h>
@@ -196,15 +199,20 @@
 
 void ServiceWorkerContainer::scheduleJob(Ref<ServiceWorkerJob>&& job)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     ASSERT(m_swConnection);
 
     setPendingActivity(this);
 
-    ServiceWorkerJob& rawJob = job.get();
-    auto result = m_jobMap.add(rawJob.identifier(), WTFMove(job));
+    auto result = m_jobMap.add(job->identifier(), job.copyRef());
     ASSERT_UNUSED(result, result.isNewEntry);
 
-    m_swConnection->scheduleJob(rawJob);
+    callOnMainThread([connection = m_swConnection, job = WTFMove(job)] {
+        connection->scheduleJob(job);
+    });
 }
 
 void ServiceWorkerContainer::getRegistration(const String& clientURL, Ref<DeferredPromise>&& promise)
@@ -293,6 +301,10 @@
 
 void ServiceWorkerContainer::jobFailedWithException(ServiceWorkerJob& job, const Exception& exception)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     if (auto* context = scriptExecutionContext()) {
         context->postTask([job = makeRef(job), exception](ScriptExecutionContext&) {
             job->promise().reject(exception);
@@ -303,6 +315,10 @@
 
 void ServiceWorkerContainer::scheduleTaskToFireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier identifier)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     if (auto* registration = m_registrations.get(identifier))
         registration->scheduleTaskToFireUpdateFoundEvent();
 }
@@ -309,6 +325,10 @@
 
 void ServiceWorkerContainer::jobResolvedWithRegistration(ServiceWorkerJob& job, ServiceWorkerRegistrationData&& data, ShouldNotifyWhenResolved shouldNotifyWhenResolved)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     auto guard = WTF::makeScopeExit([this, &job] {
         jobDidFinish(job);
     });
@@ -345,6 +365,10 @@
 
 void ServiceWorkerContainer::jobResolvedWithUnregistrationResult(ServiceWorkerJob& job, bool unregistrationResult)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     auto guard = WTF::makeScopeExit([this, &job] {
         jobDidFinish(job);
     });
@@ -362,12 +386,18 @@
 
 void ServiceWorkerContainer::startScriptFetchForJob(ServiceWorkerJob& job)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     LOG(ServiceWorker, "SeviceWorkerContainer %p starting script fetch for job %s", this, job.identifier().loggingString().utf8().data());
 
     auto* context = scriptExecutionContext();
     if (!context) {
         LOG_ERROR("ServiceWorkerContainer::jobResolvedWithRegistration called but the container's ScriptExecutionContext is gone");
-        m_swConnection->failedFetchingScript(job, { errorDomainWebKitInternal, 0, job.data().scriptURL, ASCIILiteral("Attempt to fetch service worker script with no ScriptExecutionContext") });
+        callOnMainThread([connection = m_swConnection, job = makeRef(job)] {
+            connection->failedFetchingScript(job, { errorDomainWebKitInternal, 0, job->data().scriptURL, ASCIILiteral("Attempt to fetch service worker script with no ScriptExecutionContext") });
+        });
         jobDidFinish(job);
         return;
     }
@@ -377,23 +407,39 @@
 
 void ServiceWorkerContainer::jobFinishedLoadingScript(ServiceWorkerJob& job, const String& script)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     LOG(ServiceWorker, "SeviceWorkerContainer %p finished fetching script for job %s", this, job.identifier().loggingString().utf8().data());
 
-    m_swConnection->finishedFetchingScript(job, script);
+    callOnMainThread([connection = m_swConnection, job = makeRef(job), script = script.isolatedCopy()] {
+        connection->finishedFetchingScript(job, script);
+    });
 }
 
 void ServiceWorkerContainer::jobFailedLoadingScript(ServiceWorkerJob& job, const ResourceError& error, std::optional<Exception>&& exception)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     LOG(ServiceWorker, "SeviceWorkerContainer %p failed fetching script for job %s", this, job.identifier().loggingString().utf8().data());
 
     if (exception)
         job.promise().reject(*exception);
 
-    m_swConnection->failedFetchingScript(job, error);
+    callOnMainThread([connection = m_swConnection, job = makeRef(job), error = error.isolatedCopy()] {
+        connection->failedFetchingScript(job, error);
+    });
 }
 
 void ServiceWorkerContainer::jobDidFinish(ServiceWorkerJob& job)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     auto taken = m_jobMap.take(job.identifier());
     ASSERT_UNUSED(taken, !taken || taken->ptr() == &job);
 
@@ -429,6 +475,10 @@
 
 void ServiceWorkerContainer::addRegistration(ServiceWorkerRegistration& registration)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     ensureSWClientConnection().addServiceWorkerRegistrationInServer(registration.identifier());
     m_registrations.add(registration.identifier(), &registration);
 }
@@ -435,6 +485,10 @@
 
 void ServiceWorkerContainer::removeRegistration(ServiceWorkerRegistration& registration)
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     m_swConnection->removeServiceWorkerRegistrationInServer(registration.identifier());
     m_registrations.remove(registration.identifier());
 }
@@ -441,6 +495,10 @@
 
 void ServiceWorkerContainer::scheduleTaskToFireControllerChangeEvent()
 {
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
     if (m_isStopped)
         return;
 
@@ -458,6 +516,18 @@
     removeAllEventListeners();
 }
 
+DocumentOrWorkerIdentifier ServiceWorkerContainer::contextIdentifier()
+{
+#ifndef NDEBUG
+    ASSERT(m_creationThread == currentThread());
+#endif
+
+    ASSERT(scriptExecutionContext());
+    if (is<ServiceWorkerGlobalScope>(*scriptExecutionContext()))
+        return downcast<ServiceWorkerGlobalScope>(*scriptExecutionContext()).thread().identifier();
+    return downcast<Document>(*scriptExecutionContext()).identifier();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h	2017-12-03 02:32:42 UTC (rev 225455)
@@ -96,6 +96,8 @@
     void jobDidFinish(ServiceWorkerJob&);
 
     SWServerConnectionIdentifier connectionIdentifier() final;
+    DocumentOrWorkerIdentifier contextIdentifier() final;
+
     SWClientConnection& ensureSWClientConnection();
 
     const char* activeDOMObjectName() const final;

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJob.cpp	2017-12-03 02:32:42 UTC (rev 225455)
@@ -41,6 +41,7 @@
     : m_client(client)
     , m_jobData(WTFMove(jobData))
     , m_promise(WTFMove(promise))
+    , m_contextIdentifier(client.contextIdentifier())
 {
 }
 

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJob.h (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerJob.h	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJob.h	2017-12-03 02:32:42 UTC (rev 225455)
@@ -68,6 +68,8 @@
 
     void fetchScriptWithContext(ScriptExecutionContext&);
 
+    const DocumentOrWorkerIdentifier& contextIdentifier() { return m_contextIdentifier; }
+
 private:
     ServiceWorkerJob(ServiceWorkerJobClient&, Ref<DeferredPromise>&&, ServiceWorkerJobData&&);
 
@@ -83,7 +85,7 @@
 
     bool m_completed { false };
 
-    Ref<RunLoop> m_runLoop { RunLoop::current() };
+    DocumentOrWorkerIdentifier m_contextIdentifier;
     RefPtr<WorkerScriptLoader> m_scriptLoader;
     ResourceResponse m_lastResponse;
 

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h	2017-12-03 02:32:42 UTC (rev 225455)
@@ -41,6 +41,8 @@
 public:
     virtual ~ServiceWorkerJobClient() = default;
 
+    virtual DocumentOrWorkerIdentifier contextIdentifier() = 0;
+
     virtual void jobFailedWithException(ServiceWorkerJob&, const Exception&) = 0;
     virtual void jobResolvedWithRegistration(ServiceWorkerJob&, ServiceWorkerRegistrationData&&, ShouldNotifyWhenResolved) = 0;
     virtual void jobResolvedWithUnregistrationResult(ServiceWorkerJob&, bool unregistrationResult) = 0;

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp	2017-12-03 02:32:42 UTC (rev 225455)
@@ -121,18 +121,6 @@
         return;
     }
 
-    // FIXME: Add support in workers.
-    if (!is<Document>(*context)) {
-        promise->reject(Exception { NotSupportedError, ASCIILiteral("serviceWorkerRegistration.update() is not yet supported in workers") });
-        return;
-    }
-
-    auto* container = context->serviceWorkerContainer();
-    if (!container) {
-        promise->reject(Exception(InvalidStateError));
-        return;
-    }
-
     auto* newestWorker = getNewestWorker();
     if (!newestWorker) {
         promise->reject(Exception(InvalidStateError, ASCIILiteral("newestWorker is null")));
@@ -140,7 +128,7 @@
     }
 
     // FIXME: Support worker types.
-    container->updateRegistration(m_registrationData.scopeURL, newestWorker->scriptURL(), WorkerType::Classic, WTFMove(promise));
+    m_container->updateRegistration(m_registrationData.scopeURL, newestWorker->scriptURL(), WorkerType::Classic, WTFMove(promise));
 }
 
 void ServiceWorkerRegistration::unregister(Ref<DeferredPromise>&& promise)

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerTypes.h (225454 => 225455)


--- trunk/Source/WebCore/workers/service/ServiceWorkerTypes.h	2017-12-02 23:11:12 UTC (rev 225454)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerTypes.h	2017-12-03 02:32:42 UTC (rev 225455)
@@ -27,8 +27,11 @@
 
 #if ENABLE(SERVICE_WORKER)
 
+#include "DocumentIdentifier.h"
+#include "ServiceWorkerIdentifier.h"
 #include <wtf/EnumTraits.h>
 #include <wtf/ObjectIdentifier.h>
+#include <wtf/Variant.h>
 
 namespace WebCore {
 
@@ -67,6 +70,8 @@
 enum SWServerConnectionIdentifierType { };
 using SWServerConnectionIdentifier = ObjectIdentifier<SWServerConnectionIdentifierType>;
 
+using DocumentOrWorkerIdentifier = Variant<DocumentIdentifier, ServiceWorkerIdentifier>;
+
 } // namespace WebCore
 
 namespace WTF {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to