Delay some service worker operations until after the database import completes.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Dec 2017 03:03:06 +0000 (03:03 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Dec 2017 03:03:06 +0000 (03:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180573

Reviewed by Chris Dumez.

Source/WebCore:

No new tests (Not testable yet).

Right after the storage process launches it starts importing registration records.
During this time, a lot of the decisions we make regarding registrations, fetch, etc.
are invalid, as they rely on those in-memory records being in place.

This patch delays certain things until after the initial origin table import is complete.

* workers/service/server/RegistrationStore.cpp:
(WebCore::RegistrationStore::databaseOpenedAndRecordsImported):

* workers/service/server/SWOriginStore.h:

* workers/service/server/SWServer.cpp:
(WebCore::SWServer::registrationStoreImportComplete): Tell the origin store the initial
  import was completed.
(WebCore::SWServer::addRegistrationFromStore):
* workers/service/server/SWServer.h:

Source/WebKit:

* StorageProcess/ServiceWorker/WebSWOriginStore.cpp:
(WebKit::WebSWOriginStore::importComplete): Tell the Origin Table on all connects that
  the import is complete.
(WebKit::WebSWOriginStore::registerSWServerConnection):
* StorageProcess/ServiceWorker/WebSWOriginStore.h:

* WebProcess/Storage/WebSWClientConnection.cpp:
(WebKit::WebSWClientConnection::mayHaveServiceWorkerRegisteredForOrigin const):
(WebKit::WebSWClientConnection::setSWOriginTableIsImported): Run deferred tasks!
(WebKit::WebSWClientConnection::matchRegistration): If the import isn't complete yet, delay
  the match registration task until later.
(WebKit::WebSWClientConnection::runOrDelayTask): Either send the message now or save off
  the task to wait until the import is complete.
(WebKit::WebSWClientConnection::getRegistrations): If the import isn't complete yet, delay
  the get registrations task until later.
(WebKit::WebSWClientConnection::initializeSWOriginTableAsEmpty): Deleted.
* WebProcess/Storage/WebSWClientConnection.h:
* WebProcess/Storage/WebSWClientConnection.messages.in:

* WebProcess/Storage/WebSWOriginTable.cpp:
(WebKit::WebSWOriginTable::setSharedMemory):
* WebProcess/Storage/WebSWOriginTable.h:
(WebKit::WebSWOriginTable::isImported const):
(WebKit::WebSWOriginTable::setIsImported):
(WebKit::WebSWOriginTable::isInitialized const): Deleted.
(WebKit::WebSWOriginTable::initializeAsEmpty): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225717 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/workers/service/server/RegistrationStore.cpp
Source/WebCore/workers/service/server/SWOriginStore.h
Source/WebCore/workers/service/server/SWServer.cpp
Source/WebCore/workers/service/server/SWServer.h
Source/WebKit/ChangeLog
Source/WebKit/StorageProcess/ServiceWorker/WebSWOriginStore.cpp
Source/WebKit/StorageProcess/ServiceWorker/WebSWOriginStore.h
Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
Source/WebKit/WebProcess/Storage/WebSWClientConnection.h
Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in
Source/WebKit/WebProcess/Storage/WebSWOriginTable.cpp
Source/WebKit/WebProcess/Storage/WebSWOriginTable.h

index 817147f..2b78fdf 100644 (file)
@@ -1,3 +1,29 @@
+2017-12-08  Brady Eidson  <beidson@apple.com>
+
+        Delay some service worker operations until after the database import completes.
+        https://bugs.webkit.org/show_bug.cgi?id=180573
+
+        Reviewed by Chris Dumez.
+
+        No new tests (Not testable yet).
+
+        Right after the storage process launches it starts importing registration records.
+        During this time, a lot of the decisions we make regarding registrations, fetch, etc.
+        are invalid, as they rely on those in-memory records being in place.
+        
+        This patch delays certain things until after the initial origin table import is complete.
+        
+        * workers/service/server/RegistrationStore.cpp:
+        (WebCore::RegistrationStore::databaseOpenedAndRecordsImported):
+
+        * workers/service/server/SWOriginStore.h:
+
+        * workers/service/server/SWServer.cpp:
+        (WebCore::SWServer::registrationStoreImportComplete): Tell the origin store the initial
+          import was completed.
+        (WebCore::SWServer::addRegistrationFromStore):
+        * workers/service/server/SWServer.h:
+
 2017-12-08  Youenn Fablet  <youenn@apple.com>
 
         Service Worker should use a correct user agent
index dbbd888..f4f5446 100644 (file)
@@ -100,12 +100,12 @@ void RegistrationStore::addRegistrationFromDatabase(ServiceWorkerContextData&& c
 
 void RegistrationStore::databaseFailedToOpen()
 {
-    // FIXME: Handle error in some appropriate manner.
+    m_server.registrationStoreImportComplete();
 }
 
 void RegistrationStore::databaseOpenedAndRecordsImported()
 {
-    // FIXME: Once we actually do the imports, conclude the importing phase here.
+    m_server.registrationStoreImportComplete();
 }
 
 } // namespace WebCore
index 5847d35..e11e451 100644 (file)
@@ -45,6 +45,8 @@ public:
     void clear(const SecurityOrigin&);
     void clearAll();
 
+    virtual void importComplete() = 0;
+
 private:
     virtual void addToStore(const SecurityOrigin&) = 0;
     virtual void removeFromStore(const SecurityOrigin&) = 0;
index 8c70ef7..a332518 100644 (file)
@@ -98,8 +98,16 @@ SWServerRegistration* SWServer::getRegistration(const ServiceWorkerRegistrationK
     return m_registrations.get(registrationKey);
 }
 
+void SWServer::registrationStoreImportComplete()
+{
+    m_originStore->importComplete();
+}
+
 void SWServer::addRegistrationFromStore(ServiceWorkerContextData&& data)
 {
+    // Pages should not have been able to make a new registration to this key while the import was still taking place.
+    ASSERT(!m_registrations.contains(data.registration.key));
+
     addRegistration(std::make_unique<SWServerRegistration>(*this, data.registration.key, data.registration.updateViaCache, data.registration.scopeURL, data.scriptURL));
     tryInstallContextData(WTFMove(data));
 }
index 212af47..9a0dbed 100644 (file)
@@ -169,6 +169,7 @@ public:
     void resolveRegistrationReadyRequests(SWServerRegistration&);
 
     void addRegistrationFromStore(ServiceWorkerContextData&&);
+    void registrationStoreImportComplete();
 
 private:
     void registerConnection(Connection&);
index dbd70a0..1cf57d1 100644 (file)
@@ -1,3 +1,37 @@
+2017-12-08  Brady Eidson  <beidson@apple.com>
+
+        Delay some service worker operations until after the database import completes.
+        https://bugs.webkit.org/show_bug.cgi?id=180573
+
+        Reviewed by Chris Dumez.
+
+        * StorageProcess/ServiceWorker/WebSWOriginStore.cpp:
+        (WebKit::WebSWOriginStore::importComplete): Tell the Origin Table on all connects that
+          the import is complete.
+        (WebKit::WebSWOriginStore::registerSWServerConnection):
+        * StorageProcess/ServiceWorker/WebSWOriginStore.h:
+
+        * WebProcess/Storage/WebSWClientConnection.cpp:
+        (WebKit::WebSWClientConnection::mayHaveServiceWorkerRegisteredForOrigin const):
+        (WebKit::WebSWClientConnection::setSWOriginTableIsImported): Run deferred tasks!
+        (WebKit::WebSWClientConnection::matchRegistration): If the import isn't complete yet, delay
+          the match registration task until later.
+        (WebKit::WebSWClientConnection::runOrDelayTask): Either send the message now or save off
+          the task to wait until the import is complete.
+        (WebKit::WebSWClientConnection::getRegistrations): If the import isn't complete yet, delay
+          the get registrations task until later.
+        (WebKit::WebSWClientConnection::initializeSWOriginTableAsEmpty): Deleted.
+        * WebProcess/Storage/WebSWClientConnection.h:
+        * WebProcess/Storage/WebSWClientConnection.messages.in:
+
+        * WebProcess/Storage/WebSWOriginTable.cpp:
+        (WebKit::WebSWOriginTable::setSharedMemory):
+        * WebProcess/Storage/WebSWOriginTable.h:
+        (WebKit::WebSWOriginTable::isImported const):
+        (WebKit::WebSWOriginTable::setIsImported):
+        (WebKit::WebSWOriginTable::isInitialized const): Deleted.
+        (WebKit::WebSWOriginTable::initializeAsEmpty): Deleted.
+
 2017-12-08  Youenn Fablet  <youenn@apple.com>
 
         Service Worker should use a correct user agent
index 240b67f..9dcad94 100644 (file)
@@ -58,16 +58,22 @@ void WebSWOriginStore::clearStore()
     m_store.clear();
 }
 
+void WebSWOriginStore::importComplete()
+{
+    m_isImported = true;
+    for (auto* connection : m_webSWServerConnections)
+        connection->send(Messages::WebSWClientConnection::SetSWOriginTableIsImported());
+}
+
 void WebSWOriginStore::registerSWServerConnection(WebSWServerConnection& connection)
 {
     m_webSWServerConnections.add(&connection);
 
-    if (m_store.isEmpty()) {
-        connection.send(Messages::WebSWClientConnection::InitializeSWOriginTableAsEmpty());
-        return;
-    }
+    if (!m_store.isEmpty())
+        sendStoreHandle(connection);
 
-    sendStoreHandle(connection);
+    if (m_isImported)
+        connection.send(Messages::WebSWClientConnection::SetSWOriginTableIsImported());
 }
 
 void WebSWOriginStore::unregisterSWServerConnection(WebSWServerConnection& connection)
index a23fdf7..7f8c987 100644 (file)
@@ -45,6 +45,7 @@ public:
 
     void registerSWServerConnection(WebSWServerConnection&);
     void unregisterSWServerConnection(WebSWServerConnection&);
+    void importComplete() final;
 
 private:
     void sendStoreHandle(WebSWServerConnection&);
@@ -57,6 +58,7 @@ private:
     void didInvalidateSharedMemory() final;
 
     SharedStringHashStore m_store;
+    bool m_isImported { false };
     HashSet<WebSWServerConnection*> m_webSWServerConnections;
 };
 
