diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-25 23:37:19 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-25 23:37:19 +0000 |
commit | ab30809a167f60c09bb25c303213cf416db05a8a (patch) | |
tree | 1aaad2881475e9f1f6d1f10d301807c7da9e6e15 /content/browser/in_process_webkit | |
parent | f1b666505ae42a96f2bfd230f40ff3bca8cf283b (diff) | |
download | chromium_src-ab30809a167f60c09bb25c303213cf416db05a8a.zip chromium_src-ab30809a167f60c09bb25c303213cf416db05a8a.tar.gz chromium_src-ab30809a167f60c09bb25c303213cf416db05a8a.tar.bz2 |
* Wire up the delete command in the cookie tree UI to actually delete indexedDBs. Also cleaned up some internal structures used by the UI layer.
* Clean up some loose ends around the transition from sqlite backing to leveldb backing. Code had not been updated to reflect that the indexedDBpath is a directory path instead of a file path.
* Fix a problem with reporting inconsistent size value to the quota manager. Now we always compute deltas against a cached size value and don't change the cached size value w/o reporting a delta.
* Fix a problem with erroneously accessing the filesystem for queries about indexed db usage when working with incognito profiles.
BUG=56249,76641
Review URL: http://codereview.chromium.org/7692016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98352 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/in_process_webkit')
5 files changed, 172 insertions, 92 deletions
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc index 7ccc8d8..ee5386c 100644 --- a/content/browser/in_process_webkit/indexed_db_browsertest.cc +++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc @@ -17,9 +17,12 @@ #include "content/browser/in_process_webkit/webkit_context.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/content_switches.h" +#include "webkit/database/database_util.h" #include "webkit/quota/quota_manager.h" +#include "webkit/quota/special_storage_policy.h" using quota::QuotaManager; +using webkit_database::DatabaseUtil; // This browser test is aimed towards exercising the IndexedDB bindings and // the actual implementation that lives in the browser side (in_process_webkit). @@ -124,41 +127,48 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug84933Test) { // In proc browser test is needed here because ClearLocalState indirectly calls // WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin. IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) { - // Create test files. ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - FilePath indexeddb_dir = temp_dir.path().Append( - IndexedDBContext::kIndexedDBDirectory); - ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir)); - FilePath::StringType file_name_1(FILE_PATH_LITERAL("http_foo_0")); - file_name_1.append(IndexedDBContext::kIndexedDBExtension); - FilePath::StringType file_name_2(FILE_PATH_LITERAL("chrome-extension_foo_0")); - file_name_2.append(IndexedDBContext::kIndexedDBExtension); - FilePath temp_file_path_1 = indexeddb_dir.Append(file_name_1); - FilePath temp_file_path_2 = indexeddb_dir.Append(file_name_2); - - ASSERT_EQ(1, file_util::WriteFile(temp_file_path_1, ".", 1)); - ASSERT_EQ(1, file_util::WriteFile(temp_file_path_2, "o", 1)); + FilePath protected_path; + FilePath unprotected_path; // Create the scope which will ensure we run the destructor of the webkit // context which should trigger the clean up. { TestingProfile profile; + + // Test our assumptions about what is protected and what is not. + const GURL kProtectedOrigin("chrome-extension://foo/"); + const GURL kUnprotectedOrigin("http://foo/"); + quota::SpecialStoragePolicy* policy = profile.GetSpecialStoragePolicy(); + ASSERT_TRUE(policy->IsStorageProtected(kProtectedOrigin)); + ASSERT_FALSE(policy->IsStorageProtected(kUnprotectedOrigin)); + + // Create some indexedDB paths. + // With the levelDB backend, these are directories. WebKitContext *webkit_context = profile.GetWebKitContext(); - webkit_context->indexed_db_context()->set_data_path(indexeddb_dir); + IndexedDBContext* idb_context = webkit_context->indexed_db_context(); + idb_context->set_data_path(temp_dir.path()); + protected_path = idb_context->GetIndexedDBFilePath( + DatabaseUtil::GetOriginIdentifier(kProtectedOrigin)); + unprotected_path = idb_context->GetIndexedDBFilePath( + DatabaseUtil::GetOriginIdentifier(kUnprotectedOrigin)); + ASSERT_TRUE(file_util::CreateDirectory(protected_path)); + ASSERT_TRUE(file_util::CreateDirectory(unprotected_path)); + + // Setup to clear all unprotected origins on exit. webkit_context->set_clear_local_state_on_exit(true); } + // Make sure we wait until the destructor has run. scoped_refptr<base::ThreadTestHelper> helper( new base::ThreadTestHelper( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::WEBKIT))); ASSERT_TRUE(helper->Run()); - // Because we specified https for scheme to be skipped the second file - // should survive and the first go into vanity. - ASSERT_FALSE(file_util::PathExists(temp_file_path_1)); - ASSERT_TRUE(file_util::PathExists(temp_file_path_2)); + ASSERT_TRUE(file_util::DirectoryExists(protected_path)); + ASSERT_FALSE(file_util::DirectoryExists(unprotected_path)); } class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest { diff --git a/content/browser/in_process_webkit/indexed_db_context.cc b/content/browser/in_process_webkit/indexed_db_context.cc index 0c9c8ff..3249ba8 100644 --- a/content/browser/in_process_webkit/indexed_db_context.cc +++ b/content/browser/in_process_webkit/indexed_db_context.cc @@ -15,7 +15,6 @@ #include "content/browser/in_process_webkit/indexed_db_quota_client.h" #include "content/browser/in_process_webkit/webkit_context.h" #include "content/common/content_switches.h" -#include "googleurl/src/gurl.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h" @@ -33,23 +32,42 @@ using WebKit::WebSecurityOrigin; namespace { -void ClearLocalState( +void GetAllOriginsAndPaths( const FilePath& indexeddb_path, - scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) { - file_util::FileEnumerator file_enumerator( - indexeddb_path, false, file_util::FileEnumerator::FILES); - // TODO(pastarmovj): We might need to consider exchanging this loop for - // something more efficient in the future. + std::vector<GURL>* origins, + std::vector<FilePath>* file_paths) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); + if (indexeddb_path.empty()) + return; + file_util::FileEnumerator file_enumerator(indexeddb_path, + false, file_util::FileEnumerator::DIRECTORIES); for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); file_path = file_enumerator.Next()) { - if (file_path.Extension() != IndexedDBContext::kIndexedDBExtension) - continue; - WebSecurityOrigin origin = - WebSecurityOrigin::createFromDatabaseIdentifier( - webkit_glue::FilePathToWebString(file_path.BaseName())); - if (special_storage_policy->IsStorageProtected(GURL(origin.toString()))) + if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) { + WebKit::WebString origin_id_webstring = + webkit_glue::FilePathToWebString(file_path.BaseName()); + origins->push_back( + DatabaseUtil::GetOriginFromIdentifier(origin_id_webstring)); + if (file_paths) + file_paths->push_back(file_path); + } + } +} + +void ClearLocalState( + const FilePath& indexeddb_path, + scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); + std::vector<GURL> origins; + std::vector<FilePath> file_paths; + GetAllOriginsAndPaths(indexeddb_path, &origins, &file_paths); + DCHECK_EQ(origins.size(), file_paths.size()); + std::vector<FilePath>::const_iterator file_path_iter = file_paths.begin(); + for (std::vector<GURL>::const_iterator iter = origins.begin(); + iter != origins.end(); ++iter, ++file_path_iter) { + if (special_storage_policy->IsStorageProtected(*iter)) continue; - file_util::Delete(file_path, false); + file_util::Delete(*file_path_iter, true); } } @@ -104,7 +122,8 @@ IndexedDBContext::IndexedDBContext( : clear_local_state_on_exit_(false), special_storage_policy_(special_storage_policy), quota_manager_proxy_(quota_manager_proxy) { - data_path_ = webkit_context->data_path().Append(kIndexedDBDirectory); + if (!webkit_context->is_incognito()) + data_path_ = webkit_context->data_path().Append(kIndexedDBDirectory); if (quota_manager_proxy && !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { quota_manager_proxy->RegisterClient( @@ -117,7 +136,7 @@ IndexedDBContext::~IndexedDBContext() { if (factory) BrowserThread::DeleteSoon(BrowserThread::WEBKIT, FROM_HERE, factory); - if (clear_local_state_on_exit_) { + if (clear_local_state_on_exit_ && !data_path_.empty()) { // No WEBKIT thread here means we are running in a unit test where no clean // up is needed. BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, @@ -127,32 +146,33 @@ IndexedDBContext::~IndexedDBContext() { } WebIDBFactory* IndexedDBContext::GetIDBFactory() { - if (!idb_factory_.get()) + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); + if (!idb_factory_.get()) { + // Prime our cache of origins with existing databases so we can + // detect when dbs are newly created. + GetOriginSet(); idb_factory_.reset(WebIDBFactory::create()); - DCHECK(idb_factory_.get()); + } return idb_factory_.get(); } -FilePath IndexedDBContext::GetIndexedDBFilePath( - const string16& origin_id) const { - FilePath::StringType id = - webkit_glue::WebStringToFilePathString(origin_id).append( - FILE_PATH_LITERAL(".indexeddb")); - return data_path_.Append(id.append(kIndexedDBExtension)); -} - -// Note: This is not called in response to a UI action in Content Settings. Only -// extension data deleter and quota manager currently call this. void IndexedDBContext::DeleteIndexedDBForOrigin(const GURL& origin_url) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); - string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); - FilePath idb_directory = GetIndexedDBFilePath(origin_id); - if (idb_directory.BaseName().value().substr(0, strlen("chrome-extension")) == - FILE_PATH_LITERAL("chrome-extension") || - connection_count_.find(origin_url) == connection_count_.end()) { + if (data_path_.empty() || !IsInOriginSet(origin_url)) + return; + // TODO(michaeln): When asked to delete an origin with open connections, + // forcibly close those connections then delete. + if (connection_count_.find(origin_url) == connection_count_.end()) { + string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); + FilePath idb_directory = GetIndexedDBFilePath(origin_id); EnsureDiskUsageCacheInitialized(origin_url); - file_util::Delete(idb_directory, true /*recursive*/); + bool deleted = file_util::Delete(idb_directory, true /*recursive*/); QueryDiskAndUpdateQuotaUsage(origin_url); + if (deleted) { + RemoveFromOriginSet(origin_url); + origin_size_map_.erase(origin_url); + space_available_map_.erase(origin_url); + } } } @@ -161,25 +181,31 @@ bool IndexedDBContext::IsUnlimitedStorageGranted( return special_storage_policy_->IsStorageUnlimited(origin); } -// TODO(dgrogan): Merge this code with the similar loop in -// BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread. -void IndexedDBContext::GetAllOriginIdentifiers( - std::vector<string16>* origin_ids) { +void IndexedDBContext::GetAllOrigins(std::vector<GURL>* origins) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); - file_util::FileEnumerator file_enumerator(data_path_, - false, file_util::FileEnumerator::DIRECTORIES); - for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); - file_path = file_enumerator.Next()) { - if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) { - WebKit::WebString origin_id_webstring = - webkit_glue::FilePathToWebString(file_path.BaseName()); - origin_ids->push_back(origin_id_webstring); - } + std::set<GURL>* origins_set = GetOriginSet(); + for (std::set<GURL>::const_iterator iter = origins_set->begin(); + iter != origins_set->end(); ++iter) { + origins->push_back(*iter); } } int64 IndexedDBContext::GetOriginDiskUsage(const GURL& origin_url) { - return ResetDiskUsageCache(origin_url); + if (data_path_.empty() || !IsInOriginSet(origin_url)) + return 0; + EnsureDiskUsageCacheInitialized(origin_url); + return origin_size_map_[origin_url]; +} + +base::Time IndexedDBContext::GetOriginLastModified(const GURL& origin_url) { + if (data_path_.empty() || !IsInOriginSet(origin_url)) + return base::Time(); + string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); + FilePath idb_directory = GetIndexedDBFilePath(origin_id); + base::PlatformFileInfo file_info; + if (!file_util::GetFileInfo(idb_directory, &file_info)) + return base::Time(); + return file_info.last_modified; } void IndexedDBContext::ConnectionOpened(const GURL& origin_url) { @@ -189,8 +215,13 @@ void IndexedDBContext::ConnectionOpened(const GURL& origin_url) { quota::kStorageTypeTemporary); } connection_count_[origin_url]++; + if (AddToOriginSet(origin_url)) { + // A newly created db, notify the quota system. + QueryDiskAndUpdateQuotaUsage(origin_url); + } else { + EnsureDiskUsageCacheInitialized(origin_url); + } QueryAvailableQuota(origin_url); - EnsureDiskUsageCacheInitialized(origin_url); } void IndexedDBContext::ConnectionClosed(const GURL& origin_url) { @@ -213,6 +244,15 @@ void IndexedDBContext::TransactionComplete(const GURL& origin_url) { QueryAvailableQuota(origin_url); } +FilePath IndexedDBContext::GetIndexedDBFilePath( + const string16& origin_id) const { + DCHECK(!data_path_.empty()); + FilePath::StringType id = + webkit_glue::WebStringToFilePathString(origin_id).append( + FILE_PATH_LITERAL(".indexeddb")); + return data_path_.Append(id.append(kIndexedDBExtension)); +} + bool IndexedDBContext::WouldBeOverQuota(const GURL& origin_url, int64 additional_bytes) { if (space_available_map_.find(origin_url) == space_available_map_.end()) { @@ -233,6 +273,8 @@ quota::QuotaManagerProxy* IndexedDBContext::quota_manager_proxy() { } int64 IndexedDBContext::ReadUsageFromDisk(const GURL& origin_url) const { + if (data_path_.empty()) + return 0; string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); FilePath file_path = GetIndexedDBFilePath(origin_id); return file_util::ComputeDirectorySize(file_path); @@ -240,7 +282,7 @@ int64 IndexedDBContext::ReadUsageFromDisk(const GURL& origin_url) const { void IndexedDBContext::EnsureDiskUsageCacheInitialized(const GURL& origin_url) { if (origin_size_map_.find(origin_url) == origin_size_map_.end()) - ResetDiskUsageCache(origin_url); + origin_size_map_[origin_url] = ReadUsageFromDisk(origin_url); } void IndexedDBContext::QueryDiskAndUpdateQuotaUsage(const GURL& origin_url) { @@ -285,7 +327,21 @@ void IndexedDBContext::QueryAvailableQuota(const GURL& origin_url) { callback); } -int64 IndexedDBContext::ResetDiskUsageCache(const GURL& origin_url) { - origin_size_map_[origin_url] = ReadUsageFromDisk(origin_url); - return origin_size_map_[origin_url]; +std::set<GURL>* IndexedDBContext::GetOriginSet() { + if (!origin_set_.get()) { + origin_set_.reset(new std::set<GURL>); + std::vector<GURL> origins; + GetAllOriginsAndPaths(data_path_, &origins, NULL); + for (std::vector<GURL>::const_iterator iter = origins.begin(); + iter != origins.end(); ++iter) { + origin_set_->insert(*iter); + } + } + return origin_set_.get(); +} + +void IndexedDBContext::ResetCaches() { + origin_set_.reset(); + origin_size_map_.clear(); + space_available_map_.clear(); } diff --git a/content/browser/in_process_webkit/indexed_db_context.h b/content/browser/in_process_webkit/indexed_db_context.h index 5ce0a6a..dd8ad0f 100644 --- a/content/browser/in_process_webkit/indexed_db_context.h +++ b/content/browser/in_process_webkit/indexed_db_context.h @@ -7,12 +7,16 @@ #pragma once #include <map> +#include <set> +#include <vector> #include "base/basictypes.h" #include "base/file_path.h" +#include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "content/browser/browser_thread.h" +#include "googleurl/src/gurl.h" class GURL; class FilePath; @@ -48,9 +52,6 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> { // The indexed db file extension. static const FilePath::CharType kIndexedDBExtension[]; - // Get the file name of the indexed db file for the given origin. - FilePath GetIndexedDBFilePath(const string16& origin_id) const; - void set_clear_local_state_on_exit(bool clear_local_state) { clear_local_state_on_exit_ = clear_local_state; } @@ -59,11 +60,12 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> { void DeleteIndexedDBForOrigin(const GURL& origin_url); // Does a particular origin get unlimited storage? - bool IsUnlimitedStorageGranted(const GURL& origin) const; + bool IsUnlimitedStorageGranted(const GURL& origin_url) const; // Methods used in response to QuotaManager requests. - void GetAllOriginIdentifiers(std::vector<string16>* origin_ids); + void GetAllOrigins(std::vector<GURL>* origins); int64 GetOriginDiskUsage(const GURL& origin_url); + base::Time GetOriginLastModified(const GURL& origin_url); // Methods called by IndexedDBDispatcherHost for quota support. void ConnectionOpened(const GURL& origin_url); @@ -80,28 +82,41 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> { #endif private: + FRIEND_TEST(ExtensionServiceTest, ClearExtensionData); + FRIEND_TEST(IndexedDBBrowserTest, ClearLocalState); + friend class IndexedDBQuotaClientTest; + typedef std::map<GURL, int64> OriginToSizeMap; class IndexedDBGetUsageAndQuotaCallback; + FilePath GetIndexedDBFilePath(const string16& origin_id) const; int64 ReadUsageFromDisk(const GURL& origin_url) const; void EnsureDiskUsageCacheInitialized(const GURL& origin_url); void QueryDiskAndUpdateQuotaUsage(const GURL& origin_url); void GotUpdatedQuota(const GURL& origin_url, int64 usage, int64 quota); void QueryAvailableQuota(const GURL& origin_url); - int64 ResetDiskUsageCache(const GURL& origin_url); - scoped_ptr<WebKit::WebIDBFactory> idb_factory_; + std::set<GURL>* GetOriginSet(); + bool AddToOriginSet(const GURL& origin_url) { + return GetOriginSet()->insert(origin_url).second; + } + void RemoveFromOriginSet(const GURL& origin_url) { + GetOriginSet()->erase(origin_url); + } + bool IsInOriginSet(const GURL& origin_url) { + std::set<GURL>* set = GetOriginSet(); + return set->find(origin_url) != set->end(); + } - // Path where the indexed db data is stored - FilePath data_path_; + // Only for testing. + void ResetCaches(); - // True if the destructor should delete its files. + scoped_ptr<WebKit::WebIDBFactory> idb_factory_; + FilePath data_path_; bool clear_local_state_on_exit_; - scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; - scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_; - + scoped_ptr<std::set<GURL> > origin_set_; OriginToSizeMap origin_size_map_; OriginToSizeMap space_available_map_; std::map<GURL, unsigned int> connection_count_; diff --git a/content/browser/in_process_webkit/indexed_db_quota_client.cc b/content/browser/in_process_webkit/indexed_db_quota_client.cc index 606188b..618f147 100644 --- a/content/browser/in_process_webkit/indexed_db_quota_client.cc +++ b/content/browser/in_process_webkit/indexed_db_quota_client.cc @@ -88,14 +88,12 @@ class IndexedDBQuotaClient::GetOriginsTaskBase : public HelperTask { virtual bool ShouldAddOrigin(const GURL& origin) = 0; virtual void RunOnTargetThread() OVERRIDE { - std::vector<string16> origin_identifiers; - indexed_db_context_->GetAllOriginIdentifiers(&origin_identifiers); - for (std::vector<string16>::const_iterator iter = - origin_identifiers.begin(); - iter != origin_identifiers.end(); ++iter) { - GURL origin = DatabaseUtil::GetOriginFromIdentifier(*iter); - if (ShouldAddOrigin(origin)) - origins_.insert(origin); + std::vector<GURL> origins; + indexed_db_context_->GetAllOrigins(&origins); + for (std::vector<GURL>::const_iterator iter = origins.begin(); + iter != origins.end(); ++iter) { + if (ShouldAddOrigin(*iter)) + origins_.insert(*iter); } } diff --git a/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc b/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc index a4cc8f6..19a544c 100644 --- a/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc +++ b/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc @@ -122,6 +122,7 @@ class IndexedDBQuotaClientTest : public TestingBrowserProcessTest { } file_path_origin = file_path_origin.Append(FILE_PATH_LITERAL("fake_file")); SetFileSizeTo(file_path_origin, size); + idb_context()->ResetCaches(); } private: |