Diff
Modified: trunk/Source/WebCore/ChangeLog (225660 => 225661)
--- trunk/Source/WebCore/ChangeLog 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/ChangeLog 2017-12-08 01:27:00 UTC (rev 225661)
@@ -1,3 +1,55 @@
+2017-12-07 Brady Eidson <beid...@apple.com>
+
+ Read registrations in from disk.
+ https://bugs.webkit.org/show_bug.cgi?id=180543
+
+ Reviewed by Andy Estes.
+
+ No new tests (Not testable quite yet)
+
+ On launch, read through the database.
+
+ Set up enough objects in the SWServer necessary to cause fetches and postMessages to
+ go to a worker that has never run before.
+
+ * workers/service/ServiceWorkerContextData.cpp:
+ (WebCore::ServiceWorkerContextData::isolatedCopy const):
+ * workers/service/ServiceWorkerContextData.h:
+ (WebCore::ServiceWorkerContextData::encode const):
+ (WebCore::ServiceWorkerContextData::decode):
+
+ * workers/service/ServiceWorkerRegistrationKey.cpp:
+ (WebCore::ServiceWorkerRegistrationKey::toDatabaseKey const):
+ (WebCore::ServiceWorkerRegistrationKey::fromDatabaseKey):
+ * workers/service/ServiceWorkerRegistrationKey.h:
+
+ * workers/service/server/RegistrationDatabase.cpp:
+ (WebCore::stringToUpdateViaCache):
+ (WebCore::stringToWorkerType):
+ (WebCore::RegistrationDatabase::doPushChanges):
+ (WebCore::RegistrationDatabase::importRecords):
+ (WebCore::RegistrationDatabase::addRegistrationToStore):
+ * workers/service/server/RegistrationDatabase.h:
+
+ * workers/service/server/RegistrationStore.cpp:
+ (WebCore::RegistrationStore::RegistrationStore):
+ (WebCore::RegistrationStore::addRegistrationFromDatabase):
+ * workers/service/server/RegistrationStore.h:
+
+ * workers/service/server/SWServer.cpp:
+ (WebCore::SWServer::addRegistrationFromStore):
+ (WebCore::SWServer::SWServer):
+ (WebCore::SWServer::updateWorker):
+ (WebCore::SWServer::tryInstallContextData):
+ (WebCore::SWServer::installContextData):
+ (WebCore::generateServiceWorkerIdentifier): Deleted.
+ * workers/service/server/SWServer.h:
+
+ * workers/service/server/SWServerRegistration.h:
+
+ * workers/service/server/SWServerWorker.cpp:
+ (WebCore::SWServerWorker::contextData const):
+
2017-12-07 Yusuke Suzuki <utatane....@gmail.com>
Use WTF Locking primitives in WebThread and drop pthread_xxx use
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContextData.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/ServiceWorkerContextData.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContextData.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -32,7 +32,7 @@
ServiceWorkerContextData ServiceWorkerContextData::isolatedCopy() const
{
- return { jobDataIdentifier, registration.isolatedCopy(), serviceWorkerIdentifier, script.isolatedCopy(), scriptURL.isolatedCopy(), workerType };
+ return { jobDataIdentifier, registration.isolatedCopy(), serviceWorkerIdentifier, script.isolatedCopy(), scriptURL.isolatedCopy(), workerType, loadedFromDisk };
}
} // namespace WebCore
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContextData.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/ServiceWorkerContextData.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContextData.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -42,6 +42,7 @@
String script;
URL scriptURL;
WorkerType workerType;
+ bool loadedFromDisk;
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static std::optional<ServiceWorkerContextData> decode(Decoder&);
@@ -52,7 +53,7 @@
template<class Encoder>
void ServiceWorkerContextData::encode(Encoder& encoder) const
{
- encoder << jobDataIdentifier << registration << serviceWorkerIdentifier << script << scriptURL << workerType;
+ encoder << jobDataIdentifier << registration << serviceWorkerIdentifier << script << scriptURL << workerType << loadedFromDisk;
}
template<class Decoder>
@@ -83,8 +84,12 @@
WorkerType workerType;
if (!decoder.decodeEnum(workerType))
return std::nullopt;
-
- return {{ WTFMove(*jobDataIdentifier), WTFMove(*registration), WTFMove(*serviceWorkerIdentifier), WTFMove(script), WTFMove(scriptURL), workerType }};
+
+ bool loadedFromDisk;
+ if (!decoder.decode(loadedFromDisk))
+ return std::nullopt;
+
+ return {{ WTFMove(*jobDataIdentifier), WTFMove(*registration), WTFMove(*serviceWorkerIdentifier), WTFMove(script), WTFMove(scriptURL), workerType, loadedFromDisk}};
}
} // namespace WebCore
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -80,9 +80,47 @@
String ServiceWorkerRegistrationKey::toDatabaseKey() const
{
- return makeString(m_topOrigin.protocol, separatorCharacter, m_topOrigin.host, separatorCharacter, m_topOrigin.port.value_or(0), separatorCharacter, m_scope.path());
+ if (m_topOrigin.port)
+ return makeString(m_topOrigin.protocol, separatorCharacter, m_topOrigin.host, separatorCharacter, String::number(m_topOrigin.port.value()), separatorCharacter, m_scope.string());
+ return makeString(m_topOrigin.protocol, separatorCharacter, m_topOrigin.host, separatorCharacter, separatorCharacter, m_scope.string());
}
+std::optional<ServiceWorkerRegistrationKey> ServiceWorkerRegistrationKey::fromDatabaseKey(const String& key)
+{
+ auto first = key.find(separatorCharacter, 0);
+ auto second = key.find(separatorCharacter, first + 1);
+ auto third = key.find(separatorCharacter, second + 1);
+
+ if (first == second || second == third)
+ return std::nullopt;
+
+ std::optional<uint16_t> shortPort;
+
+ // If there's a gap between third and second, we expect to have a port to decode
+ if (third - second > 1) {
+ bool ok;
+ unsigned port;
+ if (key.is8Bit())
+ port = charactersToUIntStrict(key.characters8() + second + 1, third - second - 1 , &ok);
+ else
+ port = charactersToUIntStrict(key.characters16() + second + 1, third - second - 1, &ok);
+
+ if (!ok)
+ return std::nullopt;
+
+ if (port > std::numeric_limits<uint16_t>::max())
+ return std::nullopt;
+
+ shortPort = static_cast<uint16_t>(port);
+ }
+
+ auto scope = URL { URL(), key.substring(third + 1) };
+ if (!scope.isValid())
+ return std::nullopt;
+
+ return ServiceWorkerRegistrationKey { { key.substring(0, first), key.substring(first + 1, second - first - 1), shortPort }, WTFMove(scope) };
+}
+
#ifndef NDEBUG
String ServiceWorkerRegistrationKey::loggingString() const
{
Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistrationKey.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -55,6 +55,7 @@
template<class Decoder> static std::optional<ServiceWorkerRegistrationKey> decode(Decoder&);
String toDatabaseKey() const;
+ static std::optional<ServiceWorkerRegistrationKey> fromDatabaseKey(const String&);
#ifndef NDEBUG
String loggingString() const;
Modified: trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/RegistrationDatabase.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -165,6 +165,18 @@
RELEASE_ASSERT_NOT_REACHED();
}
+static std::optional<ServiceWorkerUpdateViaCache> stringToUpdateViaCache(const String& update)
+{
+ if (update == "Imports")
+ return ServiceWorkerUpdateViaCache::Imports;
+ if (update == "All")
+ return ServiceWorkerUpdateViaCache::All;
+ if (update == "None")
+ return ServiceWorkerUpdateViaCache::None;
+
+ return std::nullopt;
+}
+
static String workerTypeToString(WorkerType workerType)
{
switch (workerType) {
@@ -177,6 +189,16 @@
RELEASE_ASSERT_NOT_REACHED();
}
+static std::optional<WorkerType> stringToWorkerType(const String& type)
+{
+ if (type == "Classic")
+ return WorkerType::Classic;
+ if (type == "Module")
+ return WorkerType::Module;
+
+ return std::nullopt;
+}
+
void RegistrationDatabase::pushChanges(Vector<ServiceWorkerContextData>&& datas)
{
postTask(createCrossThreadTask(*this, &RegistrationDatabase::doPushChanges, datas));
@@ -191,7 +213,7 @@
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());
+ LOG_ERROR("Failed to prepare statement to store registration data into records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
return;
}
@@ -231,10 +253,50 @@
String RegistrationDatabase::importRecords()
{
ASSERT(!isMainThread());
- // FIXME: Implement
+
+ SQLiteStatement sql(*m_database, ASCIILiteral("SELECT * FROM Records;"));
+ if (sql.prepare() != SQLITE_OK)
+ return String::format("Failed to prepare statement to retrieve registrations from records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+
+ int result = sql.step();
+
+ for (; result == SQLITE_ROW; result = sql.step()) {
+ auto key = ServiceWorkerRegistrationKey::fromDatabaseKey(sql.getColumnText(0));
+ auto originURL = URL { URL(), sql.getColumnText(1) };
+ auto scopePath = sql.getColumnText(2);
+ auto topOrigin = SecurityOriginData::fromDatabaseIdentifier(sql.getColumnText(3));
+ auto lastUpdateCheckTime = WallTime::fromRawSeconds(sql.getColumnDouble(4));
+ auto updateViaCache = stringToUpdateViaCache(sql.getColumnText(5));
+ auto scriptURL = URL { URL(), sql.getColumnText(6) };
+ auto script = sql.getColumnText(7);
+ auto workerType = stringToWorkerType(sql.getColumnText(8));
+
+ // Validate the input for this registration.
+ // If any part of this input is invalid, let's skip this registration.
+ // FIXME: Should we return an error skipping *all* registrations?
+ if (!key || !originURL.isValid() || !topOrigin || !updateViaCache || !scriptURL.isValid() || !workerType)
+ continue;
+
+ auto workerIdentifier = generateObjectIdentifier<ServiceWorkerIdentifierType>();
+ auto registrationIdentifier = generateObjectIdentifier<ServiceWorkerRegistrationIdentifierType>();
+ auto serviceWorkerData = ServiceWorkerData { workerIdentifier, scriptURL, ServiceWorkerState::Activated, *workerType, registrationIdentifier };
+ auto registration = ServiceWorkerRegistrationData { WTFMove(*key), registrationIdentifier, URL(originURL, scopePath), *updateViaCache, lastUpdateCheckTime, std::nullopt, std::nullopt, WTFMove(serviceWorkerData) };
+ auto contextData = ServiceWorkerContextData { std::nullopt, WTFMove(registration), workerIdentifier, WTFMove(script), WTFMove(scriptURL), *workerType, true };
+
+ postTaskReply(createCrossThreadTask(*this, &RegistrationDatabase::addRegistrationToStore, WTFMove(contextData)));
+ }
+
+ if (result != SQLITE_DONE)
+ return String::format("Failed to import at least one registration from records table (%i) - %s", m_database->lastError(), m_database->lastErrorMsg());
+
return { };
}
+void RegistrationDatabase::addRegistrationToStore(ServiceWorkerContextData&& context)
+{
+ m_store.addRegistrationFromDatabase(WTFMove(context));
+}
+
void RegistrationDatabase::databaseFailedToOpen()
{
m_store.databaseFailedToOpen();
Modified: trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/RegistrationDatabase.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -52,8 +52,9 @@
String ensureValidRecordsTable();
String importRecords();
void doPushChanges(Vector<ServiceWorkerContextData>&&);
-
+
// Replies to the main thread
+ void addRegistrationToStore(ServiceWorkerContextData&&);
void databaseFailedToOpen();
void databaseOpenedAndRecordsImported();
Modified: trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/RegistrationStore.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -32,8 +32,9 @@
namespace WebCore {
-RegistrationStore::RegistrationStore(const String& databaseDirectory)
- : m_database(*this, databaseDirectory)
+RegistrationStore::RegistrationStore(SWServer& server, const String& databaseDirectory)
+ : m_server(server)
+ , m_database(*this, databaseDirectory)
, m_databasePushTimer(*this, &RegistrationStore::pushChangesToDatabase)
{
}
@@ -75,6 +76,11 @@
scheduleDatabasePushIfNecessary();
}
+void RegistrationStore::addRegistrationFromDatabase(ServiceWorkerContextData&& context)
+{
+ m_server.addRegistrationFromStore(WTFMove(context));
+}
+
void RegistrationStore::databaseFailedToOpen()
{
// FIXME: Handle error in some appropriate manner.
@@ -84,7 +90,7 @@
{
// FIXME: Once we actually do the imports, conclude the importing phase here.
}
-
+
} // namespace WebCore
#endif // ENABLE(SERVICE_WORKER)
Modified: trunk/Source/WebCore/workers/service/server/RegistrationStore.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/RegistrationStore.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/RegistrationStore.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -37,12 +37,13 @@
namespace WebCore {
+class SWServer;
class SWServerRegistration;
class RegistrationStore {
WTF_MAKE_FAST_ALLOCATED;
public:
- explicit RegistrationStore(const String& databaseDirectory);
+ explicit RegistrationStore(SWServer&, const String& databaseDirectory);
~RegistrationStore();
// Callbacks from the SWServer
@@ -50,6 +51,7 @@
void removeRegistration(SWServerRegistration&);
// Callbacks from the database
+ void addRegistrationFromDatabase(ServiceWorkerContextData&&);
void databaseFailedToOpen();
void databaseOpenedAndRecordsImported();
@@ -57,6 +59,7 @@
void scheduleDatabasePushIfNecessary();
void pushChangesToDatabase();
+ SWServer& m_server;
RegistrationDatabase m_database;
HashMap<ServiceWorkerRegistrationKey, ServiceWorkerContextData> m_updatedRegistrations;
Modified: trunk/Source/WebCore/workers/service/server/SWServer.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/SWServer.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -48,11 +48,6 @@
namespace WebCore {
-static ServiceWorkerIdentifier generateServiceWorkerIdentifier()
-{
- return generateObjectIdentifier<ServiceWorkerIdentifierType>();
-}
-
static Seconds terminationDelay { 10_s };
SWServer::Connection::Connection(SWServer& server)
@@ -103,6 +98,12 @@
return m_registrations.get(registrationKey);
}
+void SWServer::addRegistrationFromStore(ServiceWorkerContextData&& data)
+{
+ addRegistration(std::make_unique<SWServerRegistration>(*this, data.registration.key, data.registration.updateViaCache, data.registration.scopeURL, data.scriptURL));
+ tryInstallContextData(WTFMove(data));
+}
+
void SWServer::addRegistration(std::unique_ptr<SWServerRegistration>&& registration)
{
auto key = registration->key();
@@ -198,7 +199,7 @@
SWServer::SWServer(UniqueRef<SWOriginStore>&& originStore, const String& registrationDatabaseDirectory)
: m_originStore(WTFMove(originStore))
- , m_registrationStore(registrationDatabaseDirectory)
+ , m_registrationStore(*this, registrationDatabaseDirectory)
{
UNUSED_PARAM(registrationDatabaseDirectory);
allServers().add(this);
@@ -405,11 +406,13 @@
void SWServer::updateWorker(Connection&, const ServiceWorkerJobDataIdentifier& jobDataIdentifier, SWServerRegistration& registration, const URL& url, const String& script, WorkerType type)
{
registration.setLastUpdateTime(WallTime::now());
+ tryInstallContextData({ jobDataIdentifier, registration.data(), generateObjectIdentifier<ServiceWorkerIdentifierType>(), script, url, type, false });
+}
- ServiceWorkerContextData data = { jobDataIdentifier, registration.data(), generateServiceWorkerIdentifier(), script, url, type };
-
+void SWServer::tryInstallContextData(ServiceWorkerContextData&& data)
+{
// 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
+ // And it should always exist if we're trying to install context data.
auto* connection = SWServerToContextConnection::globalServerToContextConnection();
if (!connection) {
m_pendingContextDatas.append(WTFMove(data));
@@ -438,7 +441,8 @@
void SWServer::installContextData(const ServiceWorkerContextData& data)
{
- m_registrationStore.updateRegistration(data);
+ if (!data.loadedFromDisk)
+ m_registrationStore.updateRegistration(data);
auto* connection = SWServerToContextConnection::globalServerToContextConnection();
ASSERT(connection);
@@ -446,11 +450,19 @@
auto* registration = m_registrations.get(data.registration.key);
RELEASE_ASSERT(registration);
- auto result = m_runningOrTerminatingWorkers.add(data.serviceWorkerIdentifier, SWServerWorker::create(*this, *registration, connection->identifier(), data.scriptURL, data.script, data.workerType, data.serviceWorkerIdentifier));
- ASSERT(result.isNewEntry);
+ auto worker = SWServerWorker::create(*this, *registration, connection->identifier(), data.scriptURL, data.script, data.workerType, data.serviceWorkerIdentifier);
- result.iterator->value->setState(SWServerWorker::State::Running);
+ // We don't immediately launch all workers that were just read in from disk,
+ // as it is unlikely they will be needed immediately.
+ if (data.loadedFromDisk) {
+ registration->updateRegistrationState(ServiceWorkerRegistrationState::Active, worker.ptr());
+ return;
+ }
+ worker->setState(SWServerWorker::State::Running);
+ auto result = m_runningOrTerminatingWorkers.add(data.serviceWorkerIdentifier, WTFMove(worker));
+ ASSERT_UNUSED(result, result.isNewEntry);
+
connection->installServiceWorkerContext(data);
}
Modified: trunk/Source/WebCore/workers/service/server/SWServer.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/SWServer.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -168,6 +168,8 @@
void setClientActiveWorker(ServiceWorkerClientIdentifier, ServiceWorkerIdentifier);
void resolveRegistrationReadyRequests(SWServerRegistration&);
+ void addRegistrationFromStore(ServiceWorkerContextData&&);
+
private:
void registerConnection(Connection&);
void unregisterConnection(Connection&);
@@ -185,6 +187,7 @@
WEBCORE_EXPORT SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL);
bool runServiceWorker(ServiceWorkerIdentifier);
+ void tryInstallContextData(ServiceWorkerContextData&&);
void installContextData(const ServiceWorkerContextData&);
SWServerRegistration* registrationFromServiceWorkerIdentifier(ServiceWorkerIdentifier);
Modified: trunk/Source/WebCore/workers/service/server/SWServerRegistration.h (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/SWServerRegistration.h 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/SWServerRegistration.h 2017-12-08 01:27:00 UTC (rev 225661)
@@ -42,6 +42,7 @@
enum class ServiceWorkerRegistrationState;
enum class ServiceWorkerState;
struct ExceptionData;
+struct ServiceWorkerContextData;
struct ServiceWorkerFetchResult;
class SWServerRegistration {
Modified: trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp (225660 => 225661)
--- trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp 2017-12-08 01:26:27 UTC (rev 225660)
+++ trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp 2017-12-08 01:27:00 UTC (rev 225661)
@@ -65,7 +65,7 @@
auto* registration = m_server.getRegistration(m_registrationKey);
ASSERT(registration);
- return { std::nullopt, registration->data(), m_data.identifier, m_script, m_data.scriptURL, m_data.type };
+ return { std::nullopt, registration->data(), m_data.identifier, m_script, m_data.scriptURL, m_data.type, false };
}
void SWServerWorker::terminate()