index 080fbf4..4a2431d 100644 (file)
@@ -109,7 +109,7 @@ void WebSWClientConnection::didResolveRegistrationPromise(const ServiceWorkerReg
 
 bool WebSWClientConnection::mayHaveServiceWorkerRegisteredForOrigin(const SecurityOrigin& origin) const
 {
-    if (!m_swOriginTable->isInitialized())
+    if (!m_swOriginTable->isImported())
         return true;
 
     return m_swOriginTable->contains(origin);
@@ -120,9 +120,11 @@ void WebSWClientConnection::setSWOriginTableSharedMemory(const SharedMemory::Han
     m_swOriginTable->setSharedMemory(handle);
 }
 
-void WebSWClientConnection::initializeSWOriginTableAsEmpty()
+void WebSWClientConnection::setSWOriginTableIsImported()
 {
-    m_swOriginTable->initializeAsEmpty();
+    m_swOriginTable->setIsImported();
+    while (!m_tasksPendingOriginImport.isEmpty())
+        m_tasksPendingOriginImport.takeFirst()();
 }
 
 void WebSWClientConnection::didMatchRegistration(uint64_t matchingRequest, std::optional<ServiceWorkerRegistrationData>&& result)
@@ -150,9 +152,19 @@ void WebSWClientConnection::matchRegistration(const SecurityOrigin& topOrigin, c
         return;
     }
 
-    uint64_t callbackID = ++m_previousCallbackIdentifier;
-    m_ongoingMatchRegistrationTasks.add(callbackID, WTFMove(callback));
-    send(Messages::WebSWServerConnection::MatchRegistration(callbackID, SecurityOriginData::fromSecurityOrigin(topOrigin), clientURL));
+    runOrDelayTaskForImport([this, callback = WTFMove(callback), topOrigin = SecurityOriginData::fromSecurityOrigin(topOrigin), clientURL]() mutable {
+        uint64_t callbackID = ++m_previousCallbackIdentifier;
+        m_ongoingMatchRegistrationTasks.add(callbackID, WTFMove(callback));
+        send(Messages::WebSWServerConnection::MatchRegistration(callbackID, topOrigin, clientURL));
+    });
+}
+
+void WebSWClientConnection::runOrDelayTaskForImport(WTF::Function<void()>&& task)
+{
+    if (m_swOriginTable->isImported())
+        task();
+    else
+        m_tasksPendingOriginImport.append(WTFMove(task));
 }
 
 void WebSWClientConnection::whenRegistrationReady(const SecurityOrigin& topOrigin, const URL& clientURL, WhenRegistrationReadyCallback&& callback)
@@ -178,9 +190,11 @@ void WebSWClientConnection::getRegistrations(const SecurityOrigin& topOrigin, co
         return;
     }
 
-    uint64_t callbackID = ++m_previousCallbackIdentifier;
-    m_ongoingGetRegistrationsTasks.add(callbackID, WTFMove(callback));
-    send(Messages::WebSWServerConnection::GetRegistrations(callbackID, SecurityOriginData::fromSecurityOrigin(topOrigin), clientURL));
+    runOrDelayTaskForImport([this, callback = WTFMove(callback), topOrigin = SecurityOriginData::fromSecurityOrigin(topOrigin), clientURL]() mutable {
+        uint64_t callbackID = ++m_previousCallbackIdentifier;
+        m_ongoingGetRegistrationsTasks.add(callbackID, WTFMove(callback));
+        send(Messages::WebSWServerConnection::GetRegistrations(callbackID, topOrigin, clientURL));
+    });
 }
 
 void WebSWClientConnection::startFetch(const ResourceLoader& loader, uint64_t identifier)
