Chromium Code Reviews| Index: content/browser/in_process_webkit/indexed_db_context.cc |
| diff --git a/content/browser/in_process_webkit/indexed_db_context.cc b/content/browser/in_process_webkit/indexed_db_context.cc |
| index 8e091c1678572dca7c3192b74addfff3e3a338cf..29c45aceb909a1af763693fd314835b1b5e41808 100644 |
| --- a/content/browser/in_process_webkit/indexed_db_context.cc |
| +++ b/content/browser/in_process_webkit/indexed_db_context.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/logging.h" |
| #include "base/message_loop_proxy.h" |
| #include "base/string_util.h" |
| +#include "base/task.h" |
| #include "base/utf_string_conversions.h" |
| #include "content/browser/browser_thread.h" |
| #include "content/browser/in_process_webkit/indexed_db_quota_client.h" |
| @@ -18,10 +19,12 @@ |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
| +#include "webkit/database/database_util.h" |
| #include "webkit/glue/webkit_glue.h" |
| #include "webkit/quota/quota_manager.h" |
| #include "webkit/quota/special_storage_policy.h" |
| +using webkit_database::DatabaseUtil; |
| using WebKit::WebIDBDatabase; |
| using WebKit::WebIDBFactory; |
| using WebKit::WebSecurityOrigin; |
| @@ -56,6 +59,41 @@ const FilePath::CharType IndexedDBContext::kIndexedDBDirectory[] = |
| const FilePath::CharType IndexedDBContext::kIndexedDBExtension[] = |
| FILE_PATH_LITERAL(".leveldb"); |
| +class IndexedDBContext::IndexedDBGetUsageAndQuotaCallback : |
|
dgrogan
2011/08/04 23:44:56
I recall seeing something that said nested class i
|
| + public quota::QuotaManager::GetUsageAndQuotaCallback { |
| + public: |
| + IndexedDBGetUsageAndQuotaCallback(IndexedDBContext* context, |
| + const GURL& origin_url) |
| + : context_(context), |
| + origin_url_(origin_url) { |
| + } |
| + |
| + void Run(quota::QuotaStatusCode status, int64 usage, int64 quota) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DCHECK(status == quota::kQuotaStatusOk || status == quota::kQuotaErrorAbort) |
| + << "status was " << status; |
| + if (status == quota::kQuotaErrorAbort) { |
| + // We seem to no longer care to wait around for the answer. |
| + return; |
| + } |
| + BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, |
| + NewRunnableMethod(context_.get(), |
| + &IndexedDBContext::GotUpdatedQuota, |
| + origin_url_, |
| + usage, |
| + quota)); |
| + } |
| + |
| + virtual void RunWithParams( |
| + const Tuple3<quota::QuotaStatusCode, int64, int64>& params) { |
| + Run(params.a, params.b, params.c); |
| + } |
| + |
| + private: |
| + scoped_refptr<IndexedDBContext> context_; |
| + const GURL origin_url_; |
| +}; |
| + |
| IndexedDBContext::IndexedDBContext( |
| WebKitContext* webkit_context, |
| quota::SpecialStoragePolicy* special_storage_policy, |
| @@ -100,19 +138,18 @@ FilePath IndexedDBContext::GetIndexedDBFilePath( |
| return data_path_.Append(id.append(kIndexedDBExtension)); |
| } |
| -void IndexedDBContext::DeleteIndexedDBFile(const FilePath& file_path) { |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| - // TODO(pastarmovj): Close all database connections that use that file. |
| - file_util::Delete(file_path, false); |
| -} |
| - |
| -void IndexedDBContext::DeleteIndexedDBForOrigin(const string16& origin_id) { |
| +// 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)); |
| - // TODO(pastarmovj): Remove this check once we are safe to delete any time. |
| - FilePath idb_file = GetIndexedDBFilePath(origin_id); |
| - DCHECK_EQ(idb_file.BaseName().value().substr(0, strlen("chrome-extension")), |
| - FILE_PATH_LITERAL("chrome-extension")); |
| - DeleteIndexedDBFile(GetIndexedDBFilePath(origin_id)); |
| + 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()) { |
| + file_util::Delete(idb_directory, true /*recursive*/); |
| + QueryDiskAndUpdateQuotaUsage(origin_url); |
| + } |
| } |
| bool IndexedDBContext::IsUnlimitedStorageGranted( |
| @@ -137,6 +174,113 @@ void IndexedDBContext::GetAllOriginIdentifiers( |
| } |
| } |
| +int64 IndexedDBContext::GetOriginDiskUsage(const GURL& origin_url) { |
| + return ResetDiskUsageCache(origin_url); |
| +} |
| + |
| +void IndexedDBContext::ConnectionOpened(const GURL& origin_url) { |
| + if (quota_manager_proxy()) { |
| + quota_manager_proxy()->NotifyStorageAccessed( |
| + quota::QuotaClient::kIndexedDatabase, origin_url, |
| + quota::kStorageTypeTemporary); |
| + } |
| + connection_count_[origin_url]++; |
| + QueryAvailableQuota(origin_url); |
| + EnsureDiskUsageCacheInitialized(origin_url); |
| +} |
| + |
| +void IndexedDBContext::ConnectionClosed(const GURL& origin_url) { |
| + if (quota_manager_proxy()) { |
| + quota_manager_proxy()->NotifyStorageAccessed( |
| + quota::QuotaClient::kIndexedDatabase, origin_url, |
| + quota::kStorageTypeTemporary); |
| + } |
| + connection_count_[origin_url]--; |
| + if (connection_count_[origin_url] == 0) { |
| + QueryDiskAndUpdateQuotaUsage(origin_url); |
| + connection_count_.erase(origin_url); |
| + } |
| +} |
| + |
| +void IndexedDBContext::TransactionComplete(const GURL& origin_url) { |
| + QueryDiskAndUpdateQuotaUsage(origin_url); |
| + QueryAvailableQuota(origin_url); |
| +} |
| + |
| +bool IndexedDBContext::WouldBeOverQuota(const GURL& origin_url, |
| + int64 additional_bytes) { |
| + if (space_available_map_.find(origin_url) == space_available_map_.end()) { |
| + // We haven't heard back from the QuotaManager yet, just let it through. |
| + return false; |
| + } |
| + bool over_quota = additional_bytes > space_available_map_[origin_url]; |
| + return over_quota; |
| +} |
| + |
| +bool IndexedDBContext::IsOverQuota(const GURL& origin_url) { |
| + const int kOneAdditionalByte = 1; |
| + return WouldBeOverQuota(origin_url, kOneAdditionalByte); |
| +} |
| + |
| quota::QuotaManagerProxy* IndexedDBContext::quota_manager_proxy() { |
| return quota_manager_proxy_; |
| } |
| + |
| +int64 IndexedDBContext::ReadUsageFromDisk(const GURL& origin_url) const { |
| + string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); |
| + FilePath file_path = GetIndexedDBFilePath(origin_id); |
| + return file_util::ComputeDirectorySize(file_path); |
| +} |
| + |
| +void IndexedDBContext::EnsureDiskUsageCacheInitialized(const GURL& origin_url) { |
| + if (origin_size_map_.find(origin_url) == origin_size_map_.end()) |
| + ResetDiskUsageCache(origin_url); |
| +} |
| + |
| +void IndexedDBContext::QueryDiskAndUpdateQuotaUsage(const GURL& origin_url) { |
| + EnsureDiskUsageCacheInitialized(origin_url); |
| + int64 former_disk_usage = origin_size_map_[origin_url]; |
| + int64 current_disk_usage = ReadUsageFromDisk(origin_url); |
| + int64 difference = current_disk_usage - former_disk_usage; |
| + if (difference) { |
| + origin_size_map_[origin_url] = current_disk_usage; |
| + // quota_manager_proxy() is NULL in unit tests. |
| + if (quota_manager_proxy()) |
| + quota_manager_proxy()->NotifyStorageModified( |
| + quota::QuotaClient::kIndexedDatabase, |
| + origin_url, |
| + quota::kStorageTypeTemporary, |
| + difference); |
| + } |
| +} |
| + |
| +void IndexedDBContext::GotUpdatedQuota(const GURL& origin_url, int64 usage, |
| + int64 quota) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| + space_available_map_[origin_url] = quota - usage; |
| +} |
| + |
| +void IndexedDBContext::QueryAvailableQuota(const GURL& origin_url) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| + if (quota_manager_proxy()) |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, &IndexedDBContext::QueryAvailableQuota, |
| + origin_url)); |
| + return; |
| + } |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (!quota_manager_proxy()->quota_manager()) |
| + return; |
| + IndexedDBGetUsageAndQuotaCallback* callback = |
| + new IndexedDBGetUsageAndQuotaCallback(this, origin_url); |
| + quota_manager_proxy()->quota_manager()->GetUsageAndQuota( |
| + origin_url, |
| + quota::kStorageTypeTemporary, |
| + callback); |
| +} |
| + |
| +int64 IndexedDBContext::ResetDiskUsageCache(const GURL& origin_url) { |
|
dgrogan
2011/08/04 23:44:56
The guts of the old "InitializeDiskUsage" are here
|
| + origin_size_map_[origin_url] = ReadUsageFromDisk(origin_url); |
| + return origin_size_map_[origin_url]; |
| +} |