Title: [225610] trunk/Source/WebCore
Revision
225610
Author
beid...@apple.com
Date
2017-12-06 16:41:14 -0800 (Wed, 06 Dec 2017)

Log Message

Start writing ServiceWorker registrations to disk.
https://bugs.webkit.org/show_bug.cgi?id=180488

Reviewed by Chris Dumez.

No new tests (No observable behavior change).

As registrations changes occurs, we now write them to disk.
We don't re-read them in yet.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:

* workers/service/ServiceWorkerRegistrationData.cpp:
(WebCore::ServiceWorkerRegistrationData::isolatedCopy const):
* workers/service/ServiceWorkerRegistrationData.h:
(WebCore::ServiceWorkerRegistrationData::encode const):
(WebCore::ServiceWorkerRegistrationData::decode):

* workers/service/ServiceWorkerRegistrationKey.cpp:
(WebCore::ServiceWorkerRegistrationKey::toDatabaseKey const):
* workers/service/ServiceWorkerRegistrationKey.h:

* workers/service/server/RegistrationDatabase.cpp: Added.
(WebCore::v1RecordsTableSchema):
(WebCore::v1RecordsTableSchemaAlternate):
(WebCore::databaseFilename):
(WebCore::RegistrationDatabase::RegistrationDatabase):
(WebCore::RegistrationDatabase::~RegistrationDatabase):
(WebCore::RegistrationDatabase::openSQLiteDatabase):
(WebCore::RegistrationDatabase::ensureValidRecordsTable):
(WebCore::updateViaCacheToString):
(WebCore::workerTypeToString):
(WebCore::RegistrationDatabase::pushChanges):
(WebCore::RegistrationDatabase::doPushChanges):
(WebCore::RegistrationDatabase::importRecords):
(WebCore::RegistrationDatabase::databaseFailedToOpen):
(WebCore::RegistrationDatabase::databaseOpenedAndRecordsImported):
* workers/service/server/RegistrationDatabase.h: Copied from Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp.
(WebCore::RegistrationDatabase::isClosed const):

* workers/service/server/RegistrationStore.cpp: Added.
(WebCore::RegistrationStore::RegistrationStore):
(WebCore::RegistrationStore::~RegistrationStore):
(WebCore::RegistrationStore::scheduleDatabasePushIfNecessary):
(WebCore::RegistrationStore::pushChangesToDatabase):
(WebCore::RegistrationStore::updateRegistration):
(WebCore::RegistrationStore::removeRegistration):
(WebCore::RegistrationStore::databaseFailedToOpen):
(WebCore::RegistrationStore::databaseOpenedAndRecordsImported):
* workers/service/server/RegistrationStore.h: Copied from Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp.

* workers/service/server/SWServer.cpp:
(WebCore::SWServer::removeRegistration):
(WebCore::SWServer::SWServer):
(WebCore::SWServer::updateWorker):
(WebCore::SWServer::installContextData):
* workers/service/server/SWServer.h:

* workers/service/server/SWServerRegistration.cpp:
(WebCore::SWServerRegistration::data const):
* workers/service/server/SWServerRegistration.h:
(WebCore::SWServerRegistration::setLastUpdateTime):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (225609 => 225610)


