Source/WebCore:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
Add WebKit1 API to view and delete local storage
https://bugs.webkit.org/show_bug.cgi?id=51878
Created StorageTracker as a central point for tracking and deleting LocalStorage per origin.
StorageTracker maintains its own database of origin identifiers and backing db paths,
and this allows it to contain more relational data in the future, like variable quotas per origin.
On initialization, StorageTracker syncs its database with LocalStorage files on disk. It adds
an origin entry when StorageAreaSync performs a first sync for an origin.
All StorageTracker file operations are performed on one background thread with a task queue.
Tests: storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare.html
storage/domstorage/localstorage/storagetracker/storage-tracker-2-create.html
storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all.html
storage/domstorage/localstorage/storagetracker/storage-tracker-4-create.html
storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one.html
* GNUmakefile.am:
* WebCore.exp.in:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* page/PageGroup.cpp:
(WebCore::PageGroup::clearLocalStorageForAllOrigins):
(WebCore::PageGroup::clearLocalStorageForOrigin):
(WebCore::PageGroup::syncLocalStorage):
(WebCore::PageGroup::numberOfPageGroups):
* page/PageGroup.h:
* platform/chromium/FileSystemChromium.cpp:
(WebCore::listDirectory):
* platform/posix/FileSystemPOSIX.cpp:
(WebCore::listDirectory):
* storage/LocalStorageTask.cpp:
(WebCore::LocalStorageTask::LocalStorageTask):
(WebCore::LocalStorageTask::performTask):
* storage/LocalStorageTask.h:
(WebCore::LocalStorageTask::createOriginIdentifiersImport):
(WebCore::LocalStorageTask::createSetOriginDetails):
(WebCore::LocalStorageTask::createDeleteOrigin):
(WebCore::LocalStorageTask::createDeleteAllOrigins):
* storage/StorageAreaImpl.cpp:
(WebCore::StorageAreaImpl::clearForOriginDeletion):
(WebCore::StorageAreaImpl::sync):
* storage/StorageAreaImpl.h:
* storage/StorageAreaSync.cpp:
(WebCore::StorageAreaSync::scheduleCloseDatabase):
(WebCore::StorageAreaSync::openDatabase):
(WebCore::StorageAreaSync::sync):
(WebCore::StorageAreaSync::deleteEmptyDatabase):
(WebCore::StorageAreaSync::scheduleSync):
* storage/StorageAreaSync.h:
* storage/StorageNamespace.h:
* storage/StorageNamespaceImpl.cpp:
(WebCore::StorageNamespaceImpl::clearOriginForDeletion):
(WebCore::StorageNamespaceImpl::clearAllOriginsForDeletion):
(WebCore::StorageNamespaceImpl::sync):
* storage/StorageNamespaceImpl.h:
* storage/StorageTracker.cpp: Added.
(WebCore::StorageTracker::initializeTracker):
(WebCore::StorageTracker::tracker):
(WebCore::StorageTracker::StorageTracker):
(WebCore::StorageTracker::setStorageDirectoryPath):
(WebCore::StorageTracker::trackerDatabasePath):
(WebCore::StorageTracker::openTrackerDatabase):
(WebCore::StorageTracker::importOriginIdentifiers):
(WebCore::StorageTracker::syncImportOriginIdentifiers):
(WebCore::StorageTracker::syncFileSystemAndTrackerDatabase):
(WebCore::StorageTracker::setOriginDetails):
(WebCore::StorageTracker::scheduleTask):
(WebCore::StorageTracker::syncSetOriginDetails):
(WebCore::StorageTracker::origins):
(WebCore::StorageTracker::deleteAllOrigins):
(WebCore::StorageTracker::syncDeleteAllOrigins):
(WebCore::StorageTracker::deleteOrigin):
(WebCore::StorageTracker::syncDeleteOrigin):
(WebCore::StorageTracker::willDeleteAllOrigins):
(WebCore::StorageTracker::willDeleteOrigin):
(WebCore::StorageTracker::canDeleteOrigin):
(WebCore::StorageTracker::cancelDeletingOrigin):
(WebCore::StorageTracker::setClient):
(WebCore::StorageTracker::syncLocalStorage):
* storage/StorageTracker.h: Added.
* storage/StorageTrackerClient.h: Added.
(WebCore::StorageTrackerClient::~StorageTrackerClient):
Source/WebKit:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
Add WebKit1 API to view and delete local storage
https://bugs.webkit.org/show_bug.cgi?id=51878
* WebKit.xcodeproj/project.pbxproj:
Source/WebKit/chromium:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
Add WebKit1 API to view and delete local storage
https://bugs.webkit.org/show_bug.cgi?id=51878
* src/StorageNamespaceProxy.cpp:
(WebCore::StorageNamespaceProxy::clearOriginForDeletion):
(WebCore::StorageNamespaceProxy::clearAllOriginsForDeletion):
(WebCore::StorageNamespaceProxy::sync):
* src/StorageNamespaceProxy.h:
Source/WebKit/mac:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
https://bugs.webkit.org/show_bug.cgi?id=51878
Add WebKit1 API to view and delete local storage
* Storage/WebStorageManager.mm: Added.
(+[WebStorageManager sharedWebStorageManager]):
(-[WebStorageManager origins]):
(-[WebStorageManager deleteAllOrigins]):
(-[WebStorageManager deleteOrigin:]):
(-[WebStorageManager syncLocalStorage]):
(-[WebStorageManager syncFileSystemAndTrackerDatabase]):
(storageDirectoryPath):
(WebKitInitializeStorageIfNecessary):
* Storage/WebStorageManagerInternal.h: Added.
* Storage/WebStorageManagerPrivate.h: Added.
* Storage/WebStorageTrackerClient.h: Added.
* Storage/WebStorageTrackerClient.mm: Added.
(WebStorageTrackerClient::sharedWebStorageTrackerClient):
(WebStorageTrackerClient::WebStorageTrackerClient):
(WebStorageTrackerClient::~WebStorageTrackerClient):
(WebStorageTrackerClient::dispatchDidModifyOriginOnMainThread):
(WebStorageTrackerClient::dispatchDidModifyOrigin):
* WebCoreSupport/WebSecurityOrigin.mm:
(-[WebSecurityOrigin protocol]):
(-[WebSecurityOrigin host]):
(-[WebSecurityOrigin databaseIdentifier]):
(-[WebSecurityOrigin domain]):
(-[WebSecurityOrigin _initWithWebCoreSecurityOrigin:]):
* WebCoreSupport/WebSecurityOriginPrivate.h:
* WebKit.exp:
* WebView/WebView.mm:
(-[WebView _commonInitializationWithFrameName:groupName:usesDocumentViews:]):
Tools:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
https://bugs.webkit.org/show_bug.cgi?id=51878
Add WebKit1 API to view and delete local storage
Added tests that write to LocalStorage, delete one origin, get list of origins with local storage, delete all origins.
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/LayoutTestController.cpp:
(syncLocalStorageCallback):
(observeStorageTrackerNotificationsCallback):
(deleteAllLocalStorageCallback):
(deleteLocalStorageForOriginCallback):
(originsWithLocalStorageCallback):
(LayoutTestController::staticFunctions):
* DumpRenderTree/LayoutTestController.h:
* DumpRenderTree/StorageTrackerDelegate.h: Added.
* DumpRenderTree/StorageTrackerDelegate.mm: Added.
(-[StorageTrackerDelegate init]):
(-[StorageTrackerDelegate logNotifications:controller:]):
(-[StorageTrackerDelegate originModified:]):
(-[StorageTrackerDelegate dealloc]):
(-[StorageTrackerDelegate setControllerToNotifyDone:]):
* DumpRenderTree/chromium/LayoutTestController.cpp:
(LayoutTestController::LayoutTestController):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
(observeStorageTrackerNotifications):
(syncLocalStorage):
* DumpRenderTree/chromium/LayoutTestController.h:
* DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
(LayoutTestController::observeStorageTrackerNotifications):
(LayoutTestController::syncLocalStorage):
* DumpRenderTree/mac/DumpRenderTree.mm:
(resetDefaultsToConsistentValues):
(allocateGlobalControllers):
(releaseGlobalControllers):
* DumpRenderTree/mac/DumpRenderTreeMac.h:
* DumpRenderTree/mac/LayoutTestControllerMac.mm:
(LayoutTestController::syncLocalStorage):
(LayoutTestController::observeStorageTrackerNotifications):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
* DumpRenderTree/qt/LayoutTestControllerQt.cpp:
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
(LayoutTestController::observeStorageTrackerNotifications):
(LayoutTestController::syncLocalStorage):
* DumpRenderTree/qt/LayoutTestControllerQt.h:
* DumpRenderTree/win/LayoutTestControllerWin.cpp:
(LayoutTestController::clearAllApplicationCaches):
(LayoutTestController::syncLocalStorage):
(LayoutTestController::observeStorageTrackerNotifications):
(LayoutTestController::clearAllDatabases):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
* DumpRenderTree/wx/LayoutTestControllerWx.cpp:
(LayoutTestController::syncLocalStorage):
(LayoutTestController::observeStorageTrackerNotifications):
(LayoutTestController::clearAllDatabases):
(LayoutTestController::deleteAllLocalStorage):
(LayoutTestController::originsWithLocalStorage):
(LayoutTestController::deleteLocalStorageForOrigin):
LayoutTests:
Patch by Anton D'Auria <adauria@apple.com> on 2011-03-11
Add WebKit1 API to view and delete local storage
https://bugs.webkit.org/show_bug.cgi?id=51878
* platform/chromium/test_expectations.txt:
* storage/domstorage/localstorage/storagetracker: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare-expected.txt: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare.html: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-2-create-expected.txt: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-2-create.html: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all-expected.txt: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all.html: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-4-create-expected.txt: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-4-create.html: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one-expected.txt: Added.
* storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@80892
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ Add WebKit1 API to view and delete local storage
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+
+ * platform/chromium/test_expectations.txt:
+ * storage/domstorage/localstorage/storagetracker: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare-expected.txt: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare.html: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-2-create-expected.txt: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-2-create.html: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all-expected.txt: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all.html: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-4-create-expected.txt: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-4-create.html: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one-expected.txt: Added.
+ * storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one.html: Added.
+
2011-03-11 Jessie Berlin <jberlin@apple.com>
http/tests/websocket/tests/url-with-credential.html sometimes crashes beneath SocketStreamHandle::readStreamCallback on Windows
// most likely these tests will always be JSC specific.
WONTFIX SKIP : fast/profiler = FAIL TIMEOUT
+// StorageTracker isn't used by Chromium and not all requisite platform code
+// is implemented.
+WONTFIX SKIP : storage/domstorage/localstorage/storagetracker = PASS TIMEOUT FAIL
+
// We use worker_uitests to run workers tests. Don't run them in test_shell.
WONTFIX SKIP : fast/workers = PASS TIMEOUT FAIL
WONTFIX SKIP : fast/files/workers = PASS TIMEOUT FAIL
--- /dev/null
+Prepare for StorageTracker tests by ensuring that every origin with local storage is deleted.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+This test should have no visible output on success.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../../../fast/js/resources/js-test-post-function.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("Prepare for StorageTracker tests by ensuring that every origin with local storage is deleted.");
+
+if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function test()
+{
+ if (!window.localStorage) {
+ testFailed("localStorage DOES NOT exist");
+ return;
+ }
+
+ debug("This test should have no visible output on success.");
+
+ if (layoutTestController.originsWithLocalStorage().length > 0) {
+ layoutTestController.observeStorageTrackerNotifications(1);
+ layoutTestController.deleteAllLocalStorage();
+ } else {
+ finishTest();
+ }
+}
+
+test();
+
+window.successfullyParsed = true;
+isSuccessfullyParsed();
+</script>
+</body>
+</html>
--- /dev/null
+Origin identifier: 'file__0'
+StorageTracker test - write local storage for this origin. Should be called after origins-prepare.html.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../../../fast/js/resources/js-test-post-function.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("StorageTracker test - write local storage for this origin. Should be called after origins-prepare.html.");
+
+if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function test()
+{
+ if (!window.localStorage) {
+ testFailed("localStorage DOES NOT exist");
+ return;
+ }
+
+ if (layoutTestController.originsWithLocalStorage().length > 0) {
+ // An origin already exists so we can exit.
+ testFailed("An origin already existed with local storage.");
+ layoutTestController.notifyDone();
+ } else {
+ layoutTestController.syncLocalStorage();
+
+ localStorage.someData = 'writeme';
+ // LayoutTestController's notifyDone will be called after the origin change notification comes in.
+ layoutTestController.observeStorageTrackerNotifications(1);
+ }
+}
+
+test();
+
+window.successfullyParsed = true;
+isSuccessfullyParsed();
+</script>
+</body>
+</html>
--- /dev/null
+Test API to view origins that have local storage and to delete local storage by origin.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS layoutTestController.originsWithLocalStorage().toString() is "file__0"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../../../fast/js/resources/js-test-post-function.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("Test API to view origins that have local storage and to delete local storage by origin.");
+
+if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function test()
+{
+ if (!window.localStorage) {
+ testFailed("localStorage DOES NOT exist");
+ return;
+ }
+
+ if (layoutTestController.originsWithLocalStorage().length > 0) {
+ shouldBeEqualToString("layoutTestController.originsWithLocalStorage().toString()", "file__0");
+ // We're just going to delete the existing origin, so we'll get one origin change notification.
+ layoutTestController.observeStorageTrackerNotifications(1);
+ layoutTestController.deleteAllLocalStorage();
+ } else {
+ layoutTestController.notifyDone();
+ testFailed("Ran with no origins with local storage");
+ }
+
+ // At this point, we're guaranteed to have one origin with local storage.
+}
+
+test();
+
+window.successfullyParsed = true;
+isSuccessfullyParsed();
+</script>
+</body>
+</html>
--- /dev/null
+Origin identifier: 'file__0'
+StorageTracker test - write local storage for this origin. Should be called after storage-tracker-3-delete-all.html.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+This test should have no visible output on success.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../../../fast/js/resources/js-test-post-function.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("StorageTracker test - write local storage for this origin. Should be called after storage-tracker-3-delete-all.html.");
+
+if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function test()
+{
+ if (!window.localStorage) {
+ testFailed("localStorage DOES NOT exist");
+ return;
+ }
+
+ debug("This test should have no visible output on success.");
+
+ if (layoutTestController.originsWithLocalStorage().length > 0) {
+ // An origin already exists so we can exit.
+ testFailed("An origin already existed with local storage.");
+ layoutTestController.notifyDone();
+ } else {
+ layoutTestController.syncLocalStorage();
+ localStorage.someOtherData = 'writemeMore';
+ layoutTestController.observeStorageTrackerNotifications(1);
+ }
+}
+
+test();
+
+window.successfullyParsed = true;
+isSuccessfullyParsed();
+</script>
+</body>
+</html>
--- /dev/null
+Test API to view origins that have local storage and to delete local storage by origin.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS layoutTestController.originsWithLocalStorage().toString() is "file__0"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../../../fast/js/resources/js-test-post-function.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("Test API to view origins that have local storage and to delete local storage by origin.");
+
+if (window.layoutTestController)
+ layoutTestController.waitUntilDone();
+
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function test()
+{
+ if (!window.localStorage) {
+ testFailed("localStorage DOES NOT exist");
+ return;
+ }
+
+ if (layoutTestController.originsWithLocalStorage().length > 0) {
+ shouldBeEqualToString("layoutTestController.originsWithLocalStorage().toString()", "file__0");
+ // We're just going to delete the existing origin, so we'll get one origin change notification.
+ layoutTestController.observeStorageTrackerNotifications(1);
+ // At this point, we're guaranteed to have one origin with local storage.
+ layoutTestController.deleteLocalStorageForOrigin("file://");
+ } else {
+ testFailed("Ran with no origins with local storage.");
+ layoutTestController.notifyDone();
+ }
+
+}
+
+test();
+
+window.successfullyParsed = true;
+isSuccessfullyParsed();
+</script>
+</body>
+</html>
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ Add WebKit1 API to view and delete local storage
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+
+ Created StorageTracker as a central point for tracking and deleting LocalStorage per origin.
+ StorageTracker maintains its own database of origin identifiers and backing db paths,
+ and this allows it to contain more relational data in the future, like variable quotas per origin.
+
+ On initialization, StorageTracker syncs its database with LocalStorage files on disk. It adds
+ an origin entry when StorageAreaSync performs a first sync for an origin.
+
+ All StorageTracker file operations are performed on one background thread with a task queue.
+
+ Tests: storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare.html
+ storage/domstorage/localstorage/storagetracker/storage-tracker-2-create.html
+ storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all.html
+ storage/domstorage/localstorage/storagetracker/storage-tracker-4-create.html
+ storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one.html
+
+ * GNUmakefile.am:
+ * WebCore.exp.in:
+ * WebCore.gypi:
+ * WebCore.pro:
+ * WebCore.vcproj/WebCore.vcproj:
+ * WebCore.xcodeproj/project.pbxproj:
+ * page/PageGroup.cpp:
+ (WebCore::PageGroup::clearLocalStorageForAllOrigins):
+ (WebCore::PageGroup::clearLocalStorageForOrigin):
+ (WebCore::PageGroup::syncLocalStorage):
+ (WebCore::PageGroup::numberOfPageGroups):
+ * page/PageGroup.h:
+ * platform/chromium/FileSystemChromium.cpp:
+ (WebCore::listDirectory):
+ * platform/posix/FileSystemPOSIX.cpp:
+ (WebCore::listDirectory):
+ * storage/LocalStorageTask.cpp:
+ (WebCore::LocalStorageTask::LocalStorageTask):
+ (WebCore::LocalStorageTask::performTask):
+ * storage/LocalStorageTask.h:
+ (WebCore::LocalStorageTask::createOriginIdentifiersImport):
+ (WebCore::LocalStorageTask::createSetOriginDetails):
+ (WebCore::LocalStorageTask::createDeleteOrigin):
+ (WebCore::LocalStorageTask::createDeleteAllOrigins):
+ * storage/StorageAreaImpl.cpp:
+ (WebCore::StorageAreaImpl::clearForOriginDeletion):
+ (WebCore::StorageAreaImpl::sync):
+ * storage/StorageAreaImpl.h:
+ * storage/StorageAreaSync.cpp:
+ (WebCore::StorageAreaSync::scheduleCloseDatabase):
+ (WebCore::StorageAreaSync::openDatabase):
+ (WebCore::StorageAreaSync::sync):
+ (WebCore::StorageAreaSync::deleteEmptyDatabase):
+ (WebCore::StorageAreaSync::scheduleSync):
+ * storage/StorageAreaSync.h:
+ * storage/StorageNamespace.h:
+ * storage/StorageNamespaceImpl.cpp:
+ (WebCore::StorageNamespaceImpl::clearOriginForDeletion):
+ (WebCore::StorageNamespaceImpl::clearAllOriginsForDeletion):
+ (WebCore::StorageNamespaceImpl::sync):
+ * storage/StorageNamespaceImpl.h:
+ * storage/StorageTracker.cpp: Added.
+ (WebCore::StorageTracker::initializeTracker):
+ (WebCore::StorageTracker::tracker):
+ (WebCore::StorageTracker::StorageTracker):
+ (WebCore::StorageTracker::setStorageDirectoryPath):
+ (WebCore::StorageTracker::trackerDatabasePath):
+ (WebCore::StorageTracker::openTrackerDatabase):
+ (WebCore::StorageTracker::importOriginIdentifiers):
+ (WebCore::StorageTracker::syncImportOriginIdentifiers):
+ (WebCore::StorageTracker::syncFileSystemAndTrackerDatabase):
+ (WebCore::StorageTracker::setOriginDetails):
+ (WebCore::StorageTracker::scheduleTask):
+ (WebCore::StorageTracker::syncSetOriginDetails):
+ (WebCore::StorageTracker::origins):
+ (WebCore::StorageTracker::deleteAllOrigins):
+ (WebCore::StorageTracker::syncDeleteAllOrigins):
+ (WebCore::StorageTracker::deleteOrigin):
+ (WebCore::StorageTracker::syncDeleteOrigin):
+ (WebCore::StorageTracker::willDeleteAllOrigins):
+ (WebCore::StorageTracker::willDeleteOrigin):
+ (WebCore::StorageTracker::canDeleteOrigin):
+ (WebCore::StorageTracker::cancelDeletingOrigin):
+ (WebCore::StorageTracker::setClient):
+ (WebCore::StorageTracker::syncLocalStorage):
+ * storage/StorageTracker.h: Added.
+ * storage/StorageTrackerClient.h: Added.
+ (WebCore::StorageTrackerClient::~StorageTrackerClient):
+
2011-03-11 Steve Block <steveblock@google.com>
Reviewed by Jeremy Orlow.
Source/WebCore/storage/StorageNamespaceImpl.h \
Source/WebCore/storage/StorageSyncManager.cpp \
Source/WebCore/storage/StorageSyncManager.h \
+ Source/WebCore/storage/StorageTracker.cpp \
+ Source/WebCore/storage/StorageTracker.h \
+ Source/WebCore/storage/StorageTrackerClient.h \
Source/WebCore/svg/animation/SMILTimeContainer.cpp \
Source/WebCore/svg/animation/SMILTimeContainer.h \
Source/WebCore/svg/animation/SMILTime.cpp \
__ZN7WebCore9PageGroup29removeUserStyleSheetFromWorldEPNS_15DOMWrapperWorldERKNS_4KURLE
__ZN7WebCore9PageGroup30removeUserStyleSheetsFromWorldEPNS_15DOMWrapperWorldE
__ZN7WebCore9PageGroup9pageGroupERKN3WTF6StringE
+__ZN7WebCore9PageGroup18numberOfPageGroupsEv
__ZN7WebCore9Scrollbar22maxOverlapBetweenPagesEv
__ZN7WebCore9TimerBase4stopEv
__ZN7WebCore9TimerBase5startEdd
__ZNK7WebCore14SecurityOrigin10canDisplayERKNS_4KURLE
__ZNK7WebCore14SecurityOrigin18databaseIdentifierEv
__ZNK7WebCore14SecurityOrigin5equalEPKS0_
+#if ENABLE(DOM_STORAGE)
+__ZN7WebCore14StorageTracker17initializeTrackerERKN3WTF6StringE
+__ZN7WebCore14StorageTracker16deleteAllOriginsEv
+__ZN7WebCore14StorageTracker12deleteOriginEPNS_14SecurityOriginE
+__ZN7WebCore14StorageTracker7trackerEv
+__ZN7WebCore14StorageTracker7originsERN3WTF6VectorINS1_6RefPtrINS_14SecurityOriginEEELm0EEE
+__ZN7WebCore14StorageTracker9setClientEPNS_20StorageTrackerClientE
+__ZN7WebCore14StorageTracker16syncLocalStorageEv
+__ZN7WebCore14StorageTracker32syncFileSystemAndTrackerDatabaseEv
+#endif
__ZNK7WebCore15FocusController18focusedOrMainFrameEv
__ZNK7WebCore15GraphicsContext15platformContextEv
__ZNK7WebCore15GraphicsContext16paintingDisabledEv
'storage/StorageNamespaceImpl.h',
'storage/StorageSyncManager.cpp',
'storage/StorageSyncManager.h',
+ 'storage/StorageTracker.cpp',
+ 'storage/StorageTracker.h',
'storage/chromium/DatabaseObserver.h',
'storage/chromium/DatabaseTrackerChromium.cpp',
'storage/chromium/IDBFactoryBackendInterface.cpp',
storage/StorageMap.h \
storage/StorageNamespace.h \
storage/StorageNamespaceImpl.h \
- storage/StorageSyncManager.h
+ storage/StorageSyncManager.h \
+ storage/StorageTracker.h \
+ storage/StorageTrackerClient.h
!v8 {
SOURCES += \
storage/StorageMap.cpp \
storage/StorageNamespace.cpp \
storage/StorageNamespaceImpl.cpp \
- storage/StorageSyncManager.cpp
+ storage/StorageSyncManager.cpp \
+ storage/StorageTracker.cpp
}
contains(DEFINES, ENABLE_FILE_SYSTEM=1) {
>
</File>
<File
- RelativePath="..\storage\VersionChangeCallback.h"
+ RelativePath="..\storage\StorageTracker.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\storage\StorageTracker.h"
>
</File>
+ <File
+ RelativePath="..\storage\VersionChangeCallback.h"
+ >
+ </File>
+
</Filter>
<Filter
Name="strings"
37F818FD0D657606005E1F05 /* WebCoreURLResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
37F818FE0D657606005E1F05 /* WebCoreURLResponse.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */; };
37FD4298118368460093C029 /* TreeDepthLimit.h in Headers */ = {isa = PBXBuildFile; fileRef = 37FD4297118368460093C029 /* TreeDepthLimit.h */; };
+ 3AB02D2A12D4F91600FBB694 /* StorageTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB02D2812D4F91600FBB694 /* StorageTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 3AB02D2B12D4F91600FBB694 /* StorageTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB02D2912D4F91600FBB694 /* StorageTracker.cpp */; };
+ 3AC3680012EF7A09006A3D6F /* StorageTrackerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC367FE12EF7A09006A3D6F /* StorageTrackerClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
3AC648B2129E146500C3EB25 /* EditingBoundary.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC648B1129E146500C3EB25 /* EditingBoundary.h */; settings = {ATTRIBUTES = (Private, ); }; };
41002CCD0F66EDEF009E660D /* ScriptFunctionCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */; };
41002CCE0F66EDEF009E660D /* ScriptFunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41002CCC0F66EDEF009E660D /* ScriptFunctionCall.cpp */; };
37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponse.mm; sourceTree = "<group>"; };
37FC96DA1104ED71003E1FAD /* TrailingFloatsRootInlineBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrailingFloatsRootInlineBox.h; sourceTree = "<group>"; };
37FD4297118368460093C029 /* TreeDepthLimit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TreeDepthLimit.h; sourceTree = "<group>"; };
+ 3AB02D2812D4F91600FBB694 /* StorageTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageTracker.h; sourceTree = "<group>"; };
+ 3AB02D2912D4F91600FBB694 /* StorageTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageTracker.cpp; sourceTree = "<group>"; };
+ 3AC367FE12EF7A09006A3D6F /* StorageTrackerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageTrackerClient.h; sourceTree = "<group>"; };
3AC648B1129E146500C3EB25 /* EditingBoundary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingBoundary.h; sourceTree = "<group>"; };
41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFunctionCall.h; sourceTree = "<group>"; };
41002CCC0F66EDEF009E660D /* ScriptFunctionCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptFunctionCall.cpp; sourceTree = "<group>"; };
C55E38BB10040D5D00A56BDB /* StorageNamespaceImpl.h */,
C5102D930FD9AA2D00FAFF04 /* StorageSyncManager.cpp */,
C5102D920FD9AA2D00FAFF04 /* StorageSyncManager.h */,
+ 3AB02D2812D4F91600FBB694 /* StorageTracker.h */,
+ 3AB02D2912D4F91600FBB694 /* StorageTracker.cpp */,
+ 3AC367FE12EF7A09006A3D6F /* StorageTrackerClient.h */,
);
indentWidth = 4;
path = storage;
C50D0E830FF4272900AC2644 /* StorageNamespace.h in Headers */,
C55E38BF10040D5D00A56BDB /* StorageNamespaceImpl.h in Headers */,
C5102D940FD9AA2D00FAFF04 /* StorageSyncManager.h in Headers */,
+ 3AB02D2A12D4F91600FBB694 /* StorageTracker.h in Headers */,
65488D6B0DD5A83D009D83B2 /* StringSourceProvider.h in Headers */,
B23540F30D00782E002382FA /* StringTruncator.h in Headers */,
849F77760EFEC6200090849D /* StrokeStyleApplier.h in Headers */,
E1F1E8300C3C2BB9006DB391 /* XSLTExtensions.h in Headers */,
93F199ED08245E59001E9ABC /* XSLTProcessor.h in Headers */,
E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
+ 3AC3680012EF7A09006A3D6F /* StorageTrackerClient.h in Headers */,
977E2E0F12F0FC9C00C13379 /* XSSFilter.h in Headers */,
E49BD9FA131FD2ED003C56F0 /* CSSPrimitiveValueCache.h in Headers */,
5A574F25131DB93900471B88 /* RenderQuote.h in Headers */,
C50D0E820FF4272900AC2644 /* StorageNamespace.cpp in Sources */,
C55E38C010040D5D00A56BDB /* StorageNamespaceImpl.cpp in Sources */,
C5102D950FD9AA2D00FAFF04 /* StorageSyncManager.cpp in Sources */,
+ 3AB02D2B12D4F91600FBB694 /* StorageTracker.cpp in Sources */,
B2C3DA300D006C1D00EF6F26 /* String.cpp in Sources */,
B2B2645C0D00A77E000ACC1D /* StringCF.cpp in Sources */,
B2B2645D0D00A77E000ACC1D /* StringImplCF.cpp in Sources */,
#include "GroupSettings.h"
#include "IDBFactoryBackendInterface.h"
#include "Page.h"
+#include "SecurityOrigin.h"
#include "Settings.h"
#include "StorageNamespace.h"
#endif
}
+#if ENABLE(DOM_STORAGE)
+
+void PageGroup::clearLocalStorageForAllOrigins()
+{
+ if (!pageGroups)
+ return;
+
+ PageGroupMap::iterator end = pageGroups->end();
+ for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
+ if (it->second->hasLocalStorage())
+ it->second->localStorage()->clearAllOriginsForDeletion();
+ }
+}
+
+void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin)
+{
+ if (!pageGroups)
+ return;
+
+ PageGroupMap::iterator end = pageGroups->end();
+ for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
+ if (it->second->hasLocalStorage())
+ it->second->localStorage()->clearOriginForDeletion(origin);
+ }
+}
+
+void PageGroup::syncLocalStorage()
+{
+ if (!pageGroups)
+ return;
+
+ PageGroupMap::iterator end = pageGroups->end();
+ for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) {
+ if (it->second->hasLocalStorage())
+ it->second->localStorage()->sync();
+ }
+}
+
+unsigned PageGroup::numberOfPageGroups()
+{
+ if (!pageGroups)
+ return 0;
+
+ return pageGroups->size();
+}
+
+#endif
+
void PageGroup::addPage(Page* page)
{
ASSERT(page);
return m_localStorage.get();
}
+
#endif
#if ENABLE(INDEXED_DATABASE)
class GroupSettings;
class IDBFactoryBackendInterface;
class Page;
+ class SecurityOrigin;
class StorageNamespace;
class PageGroup {
~PageGroup();
static PageGroup* pageGroup(const String& groupName);
+
+#if ENABLE(DOM_STORAGE)
static void closeLocalStorage();
+ static void clearLocalStorageForAllOrigins();
+ static void clearLocalStorageForOrigin(SecurityOrigin*);
+ // DumpRenderTree helper that triggers a StorageArea sync.
+ static void syncLocalStorage();
+#endif
+ static unsigned numberOfPageGroups();
const HashSet<Page*>& pages() const { return m_pages; }
return PlatformBridge::writeToFile(handle, data, length);
}
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ notImplemented();
+
+ return Vector<String>();
+}
+
} // namespace WebCore
#include "FileSystem.h"
#include "PlatformString.h"
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <fnmatch.h>
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
return dirname(fsRep.mutableData());
}
-// OK to not implement listDirectory at the moment, because it's only used for plug-ins, and
-// all platforms that use the shared plug-in implementation have implementations. We'd need
-// to implement it if we wanted to use PluginDatabase.cpp on the Mac. Better to not implement
-// at all and get a link error in case this arises, rather than having a stub here, because
-// with a stub you learn about the problem at runtime instead of link time.
+Vector<String> listDirectory(const String& path, const String& filter)
+{
+ Vector<String> entries;
+ CString cpath = path.utf8();
+ CString cfilter = filter.utf8();
+ DIR* dir = opendir(cpath.data());
+ if (dir) {
+ struct dirent* dp;
+ while ((dp = readdir(dir))) {
+ const char* name = dp->d_name;
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+ if (fnmatch(cfilter.data(), name, 0))
+ continue;
+ char filePath[1024];
+ if (static_cast<int>(sizeof(filePath) - 1) < snprintf(filePath, sizeof(filePath), "%s/%s", cpath.data(), name))
+ continue; // buffer overflow
+ entries.append(filePath);
+ }
+ closedir(dir);
+ }
+ return entries;
+}
} // namespace WebCore
#include "LocalStorageThread.h"
#include "StorageAreaSync.h"
+#include "StorageTracker.h"
namespace WebCore {
ASSERT(m_thread);
ASSERT(m_type == TerminateThread);
}
+
+LocalStorageTask::LocalStorageTask(Type type)
+ : m_type(type)
+{
+ ASSERT(m_type == ImportOrigins || m_type == DeleteAllOrigins);
+}
+
+LocalStorageTask::LocalStorageTask(Type type, const String& originIdentifier)
+ : m_type(type)
+ , m_originIdentifier(originIdentifier)
+{
+ ASSERT(m_type == DeleteOrigin);
+}
+
+LocalStorageTask::LocalStorageTask(Type type, const String& originIdentifier, const String& databaseFilename)
+ : m_type(type)
+ , m_originIdentifier(originIdentifier)
+ , m_databaseFilename(databaseFilename)
+{
+ ASSERT(m_type == SetOriginDetails);
+}
LocalStorageTask::~LocalStorageTask()
{
case AreaSync:
m_area->performSync();
break;
+ case SetOriginDetails:
+ StorageTracker::tracker().syncSetOriginDetails(m_originIdentifier, m_databaseFilename);
+ break;
+ case ImportOrigins:
+ StorageTracker::tracker().syncImportOriginIdentifiers();
+ break;
+ case DeleteAllOrigins:
+ StorageTracker::tracker().syncDeleteAllOrigins();
+ break;
+ case DeleteOrigin:
+ StorageTracker::tracker().syncDeleteOrigin(m_originIdentifier);
+ break;
case DeleteEmptyDatabase:
m_area->deleteEmptyDatabase();
break;
#if ENABLE(DOM_STORAGE)
+#include "PlatformString.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/Threading.h>
class LocalStorageTask {
WTF_MAKE_NONCOPYABLE(LocalStorageTask); WTF_MAKE_FAST_ALLOCATED;
public:
- enum Type { AreaImport, AreaSync, DeleteEmptyDatabase, TerminateThread };
+ enum Type { AreaImport, AreaSync, DeleteEmptyDatabase, SetOriginDetails, ImportOrigins, DeleteAllOrigins, DeleteOrigin, TerminateThread };
~LocalStorageTask();
static PassOwnPtr<LocalStorageTask> createImport(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(AreaImport, area)); }
static PassOwnPtr<LocalStorageTask> createSync(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(AreaSync, area)); }
static PassOwnPtr<LocalStorageTask> createDeleteEmptyDatabase(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(DeleteEmptyDatabase, area)); }
+ static PassOwnPtr<LocalStorageTask> createOriginIdentifiersImport() { return adoptPtr(new LocalStorageTask(ImportOrigins)); }
+ static PassOwnPtr<LocalStorageTask> createSetOriginDetails(const String& originIdentifier, const String& databaseFilename) { return adoptPtr(new LocalStorageTask(SetOriginDetails, originIdentifier, databaseFilename)); }
+ static PassOwnPtr<LocalStorageTask> createDeleteOrigin(const String& originIdentifier) { return adoptPtr(new LocalStorageTask(DeleteOrigin, originIdentifier)); }
+ static PassOwnPtr<LocalStorageTask> createDeleteAllOrigins() { return adoptPtr(new LocalStorageTask(DeleteAllOrigins)); }
static PassOwnPtr<LocalStorageTask> createTerminate(LocalStorageThread* thread) { return adoptPtr(new LocalStorageTask(TerminateThread, thread)); }
void performTask();
private:
LocalStorageTask(Type, StorageAreaSync*);
LocalStorageTask(Type, LocalStorageThread*);
+ LocalStorageTask(Type, const String& originIdentifier);
+ LocalStorageTask(Type, const String& originIdentifier, const String& databaseFilename);
+ LocalStorageTask(Type);
Type m_type;
StorageAreaSync* m_area;
LocalStorageThread* m_thread;
+ String m_originIdentifier;
+ String m_databaseFilename;
};
} // namespace WebCore
#endif
}
+void StorageAreaImpl::clearForOriginDeletion()
+{
+ ASSERT(!m_isShutdown);
+ blockUntilImportComplete();
+
+ if (m_storageMap->length()) {
+ unsigned quota = m_storageMap->quota();
+ m_storageMap = StorageMap::create(quota);
+ }
+
+ if (m_storageAreaSync) {
+ m_storageAreaSync->scheduleClear();
+ m_storageAreaSync->scheduleCloseDatabase();
+ }
+}
+
+void StorageAreaImpl::sync()
+{
+ ASSERT(!m_isShutdown);
+ blockUntilImportComplete();
+
+ if (m_storageAreaSync)
+ m_storageAreaSync->scheduleSync();
+}
+
void StorageAreaImpl::blockUntilImportComplete() const
{
if (m_storageAreaSync)
// Only called from a background thread.
void importItem(const String& key, const String& value);
+ // Used to clear a StorageArea and close db before backing db file is deleted.
+ void clearForOriginDeletion();
+
+ void sync();
+
private:
StorageAreaImpl(StorageType, PassRefPtr<SecurityOrigin>, PassRefPtr<StorageSyncManager>, unsigned quota);
StorageAreaImpl(StorageAreaImpl*);
#include "SecurityOrigin.h"
#include "StorageAreaImpl.h"
#include "StorageSyncManager.h"
+#include "StorageTracker.h"
#include "SuddenTermination.h"
#include <wtf/text/CString.h>
}
}
+void StorageAreaSync::scheduleCloseDatabase()
+{
+ ASSERT(isMainThread());
+ ASSERT(!m_finalSyncScheduled);
+
+ if (!m_database.isOpen())
+ return;
+
+ m_syncCloseDatabase = true;
+
+ if (!m_syncTimer.isActive()) {
+ m_syncTimer.startOneShot(StorageSyncInterval);
+
+ // The following is balanced by the call to enableSuddenTermination in the
+ // syncTimerFired function.
+ disableSuddenTermination();
+ }
+}
+
void StorageAreaSync::syncTimerFired(Timer<StorageAreaSync>*)
{
ASSERT(isMainThread());
return;
}
+ // A StorageTracker thread may have been scheduled to delete the db we're
+ // reopening, so cancel possible deletion.
+ StorageTracker::tracker().cancelDeletingOrigin(m_databaseIdentifier);
+
if (!m_database.open(databaseFilename)) {
LOG_ERROR("Failed to open database file %s for local storage", databaseFilename.utf8().data());
markImported();
m_databaseOpenFailed = true;
return;
}
+
+ StorageTracker::tracker().setOriginDetails(m_databaseIdentifier, databaseFilename);
}
void StorageAreaSync::performImport()
if (!m_database.isOpen())
return;
+ // Closing this db because it is about to be deleted by StorageTracker.
+ // The delete will be cancelled if StorageAreaSync needs to reopen the db
+ // to write new items created after the request to delete the db.
+ if (m_syncCloseDatabase) {
+ m_syncCloseDatabase = false;
+ m_database.close();
+ return;
+ }
+
// If the clear flag is set, then we clear all items out before we write any new ones in.
if (clearItems) {
SQLiteStatement clear(m_database, "DELETE FROM ItemTable");
if (!count) {
query.finalize();
m_database.close();
- String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier);
- if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename))
- LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data());
+ if (StorageTracker::tracker().isActive())
+ StorageTracker::tracker().deleteOrigin(m_databaseIdentifier);
+ else {
+ String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier);
+ if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename))
+ LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data());
+ }
}
}
+void StorageAreaSync::scheduleSync()
+{
+ syncTimerFired(&m_syncTimer);
+}
+
} // namespace WebCore
#endif // ENABLE(DOM_STORAGE)
void scheduleItemForSync(const String& key, const String& value);
void scheduleClear();
+ void scheduleCloseDatabase();
+
+ void scheduleSync();
private:
StorageAreaSync(PassRefPtr<StorageSyncManager>, PassRefPtr<StorageAreaImpl>, const String& databaseIdentifier);
bool m_syncScheduled;
bool m_syncInProgress;
bool m_databaseOpenFailed;
+
+ bool m_syncCloseDatabase;
mutable Mutex m_importLock;
mutable ThreadCondition m_importCondition;
virtual PassRefPtr<StorageNamespace> copy() = 0;
virtual void close() = 0;
virtual void unlock() = 0;
+ virtual void clearOriginForDeletion(SecurityOrigin*) = 0;
+ virtual void clearAllOriginsForDeletion() = 0;
+ virtual void sync() = 0;
};
} // namespace WebCore
#include "StorageAreaImpl.h"
#include "StorageMap.h"
#include "StorageSyncManager.h"
+#include "StorageTracker.h"
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
// Because there's a single event loop per-process, this is a no-op.
}
+void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin)
+{
+ ASSERT(isMainThread());
+
+ RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin);
+ if (storageArea)
+ storageArea->clearForOriginDeletion();
+}
+
+void StorageNamespaceImpl::clearAllOriginsForDeletion()
+{
+ ASSERT(isMainThread());
+
+ StorageAreaMap::iterator end = m_storageAreaMap.end();
+ for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
+ it->second->clearForOriginDeletion();
+}
+
+void StorageNamespaceImpl::sync()
+{
+ ASSERT(isMainThread());
+ StorageAreaMap::iterator end = m_storageAreaMap.end();
+ for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
+ it->second->sync();
+}
+
} // namespace WebCore
#endif // ENABLE(DOM_STORAGE)
virtual void close();
virtual void unlock();
+ // Not removing the origin's StorageArea from m_storageAreaMap because
+ // we're just deleting the underlying db file. If an item is added immediately
+ // after file deletion, we want the same StorageArea to eventually trigger
+ // a sync and for StorageAreaSync to recreate the backing db file.
+ virtual void clearOriginForDeletion(SecurityOrigin*);
+ virtual void clearAllOriginsForDeletion();
+ virtual void sync();
+
private:
StorageNamespaceImpl(StorageType, const String& path, unsigned quota);
--- /dev/null
+/*
+ * Copyright (C) 2011 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 "StorageTracker.h"
+
+#include "DatabaseThread.h"
+#include "FileSystem.h"
+#include "LocalStorageTask.h"
+#include "LocalStorageThread.h"
+#include "Logging.h"
+#include "PageGroup.h"
+#include "SQLiteFileSystem.h"
+#include "SQLiteStatement.h"
+#include "SecurityOrigin.h"
+#include "StorageTrackerClient.h"
+#include <wtf/MainThread.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+static StorageTracker* storageTracker = 0;
+
+void StorageTracker::initializeTracker(const String& storagePath)
+{
+ ASSERT(!storageTracker);
+ if (storageTracker)
+ return;
+
+ storageTracker = new StorageTracker(storagePath);
+ storageTracker->setIsActive(true);
+ storageTracker->importOriginIdentifiers();
+}
+
+StorageTracker& StorageTracker::tracker()
+{
+ if (!storageTracker) {
+ storageTracker = new StorageTracker("");
+ storageTracker->importOriginIdentifiers();
+ }
+
+ return *storageTracker;
+}
+
+StorageTracker::StorageTracker(const String& storagePath)
+ : m_client(0)
+ , m_thread(LocalStorageThread::create())
+ , m_isActive(false)
+{
+ ASSERT(isMainThread());
+
+ setStorageDirectoryPath(storagePath);
+
+ SQLiteFileSystem::registerSQLiteVFS();
+
+ m_thread->start();
+}
+
+void StorageTracker::setStorageDirectoryPath(const String& path)
+{
+ MutexLocker lockDatabase(m_databaseGuard);
+ ASSERT(!m_database.isOpen());
+
+ m_storageDirectoryPath = path.threadsafeCopy();
+}
+
+String StorageTracker::trackerDatabasePath() const
+{
+ return SQLiteFileSystem::appendDatabaseFileNameToPath(m_storageDirectoryPath, "StorageTracker.db");
+}
+
+void StorageTracker::openTrackerDatabase(bool createIfDoesNotExist)
+{
+ ASSERT(m_isActive);
+ ASSERT(!isMainThread());
+ ASSERT(!m_databaseGuard.tryLock());
+
+ if (m_database.isOpen())
+ return;
+
+ String databasePath = trackerDatabasePath();
+
+ if (!SQLiteFileSystem::ensureDatabaseFileExists(databasePath, createIfDoesNotExist)) {
+ if (createIfDoesNotExist)
+ LOG_ERROR("Failed to create database file '%s'", databasePath.ascii().data());
+ return;
+ }
+
+ if (!m_database.open(databasePath)) {
+ LOG_ERROR("Failed to open databasePath %s.", databasePath.ascii().data());
+ return;
+ }
+
+ m_database.disableThreadingChecks();
+
+ if (!m_database.tableExists("Origins")) {
+ if (!m_database.executeCommand("CREATE TABLE Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, path TEXT);"))
+ LOG_ERROR("Failed to create Origins table.");
+ }
+}
+
+void StorageTracker::importOriginIdentifiers()
+{
+ if (!m_isActive)
+ return;
+
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ m_thread->scheduleTask(LocalStorageTask::createOriginIdentifiersImport());
+}
+
+void StorageTracker::syncImportOriginIdentifiers()
+{
+ ASSERT(m_isActive);
+
+ ASSERT(!isMainThread());
+
+ {
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ openTrackerDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
+ SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Failed to prepare statement.");
+ return;
+ }
+
+ int result;
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ while ((result = statement.step()) == SQLResultRow)
+ m_originSet.add(statement.getColumnText(0).threadsafeCopy());
+ }
+
+ if (result != SQLResultDone)
+ LOG_ERROR("Failed to read in all origins from the database.");
+ }
+
+ syncFileSystemAndTrackerDatabase();
+
+ if (m_client) {
+ MutexLocker lockOrigins(m_originSetGuard);
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ m_client->dispatchDidModifyOrigin(*it);
+ }
+}
+
+void StorageTracker::syncFileSystemAndTrackerDatabase()
+{
+ ASSERT(m_isActive);
+
+ DEFINE_STATIC_LOCAL(const String, fileMatchPattern, ("*.localstorage"));
+ DEFINE_STATIC_LOCAL(const String, fileExt, (".localstorage"));
+ DEFINE_STATIC_LOCAL(const unsigned, fileExtLength, (fileExt.length()));
+
+ Vector<String> paths = listDirectory(m_storageDirectoryPath, fileMatchPattern);
+
+ // Add missing StorageTracker records.
+ OriginSet foundOrigins;
+ Vector<String>::const_iterator end = paths.end();
+ for (Vector<String>::const_iterator it = paths.begin(); it != end; ++it) {
+ String path = *it;
+ if (path.endsWith(fileExt, true) && path.length() > fileExtLength) {
+ String file = pathGetFileName(path);
+ String originIdentifier = file.substring(0, file.length() - fileExtLength);
+ if (!m_originSet.contains(originIdentifier)) {
+ if (isMainThread())
+ setOriginDetails(originIdentifier, path);
+ else
+ syncSetOriginDetails(originIdentifier, path);
+ }
+
+ foundOrigins.add(originIdentifier);
+ }
+ }
+
+ // Delete stale StorageTracker records.
+ OriginSet::const_iterator setEnd = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != setEnd; ++it) {
+ if (!foundOrigins.contains(*it)) {
+ if (isMainThread())
+ deleteOrigin(*it);
+ else
+ syncDeleteOrigin(*it);
+ }
+ }
+}
+
+void StorageTracker::setOriginDetails(const String& originIdentifier, const String& databaseFile)
+{
+ if (!m_isActive)
+ return;
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+
+ if (m_originSet.contains(originIdentifier))
+ return;
+
+ m_originSet.add(originIdentifier);
+ }
+
+ LocalStorageTask* task = LocalStorageTask::createSetOriginDetails(originIdentifier.threadsafeCopy(), databaseFile).leakPtr();
+
+ if (isMainThread()) {
+ ASSERT(m_thread);
+ m_thread->scheduleTask(task);
+ } else
+ callOnMainThread(scheduleTask, (void*)task);
+}
+
+void StorageTracker::scheduleTask(void* task)
+{
+ ASSERT(isMainThread());
+ ASSERT(StorageTracker::tracker().m_thread);
+
+ if (StorageTracker::tracker().m_thread)
+ StorageTracker::tracker().m_thread->scheduleTask((LocalStorageTask*)task);
+}
+
+void StorageTracker::syncSetOriginDetails(const String& originIdentifier, const String& databaseFile)
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ openTrackerDatabase(true);
+
+ if (!m_database.isOpen())
+ return;
+
+ SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());
+ return;
+ }
+
+ statement.bindText(1, originIdentifier);
+ statement.bindText(2, databaseFile);
+
+ if (statement.step() != SQLResultDone)
+ LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ if (!m_originSet.contains(originIdentifier))
+ m_originSet.add(originIdentifier);
+ }
+
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(originIdentifier);
+}
+
+void StorageTracker::origins(Vector<RefPtr<SecurityOrigin> >& result)
+{
+ ASSERT(m_isActive);
+
+ if (!m_isActive)
+ return;
+
+ // FIXME: StorageTracker is currently a singleton and should be assumed
+ // to have undefined behavior with more than one PageGroup.
+ ASSERT(PageGroup::numberOfPageGroups() == 1);
+
+ MutexLocker lockOrigins(m_originSetGuard);
+
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ result.append(SecurityOrigin::createFromDatabaseIdentifier(*it));
+}
+
+void StorageTracker::deleteAllOrigins()
+{
+ ASSERT(m_isActive);
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ if (!m_isActive)
+ return;
+
+ // FIXME: StorageTracker is currently a singleton and should be assumed
+ // to have undefined behavior with more than one PageGroup.
+ ASSERT(PageGroup::numberOfPageGroups() == 1);
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ willDeleteAllOrigins();
+ m_originSet.clear();
+ }
+
+ PageGroup::clearLocalStorageForAllOrigins();
+
+ m_thread->scheduleTask(LocalStorageTask::createDeleteAllOrigins());
+}
+
+void StorageTracker::syncDeleteAllOrigins()
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ openTrackerDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
+ SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Failed to prepare statement.");
+ return;
+ }
+
+ int result;
+ while ((result = statement.step()) == SQLResultRow) {
+ if (!canDeleteOrigin(statement.getColumnText(0)))
+ continue;
+
+ SQLiteFileSystem::deleteDatabaseFile(statement.getColumnText(1));
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(statement.getColumnText(0));
+ }
+
+ if (result != SQLResultDone)
+ LOG_ERROR("Failed to read in all origins from the database.");
+
+ if (m_database.isOpen())
+ m_database.close();
+
+ SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
+ SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
+}
+
+void StorageTracker::deleteOrigin(const String& originIdentifier)
+{
+ deleteOrigin(SecurityOrigin::createFromDatabaseIdentifier(originIdentifier).get());
+}
+
+void StorageTracker::deleteOrigin(SecurityOrigin* origin)
+{
+ ASSERT(m_isActive);
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ if (!m_isActive)
+ return;
+
+ // FIXME: StorageTracker is currently a singleton and should be assumed
+ // to have undefined behavior with more than one PageGroup.
+ ASSERT(PageGroup::numberOfPageGroups() == 1);
+
+ // Before deleting database, we need to clear in-memory local storage data
+ // in StorageArea, and to close the StorageArea db. It's possible for an
+ // item to be added immediately after closing the db and cause StorageAreaSync
+ // to reopen the db before the db is deleted by a StorageTracker thread.
+ // In this case, reopening the db in StorageAreaSync will cancel a pending
+ // StorageTracker db deletion.
+ PageGroup::clearLocalStorageForOrigin(origin);
+
+ String originId = origin->databaseIdentifier();
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ willDeleteOrigin(originId);
+ m_originSet.remove(originId);
+ }
+
+ m_thread->scheduleTask(LocalStorageTask::createDeleteOrigin(originId));
+}
+
+void StorageTracker::syncDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ if (!canDeleteOrigin(originIdentifier)) {
+ LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data());
+ return;
+ }
+
+ openTrackerDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
+ // Get origin's db file path, delete entry in tracker's db, then delete db file.
+ SQLiteStatement pathStatement(m_database, "SELECT path FROM Origins WHERE origin=?");
+ if (pathStatement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to prepare selection of path for origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+ pathStatement.bindText(1, originIdentifier);
+ int result = pathStatement.step();
+ if (result != SQLResultRow) {
+ LOG_ERROR("Unable to find origin '%s' in Origins table", originIdentifier.ascii().data());
+ return;
+ }
+
+ String path = pathStatement.getColumnText(0);
+
+ ASSERT(!path.isEmpty());
+
+ SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
+ if (deleteStatement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+ deleteStatement.bindText(1, originIdentifier);
+ if (!deleteStatement.executeCommand()) {
+ LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+
+ SQLiteFileSystem::deleteDatabaseFile(path);
+
+ bool shouldDeleteTrackerFiles = false;
+ {
+ MutexLocker originLock(m_originSetGuard);
+ m_originSet.remove(originIdentifier);
+ shouldDeleteTrackerFiles = m_originSet.isEmpty();
+ }
+
+ if (shouldDeleteTrackerFiles) {
+ m_database.close();
+ SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
+ SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
+ }
+
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(originIdentifier);
+}
+
+void StorageTracker::willDeleteAllOrigins()
+{
+ ASSERT(!m_originSetGuard.tryLock());
+
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ m_originsBeingDeleted.add((*it).threadsafeCopy());
+}
+
+void StorageTracker::willDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(isMainThread());
+ ASSERT(!m_originSetGuard.tryLock());
+
+ m_originsBeingDeleted.add(originIdentifier);
+}
+
+bool StorageTracker::canDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(!m_databaseGuard.tryLock());
+ MutexLocker lockOrigins(m_originSetGuard);
+ return m_originsBeingDeleted.contains(originIdentifier);
+}
+
+void StorageTracker::cancelDeletingOrigin(const String& originIdentifier)
+{
+ if (!m_isActive)
+ return;
+
+ MutexLocker lockOrigins(m_originSetGuard);
+ MutexLocker lockDatabase(m_databaseGuard);
+ if (!m_originsBeingDeleted.isEmpty())
+ m_originsBeingDeleted.remove(originIdentifier);
+}
+
+void StorageTracker::setClient(StorageTrackerClient* client)
+{
+ m_client = client;
+}
+
+void StorageTracker::syncLocalStorage()
+{
+ PageGroup::syncLocalStorage();
+}
+
+bool StorageTracker::isActive()
+{
+ return m_isActive;
+}
+
+void StorageTracker::setIsActive(bool flag)
+{
+ m_isActive = flag;
+}
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef StorageTracker_h
+#define StorageTracker_h
+
+#if ENABLE(DOM_STORAGE)
+
+#include "PlatformString.h"
+#include "SQLiteDatabase.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class LocalStorageTask;
+class LocalStorageThread;
+class SecurityOrigin;
+class StorageTrackerClient;
+
+class StorageTracker {
+ WTF_MAKE_NONCOPYABLE(StorageTracker);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static void initializeTracker(const String& storagePath);
+ static StorageTracker& tracker();
+ static void scheduleTask(void*);
+
+ void importOriginIdentifiers();
+ void setOriginDetails(const String& originIdentifier, const String& databaseFile);
+
+ void deleteAllOrigins();
+ void deleteOrigin(SecurityOrigin*);
+ void deleteOrigin(const String& originIdentifier);
+ void origins(Vector<RefPtr<SecurityOrigin> >& result);
+
+ void cancelDeletingOrigin(const String& originIdentifier);
+
+ void setClient(StorageTrackerClient*);
+
+ bool isActive();
+
+ // Sync to disk on background thread.
+ void syncDeleteAllOrigins();
+ void syncDeleteOrigin(const String& originIdentifier);
+ void syncSetOriginDetails(const String& originIdentifier, const String& databaseFile);
+ void syncImportOriginIdentifiers();
+ void syncFileSystemAndTrackerDatabase();
+
+ void syncLocalStorage();
+
+private:
+ StorageTracker(const String& storagePath);
+
+ String trackerDatabasePath() const;
+ void openTrackerDatabase(bool createIfDoesNotExist);
+
+ void setStorageDirectoryPath(const String&);
+
+ void deleteTrackerFiles();
+
+ bool canDeleteOrigin(const String& originIdentifier);
+ void willDeleteOrigin(const String& originIdentifier);
+ void willDeleteAllOrigins();
+
+ void originFilePaths(Vector<String>& paths);
+
+ void setIsActive(bool);
+
+ Mutex m_databaseGuard;
+ SQLiteDatabase m_database;
+
+ String m_storageDirectoryPath;
+
+ StorageTrackerClient* m_client;
+
+ typedef HashSet<String> OriginSet;
+
+ Mutex m_originSetGuard;
+ OriginSet m_originSet;
+ OriginSet m_originsBeingDeleted;
+
+ OwnPtr<LocalStorageThread> m_thread;
+
+ bool m_isActive;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DOM_STORAGE)
+
+#endif // StorageTracker_h
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef StorageTrackerClient_h
+#define StorageTrackerClient_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class StorageTrackerClient {
+public:
+ virtual ~StorageTrackerClient() { }
+ virtual void dispatchDidModifyOrigin(const String& originIdentifier) = 0;
+};
+
+} // namespace WebCore
+
+#endif // StorageTrackerClient_h
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ Add WebKit1 API to view and delete local storage
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+
+ * WebKit.xcodeproj/project.pbxproj:
+
2011-03-02 Sam Weinig <sam@webkit.org>
Reviewed by Anders Carlsson.
37B6FB4F1063530C000FDB3B /* WebPDFDocumentExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37B6FB4D1063530C000FDB3B /* WebPDFDocumentExtras.mm */; };
37D1DCA81065928C0068F7EF /* WebJSPDFDoc.h in Headers */ = {isa = PBXBuildFile; fileRef = 37D1DCA61065928C0068F7EF /* WebJSPDFDoc.h */; };
37D1DCA91065928C0068F7EF /* WebJSPDFDoc.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37D1DCA71065928C0068F7EF /* WebJSPDFDoc.mm */; };
+ 3AB02AF612C1319B00FBB694 /* WebStorageManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3AB02AF512C1319B00FBB694 /* WebStorageManager.mm */; };
+ 3AB02B0012C132B200FBB694 /* WebStorageManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB02AFF12C132B200FBB694 /* WebStorageManagerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 3ABB3C7A1309C3B500E93D94 /* WebStorageTrackerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ABB3C781309C3B500E93D94 /* WebStorageTrackerClient.h */; };
+ 3ABB3C7B1309C3B500E93D94 /* WebStorageTrackerClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3ABB3C791309C3B500E93D94 /* WebStorageTrackerClient.mm */; };
+ 3AE15D5012DBDED4009323C8 /* WebStorageManagerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AE15D4F12DBDED4009323C8 /* WebStorageManagerInternal.h */; };
41F4484F10338E8C0030E55E /* WebWorkersPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F4484D10338E8C0030E55E /* WebWorkersPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
41F4485010338E8C0030E55E /* WebWorkersPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41F4484E10338E8C0030E55E /* WebWorkersPrivate.mm */; };
44BB8B141241A022001E3A22 /* WebArchiveInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 44BB8B131241A022001E3A22 /* WebArchiveInternal.h */; };
3944607E020F50ED0ECA1767 /* WebBackForwardList.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebBackForwardList.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
3944607F020F50ED0ECA1767 /* WebHistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebHistoryItem.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
39446080020F50ED0ECA1767 /* WebHistoryItem.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebHistoryItem.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+ 3AB02AF512C1319B00FBB694 /* WebStorageManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebStorageManager.mm; sourceTree = "<group>"; };
+ 3AB02AFF12C132B200FBB694 /* WebStorageManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebStorageManagerPrivate.h; sourceTree = "<group>"; };
+ 3ABB3C781309C3B500E93D94 /* WebStorageTrackerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebStorageTrackerClient.h; sourceTree = "<group>"; };
+ 3ABB3C791309C3B500E93D94 /* WebStorageTrackerClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebStorageTrackerClient.mm; sourceTree = "<group>"; };
+ 3AE15D4F12DBDED4009323C8 /* WebStorageManagerInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebStorageManagerInternal.h; sourceTree = "<group>"; };
41F4484D10338E8C0030E55E /* WebWorkersPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebWorkersPrivate.h; path = mac/Workers/WebWorkersPrivate.h; sourceTree = "<group>"; };
41F4484E10338E8C0030E55E /* WebWorkersPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebWorkersPrivate.mm; path = mac/Workers/WebWorkersPrivate.mm; sourceTree = "<group>"; };
449098B90F8F82DF0076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; };
A5DEFC0E11D5343E00885273 /* WebDatabaseQuotaManager.mm */,
511F3FD30CECC88F00852565 /* WebDatabaseTrackerClient.h */,
511F3FD40CECC88F00852565 /* WebDatabaseTrackerClient.mm */,
+ 3AB02AF512C1319B00FBB694 /* WebStorageManager.mm */,
+ 3AB02AFF12C132B200FBB694 /* WebStorageManagerPrivate.h */,
+ 3AE15D4F12DBDED4009323C8 /* WebStorageManagerInternal.h */,
+ 3ABB3C781309C3B500E93D94 /* WebStorageTrackerClient.h */,
+ 3ABB3C791309C3B500E93D94 /* WebStorageTrackerClient.mm */,
);
name = Storage;
path = mac/Storage;
598AD92A1201CF3B00ABAE4E /* WebDeviceOrientationProviderMockInternal.h in Headers */,
598ADA461202275000ABAE4E /* WebDeviceOrientationProvider.h in Headers */,
93E2A1A4123B0B3C009FE12A /* WebDashboardRegion.h in Headers */,
+ 3AB02B0012C132B200FBB694 /* WebStorageManagerPrivate.h in Headers */,
CDA62AE2125F87C2007FD118 /* WebFullScreenController.h in Headers */,
+ 3AE15D5012DBDED4009323C8 /* WebStorageManagerInternal.h in Headers */,
+ 3ABB3C7A1309C3B500E93D94 /* WebStorageTrackerClient.h in Headers */,
BC42D324131ED1E00075FA4B /* WebLocalizableStringsInternal.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
598AD9221201CF1000ABAE4E /* WebDeviceOrientation.mm in Sources */,
598AD9281201CF3200ABAE4E /* WebDeviceOrientationProviderMock.mm in Sources */,
93E2A1A5123B0B3C009FE12A /* WebDashboardRegion.mm in Sources */,
+ 3AB02AF612C1319B00FBB694 /* WebStorageManager.mm in Sources */,
CDA62AE3125F87C2007FD118 /* WebFullScreenController.mm in Sources */,
+ 3ABB3C7B1309C3B500E93D94 /* WebStorageTrackerClient.mm in Sources */,
BC42D34D131ED3880075FA4B /* WebLocalizableStringsInternal.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ Add WebKit1 API to view and delete local storage
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+
+ * src/StorageNamespaceProxy.cpp:
+ (WebCore::StorageNamespaceProxy::clearOriginForDeletion):
+ (WebCore::StorageNamespaceProxy::clearAllOriginsForDeletion):
+ (WebCore::StorageNamespaceProxy::sync):
+ * src/StorageNamespaceProxy.h:
+
2011-03-11 Dominic Mazzoni <dmazzoni@google.com>
Reviewed by Dimitri Glazkov.
// FIXME: Implement.
}
+void StorageNamespaceProxy::clearOriginForDeletion(SecurityOrigin* origin)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void StorageNamespaceProxy::clearAllOriginsForDeletion()
+{
+ ASSERT_NOT_REACHED();
+}
+
+void StorageNamespaceProxy::sync()
+{
+ ASSERT_NOT_REACHED();
+}
+
} // namespace WebCore
#endif // ENABLE(DOM_STORAGE)
virtual PassRefPtr<StorageNamespace> copy();
virtual void close();
virtual void unlock();
+
+ virtual void clearOriginForDeletion(SecurityOrigin*);
+ virtual void clearAllOriginsForDeletion();
+
+ virtual void sync();
private:
OwnPtr<WebKit::WebStorageNamespace> m_storageNamespace;
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+ Add WebKit1 API to view and delete local storage
+
+ * Storage/WebStorageManager.mm: Added.
+ (+[WebStorageManager sharedWebStorageManager]):
+ (-[WebStorageManager origins]):
+ (-[WebStorageManager deleteAllOrigins]):
+ (-[WebStorageManager deleteOrigin:]):
+ (-[WebStorageManager syncLocalStorage]):
+ (-[WebStorageManager syncFileSystemAndTrackerDatabase]):
+ (storageDirectoryPath):
+ (WebKitInitializeStorageIfNecessary):
+ * Storage/WebStorageManagerInternal.h: Added.
+ * Storage/WebStorageManagerPrivate.h: Added.
+ * Storage/WebStorageTrackerClient.h: Added.
+ * Storage/WebStorageTrackerClient.mm: Added.
+ (WebStorageTrackerClient::sharedWebStorageTrackerClient):
+ (WebStorageTrackerClient::WebStorageTrackerClient):
+ (WebStorageTrackerClient::~WebStorageTrackerClient):
+ (WebStorageTrackerClient::dispatchDidModifyOriginOnMainThread):
+ (WebStorageTrackerClient::dispatchDidModifyOrigin):
+ * WebCoreSupport/WebSecurityOrigin.mm:
+ (-[WebSecurityOrigin protocol]):
+ (-[WebSecurityOrigin host]):
+ (-[WebSecurityOrigin databaseIdentifier]):
+ (-[WebSecurityOrigin domain]):
+ (-[WebSecurityOrigin _initWithWebCoreSecurityOrigin:]):
+ * WebCoreSupport/WebSecurityOriginPrivate.h:
+ * WebKit.exp:
+ * WebView/WebView.mm:
+ (-[WebView _commonInitializationWithFrameName:groupName:usesDocumentViews:]):
+
2011-03-10 Anders Carlsson <andersca@apple.com>
Reviewed by Sam Weinig.
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#if ENABLE(DOM_STORAGE)
+
+#import "WebSecurityOriginInternal.h"
+#import "WebStorageManagerPrivate.h"
+#import "WebStorageManagerInternal.h"
+#import "WebStorageTrackerClient.h"
+
+#import <WebCore/SecurityOrigin.h>
+#import <WebCore/StorageTracker.h>
+
+using namespace WebCore;
+
+NSString * const WebStorageDirectoryDefaultsKey = @"WebKitLocalStorageDatabasePathPreferenceKey";
+NSString * const WebStorageDidModifyOriginNotification = @"WebStorageDidModifyOriginNotification";
+
+static NSString *storageDirectoryPath();
+
+@implementation WebStorageManager
+
++ (WebStorageManager *)sharedWebStorageManager
+{
+ static WebStorageManager *sharedManager = [[WebStorageManager alloc] init];
+ return sharedManager;
+}
+
+- (NSArray *)origins
+{
+ Vector<RefPtr<SecurityOrigin> > coreOrigins;
+
+ StorageTracker::tracker().origins(coreOrigins);
+
+ NSMutableArray *webOrigins = [[NSMutableArray alloc] initWithCapacity:coreOrigins.size()];
+
+ for (size_t i = 0; i < coreOrigins.size(); ++i) {
+ WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:coreOrigins[i].get()];
+ [webOrigins addObject:webOrigin];
+ [webOrigin release];
+ }
+
+ return [webOrigins autorelease];
+}
+
+- (void)deleteAllOrigins
+{
+ StorageTracker::tracker().deleteAllOrigins();
+}
+
+- (void)deleteOrigin:(WebSecurityOrigin *)origin
+{
+ StorageTracker::tracker().deleteOrigin([origin _core]);
+}
+
+- (void)syncLocalStorage
+{
+ StorageTracker::tracker().syncLocalStorage();
+}
+
+- (void)syncFileSystemAndTrackerDatabase
+{
+ StorageTracker::tracker().syncFileSystemAndTrackerDatabase();
+}
+
+static NSString *storageDirectoryPath()
+{
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ NSString *storageDirectory = [defaults objectForKey:WebStorageDirectoryDefaultsKey];
+ if (!storageDirectory || ![storageDirectory isKindOfClass:[NSString class]])
+ storageDirectory = @"~/Library/WebKit/LocalStorage";
+
+ return [storageDirectory stringByStandardizingPath];
+}
+
+void WebKitInitializeStorageIfNecessary()
+{
+ static BOOL initialized = NO;
+ if (initialized)
+ return;
+
+ StorageTracker::initializeTracker(storageDirectoryPath());
+
+ StorageTracker::tracker().setClient(WebStorageTrackerClient::sharedWebStorageTrackerClient());
+
+ initialized = YES;
+}
+
+@end
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#if ENABLE(DOM_STORAGE)
+
+void WebKitInitializeStorageIfNecessary();
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+extern NSString * const WebStorageDirectoryDefaultsKey;
+extern NSString * const WebStorageDidModifyOriginNotification;
+
+@class WebSecurityOrigin;
+
+@interface WebStorageManager : NSObject
+
++ (WebStorageManager *)sharedWebStorageManager;
+
+// Returns an array of WebSecurityOrigin objects that have LocalStorage.
+- (NSArray *)origins;
+
+- (void)deleteAllOrigins;
+- (void)deleteOrigin:(WebSecurityOrigin *)origin;
+
+- (void)syncLocalStorage;
+- (void)syncFileSystemAndTrackerDatabase;
+
+@end
+
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#if ENABLE(DOM_STORAGE)
+
+#import <WebCore/SecurityOrigin.h>
+#import <WebCore/StorageTrackerClient.h>
+
+using namespace WebCore;
+
+class WebStorageTrackerClient : public WebCore::StorageTrackerClient {
+public:
+ static WebStorageTrackerClient* sharedWebStorageTrackerClient();
+ static void dispatchDidModifyOriginOnMainThread(void* context);
+
+ virtual ~WebStorageTrackerClient();
+ virtual void dispatchDidModifyOrigin(const String& originIdentifier);
+ virtual void dispatchDidModifyOrigin(PassRefPtr<SecurityOrigin>);
+private:
+ WebStorageTrackerClient();
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#if ENABLE(DOM_STORAGE)
+
+#import "WebStorageTrackerClient.h"
+
+#import "WebSecurityOriginInternal.h"
+#import "WebStorageManagerPrivate.h"
+#import <WebCore/PlatformString.h>
+#import <WebCore/SecurityOrigin.h>
+#import <wtf/MainThread.h>
+#import <wtf/RetainPtr.h>
+
+using namespace WebCore;
+
+WebStorageTrackerClient* WebStorageTrackerClient::sharedWebStorageTrackerClient()
+{
+ static WebStorageTrackerClient* sharedClient = new WebStorageTrackerClient();
+ return sharedClient;
+}
+
+WebStorageTrackerClient::WebStorageTrackerClient()
+{
+}
+
+WebStorageTrackerClient::~WebStorageTrackerClient()
+{
+}
+
+void WebStorageTrackerClient::dispatchDidModifyOriginOnMainThread(void* context)
+{
+ ASSERT(isMainThread());
+ WebStorageTrackerClient::sharedWebStorageTrackerClient()->dispatchDidModifyOrigin(static_cast<SecurityOrigin*>(context));
+}
+
+void WebStorageTrackerClient::dispatchDidModifyOrigin(PassRefPtr<SecurityOrigin> origin)
+{
+ RetainPtr<WebSecurityOrigin> webSecurityOrigin(AdoptNS, [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin.get()]);
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:WebStorageDidModifyOriginNotification
+ object:webSecurityOrigin.get()];
+}
+
+void WebStorageTrackerClient::dispatchDidModifyOrigin(const String& originIdentifier)
+{
+ PassRefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
+
+ if (!isMainThread()) {
+ callOnMainThread(dispatchDidModifyOriginOnMainThread, static_cast<void*>(origin.leakRef()));
+ return;
+ }
+
+ dispatchDidModifyOrigin(origin);
+}
+
+#endif
RefPtr<SecurityOrigin> origin = SecurityOrigin::create(KURL([url absoluteURL]));
origin->ref();
- _private = reinterpret_cast<WebSecurityOriginPrivate*>(origin.get());
+ _private = reinterpret_cast<WebSecurityOriginPrivate *>(origin.get());
return self;
}
-- (NSString*)protocol
+- (NSString *)protocol
{
return reinterpret_cast<SecurityOrigin*>(_private)->protocol();
}
-- (NSString*)host
+- (NSString *)host
{
return reinterpret_cast<SecurityOrigin*>(_private)->host();
}
+- (NSString *)databaseIdentifier
+{
+ return reinterpret_cast<SecurityOrigin*>(_private)->databaseIdentifier();
+}
+
// Deprecated. Use host instead. This needs to stay here until we ship a new Safari.
-- (NSString*)domain
+- (NSString *)domain
{
return [self host];
}
return nil;
origin->ref();
- _private = reinterpret_cast<WebSecurityOriginPrivate*>(origin);
+ _private = reinterpret_cast<WebSecurityOriginPrivate *>(origin);
return self;
}
- (id)initWithURL:(NSURL *)url;
-- (NSString*)protocol;
-- (NSString*)host;
+- (NSString *)protocol;
+- (NSString *)host;
+
+- (NSString *)databaseIdentifier;
// Returns zero if the port is the default port for the protocol, non-zero otherwise.
- (unsigned short)port;
.objc_class_name_WebCoreStatistics
.objc_class_name_WebDataSource
.objc_class_name_WebDatabaseManager
+.objc_class_name_WebStorageManager
.objc_class_name_WebDefaultPolicyDelegate
.objc_class_name_WebDeviceOrientation
.objc_class_name_WebDeviceOrientationProviderMock
_WebScriptErrorDescriptionKey
_WebScriptErrorDomain
_WebScriptErrorLineNumberKey
+_WebStorageDirectoryDefaultsKey
+_WebStorageDidModifyOriginNotification
_WebURLNamePboardType
_WebURLPboardType
_WebViewDidBeginEditingNotification
#import "WebPreferencesPrivate.h"
#import "WebScriptDebugDelegate.h"
#import "WebScriptWorldInternal.h"
+#import "WebStorageManagerInternal.h"
#import "WebSystemInterface.h"
#import "WebTextCompletionController.h"
#import "WebTextIterator.h"
#if ENABLE(DATABASE)
WebKitInitializeDatabasesIfNecessary();
#endif
+
+#if ENABLE(DOM_STORAGE)
+ WebKitInitializeStorageIfNecessary();
+#endif
WebKitInitializeApplicationCachePathIfNecessary();
patchMailRemoveAttributesMethod();
+2011-03-11 Anton D'Auria <adauria@apple.com>
+
+ Reviewed and landed by Brady Eidson.
+
+ https://bugs.webkit.org/show_bug.cgi?id=51878
+ Add WebKit1 API to view and delete local storage
+
+ Added tests that write to LocalStorage, delete one origin, get list of origins with local storage, delete all origins.
+
+ * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
+ * DumpRenderTree/LayoutTestController.cpp:
+ (syncLocalStorageCallback):
+ (observeStorageTrackerNotificationsCallback):
+ (deleteAllLocalStorageCallback):
+ (deleteLocalStorageForOriginCallback):
+ (originsWithLocalStorageCallback):
+ (LayoutTestController::staticFunctions):
+ * DumpRenderTree/LayoutTestController.h:
+ * DumpRenderTree/StorageTrackerDelegate.h: Added.
+ * DumpRenderTree/StorageTrackerDelegate.mm: Added.
+ (-[StorageTrackerDelegate init]):
+ (-[StorageTrackerDelegate logNotifications:controller:]):
+ (-[StorageTrackerDelegate originModified:]):
+ (-[StorageTrackerDelegate dealloc]):
+ (-[StorageTrackerDelegate setControllerToNotifyDone:]):
+ * DumpRenderTree/chromium/LayoutTestController.cpp:
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+ (observeStorageTrackerNotifications):
+ (syncLocalStorage):
+ * DumpRenderTree/chromium/LayoutTestController.h:
+ * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+ (LayoutTestController::observeStorageTrackerNotifications):
+ (LayoutTestController::syncLocalStorage):
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues):
+ (allocateGlobalControllers):
+ (releaseGlobalControllers):
+ * DumpRenderTree/mac/DumpRenderTreeMac.h:
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (LayoutTestController::syncLocalStorage):
+ (LayoutTestController::observeStorageTrackerNotifications):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+ (LayoutTestController::observeStorageTrackerNotifications):
+ (LayoutTestController::syncLocalStorage):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::clearAllApplicationCaches):
+ (LayoutTestController::syncLocalStorage):
+ (LayoutTestController::observeStorageTrackerNotifications):
+ (LayoutTestController::clearAllDatabases):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+ * DumpRenderTree/wx/LayoutTestControllerWx.cpp:
+ (LayoutTestController::syncLocalStorage):
+ (LayoutTestController::observeStorageTrackerNotifications):
+ (LayoutTestController::clearAllDatabases):
+ (LayoutTestController::deleteAllLocalStorage):
+ (LayoutTestController::originsWithLocalStorage):
+ (LayoutTestController::deleteLocalStorageForOrigin):
+
2011-03-11 Jessie Berlin <jberlin@apple.com>
Reviewed by Adam Roben.
29CFBA2E12273A1000BC30C0 /* AccessibilityTextMarkerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29CFBA2D12273A1000BC30C0 /* AccessibilityTextMarkerMac.mm */; };
3713EDE2115BE19300705720 /* ColorBits-A.png in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 3713EDDF115BE16F00705720 /* ColorBits-A.png */; };
3713EDE3115BE19300705720 /* ColorBits.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 3713EDE0115BE16F00705720 /* ColorBits.ttf */; };
+ 3A5626CB131CA02A002BE6D9 /* StorageTrackerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A5626C1131C8B17002BE6D9 /* StorageTrackerDelegate.mm */; };
+ 3A5626CC131CA036002BE6D9 /* StorageTrackerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A5626C0131C8B17002BE6D9 /* StorageTrackerDelegate.h */; };
440590711268453800CFD48D /* WebArchiveDumpSupportMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 440590701268453800CFD48D /* WebArchiveDumpSupportMac.mm */; };
4437730E125CBC3600AAE02C /* WebArchiveDumpSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 44A997830FCDE86400580F10 /* WebArchiveDumpSupport.cpp */; };
4437730F125CBC4D00AAE02C /* WebArchiveDumpSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */; };
375F09770DAC3CB600C8B4E5 /* WebKitWeightWatcher700.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher700.ttf; path = fonts/WebKitWeightWatcher700.ttf; sourceTree = "<group>"; };
375F09780DAC3CB600C8B4E5 /* WebKitWeightWatcher800.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher800.ttf; path = fonts/WebKitWeightWatcher800.ttf; sourceTree = "<group>"; };
375F09790DAC3CB600C8B4E5 /* WebKitWeightWatcher900.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher900.ttf; path = fonts/WebKitWeightWatcher900.ttf; sourceTree = "<group>"; };
+ 3A5626C0131C8B17002BE6D9 /* StorageTrackerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageTrackerDelegate.h; sourceTree = "<group>"; };
+ 3A5626C1131C8B17002BE6D9 /* StorageTrackerDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StorageTrackerDelegate.mm; sourceTree = "<group>"; };
440590701268453800CFD48D /* WebArchiveDumpSupportMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebArchiveDumpSupportMac.mm; path = mac/WebArchiveDumpSupportMac.mm; sourceTree = "<group>"; };
44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebArchiveDumpSupport.h; path = cf/WebArchiveDumpSupport.h; sourceTree = "<group>"; };
44A997830FCDE86400580F10 /* WebArchiveDumpSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebArchiveDumpSupport.cpp; path = cf/WebArchiveDumpSupport.cpp; sourceTree = "<group>"; };
BCA18B5E0C9B08C200114369 /* ResourceLoadDelegate.mm */,
BCA18B5F0C9B08C200114369 /* UIDelegate.h */,
BCA18B600C9B08C200114369 /* UIDelegate.mm */,
+ 3A5626C0131C8B17002BE6D9 /* StorageTrackerDelegate.h */,
+ 3A5626C1131C8B17002BE6D9 /* StorageTrackerDelegate.mm */,
);
name = Delegates;
sourceTree = "<group>";
5185F6B310714E12007AA393 /* HistoryDelegate.h in Headers */,
E1B7816711AF31C3007E1BC2 /* MockGeolocationProvider.h in Headers */,
29CFBA10122736E600BC30C0 /* AccessibilityTextMarker.h in Headers */,
+ 3A5626CC131CA036002BE6D9 /* StorageTrackerDelegate.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E1B7816511AF31B7007E1BC2 /* MockGeolocationProvider.mm in Sources */,
29CFBA11122736E600BC30C0 /* AccessibilityTextMarker.cpp in Sources */,
29CFBA2E12273A1000BC30C0 /* AccessibilityTextMarkerMac.mm in Sources */,
+ 3A5626CB131CA02A002BE6D9 /* StorageTrackerDelegate.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
return JSValueMakeUndefined(context);
}
+static JSValueRef syncLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+
+ controller->syncLocalStorage();
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef observeStorageTrackerNotificationsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ unsigned numNotifications = JSValueToNumber(context, arguments[0], exception);
+
+ ASSERT(!*exception);
+
+ controller->observeStorageTrackerNotifications(numNotifications);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef deleteAllLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ controller->deleteAllLocalStorage();
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef deleteLocalStorageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+ ASSERT(!*exception);
+
+ controller->deleteLocalStorageForOrigin(url.get());
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef originsWithLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ return controller->originsWithLocalStorage(context);
+}
+
static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has mac & windows implementation
{ "addOriginAccessWhitelistEntry", addOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setScrollbarPolicy", setScrollbarPolicyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "authenticateSession", authenticateSessionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "deleteAllLocalStorage", deleteAllLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "syncLocalStorage", syncLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "observeStorageTrackerNotifications", observeStorageTrackerNotificationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "deleteLocalStorageForOrigin", deleteLocalStorageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "originsWithLocalStorage", originsWithLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "observeStorageTrackerNotifications", observeStorageTrackerNotificationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "syncLocalStorage", syncLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setShouldPaintBrokenImage", setShouldPaintBrokenImageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0 }
};
JSRetainPtr<JSStringRef> markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const;
+ JSValueRef originsWithLocalStorage(JSContextRef);
+ void deleteAllLocalStorage();
+ void deleteLocalStorageForOrigin(JSStringRef originIdentifier);
+ void observeStorageTrackerNotifications(unsigned number);
+ void syncLocalStorage();
+
void setShouldPaintBrokenImage(bool);
bool shouldPaintBrokenImage() const { return m_shouldPaintBrokenImage; }
--- /dev/null
+/*
+ * Copyright (C) 2011 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. ``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
+ * 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.
+ */
+
+class LayoutTestController;
+
+@interface StorageTrackerDelegate : NSObject {
+ unsigned numberOfNotificationsToLog;
+ LayoutTestController* controllerToNotifyDone;
+}
+
+- (void)logNotifications:(unsigned)number controller:(LayoutTestController*)controller;
+- (void)originModified:(NSNotification *)notification;
+- (void)setControllerToNotifyDone:(LayoutTestController*)controller;
+
+@end
--- /dev/null
+/*
+ * Copyright (C) 2011 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. ``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
+ * 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.
+ */
+
+#import "config.h"
+#import "StorageTrackerDelegate.h"
+
+#import "LayoutTestController.h"
+#import <WebKit/WebSecurityOriginPrivate.h>
+#import <WebKit/WebStorageManagerPrivate.h>
+
+@implementation StorageTrackerDelegate
+
+- (id)init
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(originModified:) name:WebStorageDidModifyOriginNotification object:nil];
+
+ return self;
+}
+
+- (void)logNotifications:(unsigned)number controller:(LayoutTestController*)controller
+{
+ controllerToNotifyDone = controller;
+
+ numberOfNotificationsToLog = number;
+}
+
+- (void)originModified:(NSNotification *)notification
+{
+ if (!numberOfNotificationsToLog)
+ return;
+
+ numberOfNotificationsToLog--;
+
+ if (numberOfNotificationsToLog == 0 && controllerToNotifyDone) {
+ NSArray *origins = [[WebStorageManager sharedWebStorageManager] origins];
+ for (WebSecurityOrigin *origin in origins)
+ printf("Origin identifier: '%s'\n", [[origin databaseIdentifier] UTF8String]);
+
+ controllerToNotifyDone->notifyDone();
+ }
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:WebStorageDidModifyOriginNotification object:nil];
+
+ [super dealloc];
+}
+
+- (void)setControllerToNotifyDone:(LayoutTestController*)controller
+{
+ controllerToNotifyDone = controller;
+}
+
+
+@end
bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled);
bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode);
bindMethod("storeWebScriptObject", &LayoutTestController::storeWebScriptObject);
-
+ bindMethod("deleteAllLocalStorage", &LayoutTestController::deleteAllLocalStorage);
+ bindMethod("originsWithLocalStorage", &LayoutTestController::originsWithLocalStorage);
+ bindMethod("deleteLocalStorageForOrigin", &LayoutTestController::deleteLocalStorageForOrigin);
+ bindMethod("observeStorageTrackerNotifications", &LayoutTestController::observeStorageTrackerNotifications);
+ bindMethod("syncLocalStorage", &LayoutTestController::syncLocalStorage);
+
// The fallback method is called when an unknown method is invoked.
bindFallbackMethod(&LayoutTestController::fallbackMethod);
input->setValue(cppVariantToWebString(arguments[1]), true);
}
+
+void LayoutTestController::deleteAllLocalStorage(const CppArgumentList& arguments, CppVariant*)
+{
+ // Not Implemented
+}
+
+void LayoutTestController::originsWithLocalStorage(const CppArgumentList& arguments, CppVariant*)
+{
+ // Not Implemented
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(const CppArgumentList& arguments, CppVariant*)
+{
+ // Not Implemented
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(const CppArgumentList&, CppVariant*)
+{
+ // Not Implemented
+}
+
+void LayoutTestController::syncLocalStorage(const CppArgumentList&, CppVariant*)
+{
+ // Not Implemented
+}
+
+
// Forwards the setValueForUser() call to the element.
void setValueForUser(const CppArgumentList&, CppVariant*);
+ // LocalStorage origin-related
+ void deleteAllLocalStorage(const CppArgumentList&, CppVariant*);
+ void originsWithLocalStorage(const CppArgumentList&, CppVariant*);
+ void deleteLocalStorageForOrigin(const CppArgumentList&, CppVariant*);
+ void observeStorageTrackerNotifications(const CppArgumentList&, CppVariant*);
+ void syncLocalStorage(const CppArgumentList&, CppVariant*);
+
public:
// The following methods are not exposed to JavaScript.
void setWorkQueueFrozen(bool frozen) { m_workQueue.setFrozen(frozen); }
webkit_security_origin_set_web_database_quota(origin, quota);
}
+JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef)
+{
+ // FIXME: implement
+}
+
+void LayoutTestController::deleteAllLocalStorage()
+{
+ // FIXME: implement
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef originIdentifier)
+{
+ // FIXME: implement
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
+{
+ // FIXME: implement
+}
+
+void LayoutTestController::syncLocalStorage()
+{
+ // FIXME: implement
+}
+
void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool, JSStringRef)
{
// FIXME: implement
#import "PixelDumpSupport.h"
#import "PolicyDelegate.h"
#import "ResourceLoadDelegate.h"
+#import "StorageTrackerDelegate.h"
#import "UIDelegate.h"
#import "WebArchiveDumpSupport.h"
#import "WorkQueue.h"
#import <WebKit/WebPreferencesPrivate.h>
#import <WebKit/WebPreferenceKeysPrivate.h>
#import <WebKit/WebResourceLoadDelegate.h>
+#import <WebKit/WebStorageManagerPrivate.h>
#import <WebKit/WebTypesInternal.h>
#import <WebKit/WebViewPrivate.h>
#import <getopt.h>
static ResourceLoadDelegate *resourceLoadDelegate;
static HistoryDelegate *historyDelegate;
PolicyDelegate *policyDelegate;
+StorageTrackerDelegate *storageDelegate;
static int dumpPixels;
static int threaded;
NSString *path = libraryPathForDumpRenderTree();
[defaults setObject:[path stringByAppendingPathComponent:@"Databases"] forKey:WebDatabaseDirectoryDefaultsKey];
+ [defaults setObject:[path stringByAppendingPathComponent:@"LocalStorage"] forKey:WebStorageDirectoryDefaultsKey];
[defaults setObject:[path stringByAppendingPathComponent:@"LocalCache"] forKey:WebKitLocalCacheDefaultsKey];
WebPreferences *preferences = [WebPreferences standardPreferences];
resourceLoadDelegate = [[ResourceLoadDelegate alloc] init];
policyDelegate = [[PolicyDelegate alloc] init];
historyDelegate = [[HistoryDelegate alloc] init];
+ storageDelegate = [[StorageTrackerDelegate alloc] init];
}
// ObjC++ doens't seem to let me pass NSObject*& sadly.
releaseAndZero(&resourceLoadDelegate);
releaseAndZero(&uiDelegate);
releaseAndZero(&policyDelegate);
+ releaseAndZero(&storageDelegate);
}
static void initializeGlobalsFromCommandLineOptions(int argc, const char *argv[])
@class DumpRenderTreeDraggingInfo;
@class NavigationController;
@class PolicyDelegate;
+@class StorageTrackerDelegate;
@class WebFrame;
@class WebScriptWorld;
@class WebView;
class DumpRenderTreeDraggingInfo;
class NavigationController;
class PolicyDelegate;
+class StorageTrackerDelegate;
class WebFrame;
class WebScriptWorld;
class WebView;
extern DumpRenderTreeDraggingInfo *draggingInfo;
extern NavigationController* gNavigationController;
extern PolicyDelegate* policyDelegate;
+extern StorageTrackerDelegate* storageDelegate;
extern const unsigned maxViewHeight;
extern const unsigned maxViewWidth;
#import "EditingDelegate.h"
#import "MockGeolocationProvider.h"
#import "PolicyDelegate.h"
+#import "StorageTrackerDelegate.h"
#import "UIDelegate.h"
#import "WorkQueue.h"
#import "WorkQueueItem.h"
#import <WebKit/WebQuotaManager.h>
#import <WebKit/WebScriptWorld.h>
#import <WebKit/WebSecurityOriginPrivate.h>
+#import <WebKit/WebStorageManagerPrivate.h>
#import <WebKit/WebTypesInternal.h>
#import <WebKit/WebView.h>
#import <WebKit/WebViewPrivate.h>
[WebApplicationCache deleteAllApplicationCaches];
}
+void LayoutTestController::syncLocalStorage()
+{
+ [[WebStorageManager sharedWebStorageManager] syncLocalStorage];
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
+{
+ [storageDelegate logNotifications:number controller:this];
+}
+
void LayoutTestController::clearAllDatabases()
{
[[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases];
}
+void LayoutTestController::deleteAllLocalStorage()
+{
+ [[WebStorageManager sharedWebStorageManager] deleteAllOrigins];
+}
+
+JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
+{
+ WebStorageManager *storage = [WebStorageManager sharedWebStorageManager];
+
+ NSArray *origins = [storage origins];
+ NSInteger count = [origins count];
+
+ JSValueRef jsOriginsArray[count];
+ for (NSInteger i = 0; i < count; i++) {
+ NSString *origin = [[origins objectAtIndex:i] databaseIdentifier];
+ JSStringRef str = JSStringCreateWithCFString((CFStringRef)origin);
+ jsOriginsArray[i] = JSValueMakeString(context, str);
+ }
+
+ JSObjectRef jsArrayObject = JSObjectMakeArray(context, count, jsOriginsArray, NULL);
+ return jsArrayObject;
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
+{
+ RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, URL));
+
+ WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]];
+
+ [[WebStorageManager sharedWebStorageManager] deleteOrigin:origin];
+}
+
void LayoutTestController::clearBackForwardList()
{
WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList];
DumpRenderTreeSupportQt::setMinimumTimerInterval(m_drt->webPage(), minimumTimerInterval);
}
+void LayoutTestController::originsWithLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::deleteAllLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(const QString& originIdentifier)
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::syncLocalStorage()
+{
+ // FIXME: Implement.
+}
+
const unsigned LayoutTestController::maxViewWidth = 800;
const unsigned LayoutTestController::maxViewHeight = 600;
void addUserStyleSheet(const QString& sourceCode);
void setMinimumTimerInterval(double);
+
+ void originsWithLocalStorage();
+ void deleteAllLocalStorage();
+ void deleteLocalStorageForOrigin(const QString& originIdentifier);
+ void observeStorageTrackerNotifications(unsigned number);
+ void syncLocalStorage();
private slots:
void processWork();
// FIXME: Implement.
}
+void LayoutTestController::syncLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::deleteAllLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
+{
+ // FIXME: Implement.
+ return JSValueMakeUndefined(context);
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
+{
+ // FIXME: Implement.
+}
+
void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
{
COMPtr<IWebView> webView;
viewPrivate->setMinimumTimerInterval(minimumTimerInterval);
}
+
+
void LayoutTestController::setMinimumTimerInterval(double interval) {
}
-
+
+void LayoutTestController::syncLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::clearAllDatabases()
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::deleteAllLocalStorage()
+{
+ // FIXME: Implement.
+}
+
+JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
+{
+ // FIXME: Implement.
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef URL)
+{
+ // FIXME: Implement.
+}