| 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..4b9a5d52fa1d6e4b00b7a76f8e5b20dc4dd3bd75 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 :
|
| + 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,19 @@ 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()) {
|
| + EnsureDiskUsageCacheInitialized(origin_url);
|
| + file_util::Delete(idb_directory, true /*recursive*/);
|
| + QueryDiskAndUpdateQuotaUsage(origin_url);
|
| + }
|
| }
|
|
|
| bool IndexedDBContext::IsUnlimitedStorageGranted(
|
| @@ -137,6 +175,114 @@ 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) {
|
| + DCHECK(connection_count_[origin_url] > 0);
|
| + 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) {
|
| + DCHECK(connection_count_[origin_url] > 0);
|
| + 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) {
|
| + 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) {
|
| + origin_size_map_[origin_url] = ReadUsageFromDisk(origin_url);
|
| + return origin_size_map_[origin_url];
|
| +}
|
|
|