--- trunk/Source/WebCore/ChangeLog	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/ChangeLog	2017-12-07 00:41:14 UTC (rev 225610)
@@ -1,3 +1,69 @@
+2017-12-06  Brady Eidson  <beid...@apple.com>
+
+        Start writing ServiceWorker registrations to disk.
+        https://bugs.webkit.org/show_bug.cgi?id=180488
+
+        Reviewed by Chris Dumez.
+
+        No new tests (No observable behavior change).
+
+        As registrations changes occurs, we now write them to disk.
+        We don't re-read them in yet.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * workers/service/ServiceWorkerRegistrationData.cpp:
+        (WebCore::ServiceWorkerRegistrationData::isolatedCopy const):
+        * workers/service/ServiceWorkerRegistrationData.h:
+        (WebCore::ServiceWorkerRegistrationData::encode const):
+        (WebCore::ServiceWorkerRegistrationData::decode):
+
+        * workers/service/ServiceWorkerRegistrationKey.cpp:
+        (WebCore::ServiceWorkerRegistrationKey::toDatabaseKey const):
+        * workers/service/ServiceWorkerRegistrationKey.h:
+
+        * workers/service/server/RegistrationDatabase.cpp: Added.
+        (WebCore::v1RecordsTableSchema):
+        (WebCore::v1RecordsTableSchemaAlternate):
+        (WebCore::databaseFilename):
+        (WebCore::RegistrationDatabase::RegistrationDatabase):
+        (WebCore::RegistrationDatabase::~RegistrationDatabase):
+        (WebCore::RegistrationDatabase::openSQLiteDatabase):
+        (WebCore::RegistrationDatabase::ensureValidRecordsTable):
+        (WebCore::updateViaCacheToString):
+        (WebCore::workerTypeToString):
+        (WebCore::RegistrationDatabase::pushChanges):
+        (WebCore::RegistrationDatabase::doPushChanges):
+        (WebCore::RegistrationDatabase::importRecords):
+        (WebCore::RegistrationDatabase::databaseFailedToOpen):
+        (WebCore::RegistrationDatabase::databaseOpenedAndRecordsImported):
+        * workers/service/server/RegistrationDatabase.h: Copied from Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp.
+        (WebCore::RegistrationDatabase::isClosed const):
+
+        * workers/service/server/RegistrationStore.cpp: Added.
+        (WebCore::RegistrationStore::RegistrationStore):
+        (WebCore::RegistrationStore::~RegistrationStore):
+        (WebCore::RegistrationStore::scheduleDatabasePushIfNecessary):
+        (WebCore::RegistrationStore::pushChangesToDatabase):
+        (WebCore::RegistrationStore::updateRegistration):
+        (WebCore::RegistrationStore::removeRegistration):
+        (WebCore::RegistrationStore::databaseFailedToOpen):
+        (WebCore::RegistrationStore::databaseOpenedAndRecordsImported):
+        * workers/service/server/RegistrationStore.h: Copied from Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp.
+
+        * workers/service/server/SWServer.cpp:
+        (WebCore::SWServer::removeRegistration):
+        (WebCore::SWServer::SWServer):
+        (WebCore::SWServer::updateWorker):
+        (WebCore::SWServer::installContextData):
+        * workers/service/server/SWServer.h:
+
+        * workers/service/server/SWServerRegistration.cpp:
+        (WebCore::SWServerRegistration::data const):
+        * workers/service/server/SWServerRegistration.h:
+        (WebCore::SWServerRegistration::setLastUpdateTime):
+
 2017-12-06  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, fix build after r225577.

Modified: trunk/Source/WebCore/Sources.txt (225609 => 225610)


--- trunk/Source/WebCore/Sources.txt	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/Sources.txt	2017-12-07 00:41:14 UTC (rev 225610)
@@ -2212,6 +2212,8 @@
 workers/service/context/ServiceWorkerThreadProxy.cpp
 workers/service/context/SWContextManager.cpp
 
+workers/service/server/RegistrationDatabase.cpp
+workers/service/server/RegistrationStore.cpp
 workers/service/server/SWOriginStore.cpp
 workers/service/server/SWServer.cpp
 workers/service/server/SWServerJobQueue.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (225609 => 225610)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-12-07 00:41:14 UTC (rev 225610)
