Skip to content
Permalink
Browse files
Don't create LocalStorage database for read if it does not exist
https://bugs.webkit.org/show_bug.cgi?id=234569

Reviewed by Alex Christensen.

Source/WebKit:

If database does not exists when read, we can return empty or null, instead of creating an empty database.

New API test: WKWebView.LocalStorageNoRecordAfterGetItem

* NetworkProcess/storage/SQLiteStorageArea.cpp:
(WebKit::SQLiteStorageArea::isEmpty):
(WebKit::SQLiteStorageArea::prepareDatabase):
(WebKit::SQLiteStorageArea::getItemFromDatabase):
(WebKit::SQLiteStorageArea::allItems):
(WebKit::SQLiteStorageArea::setItem):
(WebKit::SQLiteStorageArea::removeItem):
(WebKit::SQLiteStorageArea::clear):
* NetworkProcess/storage/SQLiteStorageArea.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm:
(-[LocalStorageUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(TEST):



Canonical link: https://commits.webkit.org/245553@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287418 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
szewai committed Dec 24, 2021
1 parent 05c35df commit ae946a814765cae1d4dbca5c54604e2d66d97829
Showing 5 changed files with 100 additions and 11 deletions.
@@ -1,3 +1,24 @@
2021-12-23 Sihui Liu <sihui_liu@apple.com>

Don't create LocalStorage database for read if it does not exist
https://bugs.webkit.org/show_bug.cgi?id=234569

Reviewed by Alex Christensen.

If database does not exists when read, we can return empty or null, instead of creating an empty database.

New API test: WKWebView.LocalStorageNoRecordAfterGetItem

* NetworkProcess/storage/SQLiteStorageArea.cpp:
(WebKit::SQLiteStorageArea::isEmpty):
(WebKit::SQLiteStorageArea::prepareDatabase):
(WebKit::SQLiteStorageArea::getItemFromDatabase):
(WebKit::SQLiteStorageArea::allItems):
(WebKit::SQLiteStorageArea::setItem):
(WebKit::SQLiteStorageArea::removeItem):
(WebKit::SQLiteStorageArea::clear):
* NetworkProcess/storage/SQLiteStorageArea.h:

2021-12-23 Matt Woodrow <mattwoodrow@apple.com>

Check allowed network hosts list when we schedule the load in the network process
@@ -101,7 +101,10 @@ bool SQLiteStorageArea::isEmpty()
if (m_cache)
return m_cache->isEmpty();

if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::No))
return true;

if (!m_database)
return true;

auto statement = cachedStatement(StatementType::CountItems);
@@ -148,11 +151,15 @@ bool SQLiteStorageArea::createTableIfNecessary()
return true;
}

