Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: content/browser/in_process_webkit/indexed_db_context.cc

Issue 7470008: Improve IndexedDB's quota support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged delete methods; simplify GetUsageCallback Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/in_process_webkit/indexed_db_context.h" 5 #include "content/browser/in_process_webkit/indexed_db_context.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop_proxy.h" 9 #include "base/message_loop_proxy.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/task.h"
11 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
12 #include "content/browser/browser_thread.h" 13 #include "content/browser/browser_thread.h"
13 #include "content/browser/in_process_webkit/indexed_db_quota_client.h" 14 #include "content/browser/in_process_webkit/indexed_db_quota_client.h"
14 #include "content/browser/in_process_webkit/webkit_context.h" 15 #include "content/browser/in_process_webkit/webkit_context.h"
15 #include "googleurl/src/gurl.h" 16 #include "googleurl/src/gurl.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h" 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
22 #include "webkit/database/database_util.h"
21 #include "webkit/glue/webkit_glue.h" 23 #include "webkit/glue/webkit_glue.h"
22 #include "webkit/quota/quota_manager.h" 24 #include "webkit/quota/quota_manager.h"
23 #include "webkit/quota/special_storage_policy.h" 25 #include "webkit/quota/special_storage_policy.h"
24 26
27 using webkit_database::DatabaseUtil;
25 using WebKit::WebIDBDatabase; 28 using WebKit::WebIDBDatabase;
26 using WebKit::WebIDBFactory; 29 using WebKit::WebIDBFactory;
27 using WebKit::WebSecurityOrigin; 30 using WebKit::WebSecurityOrigin;
28 31
29 namespace { 32 namespace {
30 33
31 void ClearLocalState( 34 void ClearLocalState(
32 const FilePath& indexeddb_path, 35 const FilePath& indexeddb_path,
33 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) { 36 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) {
34 file_util::FileEnumerator file_enumerator( 37 file_util::FileEnumerator file_enumerator(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } 96 }
94 97
95 FilePath IndexedDBContext::GetIndexedDBFilePath( 98 FilePath IndexedDBContext::GetIndexedDBFilePath(
96 const string16& origin_id) const { 99 const string16& origin_id) const {
97 FilePath::StringType id = 100 FilePath::StringType id =
98 webkit_glue::WebStringToFilePathString(origin_id).append( 101 webkit_glue::WebStringToFilePathString(origin_id).append(
99 FILE_PATH_LITERAL(".indexeddb")); 102 FILE_PATH_LITERAL(".indexeddb"));
100 return data_path_.Append(id.append(kIndexedDBExtension)); 103 return data_path_.Append(id.append(kIndexedDBExtension));
101 } 104 }
102 105
103 void IndexedDBContext::DeleteIndexedDBFile(const FilePath& file_path) { 106 // Note: This is not called in response to a UI action in Content Settings. Only
107 // extension data deleter and quota manager currently call this.
108 void IndexedDBContext::DeleteIndexedDBForOrigin(const GURL& origin_url) {
michaeln 2011/08/04 22:11:55 Thnx for consolidating the various Delete methods!
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
105 // TODO(pastarmovj): Close all database connections that use that file. 110 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
106 file_util::Delete(file_path, false); 111 FilePath idb_directory = GetIndexedDBFilePath(origin_id);
107 } 112 if (idb_directory.BaseName().value().substr(0, strlen("chrome-extension")) ==
108 113 FILE_PATH_LITERAL("chrome-extension") ||
109 void IndexedDBContext::DeleteIndexedDBForOrigin(const string16& origin_id) { 114 connection_count_.find(origin_url) == connection_count_.end()) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 115 file_util::Delete(idb_directory, true /*recursive*/);
111 // TODO(pastarmovj): Remove this check once we are safe to delete any time. 116 QueryDiskAndUpdateQuotaUsage(origin_url);
michaeln 2011/08/04 22:11:55 The QueryDiskAndUpdateQuotaUsage method relies on
dgrogan 2011/08/04 23:44:56 Good point. I added a EnsureDiskUsageCacheInitial
112 FilePath idb_file = GetIndexedDBFilePath(origin_id); 117 }
113 DCHECK_EQ(idb_file.BaseName().value().substr(0, strlen("chrome-extension")),
114 FILE_PATH_LITERAL("chrome-extension"));
115 DeleteIndexedDBFile(GetIndexedDBFilePath(origin_id));
116 } 118 }
117 119
118 bool IndexedDBContext::IsUnlimitedStorageGranted( 120 bool IndexedDBContext::IsUnlimitedStorageGranted(
119 const GURL& origin) const { 121 const GURL& origin) const {
120 return special_storage_policy_->IsStorageUnlimited(origin); 122 return special_storage_policy_->IsStorageUnlimited(origin);
121 } 123 }
122 124
123 // TODO(dgrogan): Merge this code with the similar loop in 125 // TODO(dgrogan): Merge this code with the similar loop in
124 // BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread. 126 // BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread.
125 void IndexedDBContext::GetAllOriginIdentifiers( 127 void IndexedDBContext::GetAllOriginIdentifiers(
126 std::vector<string16>* origin_ids) { 128 std::vector<string16>* origin_ids) {
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
128 file_util::FileEnumerator file_enumerator(data_path_, 130 file_util::FileEnumerator file_enumerator(data_path_,
129 false, file_util::FileEnumerator::DIRECTORIES); 131 false, file_util::FileEnumerator::DIRECTORIES);
130 for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); 132 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
131 file_path = file_enumerator.Next()) { 133 file_path = file_enumerator.Next()) {
132 if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) { 134 if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) {
133 WebKit::WebString origin_id_webstring = 135 WebKit::WebString origin_id_webstring =
134 webkit_glue::FilePathToWebString(file_path.BaseName()); 136 webkit_glue::FilePathToWebString(file_path.BaseName());
135 origin_ids->push_back(origin_id_webstring); 137 origin_ids->push_back(origin_id_webstring);
136 } 138 }
137 } 139 }
138 } 140 }
139 141
142 int64 IndexedDBContext::InitializeDiskUsage(const GURL& origin_url) {
143 int64 disk_usage = ReadUsageFromDisk(origin_url);
144 origin_size_map_[origin_url] = disk_usage;
145 return disk_usage;
146 }
147
148 int64 IndexedDBContext::ReadUsageFromDisk(const GURL& origin_url) const {
149 string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
150 FilePath file_path = GetIndexedDBFilePath(origin_id);
151 return file_util::ComputeDirectorySize(file_path);
152 }
153
154 void IndexedDBContext::ConnectionClosed(const GURL& origin_url) {
michaeln 2011/08/04 22:11:55 please put the methods in the .cc file in the same
dgrogan 2011/08/04 23:44:56 Sorry. Reordered.
155 if (quota_manager_proxy()) {
156 quota_manager_proxy()->NotifyStorageAccessed(
157 quota::QuotaClient::kIndexedDatabase, origin_url,
158 quota::kStorageTypeTemporary);
159 }
160 connection_count_[origin_url]--;
161 if (connection_count_[origin_url] == 0) {
162 QueryDiskAndUpdateQuotaUsage(origin_url);
163 connection_count_.erase(origin_url);
164 }
165 }
166
167 void IndexedDBContext::ConnectionOpened(const GURL& origin_url) {
168 if (quota_manager_proxy()) {
169 quota_manager_proxy()->NotifyStorageAccessed(
170 quota::QuotaClient::kIndexedDatabase, origin_url,
171 quota::kStorageTypeTemporary);
172 }
173 connection_count_[origin_url]++;
174 QueryAvailableQuota(origin_url);
michaeln 2011/08/04 22:11:55 what about guaranteeing that the size_map for the
dgrogan 2011/08/04 23:44:56 Sorry, hadn't gotten there yet, but it should be t
175 }
176
177 bool IndexedDBContext::WouldBeOverQuota(const GURL& origin_url,
178 int64 additional_bytes) {
179 if (space_available_map_.find(origin_url) == space_available_map_.end()) {
180 // We haven't heard back from the QuotaManager yet, just let it through.
181 return false;
182 }
183 bool over_quota = additional_bytes > space_available_map_[origin_url];
184 return over_quota;
185 }
186
187 bool IndexedDBContext::IsOverQuota(const GURL& origin_url) {
188 const int kOneAdditionalByte = 1;
189 return WouldBeOverQuota(origin_url, kOneAdditionalByte);
190 }
191
192 void IndexedDBContext::TransactionComplete(const GURL& origin_url) {
193 QueryDiskAndUpdateQuotaUsage(origin_url);
194 QueryAvailableQuota(origin_url);
195 }
196
197 void IndexedDBContext::QueryDiskAndUpdateQuotaUsage(const GURL& origin_url) {
198 int64 former_disk_usage = origin_size_map_[origin_url];
199 int64 current_disk_usage = ReadUsageFromDisk(origin_url);
200 int64 difference = current_disk_usage - former_disk_usage;
201 if (difference) {
202 origin_size_map_[origin_url] = current_disk_usage;
203 // quota_manager_proxy() is NULL in unit tests.
204 if (quota_manager_proxy())
205 quota_manager_proxy()->NotifyStorageModified(
206 quota::QuotaClient::kIndexedDatabase,
207 origin_url,
208 quota::kStorageTypeTemporary,
209 difference);
210 }
211 }
212
213 void IndexedDBContext::GotUpdatedQuota(const GURL& origin_url, int64 usage,
214 int64 quota) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
216 space_available_map_[origin_url] = quota - usage;
217 }
218
219 class IndexedDBContext::IndexedDBGetUsageAndQuotaCallback :
220 public quota::QuotaManager::GetUsageAndQuotaCallback {
221 public:
222 IndexedDBGetUsageAndQuotaCallback(IndexedDBContext* context,
223 const GURL& origin_url)
224 : context_(context),
225 origin_url_(origin_url) {
226 }
227
228 void Run(quota::QuotaStatusCode status, int64 usage, int64 quota) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230 DCHECK(status == quota::kQuotaStatusOk || status == quota::kQuotaErrorAbort)
231 << "status was " << status;
232 context_->Release();
233 if (status == quota::kQuotaErrorAbort) {
234 // We seem to no longer care to wait around for the answer.
235 return;
236 }
237 BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE,
238 NewRunnableMethod(context_.get(),
239 &IndexedDBContext::GotUpdatedQuota,
240 origin_url_,
241 usage,
242 quota));
243 }
244
245 virtual void RunWithParams(
246 const Tuple3<quota::QuotaStatusCode, int64, int64>& params) {
michaeln 2011/08/04 22:11:55 doh... i see origin_url is not available here
247 Run(params.a, params.b, params.c);
248 }
249
250 private:
251 scoped_refptr<IndexedDBContext> context_;
252 const GURL origin_url_;
253 };
254
255 void IndexedDBContext::QueryAvailableQuota(const GURL& origin_url) {
256 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
258 if (quota_manager_proxy())
259 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
260 NewRunnableMethod(this, &IndexedDBContext::QueryAvailableQuota,
261 origin_url));
262 return;
263 }
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
265 if (!quota_manager_proxy()->quota_manager())
266 return;
267 AddRef(); // Balanced in IndexedDBGetUsageAndQuotaCallback::Run.
michaeln 2011/08/04 22:11:55 AddRef (and balancing Release) is not needed since
dgrogan 2011/08/04 23:44:56 Ah, right. Removed.
268 IndexedDBGetUsageAndQuotaCallback* callback =
269 new IndexedDBGetUsageAndQuotaCallback(this, origin_url);
270 quota_manager_proxy()->quota_manager()->GetUsageAndQuota(
271 origin_url,
272 quota::kStorageTypeTemporary,
273 callback);
274 }
275
140 quota::QuotaManagerProxy* IndexedDBContext::quota_manager_proxy() { 276 quota::QuotaManagerProxy* IndexedDBContext::quota_manager_proxy() {
141 return quota_manager_proxy_; 277 return quota_manager_proxy_;
142 } 278 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698