@@ -1405,6 +1405,8 @@
 		51AF503616F100F60095B2E8 /* ResourceLoaderTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 51AF503516F100F60095B2E8 /* ResourceLoaderTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51B454EA1B4DAE7D0085EAA6 /* PingHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 51B454E91B4DAE7D0085EAA6 /* PingHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51B45D211AB8D1E200117CD2 /* ContentExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 51B45D1F1AB8D1E200117CD2 /* ContentExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		51B914101FD2782D00EE2859 /* RegistrationDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 51B9140C1FD2782500EE2859 /* RegistrationDatabase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		51B914111FD2782D00EE2859 /* RegistrationStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51B9140B1FD2782500EE2859 /* RegistrationStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51BA4AC41BBB5CD800DF3D6D /* IDBDatabaseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA4AC21BBB5CBF00DF3D6D /* IDBDatabaseInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51BA4ACB1BBC5BD900DF3D6D /* MemoryIDBBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA4AC91BBC5B9E00DF3D6D /* MemoryIDBBackingStore.h */; };
 		51BA4ACC1BBC5BDD00DF3D6D /* IDBBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51BA4AC71BBC5AD600DF3D6D /* IDBBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7775,6 +7777,10 @@
 		51B454E91B4DAE7D0085EAA6 /* PingHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PingHandle.h; sourceTree = "<group>"; };
 		51B45D1E1AB8D1E200117CD2 /* ContentExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtension.cpp; sourceTree = "<group>"; };
 		51B45D1F1AB8D1E200117CD2 /* ContentExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtension.h; sourceTree = "<group>"; };
+		51B9140B1FD2782500EE2859 /* RegistrationStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationStore.h; sourceTree = "<group>"; };
+		51B9140C1FD2782500EE2859 /* RegistrationDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationDatabase.h; sourceTree = "<group>"; };
+		51B9140D1FD2782500EE2859 /* RegistrationDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegistrationDatabase.cpp; sourceTree = "<group>"; };
+		51B9140E1FD2782500EE2859 /* RegistrationStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegistrationStore.cpp; sourceTree = "<group>"; };
 		51BA4AC11BBB5CBF00DF3D6D /* IDBDatabaseInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBDatabaseInfo.cpp; sourceTree = "<group>"; };
 		51BA4AC21BBB5CBF00DF3D6D /* IDBDatabaseInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBDatabaseInfo.h; sourceTree = "<group>"; };
 		51BA4AC71BBC5AD600DF3D6D /* IDBBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBBackingStore.h; sourceTree = "<group>"; };
@@ -17156,6 +17162,10 @@
 		517A52EC1F47532D00DCDC0A /* server */ = {
 			isa = PBXGroup;
 			children = (
+				51B9140D1FD2782500EE2859 /* RegistrationDatabase.cpp */,
+				51B9140C1FD2782500EE2859 /* RegistrationDatabase.h */,
+				51B9140E1FD2782500EE2859 /* RegistrationStore.cpp */,
+				51B9140B1FD2782500EE2859 /* RegistrationStore.h */,
 				4151E5B91FBA4C7600E47E2D /* SWOriginStore.cpp */,
 				4151E5B71FBA4C7500E47E2D /* SWOriginStore.h */,
 				517A52EF1F47535900DCDC0A /* SWServer.cpp */,
@@ -28688,6 +28698,8 @@
 				BCAB418213E356E800D8AAF3 /* Region.h in Headers */,
 				26B9998F1803AE7200D01121 /* RegisterAllocator.h in Headers */,
 				85031B4C0A44EFC700F992E0 /* RegisteredEventListener.h in Headers */,
+				51B914101FD2782D00EE2859 /* RegistrationDatabase.h in Headers */,
+				51B914111FD2782D00EE2859 /* RegistrationStore.h in Headers */,
 				A578F43F1DE0B630003DFC6A /* RejectedPromiseTracker.h in Headers */,
 				CDFC360618CA61C20026E56F /* RemoteCommandListener.h in Headers */,
 				CD8ACA891D237AA200ECC59E /* RemoteCommandListenerMac.h in Headers */,

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp (225609 => 225610)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -37,6 +37,7 @@
         identifier,
         scopeURL.isolatedCopy(),
         updateViaCache,
+        lastUpdateTime,
         installingWorker ? std::optional<ServiceWorkerData>(installingWorker->isolatedCopy()) : std::nullopt,
         waitingWorker ? std::optional<ServiceWorkerData>(waitingWorker->isolatedCopy()) : std::nullopt,
         activeWorker ? std::optional<ServiceWorkerData>(activeWorker->isolatedCopy()) : std::nullopt,

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.h (225609 => 225610)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.h	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -32,6 +32,7 @@
 #include "ServiceWorkerRegistrationKey.h"
 #include "ServiceWorkerTypes.h"
 #include "ServiceWorkerUpdateViaCache.h"
+#include <wtf/WallTime.h>
 
 namespace WebCore {
 
@@ -42,6 +43,7 @@
     ServiceWorkerRegistrationIdentifier identifier;
     URL scopeURL;
     ServiceWorkerUpdateViaCache updateViaCache;
+    WallTime lastUpdateTime;
 
     std::optional<ServiceWorkerData> installingWorker;
     std::optional<ServiceWorkerData> waitingWorker;
@@ -57,7 +59,7 @@
 template<class Encoder>
 void ServiceWorkerRegistrationData::encode(Encoder& encoder) const
 {
-    encoder << key << identifier << scopeURL << updateViaCache << installingWorker << waitingWorker << activeWorker;
+    encoder << key << identifier << scopeURL << updateViaCache << lastUpdateTime.secondsSinceEpoch().value() << installingWorker << waitingWorker << activeWorker;
 }
 
 template<class Decoder>
@@ -83,6 +85,11 @@
     if (!updateViaCache)
         return std::nullopt;
 
+    std::optional<double> rawWallTime;
+    decoder >> rawWallTime;
+    if (!rawWallTime)
+        return std::nullopt;
+
     std::optional<std::optional<ServiceWorkerData>> installingWorker;
     decoder >> installingWorker;
     if (!installingWorker)
@@ -98,7 +105,7 @@
     if (!activeWorker)
         return std::nullopt;
 
-    return { { WTFMove(*key), WTFMove(*identifier), WTFMove(*scopeURL), WTFMove(*updateViaCache), WTFMove(*installingWorker), WTFMove(*waitingWorker), WTFMove(*activeWorker) } };
+    return { { WTFMove(*key), WTFMove(*identifier), WTFMove(*scopeURL), WTFMove(*updateViaCache), WallTime::fromRawSeconds(*rawWallTime), WTFMove(*installingWorker), WTFMove(*waitingWorker), WTFMove(*activeWorker) } };
 }
 
 } // namespace WTF

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp (225609 => 225610)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -76,6 +76,13 @@
     return protocolHostAndPortAreEqual(clientURL, m_scope);
 }
 
