Title: [225513] trunk
Revision
225513
Author
cdu...@apple.com
Date
2017-12-04 18:06:26 -0800 (Mon, 04 Dec 2017)

Log Message

Support container.getRegistration() / getRegistrations() inside service workers
https://bugs.webkit.org/show_bug.cgi?id=180360

Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

* web-platform-tests/service-workers/service-worker/activation.https-expected.txt:
Rebaseline test with slightly different output.

* web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https-expected.txt:
* web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html:
With my change, this test started running and passing a check before timing out. When investigating the time
out, I found out that this is caused by the test unregistering the worker while the test is still running
in the service worker, which causes the worker to terminate early. To address the issue, we no longer add
a cleanup step to unregister. The test now passes all checks.

Source/WebCore:

Support container.getRegistration() / getRegistrations() inside service workers
by making sure we hop to the right thread when needed.

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

* dom/ScriptExecutionContext.cpp:
(WebCore::ScriptExecutionContext::postTaskTo):
* dom/ScriptExecutionContext.h:
* workers/service/SWClientConnection.cpp:
(WebCore::SWClientConnection::jobRejectedInServer):
(WebCore::SWClientConnection::registrationJobResolvedInServer):
(WebCore::SWClientConnection::unregistrationJobResolvedInServer):
(WebCore::SWClientConnection::startScriptFetchForServer):
(WebCore::SWClientConnection::clearPendingJobs):
* workers/service/SWClientConnection.h:
* workers/service/ServiceWorkerContainer.cpp:
(WebCore::ServiceWorkerContainer::getRegistration):
(WebCore::ServiceWorkerContainer::didFinishGetRegistrationRequest):
(WebCore::ServiceWorkerContainer::getRegistrations):
(WebCore::ServiceWorkerContainer::didFinishGetRegistrationsRequest):
(WebCore::ServiceWorkerContainer::stop):
* workers/service/ServiceWorkerContainer.h:

Source/WebKit:

* WebProcess/Storage/WebSWClientConnection.cpp:
(WebKit::WebSWClientConnection::didMatchRegistration):
(WebKit::WebSWClientConnection::didGetRegistrations):
(WebKit::WebSWClientConnection::matchRegistration):
(WebKit::WebSWClientConnection::getRegistrations):

LayoutTests:

Add layout test coverage.

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

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225512 => 225513)


--- trunk/LayoutTests/ChangeLog	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/ChangeLog	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,3 +1,16 @@
+2017-12-04  Chris Dumez  <cdu...@apple.com>
+
+        Support container.getRegistration() / getRegistrations() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180360
+
+        Reviewed by Youenn Fablet.
+
+        Add layout test coverage.
+
+        * http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration-expected.txt: Added.
+        * http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration.html: Added.
+        * http/tests/workers/service/resources/ServiceWorkerGlobalScope_getRegistration-worker.js: Added.
+
 2017-12-04  Nan Wang  <n_w...@apple.com>
 
         AX: AOM: Implement relation type properties

Modified: trunk/LayoutTests/TestExpectations (225512 => 225513)


--- trunk/LayoutTests/TestExpectations	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/TestExpectations	2017-12-05 02:06:26 UTC (rev 225513)
@@ -161,7 +161,6 @@
 webkit.org/b/179452 imported/w3c/web-platform-tests/service-workers/service-worker/register-same-scope-different-script-url.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/respond-with-body-accessed-response.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html [ Skip ]
-imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/update-after-navigation-fetch-event.https.html [ Skip ]
 imported/w3c/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html [ Skip ]

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


--- trunk/LayoutTests/http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration-expected.txt	2017-12-05 02:06:26 UTC (rev 225513)
@@ -0,0 +1,8 @@
+* Tests that serviceWorker.getRegistration() / getRegistrations() inside service workers
+
+PASS: Registration succeeded
+PASS: getRegistration() returned the right registration
+PASS: getRegistrations() returned 2 registrations
+PASS: getRegistrations()[0] is the right registration
+PASS: getRegistrations()[1] is the right registration
+

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


