Index: content/browser/in_process_webkit/indexed_db_context.cc |
=================================================================== |
--- content/browser/in_process_webkit/indexed_db_context.cc (revision 97928) |
+++ content/browser/in_process_webkit/indexed_db_context.cc (working copy) |
@@ -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 @@ |
namespace { |
+void GetAllOriginsAndPaths( |
+ const FilePath& indexeddb_path, |
+ 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) { |
+ 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) { |
- 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. |
- for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); |
- file_path = file_enumerator.Next()) { |
- if (file_path.Extension() != IndexedDBContext::kIndexedDBExtension) |
+ 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; |
- WebSecurityOrigin origin = |
- WebSecurityOrigin::createFromDatabaseIdentifier( |
- webkit_glue::FilePathToWebString(file_path.BaseName())); |
- if (special_storage_policy->IsStorageProtected(GURL(origin.toString()))) |
- continue; |
- file_util::Delete(file_path, false); |
+ file_util::Delete(*file_path_iter, true); |
} |
} |
@@ -104,7 +122,8 @@ |
: 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 @@ |
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 @@ |
} |
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,27 +181,33 @@ |
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) { |
if (quota_manager_proxy()) { |
quota_manager_proxy()->NotifyStorageAccessed( |
@@ -189,8 +215,13 @@ |
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 @@ |
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 @@ |
} |
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 @@ |
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 @@ |
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(); |
+} |