+static const char separatorCharacter = '_';
+
+String ServiceWorkerRegistrationKey::toDatabaseKey() const
+{
+    return makeString(m_topOrigin.protocol, separatorCharacter, m_topOrigin.host, separatorCharacter, m_topOrigin.port.value_or(0), separatorCharacter, m_scope.path());
+}
+
 #ifndef NDEBUG
 String ServiceWorkerRegistrationKey::loggingString() const
 {

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h (225609 => 225610)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -54,6 +54,8 @@
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<ServiceWorkerRegistrationKey> decode(Decoder&);
 
+    String toDatabaseKey() const;
+
 #ifndef NDEBUG
     String loggingString() const;
 #endif

Added: trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp (0 => 225610)


--- trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp	                        (rev 0)
+++ trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RegistrationDatabase.h"
+
+#if ENABLE(SERVICE_WORKER)
+
+#include "FileSystem.h"
+#include "Logging.h"
+#include "RegistrationStore.h"
+#include "SQLiteDatabase.h"
+#include "SQLiteStatement.h"
+#include "SQLiteTransaction.h"
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Scope.h>
+
+namespace WebCore {
+
+static const String v1RecordsTableSchema(const String& tableName)
+{
+    return makeString("CREATE TABLE ", tableName, " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, origin TEXT NOT NULL ON CONFLICT FAIL, scopeURL TEXT NOT NULL ON CONFLICT FAIL, topOrigin TEXT NOT NULL ON CONFLICT FAIL, lastUpdateCheckTime DOUBLE NOT NULL ON CONFLICT FAIL, updateViaCache TEXT NOT NULL ON CONFLICT FAIL, scriptURL TEXT NOT NULL ON CONFLICT FAIL, script TEXT NOT NULL ON CONFLICT FAIL, workerType TEXT NOT NULL ON CONFLICT FAIL)");
+}
+
+static const String v1RecordsTableSchema()
+{
+    static NeverDestroyed<WTF::String> schema(v1RecordsTableSchema("Records"));
+    return schema;
+}
+
+static const String v1RecordsTableSchemaAlternate()
+{
+    static NeverDestroyed<WTF::String> schema(v1RecordsTableSchema("\"Records\""));
+    return schema;
+}
+
+static const String& databaseFilename()
+{
+    static NeverDestroyed<String> filename = "ServiceWorkerRegistrations.sqlite3";
+    return filename;
+}
+
+RegistrationDatabase::RegistrationDatabase(RegistrationStore& store, const String& databaseDirectory)
+    : CrossThreadTaskHandler("ServiceWorker I/O Thread")
+    , m_store(store)
+    , m_databaseDirectory(databaseDirectory)
+{
+    ASSERT(isMainThread());
+
+    postTask(createCrossThreadTask(*this, &RegistrationDatabase::openSQLiteDatabase, FileSystem::pathByAppendingComponent(m_databaseDirectory, databaseFilename())));
+}
+
+RegistrationDatabase::~RegistrationDatabase()
+{
+    ASSERT(!m_database);
+    ASSERT(isMainThread());
+}
+
+void RegistrationDatabase::openSQLiteDatabase(const String& fullFilename)
+{
+    ASSERT(!isMainThread());
+    ASSERT(!m_database);
+
+    LOG(ServiceWorker, "ServiceWorker RegistrationDatabase opening file %s", fullFilename.utf8().data());
+
+    String errorMessage;
+    auto scopeExit = makeScopeExit([&, errorMessage = &errorMessage] {
+        ASSERT(!errorMessage->isNull());
+        LOG_ERROR("Failed to open Service Worker registration database: %s", errorMessage->utf8().data());
+        m_database = nullptr;
+        postTaskReply(createCrossThreadTask(*this, &RegistrationDatabase::databaseFailedToOpen));
+    });
+    
+    m_database = std::make_unique<SQLiteDatabase>();
+    if (!m_database->open(fullFilename)) {
+        errorMessage = "Failed to open registration database";
+        return;
+    }
+    
+    errorMessage = ensureValidRecordsTable();
+    if (!errorMessage.isNull())
+        return;
+    
+    errorMessage = importRecords();
+    if (!errorMessage.isNull())
+        return;
+    
+    scopeExit.release();
+    postTaskReply(createCrossThreadTask(*this, &RegistrationDatabase::databaseOpenedAndRecordsImported));
+}
+
+String RegistrationDatabase::ensureValidRecordsTable()
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_database);
+    ASSERT(m_database->isOpen());
+
+    String currentSchema;
+    {
+        // Fetch the schema for an existing records table.
+        SQLiteStatement statement(*m_database, "SELECT type, sql FROM sqlite_master WHERE tbl_name='Records'");
+        if (statement.prepare() != SQLITE_OK)
+            return "Unable to prepare statement to fetch schema for the Records table.";
+
+        int sqliteResult = statement.step();
+
+        // If there is no Records table at all, create it and then bail.
+        if (sqliteResult == SQLITE_DONE) {
+            if (!m_database->executeCommand(v1RecordsTableSchema()))
+                return String::format("Could not create Records table in database (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+            return { };
+        }
+
+        if (sqliteResult != SQLITE_ROW)
+            return "Error executing statement to fetch schema for the Records table.";
+
+        currentSchema = statement.getColumnText(1);
+    }
+
+    ASSERT(!currentSchema.isEmpty());
+    
+    if (currentSchema == v1RecordsTableSchema() || currentSchema == v1RecordsTableSchemaAlternate())
+        return { };
+
+    // This database has a Records table but it is not a schema we expect.
+    // Trying to recover by deleting the data contained within is dangerous so
+    // we should consider this an unrecoverable error.
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static String updateViaCacheToString(ServiceWorkerUpdateViaCache update)
+{
+    switch (update) {
+    case ServiceWorkerUpdateViaCache::Imports:
+        return "Imports";
+    case ServiceWorkerUpdateViaCache::All:
+        return "All";
+    case ServiceWorkerUpdateViaCache::None:
+        return "None";
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static String workerTypeToString(WorkerType workerType)
+{
+    switch (workerType) {
+    case WorkerType::Classic:
+        return "Classic";
+    case WorkerType::Module:
+        return "Module";
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void RegistrationDatabase::pushChanges(Vector<ServiceWorkerContextData>&& datas)
+{
+    postTask(createCrossThreadTask(*this, &RegistrationDatabase::doPushChanges, datas));
+}
+
+void RegistrationDatabase::doPushChanges(Vector<ServiceWorkerContextData>&& datas)
+{
+    ASSERT(m_database);
+
+    SQLiteTransaction transaction(*m_database);
+    transaction.begin();
+
+    SQLiteStatement sql(*m_database, ASCIILiteral("INSERT INTO Records VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+    if (sql.prepare() != SQLITE_OK) {
+        LOG_ERROR("Failed to prepared statement to store registration data into records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+        return;
+    }
+
+    for (auto& data : datas) {
+        if (data.registration.identifier == ServiceWorkerRegistrationIdentifier()) {
+            SQLiteStatement sql(*m_database, "DELETE FROM Records WHERE key = ?");
+            if (sql.prepare() != SQLITE_OK
+                || sql.bindText(1, data.registration.key.toDatabaseKey()) != SQLITE_OK
+                || sql.step() != SQLITE_DONE) {
+                LOG_ERROR("Failed to remove registration data from records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+                return;
+            }
+
+            continue;
+        }
+
+        if (sql.bindText(1, data.registration.key.toDatabaseKey()) != SQLITE_OK
+            || sql.bindText(2, data.registration.scopeURL.protocolHostAndPort()) != SQLITE_OK
+            || sql.bindText(3, data.registration.scopeURL.path()) != SQLITE_OK
+            || sql.bindText(4, data.registration.key.topOrigin().databaseIdentifier()) != SQLITE_OK
+            || sql.bindDouble(5, data.registration.lastUpdateTime.secondsSinceEpoch().value()) != SQLITE_OK
+            || sql.bindText(6, updateViaCacheToString(data.registration.updateViaCache)) != SQLITE_OK
+            || sql.bindText(7, data.scriptURL.string()) != SQLITE_OK
+            || sql.bindText(8, data.script) != SQLITE_OK
+            || sql.bindText(9, workerTypeToString(data.workerType)) != SQLITE_OK
+            || sql.step() != SQLITE_DONE) {
+            LOG_ERROR("Failed to store registration data into records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+            return;
+        }
+    }
+
+    transaction.commit();
+
+    LOG(ServiceWorker, "Pushed %zu changes to ServiceWorker registration database", datas.size());
+}
+
+String RegistrationDatabase::importRecords()
+{
+    ASSERT(!isMainThread());
+    // FIXME: Implement
+    return { };
+}
+
+void RegistrationDatabase::databaseFailedToOpen()
+{
+    m_store.databaseFailedToOpen();
+}
+
+void RegistrationDatabase::databaseOpenedAndRecordsImported()
+{
+    m_store.databaseOpenedAndRecordsImported();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_WORKER)

Copied: trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h (from rev 225608, trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp) (0 => 225610)


--- trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h	                        (rev 0)
+++ trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SERVICE_WORKER)
+
+#include <wtf/CrossThreadTaskHandler.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class RegistrationStore;
+class SQLiteDatabase;
+struct ServiceWorkerContextData;
+
+class RegistrationDatabase : public CrossThreadTaskHandler {
+WTF_MAKE_FAST_ALLOCATED;
+public:
+    RegistrationDatabase(RegistrationStore&, const String& databaseDirectory);
+    ~RegistrationDatabase();
+
+    bool isClosed() const { return !m_database; }
+
+    void pushChanges(Vector<ServiceWorkerContextData>&&);
+
+private:
+    // Methods to be run on the task thread
+    void openSQLiteDatabase(const String& fullFilename);
+    String ensureValidRecordsTable();
+    String importRecords();
+    void doPushChanges(Vector<ServiceWorkerContextData>&&);
+    
+    // Replies to the main thread
+    void databaseFailedToOpen();
+    void databaseOpenedAndRecordsImported(); 
+
+    RegistrationStore& m_store;
+    String m_databaseDirectory;
+    std::unique_ptr<SQLiteDatabase> m_database;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_WORKER)

Added: trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp (0 => 225610)


--- trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp	                        (rev 0)
+++ trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RegistrationStore.h"
+
+#if ENABLE(SERVICE_WORKER)
+
+#include "SWServerRegistration.h"
+
+namespace WebCore {
+
+RegistrationStore::RegistrationStore(const String& databaseDirectory)
+    : m_database(*this, databaseDirectory)
+    , m_databasePushTimer(*this, &RegistrationStore::pushChangesToDatabase)
+{
+}
+
+RegistrationStore::~RegistrationStore()
+{
+    ASSERT(m_database.isClosed());
+}
+
+void RegistrationStore::scheduleDatabasePushIfNecessary()
+{
+    if (m_databasePushTimer.isActive())
+        return;
+    m_databasePushTimer.startOneShot(0_s);
+}
+
+void RegistrationStore::pushChangesToDatabase()
+{
+    Vector<ServiceWorkerContextData> changesToPush;
+    changesToPush.reserveInitialCapacity(m_updatedRegistrations.size());
+    for (auto& value : m_updatedRegistrations.values())
+        changesToPush.uncheckedAppend(WTFMove(value));
+
+    m_updatedRegistrations.clear();
+    m_database.pushChanges(WTFMove(changesToPush));
+}
+
+void RegistrationStore::updateRegistration(const ServiceWorkerContextData& data)
+{
+    m_updatedRegistrations.set(data.registration.key, data);
+    scheduleDatabasePushIfNecessary();
+}
+
+void RegistrationStore::removeRegistration(SWServerRegistration& registration)
+{
+    ServiceWorkerContextData contextData;
+    contextData.registration.key = registration.key();
+    m_updatedRegistrations.set(registration.key(), WTFMove(contextData));
+    scheduleDatabasePushIfNecessary();
+}
+
+void RegistrationStore::databaseFailedToOpen()
+{
+    // FIXME: Handle error in some appropriate manner.
+}
+
+void RegistrationStore::databaseOpenedAndRecordsImported()
+{
+    // FIXME: Once we actually do the imports, conclude the importing phase here.
+}
+    
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_WORKER)

Copied: trunk/Source/WebCore/workers/service/server/RegistrationStore.h (from rev 225608, trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationData.cpp) (0 => 225610)


--- trunk/Source/WebCore/workers/service/server/RegistrationStore.h	                        (rev 0)
+++ trunk/Source/WebCore/workers/service/server/RegistrationStore.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SERVICE_WORKER)
+
+#include "RegistrationDatabase.h"
+#include "ServiceWorkerContextData.h"
+#include "ServiceWorkerRegistrationData.h"
+#include "ServiceWorkerRegistrationKey.h"
+#include "Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class SWServerRegistration;
+
+class RegistrationStore {
+WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit RegistrationStore(const String& databaseDirectory);
+    ~RegistrationStore();
+
+    // Callbacks from the SWServer
+    void updateRegistration(const ServiceWorkerContextData&);
+    void removeRegistration(SWServerRegistration&);
+
+    // Callbacks from the database
+    void databaseFailedToOpen();
+    void databaseOpenedAndRecordsImported();
+
+private:
+    void scheduleDatabasePushIfNecessary();
+    void pushChangesToDatabase();
+
+    RegistrationDatabase m_database;
+
+    HashMap<ServiceWorkerRegistrationKey, ServiceWorkerContextData> m_updatedRegistrations;
+    Timer m_databasePushTimer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_WORKER)

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


--- trunk/Source/WebCore/workers/service/server/SWServer.cpp	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -31,6 +31,7 @@
 #include "ExceptionCode.h"
 #include "ExceptionData.h"
 #include "Logging.h"
+#include "RegistrationStore.h"
 #include "SWOriginStore.h"
 #include "SWServerJobQueue.h"
 #include "SWServerRegistration.h"
@@ -124,6 +125,7 @@
     ASSERT_UNUSED(wasRemoved, wasRemoved);
 
     m_originStore->remove(topOrigin);
+    m_registrationStore.removeRegistration(*registration);
 }
 
 Vector<ServiceWorkerRegistrationData> SWServer::getRegistrations(const SecurityOriginData& topOrigin, const URL& clientURL)
@@ -196,6 +198,7 @@
 
 SWServer::SWServer(UniqueRef<SWOriginStore>&& originStore, const String& registrationDatabaseDirectory)
     : m_originStore(WTFMove(originStore))
+    , m_registrationStore(registrationDatabaseDirectory)
 {
     UNUSED_PARAM(registrationDatabaseDirectory);
     allServers().add(this);
@@ -401,9 +404,9 @@
 
 void SWServer::updateWorker(Connection&, const ServiceWorkerJobDataIdentifier& jobDataIdentifier, SWServerRegistration& registration, const URL& url, const String& script, WorkerType type)
 {
-    auto serviceWorkerIdentifier = generateServiceWorkerIdentifier();
+    registration.setLastUpdateTime(WallTime::now());
 
-    ServiceWorkerContextData data = { jobDataIdentifier, registration.data(), serviceWorkerIdentifier, script, url, type };
+    ServiceWorkerContextData data = { jobDataIdentifier, registration.data(), generateServiceWorkerIdentifier(), script, url, type };
 
     // Right now we only ever keep up to one connection to one SW context process.
     // And it should always exist if we're calling updateWorker
@@ -427,6 +430,8 @@
 
 void SWServer::installContextData(const ServiceWorkerContextData& data)
 {
+    m_registrationStore.updateRegistration(data);
+
     auto* connection = SWServerToContextConnection::globalServerToContextConnection();
     ASSERT(connection);
 

Modified: trunk/Source/WebCore/workers/service/server/SWServer.h (225609 => 225610)


--- trunk/Source/WebCore/workers/service/server/SWServer.h	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -29,6 +29,7 @@
 
 #include "ClientOrigin.h"
 #include "DocumentIdentifier.h"
+#include "RegistrationStore.h"
 #include "SWServerWorker.h"
 #include "ServiceWorkerClientData.h"
 #include "ServiceWorkerIdentifier.h"
@@ -213,6 +214,7 @@
     Lock m_mainThreadReplyLock;
     bool m_mainThreadReplyScheduled { false };
     UniqueRef<SWOriginStore> m_originStore;
+    RegistrationStore m_registrationStore;
     Deque<ServiceWorkerContextData> m_pendingContextDatas;
 };
 

Modified: trunk/Source/WebCore/workers/service/server/SWServerRegistration.cpp (225609 => 225610)


--- trunk/Source/WebCore/workers/service/server/SWServerRegistration.cpp	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/server/SWServerRegistration.cpp	2017-12-07 00:41:14 UTC (rev 225610)
@@ -131,7 +131,7 @@
     if (m_activeWorker)
         activeWorkerData = m_activeWorker->data();
 
-    return { m_registrationKey, identifier(), m_scopeURL, m_updateViaCache, WTFMove(installingWorkerData), WTFMove(waitingWorkerData), WTFMove(activeWorkerData) };
+    return { m_registrationKey, identifier(), m_scopeURL, m_updateViaCache, m_lastUpdateTime, WTFMove(installingWorkerData), WTFMove(waitingWorkerData), WTFMove(activeWorkerData) };
 }
 
 void SWServerRegistration::addClientServiceWorkerRegistration(SWServerConnectionIdentifier connectionIdentifier)

Modified: trunk/Source/WebCore/workers/service/server/SWServerRegistration.h (225609 => 225610)


--- trunk/Source/WebCore/workers/service/server/SWServerRegistration.h	2017-12-07 00:40:17 UTC (rev 225609)
+++ trunk/Source/WebCore/workers/service/server/SWServerRegistration.h	2017-12-07 00:41:14 UTC (rev 225610)
@@ -33,6 +33,7 @@
 #include "ServiceWorkerTypes.h"
 #include <wtf/HashCountedSet.h>
 #include <wtf/MonotonicTime.h>
+#include <wtf/WallTime.h>
 
 namespace WebCore {
 
@@ -58,7 +59,7 @@
     bool isUninstalling() const { return m_uninstalling; }
     void setIsUninstalling(bool);
 
-    void setLastUpdateTime(double time) { m_lastUpdateTime = time; }
+    void setLastUpdateTime(WallTime time) { m_lastUpdateTime = time; }
     ServiceWorkerUpdateViaCache updateViaCache() const { return m_updateViaCache; }
 
     void updateRegistrationState(ServiceWorkerRegistrationState, SWServerWorker*);
@@ -104,7 +105,7 @@
     RefPtr<SWServerWorker> m_waitingWorker;
     RefPtr<SWServerWorker> m_activeWorker;
 
-    double m_lastUpdateTime { 0 };
+    WallTime m_lastUpdateTime;
     
     HashCountedSet<SWServerConnectionIdentifier> m_connectionsWithClientRegistrations;
     SWServer& m_server;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to