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..20f22d2bd5080f3b28953442f90ae83986c70484 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; |
| @@ -103,7 +106,7 @@ FilePath IndexedDBContext::GetIndexedDBFilePath( |
| 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); |
| + file_util::Delete(file_path, true /*recursive*/); |
| } |
| void IndexedDBContext::DeleteIndexedDBForOrigin(const string16& origin_id) { |
| @@ -115,6 +118,17 @@ void IndexedDBContext::DeleteIndexedDBForOrigin(const string16& origin_id) { |
| DeleteIndexedDBFile(GetIndexedDBFilePath(origin_id)); |
| } |
| +// TODO(dgrogan): Once we can delete IndexedDB directories out from underneath |
| +// open webkit instances, merge this and DeleteIndexedDBForOrigin. |
| +void IndexedDBContext::EvictOrigin(const GURL& origin_url) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| + if (connection_count_.find(origin_url) == connection_count_.end()) { |
| + string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); |
| + FilePath idb_directory = GetIndexedDBFilePath(origin_id); |
| + DeleteIndexedDBFile(idb_directory); |
| + } |
| +} |
| + |
| bool IndexedDBContext::IsUnlimitedStorageGranted( |
| const GURL& origin) const { |
| return special_storage_policy_->IsStorageUnlimited(origin); |
| @@ -137,6 +151,148 @@ void IndexedDBContext::GetAllOriginIdentifiers( |
| } |
| } |
| +int64 IndexedDBContext::InitializeDiskUsage(const GURL& origin_url) { |
| + int64 disk_usage = ReadUsageFromDisk(origin_url); |
|
dgrogan
2011/08/03 01:41:29
This deviates from "the Michael design." This fun
michaeln
2011/08/03 03:40:40
Seems reasonable, although if you do have a cached
kinuko
2011/08/03 09:12:22
(fwiw: I'm planning to make QM purge its cache per
dgrogan
2011/08/04 23:44:55
I remember why this deviated. The test code write
|
| + origin_size_map_[origin_url] = disk_usage; |
| + return disk_usage; |
| +} |
| + |
| +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::ConnectionClosed(const GURL& origin_url) { |
| + if (quota_manager_proxy()) { |
| + quota_manager_proxy()->NotifyStorageAccessed( |
| + quota::QuotaClient::kIndexedDatabase, origin_url, |
| + quota::kStorageTypeTemporary); |
| + } |
| + connection_count_[origin_url] --; |
|
kinuko
2011/08/03 09:12:22
nit: extra space before -- (here and at line 185)
dgrogan
2011/08/03 21:45:47
Done.
|
| + if (connection_count_[origin_url] == 0) { |
| + QueryDiskAndUpdateQuotaUsage(origin_url); |
| + connection_count_.erase(origin_url); |
| + } |
| +} |
| + |
| +void IndexedDBContext::NewConnection(const GURL& origin_url) { |
| + if (quota_manager_proxy()) { |
| + quota_manager_proxy()->NotifyStorageAccessed( |
| + quota::QuotaClient::kIndexedDatabase, origin_url, |
| + quota::kStorageTypeTemporary); |
| + } |
| + connection_count_[origin_url] ++; |
|
michaeln
2011/08/03 03:40:40
Seems like you may want to ensure you have a cache
dgrogan
2011/08/04 23:44:55
Done.
|
| + QueryAvailableQuota(origin_url); |
| +} |
| + |
| +bool IndexedDBContext::WouldBeOverQuota(const GURL& origin_url, |
| + int64 additional_bytes) { |
| + if (origin_allocated_quota_map_.find(origin_url) == |
| + origin_allocated_quota_map_.end()) { |
| + // We haven't heard back from the QuotaManager yet, just let it through. |
|
dgrogan
2011/08/03 01:41:29
This happened a few times in the existing browser
|
| + return false; |
| + } |
| + bool over_quota = additional_bytes + origin_size_map_[origin_url] > |
|
michaeln
2011/08/03 03:40:40
Is this comparing apples to oranges?
The lhs is i
dgrogan
2011/08/03 21:45:47
No. I'm glad you noticed this.
|
| + origin_allocated_quota_map_[origin_url]; |
| + return over_quota; |
| +} |
| + |
| +bool IndexedDBContext::IsOverQuota(const GURL& origin_url) { |
| + return WouldBeOverQuota(origin_url, 0 /*additional_bytes*/); |
|
michaeln
2011/08/03 03:40:40
return space_available <= 0;
dgrogan
2011/08/03 21:45:47
I did space_available < 1
|
| +} |
| + |
| +void IndexedDBContext::TransactionComplete(const GURL& origin_url) { |
| + QueryDiskAndUpdateQuotaUsage(origin_url); |
| + QueryAvailableQuota(origin_url); |
| +} |
| + |
| +void IndexedDBContext::QueryDiskAndUpdateQuotaUsage(const GURL& 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) { |
| + quota_manager_proxy()->NotifyStorageModified( |
| + quota::QuotaClient::kIndexedDatabase, |
| + origin_url, |
| + quota::kStorageTypeTemporary, |
| + difference); |
| + origin_size_map_[origin_url] = current_disk_usage; |
| + } |
| +} |
| + |
| +void IndexedDBContext::GotUpdatedQuota(const GURL& origin_url, int64 usage, |
| + int64 quota) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| + origin_allocated_quota_map_[origin_url] = quota; |
|
michaeln
2011/08/03 03:40:40
do u really want space_available_map_[origin_url]
dgrogan
2011/08/03 21:45:47
Yes I do.
|
| +} |
| + |
| +void GotUpdatedQuota(IndexedDBContext* context, const GURL& origin_url, |
|
michaeln
2011/08/03 03:40:40
this should be static or in an anon namespace if i
dgrogan
2011/08/03 21:45:47
deleted
|
| + int64 usage, int64 quota) { |
| + context->GotUpdatedQuota(origin_url, usage, quota); |
| +} |
| + |
| +class IndexedDBGetUsageAndQuotaCallback : |
| + 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, |
| + NewRunnableFunction(&GotUpdatedQuota, |
|
michaeln
2011/08/03 03:40:40
would a runnable object method work here inplace o
dgrogan
2011/08/03 21:45:47
Done.
|
| + context_, |
| + 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_; |
| +}; |
| + |
| +void RequestQuota( |
|
michaeln
2011/08/03 03:40:40
ditto comment about static or anon namespace
dgrogan
2011/08/03 21:45:47
Now in an anon namespace.
|
| + scoped_refptr<quota::QuotaManagerProxy> proxy, const GURL& gurl, |
| + IndexedDBGetUsageAndQuotaCallback* idb_quota_callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (!proxy->quota_manager()) { |
|
dgrogan
2011/08/03 21:45:47
If I switched to NewRunnableMethod, I'm worried ab
|
| + // QuotaManager was deleted on the IO thread just before this RequestQuota |
| + // task was run. |
| + return; |
| + } |
| + proxy->quota_manager()->GetUsageAndQuota( |
| + gurl, |
| + quota::kStorageTypeTemporary, |
| + idb_quota_callback); |
| +} |
| + |
| +void IndexedDBContext::QueryAvailableQuota(const GURL& origin_url) { |
| + IndexedDBGetUsageAndQuotaCallback* callback = |
| + new IndexedDBGetUsageAndQuotaCallback(this, origin_url); |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + NewRunnableFunction(&RequestQuota, |
|
michaeln
2011/08/03 03:40:40
ditto question about runnable object method
dgrogan
2011/08/03 21:45:47
It seems like I'd want to post a RunnableMethod(qu
|
| + scoped_refptr<quota::QuotaManagerProxy>( |
| + quota_manager_proxy()), |
| + origin_url, |
| + callback)); |
| +} |
| + |
| quota::QuotaManagerProxy* IndexedDBContext::quota_manager_proxy() { |
| return quota_manager_proxy_; |
| } |