Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Ensure all ServiceWorkerRegistration files and directories are remove…
…d when registrations are cleared

https://bugs.webkit.org/show_bug.cgi?id=257857
rdar://110475749

Reviewed by Youenn Fablet.

This patch ensures -shm file, -wal file and empty Script folder are deleted when clearing ServiceWorker registrations,
so that ServiceWorker directory can become empty and also get deleted.

Test: WKWebsiteDataStore.RemoveServiceWorkerData

* Source/WebCore/workers/service/server/SWRegistrationDatabase.cpp:
(WebCore::scriptDirectoryPath):
(WebCore::scriptVersionDirectoryPath):
(WebCore::SWRegistrationDatabase::scriptStorage):
(WebCore::SWRegistrationDatabase::importRegistrations):
(WebCore::SWRegistrationDatabase::clearAllRegistrations):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm:

Canonical link: https://commits.webkit.org/264998@main
  • Loading branch information
szewai committed Jun 8, 2023
1 parent 2a3bf96 commit 05f2eb1
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 4 deletions.
19 changes: 15 additions & 4 deletions Source/WebCore/workers/service/server/SWRegistrationDatabase.cpp
Expand Up @@ -79,7 +79,16 @@ static String scriptDirectoryPath(const String& directory)
if (directory.isEmpty())
return emptyString();

return FileSystem::pathByAppendingComponents(directory, { "Scripts"_s, scriptVersion });
return FileSystem::pathByAppendingComponent(directory, "Scripts"_s);
}

static String scriptVersionDirectoryPath(const String& directory)
{
auto scriptDirectory = scriptDirectoryPath(directory);
if (scriptDirectory.isEmpty())
return emptyString();

return FileSystem::pathByAppendingComponent(scriptDirectory, scriptVersion);
}

static ASCIILiteral convertUpdateViaCacheToString(ServiceWorkerUpdateViaCache update)
Expand Down Expand Up @@ -219,7 +228,7 @@ void SWRegistrationDatabase::close()
SWScriptStorage& SWRegistrationDatabase::scriptStorage()
{
if (!m_scriptStorage)
m_scriptStorage = makeUnique<SWScriptStorage>(scriptDirectoryPath(m_directory));
m_scriptStorage = makeUnique<SWScriptStorage>(scriptVersionDirectoryPath(m_directory));

return *m_scriptStorage;
}
Expand Down Expand Up @@ -296,8 +305,10 @@ std::optional<Vector<ServiceWorkerContextData>> SWRegistrationDatabase::importRe
if (!prepareDatabase(ShouldCreateIfNotExists::No))
return std::nullopt;

if (!m_database)
if (!m_database) {
clearAllRegistrations();
return Vector<ServiceWorkerContextData> { };
}

auto statement = cachedStatement(StatementType::GetAllRecords);
if (!statement) {
Expand Down Expand Up @@ -496,7 +507,7 @@ std::optional<Vector<ServiceWorkerScripts>> SWRegistrationDatabase::updateRegist
void SWRegistrationDatabase::clearAllRegistrations()
{
close();
FileSystem::deleteFile(databaseFilePath(m_directory));
SQLiteFileSystem::deleteDatabaseFile(databaseFilePath(m_directory));
FileSystem::deleteNonEmptyDirectory(scriptDirectoryPath(m_directory));
FileSystem::deleteEmptyDirectory(m_directory);
}
Expand Down
Expand Up @@ -1714,3 +1714,58 @@ function install()
EXPECT_TRUE([fileManager fileExistsAtPath:newServiceWorkerDatabaseFilePath]);
EXPECT_FALSE([fileManager fileExistsAtPath:serviceWorkerDatabaseFile.path]);
}

TEST(WKWebsiteDataStore, RemoveServiceWorkerData)
{
[WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
NSURL *generalStorageDirectory = [NSURL fileURLWithPath:[@"~/Library/WebKit/com.apple.WebKit.TestWebKitAPI/CustomWebsiteData/Origins" stringByExpandingTildeInPath] isDirectory:YES];
websiteDataStoreConfiguration.get().generalStorageDirectory = generalStorageDirectory;
auto websiteDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);

done = false;
[websiteDataStore removeDataOfTypes:[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate] modifiedSince:[NSDate distantPast] completionHandler:^() {
done = true;
}];
TestWebKitAPI::Util::run(&done);

TestWebKitAPI::HTTPServer server({
{ "/"_s, { mainBytes } },
{ "/migratetest/sw.js"_s, { { { "Content-Type"_s, "application/javascript"_s } }, scriptBytes } },
});

// Ensure web view is closed, so ServiceWorker directory is not in use and can be removed.
@autoreleasepool {
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
[configuration setWebsiteDataStore:websiteDataStore.get()];
auto messageHandler = adoptNS([[WebsiteDataStoreCustomPathsMessageHandler alloc] init]);
[[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadRequest:server.request()];
EXPECT_WK_STREQ("Message from ServiceWorker: Hello", getNextMessage().body);

// Ensure data is stored to disk.
done = false;
[websiteDataStore _storeServiceWorkerRegistrations: ^{
done = true;
}];
TestWebKitAPI::Util::run(&done);
}

__block NSString *serviceWorkerDirectoryString = nil;
auto url = [server.request() URL];
done = false;
[websiteDataStore _originDirectoryForTesting:url topOrigin:url type:WKWebsiteDataTypeServiceWorkerRegistrations completionHandler:^(NSString *result) {
serviceWorkerDirectoryString = result;
done = true;
}];
TestWebKitAPI::Util::run(&done);
EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:serviceWorkerDirectoryString]);

done = false;
[websiteDataStore removeDataOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeServiceWorkerRegistrations, nil] modifiedSince:[NSDate distantPast] completionHandler:^() {
done = true;
}];
TestWebKitAPI::Util::run(&done);
EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:serviceWorkerDirectoryString]);
}

0 comments on commit 05f2eb1

Please sign in to comment.