--- trunk/LayoutTests/http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration.html	2017-12-05 02:06:26 UTC (rev 225513)
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+log("* Tests that serviceWorker.getRegistration() / getRegistrations() inside service workers");
+log("");
+
+navigator.serviceWorker.addEventListener("message", function(event) {
+    if (event.data ="" "DONE") {
+        finishSWTest();
+        return;
+    }
+    log(event.data);
+});
+
+navigator.serviceWorker.register("resources/ServiceWorkerGlobalScope_getRegistration-worker.js", { }).then(function(registration) {
+    registration.installing.postMessage("runTest");
+});
+</script>
+</body>
+</html>

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


--- trunk/LayoutTests/http/tests/workers/service/resources/ServiceWorkerGlobalScope_getRegistration-worker.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/resources/ServiceWorkerGlobalScope_getRegistration-worker.js	2017-12-05 02:06:26 UTC (rev 225513)
@@ -0,0 +1,49 @@
+let client = null;
+
+function log(msg)
+{
+    client.postMessage(msg);
+}
+
+async function runTest()
+{
+    try {
+        let r = await navigator.serviceWorker.register("empty-worker.js", { scope: "/test" });
+        log("PASS: Registration succeeded");
+
+        let retrievedRegistration = await navigator.serviceWorker.getRegistration("/test");
+        if (r === retrievedRegistration)
+            log("PASS: getRegistration() returned the right registration");
+        else
+            log("FAIL: getRegistration() did not return the right registration");
+
+        let retrievedRegistrations = await navigator.serviceWorker.getRegistrations();
+        if (retrievedRegistrations.length === 2)
+            log("PASS: getRegistrations() returned 2 registrations");
+        else {
+            log("FAIL: getRegistrations() returned " + retrievedRegistrations.length + " registration(s)");
+            log("DONE");
+            return;
+        }
+
+        if (retrievedRegistrations[0] === self.registration)
+            log("PASS: getRegistrations()[0] is the right registration");
+        else
+            log("FAIL: getRegistrations()[0] is not the right registration");
+
+        if (retrievedRegistrations[1] === r)
+            log("PASS: getRegistrations()[1] is the right registration");
+        else
+            log("FAIL: getRegistrations()[1] is not the right registration");
+
+        log("DONE");
+    } catch (e) {
+        log("FAIL: " + e);
+        log("DONE");
+    }
+}
+
+self.addEventListener("message", (event) => {
+    client = event.source;
+    runTest();
+});

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,3 +1,20 @@
+2017-12-04  Chris Dumez  <cdu...@apple.com>
+
+        Support container.getRegistration() / getRegistrations() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180360
+
+        Reviewed by Youenn Fablet.
+
+        * web-platform-tests/service-workers/service-worker/activation.https-expected.txt:
+        Rebaseline test with slightly different output.
+
+        * web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https-expected.txt:
+        * web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html:
+        With my change, this test started running and passing a check before timing out. When investigating the time
+        out, I found out that this is caused by the test unregistering the worker while the test is still running
+        in the service worker, which causes the worker to terminate early. To address the issue, we no longer add
+        a cleanup step to unregister. The test now passes all checks.
+
 2017-12-03  Chris Dumez  <cdu...@apple.com>
 
         Re-sync Service Workers web-platform-tests from upstream

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activation.https-expected.txt (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activation.https-expected.txt	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activation.https-expected.txt	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,5 +1,5 @@
-  
 
+
 FAIL loss of controllees triggers activation assert_not_equals: got disallowed value null
 FAIL finishing a request triggers activation assert_not_equals: got disallowed value null
 FAIL skipWaiting bypasses no controllee requirement assert_not_equals: got disallowed value null

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https-expected.txt (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https-expected.txt	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https-expected.txt	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,6 +1,4 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS Test skipWaiting while a client is using the registration 
-TIMEOUT skipWaiting Test timed out
+PASS skipWaiting 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html	2017-12-05 02:06:26 UTC (rev 225513)
@@ -50,9 +50,6 @@
         })
       .then(function(registration) {
           sw_registration = registration;
-          t.add_cleanup(function() {
-              registration.unregister();
-            });
           return saw_controllerchanged;
         })
       .then(function() {

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https-expected.txt (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https-expected.txt	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https-expected.txt	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,3 +1,4 @@
 
-FAIL Test skipWaiting while a client is not being controlled promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'document.body.appendChild')"
+PASS Test skipWaiting while a client is not being controlled 
+PASS skipWaiting 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html (225512 => 225513)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html	2017-12-05 02:06:26 UTC (rev 225513)
@@ -26,9 +26,6 @@
         })
       .then(function(registration) {
           sw_registration = registration;
-          t.add_cleanup(function() {
-              registration.unregister();
-            });
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {

Modified: trunk/Source/WebCore/ChangeLog (225512 => 225513)


--- trunk/Source/WebCore/ChangeLog	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/ChangeLog	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,3 +1,33 @@
+2017-12-04  Chris Dumez  <cdu...@apple.com>
+
+        Support container.getRegistration() / getRegistrations() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180360
+
+        Reviewed by Youenn Fablet.
+
+        Support container.getRegistration() / getRegistrations() inside service workers
+        by making sure we hop to the right thread when needed.
+
+        Test: http/tests/workers/service/ServiceWorkerGlobalScope_getRegistration.html
+
+        * dom/ScriptExecutionContext.cpp:
+        (WebCore::ScriptExecutionContext::postTaskTo):
+        * dom/ScriptExecutionContext.h:
+        * workers/service/SWClientConnection.cpp:
+        (WebCore::SWClientConnection::jobRejectedInServer):
+        (WebCore::SWClientConnection::registrationJobResolvedInServer):
+        (WebCore::SWClientConnection::unregistrationJobResolvedInServer):
+        (WebCore::SWClientConnection::startScriptFetchForServer):
+        (WebCore::SWClientConnection::clearPendingJobs):
+        * workers/service/SWClientConnection.h:
+        * workers/service/ServiceWorkerContainer.cpp:
+        (WebCore::ServiceWorkerContainer::getRegistration):
+        (WebCore::ServiceWorkerContainer::didFinishGetRegistrationRequest):
+        (WebCore::ServiceWorkerContainer::getRegistrations):
+        (WebCore::ServiceWorkerContainer::didFinishGetRegistrationsRequest):
+        (WebCore::ServiceWorkerContainer::stop):
+        * workers/service/ServiceWorkerContainer.h:
+
 2017-12-04  Simon Fraser  <simon.fra...@apple.com>
 
         Cleanup code that computes iframe content offsets in FrameView

Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.cpp (225512 => 225513)


--- trunk/Source/WebCore/dom/ScriptExecutionContext.cpp	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.cpp	2017-12-05 02:06:26 UTC (rev 225513)
@@ -44,8 +44,10 @@
 #include "RejectedPromiseTracker.h"
 #include "ResourceRequest.h"
 #include "SWClientConnection.h"
+#include "SWContextManager.h"
 #include "ScriptState.h"
 #include "ServiceWorker.h"
+#include "ServiceWorkerGlobalScope.h"
 #include "ServiceWorkerProvider.h"
 #include "Settings.h"
 #include "WorkerGlobalScope.h"
@@ -582,6 +584,24 @@
 
     return navigator ? &navigator->serviceWorker() : nullptr;
 }
+
+void ScriptExecutionContext::postTaskTo(const DocumentOrWorkerIdentifier& contextIdentifier, WTF::Function<void(ScriptExecutionContext&)>&& task)
+{
+    ASSERT(isMainThread());
+
+    switchOn(contextIdentifier, [&] (DocumentIdentifier identifier) {
+        auto* document = Document::allDocumentsMap().get(identifier);
+        if (!document)
+            return;
+        document->postTask([task = WTFMove(task)](auto& scope) {
+            task(scope);
+        });
+    }, [&](ServiceWorkerIdentifier identifier) {
+        SWContextManager::singleton().postTaskToServiceWorker(identifier, [task = WTFMove(task)](auto& scope) {
+            task(scope);
+        });
+    });
+}
 #endif
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.h (225512 => 225513)


--- trunk/Source/WebCore/dom/ScriptExecutionContext.h	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.h	2017-12-05 02:06:26 UTC (rev 225513)
@@ -30,7 +30,7 @@
 #include "ActiveDOMObject.h"
 #include "DOMTimer.h"
 #include "SecurityContext.h"
-#include "ServiceWorkerIdentifier.h"
+#include "ServiceWorkerTypes.h"
 #include <heap/HandleTypes.h>
 #include <runtime/ConsoleTypes.h>
 #include <wtf/CrossThreadTask.h>
@@ -246,6 +246,8 @@
     ServiceWorker* serviceWorker(ServiceWorkerIdentifier identifier) { return m_serviceWorkers.get(identifier); }
 
     ServiceWorkerContainer* serviceWorkerContainer();
+
+    WEBCORE_EXPORT static void postTaskTo(const DocumentOrWorkerIdentifier&, WTF::Function<void(ScriptExecutionContext&)>&&);
 #endif
 
 protected:

Modified: trunk/Source/WebCore/workers/service/SWClientConnection.cpp (225512 => 225513)


--- trunk/Source/WebCore/workers/service/SWClientConnection.cpp	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.cpp	2017-12-05 02:06:26 UTC (rev 225513)
@@ -81,7 +81,7 @@
         return;
     }
 
-    postTaskTo(job->contextIdentifier(), [job, exceptionData = exceptionData.isolatedCopy()] {
+    ScriptExecutionContext::postTaskTo(job->contextIdentifier(), [job, exceptionData = exceptionData.isolatedCopy()](ScriptExecutionContext&) {
         job->failedWithException(exceptionData.toException());
     });
 }
@@ -96,7 +96,7 @@
         return;
     }
 
-    postTaskTo(job->contextIdentifier(), [job, registrationData = registrationData.isolatedCopy(), shouldNotifyWhenResolved]() mutable {
+    ScriptExecutionContext::postTaskTo(job->contextIdentifier(), [job, registrationData = registrationData.isolatedCopy(), shouldNotifyWhenResolved](ScriptExecutionContext&) mutable {
         job->resolvedWithRegistration(WTFMove(registrationData), shouldNotifyWhenResolved);
     });
 }
@@ -111,7 +111,7 @@
         return;
     }
 
-    postTaskTo(job->contextIdentifier(), [job, unregistrationResult] {
+    ScriptExecutionContext::postTaskTo(job->contextIdentifier(), [job, unregistrationResult](ScriptExecutionContext&) {
         job->resolvedWithUnregistrationResult(unregistrationResult);
     });
 }
@@ -131,7 +131,7 @@
         return;
     }
 
-    postTaskTo(job->contextIdentifier(), [job] {
+    ScriptExecutionContext::postTaskTo(job->contextIdentifier(), [job](ScriptExecutionContext&) {
         job->startScriptFetch();
     });
 }
@@ -232,30 +232,12 @@
 
     auto jobs = WTFMove(m_scheduledJobs);
     for (auto& job : jobs.values()) {
-        postTaskTo(job->contextIdentifier(), [job] {
+        ScriptExecutionContext::postTaskTo(job->contextIdentifier(), [job](ScriptExecutionContext&) {
             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 (225512 => 225513)


--- trunk/Source/WebCore/workers/service/SWClientConnection.h	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/workers/service/SWClientConnection.h	2017-12-05 02:06:26 UTC (rev 225513)
@@ -98,7 +98,6 @@
     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 (225512 => 225513)


--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2017-12-05 02:06:26 UTC (rev 225513)
@@ -218,12 +218,6 @@
         return;
     }
 
-    // FIXME: Add support in workers.
-    if (!is<Document>(*context)) {
-        promise->reject(Exception { NotSupportedError, ASCIILiteral("serviceWorker.getRegistration() is not yet supported in workers") });
-        return;
-    }
-
     URL parsedURL = context->completeURL(clientURL);
     if (!protocolHostAndPortAreEqual(parsedURL, context->url())) {
         promise->reject(Exception { SecurityError, ASCIILiteral("Origin of clientURL is not client's origin") });
@@ -230,20 +224,41 @@
         return;
     }
 
-    return ensureSWClientConnection().matchRegistration(context->topOrigin(), parsedURL, [promise = WTFMove(promise), protectingThis = makePendingActivity(*this), this] (auto&& result) mutable {
-        if (m_isStopped)
-            return;
+    uint64_t pendingPromiseIdentifier = ++m_lastPendingPromiseIdentifier;
+    auto pendingPromise = std::make_unique<PendingPromise>(WTFMove(promise), makePendingActivity(*this));
+    m_pendingPromises.add(pendingPromiseIdentifier, WTFMove(pendingPromise));
 
-        if (!result) {
-            promise->resolve();
-            return;
-        }
-
-        auto registration = ServiceWorkerRegistration::getOrCreate(*scriptExecutionContext(), *this, WTFMove(result.value()));
-        promise->resolve<IDLInterface<ServiceWorkerRegistration>>(WTFMove(registration));
+    auto contextIdentifier = this->contextIdentifier();
+    callOnMainThread([connection = makeRef(ensureSWClientConnection()), this, topOrigin = context->topOrigin().isolatedCopy(), parsedURL = parsedURL.isolatedCopy(), contextIdentifier, pendingPromiseIdentifier]() mutable {
+        connection->matchRegistration(topOrigin, parsedURL, [this, contextIdentifier, pendingPromiseIdentifier] (auto&& result) mutable {
+            ScriptExecutionContext::postTaskTo(contextIdentifier, [this, pendingPromiseIdentifier, result = crossThreadCopy(result)](ScriptExecutionContext&) mutable {
+                didFinishGetRegistrationRequest(pendingPromiseIdentifier, WTFMove(result));
+            });
+        });
     });
 }
 
+void ServiceWorkerContainer::didFinishGetRegistrationRequest(uint64_t pendingPromiseIdentifier, std::optional<ServiceWorkerRegistrationData>&& result)
+{
+#ifndef NDEBUG
+    ASSERT(m_creationThread.ptr() == &Thread::current());
+#endif
+
+    auto pendingPromise = m_pendingPromises.take(pendingPromiseIdentifier);
+    if (!pendingPromise)
+        return;
+
+    ASSERT(!m_isStopped);
+
+    if (!result) {
+        pendingPromise->promise->resolve();
+        return;
+    }
+
+    auto registration = ServiceWorkerRegistration::getOrCreate(*scriptExecutionContext(), *this, WTFMove(result.value()));
+    pendingPromise->promise->resolve<IDLInterface<ServiceWorkerRegistration>>(WTFMove(registration));
+}
+
 void ServiceWorkerContainer::scheduleTaskToUpdateRegistrationState(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
 {
     auto* context = scriptExecutionContext();
@@ -260,33 +275,46 @@
     });
 }
 
-void ServiceWorkerContainer::getRegistrations(RegistrationsPromise&& promise)
+void ServiceWorkerContainer::getRegistrations(Ref<DeferredPromise>&& promise)
 {
     auto* context = scriptExecutionContext();
     if (!context) {
-        promise.reject(Exception { InvalidStateError });
+        promise->reject(Exception { InvalidStateError });
         return;
     }
 
-    // FIXME: Add support in workers.
-    if (!is<Document>(*context)) {
-        promise.reject(Exception { NotSupportedError, ASCIILiteral("serviceWorker.getRegistrations() is not yet supported in workers") });
+    uint64_t pendingPromiseIdentifier = ++m_lastPendingPromiseIdentifier;
+    auto pendingPromise = std::make_unique<PendingPromise>(WTFMove(promise), makePendingActivity(*this));
+    m_pendingPromises.add(pendingPromiseIdentifier, WTFMove(pendingPromise));
+
+    auto contextIdentifier = this->contextIdentifier();
+    auto contextURL = context->url();
+    callOnMainThread([connection = makeRef(ensureSWClientConnection()), this, topOrigin = context->topOrigin().isolatedCopy(), contextURL = contextURL.isolatedCopy(), contextIdentifier, pendingPromiseIdentifier]() mutable {
+        connection->getRegistrations(topOrigin, contextURL, [this, contextIdentifier, pendingPromiseIdentifier] (auto&& registrationDatas) mutable {
+            ScriptExecutionContext::postTaskTo(contextIdentifier, [this, pendingPromiseIdentifier, registrationDatas = crossThreadCopy(registrationDatas)](ScriptExecutionContext&) mutable {
+                didFinishGetRegistrationsRequest(pendingPromiseIdentifier, WTFMove(registrationDatas));
+            });
+        });
+    });
+}
+
+void ServiceWorkerContainer::didFinishGetRegistrationsRequest(uint64_t pendingPromiseIdentifier, Vector<ServiceWorkerRegistrationData>&& registrationDatas)
+{
+#ifndef NDEBUG
+    ASSERT(m_creationThread.ptr() == &Thread::current());
+#endif
+
+    auto pendingPromise = m_pendingPromises.take(pendingPromiseIdentifier);
+    if (!pendingPromise)
         return;
-    }
 
-    return ensureSWClientConnection().getRegistrations(context->topOrigin(), context->url(), [this, pendingActivity = makePendingActivity(*this), promise = WTFMove(promise)] (auto&& registrationDatas) mutable {
-        if (m_isStopped)
-            return;
+    ASSERT(!m_isStopped);
 
-        Vector<Ref<ServiceWorkerRegistration>> registrations;
-        registrations.reserveInitialCapacity(registrationDatas.size());
-        for (auto& registrationData : registrationDatas) {
-            auto registration = ServiceWorkerRegistration::getOrCreate(*scriptExecutionContext(), *this, WTFMove(registrationData));
-            registrations.uncheckedAppend(WTFMove(registration));
-        }
+    auto registrations = WTF::map(WTFMove(registrationDatas), [&] (auto&& registrationData) {
+        return ServiceWorkerRegistration::getOrCreate(*scriptExecutionContext(), *this, WTFMove(registrationData));
+    });
 
-        promise.resolve(WTFMove(registrations));
-    });
+    pendingPromise->promise->resolve<IDLSequence<IDLInterface<ServiceWorkerRegistration>>>(WTFMove(registrations));
 }
 
 void ServiceWorkerContainer::startMessages()
@@ -508,6 +536,7 @@
 {
     m_isStopped = true;
     removeAllEventListeners();
+    m_pendingPromises.clear();
 }
 
 DocumentOrWorkerIdentifier ServiceWorkerContainer::contextIdentifier()

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h (225512 => 225513)


--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h	2017-12-05 02:06:26 UTC (rev 225513)
@@ -68,8 +68,7 @@
     void scheduleTaskToFireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier);
     void scheduleTaskToFireControllerChangeEvent();
 
-    using RegistrationsPromise = DOMPromiseDeferred<IDLSequence<IDLInterface<ServiceWorkerRegistration>>>;
-    void getRegistrations(RegistrationsPromise&&);
+    void getRegistrations(Ref<DeferredPromise>&&);
 
     ServiceWorkerRegistration* registration(ServiceWorkerRegistrationIdentifier identifier) const { return m_registrations.get(identifier); }
 
@@ -95,6 +94,9 @@
 
     void jobDidFinish(ServiceWorkerJob&);
 
+    void didFinishGetRegistrationRequest(uint64_t requestIdentifier, std::optional<ServiceWorkerRegistrationData>&&);
+    void didFinishGetRegistrationsRequest(uint64_t requestIdentifier, Vector<ServiceWorkerRegistrationData>&&);
+
     SWServerConnectionIdentifier connectionIdentifier() final;
     DocumentOrWorkerIdentifier contextIdentifier() final;
 
@@ -121,6 +123,19 @@
 #ifndef NDEBUG
     Ref<Thread> m_creationThread { Thread::current() };
 #endif
+
+    struct PendingPromise {
+        PendingPromise(Ref<DeferredPromise>&& promise, Ref<PendingActivity<ServiceWorkerContainer>>&& pendingActivity)
+            : promise(WTFMove(promise))
+            , pendingActivity(WTFMove(pendingActivity))
+        { }
+
+        Ref<DeferredPromise> promise;
+        Ref<PendingActivity<ServiceWorkerContainer>> pendingActivity;
+    };
+
+    uint64_t m_lastPendingPromiseIdentifier { 0 };
+    HashMap<uint64_t, std::unique_ptr<PendingPromise>> m_pendingPromises;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (225512 => 225513)


--- trunk/Source/WebKit/ChangeLog	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebKit/ChangeLog	2017-12-05 02:06:26 UTC (rev 225513)
@@ -1,3 +1,16 @@
+2017-12-04  Chris Dumez  <cdu...@apple.com>
+
+        Support container.getRegistration() / getRegistrations() inside service workers
+        https://bugs.webkit.org/show_bug.cgi?id=180360
+
+        Reviewed by Youenn Fablet.
+
+        * WebProcess/Storage/WebSWClientConnection.cpp:
+        (WebKit::WebSWClientConnection::didMatchRegistration):
+        (WebKit::WebSWClientConnection::didGetRegistrations):
+        (WebKit::WebSWClientConnection::matchRegistration):
+        (WebKit::WebSWClientConnection::getRegistrations):
+
 2017-12-04  Brady Eidson  <beid...@apple.com>
 
         Followup to:

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp (225512 => 225513)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp	2017-12-05 01:37:20 UTC (rev 225512)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp	2017-12-05 02:06:26 UTC (rev 225513)
@@ -137,6 +137,8 @@
 
 void WebSWClientConnection::didMatchRegistration(uint64_t matchingRequest, std::optional<ServiceWorkerRegistrationData>&& result)
 {
+    ASSERT(isMainThread());
+
     if (auto completionHandler = m_ongoingMatchRegistrationTasks.take(matchingRequest))
         completionHandler(WTFMove(result));
 }
@@ -143,6 +145,8 @@
 
 void WebSWClientConnection::didGetRegistrations(uint64_t matchingRequest, Vector<ServiceWorkerRegistrationData>&& registrations)
 {
+    ASSERT(isMainThread());
+
     if (auto completionHandler = m_ongoingGetRegistrationsTasks.take(matchingRequest))
         completionHandler(WTFMove(registrations));
 }
@@ -149,6 +153,8 @@
 
 void WebSWClientConnection::matchRegistration(const SecurityOrigin& topOrigin, const URL& clientURL, RegistrationCallback&& callback)
 {
+    ASSERT(isMainThread());
+
     if (!mayHaveServiceWorkerRegisteredForOrigin(topOrigin)) {
         callback(std::nullopt);
         return;
@@ -161,6 +167,8 @@
 
 void WebSWClientConnection::getRegistrations(const SecurityOrigin& topOrigin, const URL& clientURL, GetRegistrationsCallback&& callback)
 {
+    ASSERT(isMainThread());
+
     if (!mayHaveServiceWorkerRegisteredForOrigin(topOrigin)) {
         callback({ });
         return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to