bool SQLiteStorageArea::prepareDatabase()
bool SQLiteStorageArea::prepareDatabase(ShouldCreateIfNotExists shouldCreateIfNotExists)
{
if (m_database && m_database->isOpen())
return true;

m_database = nullptr;
if (shouldCreateIfNotExists == ShouldCreateIfNotExists::No && !FileSystem::fileExists(m_path))
return true;

m_database = makeUnique<WebCore::SQLiteDatabase>();
FileSystem::makeAllDirectories(FileSystem::parentPath(m_path));
if (!m_database->open(m_path)) {
@@ -224,9 +231,12 @@ Expected<String, StorageError> SQLiteStorageArea::getItem(const String& key)

Expected<String, StorageError> SQLiteStorageArea::getItemFromDatabase(const String& key)
{
if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::No))
return makeUnexpected(StorageError::Database);

if (!m_database)
return makeUnexpected(StorageError::ItemNotFound);

auto statement = cachedStatement(StatementType::GetItem);
if (!statement || statement->bindText(1, key)) {
RELEASE_LOG_ERROR(Storage, "SQLiteStorageArea::getItemFromDatabase failed on creating statement (%d) - %s", m_database->lastError(), m_database->lastErrorMsg());
@@ -248,7 +258,7 @@ HashMap<String, String> SQLiteStorageArea::allItems()
{
ASSERT(!isMainRunLoop());

if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::No) || !m_database)
return HashMap<String, String> { };

HashMap<String, String> items;
@@ -296,11 +306,10 @@ Expected<void, StorageError> SQLiteStorageArea::setItem(IPC::Connection::UniqueI
{
ASSERT(!isMainRunLoop());

if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::Yes))
return makeUnexpected(StorageError::Database);

startTransactionIfNecessary();

String oldValue;
if (auto valueOrError = getItem(key))
oldValue = valueOrError.value();
@@ -331,9 +340,12 @@ Expected<void, StorageError> SQLiteStorageArea::removeItem(IPC::Connection::Uniq
{
ASSERT(!isMainRunLoop());

if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::No))
return makeUnexpected(StorageError::Database);

if (!m_database)
return makeUnexpected(StorageError::ItemNotFound);

startTransactionIfNecessary();
String oldValue;
if (auto valueOrError = getItem(key))
@@ -359,7 +371,7 @@ Expected<void, StorageError> SQLiteStorageArea::clear(IPC::Connection::UniqueID
{
ASSERT(!isMainRunLoop());

if (!prepareDatabase())
if (!prepareDatabase(ShouldCreateIfNotExists::No))
return makeUnexpected(StorageError::Database);

if (m_cache && m_cache->isEmpty())
@@ -368,6 +380,9 @@ Expected<void, StorageError> SQLiteStorageArea::clear(IPC::Connection::UniqueID
if (m_cache)
m_cache->clear();

if (!m_database)
return makeUnexpected(StorageError::ItemNotFound);

startTransactionIfNecessary();
auto statement = cachedStatement(StatementType::DeleteAllItems);
if (!statement || statement->step() != SQLITE_DONE) {
@@ -52,7 +52,8 @@ class SQLiteStorageArea final : public StorageAreaBase {
Expected<void, StorageError> clear(IPC::Connection::UniqueID, StorageAreaImplIdentifier, const String& urlString) final;

bool createTableIfNecessary();
bool prepareDatabase();
enum class ShouldCreateIfNotExists : bool { No, Yes };
bool prepareDatabase(ShouldCreateIfNotExists);
void startTransactionIfNecessary();

enum class StatementType : uint8_t {
@@ -1,3 +1,14 @@
2021-12-23 Sihui Liu <sihui_liu@apple.com>

Don't create LocalStorage database for read if it does not exist
https://bugs.webkit.org/show_bug.cgi?id=234569

Reviewed by Alex Christensen.

* TestWebKitAPI/Tests/WebKitCocoa/LocalStorageDatabaseTracker.mm:
(-[LocalStorageUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(TEST):

2021-12-23 Matt Woodrow <mattwoodrow@apple.com>

Check allowed network hosts list when we schedule the load in the network process
@@ -29,19 +29,30 @@
#import "PlatformUtilities.h"
#import "Test.h"
#import <WebKit/WKWebsiteDataRecordPrivate.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/WebKit.h>
#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
#import <wtf/text/WTFString.h>

@interface LocalStorageUIDelegate : NSObject <WKUIDelegate>
@interface LocalStorageUIDelegate : NSObject <WKUIDelegate> {
@private
NSString *expectedMessage;
}
- (void)setExpectedMessage:(NSString *)_expectedMessage;
@end

@implementation LocalStorageUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
EXPECT_STREQ("testValue", message.UTF8String);
EXPECT_WK_STREQ(expectedMessage, message);
readyToContinue = true;
completionHandler();
}

- (void)setExpectedMessage:(NSString *)_expectedMessage
{
expectedMessage = _expectedMessage;
}
@end

TEST(WKWebView, LocalStorageFetchDataRecords)
@@ -57,6 +68,7 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
auto uiDelegate = adoptNS([[LocalStorageUIDelegate alloc] init]);
webView.get().UIDelegate = uiDelegate.get();
[uiDelegate.get() setExpectedMessage:@"testValue"];
[webView loadHTMLString:@"<script>localStorage.setItem('testKey', 'testValue');alert(localStorage.getItem('testKey'));</script>" baseURL:[NSURL URLWithString:@"http://localhost"]];
TestWebKitAPI::Util::run(&readyToContinue);

@@ -70,3 +82,32 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin
}];
TestWebKitAPI::Util::run(&readyToContinue);
}

TEST(WKWebView, LocalStorageNoRecordAfterGetItem)
{
readyToContinue = false;
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
readyToContinue = true;
}];
TestWebKitAPI::Util::run(&readyToContinue);

auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
auto uiDelegate = adoptNS([[LocalStorageUIDelegate alloc] init]);
webView.get().UIDelegate = uiDelegate.get();
readyToContinue = false;
[uiDelegate.get() setExpectedMessage:@"null"];
[webView loadHTMLString:@"<script>alert(localStorage.getItem('testKey'));</script>" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
TestWebKitAPI::Util::run(&readyToContinue);

readyToContinue = false;
[[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
EXPECT_EQ(0u, dataRecords.count);
readyToContinue = true;
}];
TestWebKitAPI::Util::run(&readyToContinue);

RetainPtr<NSURL> url = [[[configuration websiteDataStore] _configuration] _webStorageDirectory];
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:url.get().path error:nil];
EXPECT_EQ(0U, [files count]);
}

0 comments on commit ae946a8

Please sign in to comment.