index ca37d20..8ff94de 100644 (file)
@@ -90,11 +90,13 @@ private:
 
     void scheduleStorageJob(const WebCore::ServiceWorkerJobData&);
 
+    void runOrDelayTaskForImport(WTF::Function<void()>&& task);
+
     IPC::Connection* messageSenderConnection() final { return m_connection.ptr(); }
     uint64_t messageSenderDestinationID() final { return m_identifier.toUInt64(); }
 
     void setSWOriginTableSharedMemory(const SharedMemory::Handle&);
-    void initializeSWOriginTableAsEmpty();
+    void setSWOriginTableIsImported();
 
     PAL::SessionID m_sessionID;
     WebCore::SWServerConnectionIdentifier m_identifier;
@@ -106,6 +108,7 @@ private:
     HashMap<uint64_t, RegistrationCallback> m_ongoingMatchRegistrationTasks;
     HashMap<uint64_t, GetRegistrationsCallback> m_ongoingGetRegistrationsTasks;
     HashMap<uint64_t, WhenRegistrationReadyCallback> m_ongoingRegistrationReadyTasks;
+    Deque<WTF::Function<void()>> m_tasksPendingOriginImport;
 
 }; // class WebSWServerConnection
 
index 10217e2..0b2d35f 100644 (file)
@@ -33,7 +33,7 @@ messages -> WebSWClientConnection {
     FireUpdateFoundEvent(WebCore::ServiceWorkerRegistrationIdentifier identifier)
     NotifyClientsOfControllerChange(HashSet<WebCore::DocumentIdentifier> contextIdentifiers, struct WebCore::ServiceWorkerData newController)
 
-    InitializeSWOriginTableAsEmpty()
+    SetSWOriginTableIsImported()
     SetSWOriginTableSharedMemory(WebKit::SharedMemory::Handle handle)
     PostMessageToServiceWorkerClient(WebCore::DocumentIdentifier destinationContextIdentifier, IPC::DataReference message, struct WebCore::ServiceWorkerData source, String sourceOrigin)
 
index 09b86cb..028614d 100644 (file)
@@ -44,8 +44,6 @@ bool WebSWOriginTable::contains(const SecurityOrigin& origin) const
 
 void WebSWOriginTable::setSharedMemory(const SharedMemory::Handle& handle)
 {
-    m_isInitialized = true;
-
     auto sharedMemory = SharedMemory::map(handle, SharedMemory::Protection::ReadOnly);
     if (!sharedMemory)
         return;
index aee3cf1..86a93ec 100644 (file)
@@ -40,14 +40,14 @@ class WebSWOriginTable {
 public:
     WebSWOriginTable() = default;
 
-    bool isInitialized() const { return m_isInitialized; }
+    bool isImported() const { return m_isImported; }
+    void setIsImported() { m_isImported = true; }
     bool contains(const WebCore::SecurityOrigin&) const;
     void setSharedMemory(const SharedMemory::Handle&);
-    void initializeAsEmpty() { m_isInitialized = true; }
 
 private:
     SharedStringHashTableReadOnly m_serviceWorkerOriginTable;
-    bool m_isInitialized { false };
+    bool m_isImported { false };
 };
 
 } // namespace WebKit