Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "content/browser/storage_partition_impl.h" |
| 6 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 7 | #include "base/sequenced_task_runner.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 8 | #include "base/strings/utf_string_conversions.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 9 | #include "content/browser/browser_main_loop.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 10 | #include "content/browser/fileapi/browser_file_system_helper.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 11 | #include "content/browser/gpu/shader_disk_cache.h" |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 12 | #include "content/common/dom_storage/dom_storage_types.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 13 | #include "content/public/browser/browser_context.h" |
| 14 | #include "content/public/browser/browser_thread.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 15 | #include "content/public/browser/dom_storage_context.h" |
| 16 | #include "content/public/browser/indexed_db_context.h" |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 17 | #include "content/public/browser/local_storage_usage_info.h" |
| 18 | #include "content/public/browser/session_storage_usage_info.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 19 | #include "net/base/completion_callback.h" |
| 20 | #include "net/base/net_errors.h" |
| 21 | #include "net/cookies/cookie_monster.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 22 | #include "net/url_request/url_request_context.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 23 | #include "net/url_request/url_request_context_getter.h" |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 24 | #include "webkit/browser/database/database_tracker.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 25 | #include "webkit/browser/quota/quota_manager.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 26 | |
| 27 | namespace content { |
| 28 | |
| 29 | namespace { |
| 30 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 31 | int GenerateQuotaClientMask(uint32 remove_mask) { |
| 32 | int quota_client_mask = 0; |
| 33 | |
| 34 | if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS) |
| 35 | quota_client_mask |= quota::QuotaClient::kFileSystem; |
| 36 | if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL) |
| 37 | quota_client_mask |= quota::QuotaClient::kDatabase; |
| 38 | if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE) |
| 39 | quota_client_mask |= quota::QuotaClient::kAppcache; |
| 40 | if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB) |
| 41 | quota_client_mask |= quota::QuotaClient::kIndexedDatabase; |
| 42 | |
| 43 | return quota_client_mask; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 44 | } |
| 45 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 46 | void OnClearedCookies(const base::Closure& callback, int num_deleted) { |
| 47 | // The final callback needs to happen from UI thread. |
| 48 | if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 49 | BrowserThread::PostTask( |
| 50 | BrowserThread::UI, FROM_HERE, |
| 51 | base::Bind(&OnClearedCookies, callback, num_deleted)); |
| 52 | return; |
| 53 | } |
| 54 | |
| 55 | callback.Run(); |
| 56 | } |
| 57 | |
| 58 | void ClearCookiesOnIOThread( |
| 59 | const scoped_refptr<net::URLRequestContextGetter>& rq_context, |
| 60 | const base::Time begin, |
| 61 | const base::Time end, |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 62 | const GURL& remove_origin, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 63 | const base::Closure& callback) { |
| 64 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 65 | net::CookieStore* cookie_store = rq_context-> |
| 66 | GetURLRequestContext()->cookie_store(); |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 67 | if (remove_origin.is_empty()) { |
| 68 | cookie_store->GetCookieMonster()->DeleteAllCreatedBetweenAsync( |
| 69 | begin, |
| 70 | end, |
| 71 | base::Bind(&OnClearedCookies, callback)); |
| 72 | } else { |
| 73 | cookie_store->GetCookieMonster()->DeleteAllCreatedBetweenForHostAsync( |
| 74 | begin, |
| 75 | end, |
| 76 | remove_origin, base::Bind(&OnClearedCookies, callback)); |
| 77 | } |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | void OnQuotaManagedOriginDeleted(const GURL& origin, |
| 81 | quota::StorageType type, |
| 82 | size_t* origins_to_delete_count, |
| 83 | const base::Closure& callback, |
| 84 | quota::QuotaStatusCode status) { |
| 85 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 86 | DCHECK_GT(*origins_to_delete_count, 0u); |
| 87 | if (status != quota::kQuotaStatusOk) { |
| 88 | DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " |
| 89 | << origin << ". Status: " << status; |
| 90 | } |
| 91 | |
| 92 | (*origins_to_delete_count)--; |
| 93 | if (*origins_to_delete_count == 0) { |
| 94 | delete origins_to_delete_count; |
| 95 | callback.Run(); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | void ClearQuotaManagedOriginsOnIOThread(quota::QuotaManager* quota_manager, |
| 100 | uint32 remove_mask, |
| 101 | const base::Closure& callback, |
| 102 | const std::set<GURL>& origins, |
| 103 | quota::StorageType quota_storage_type) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 104 | // The QuotaManager manages all storage other than cookies, LocalStorage, |
| 105 | // and SessionStorage. This loop wipes out most HTML5 storage for the given |
| 106 | // origins. |
| 107 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 108 | |
| 109 | if (!origins.size()) { |
| 110 | // No origins to clear. |
| 111 | callback.Run(); |
| 112 | return; |
| 113 | } |
| 114 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 115 | std::set<GURL>::const_iterator origin; |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 116 | size_t* origins_to_delete_count = new size_t(origins.size()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 117 | for (std::set<GURL>::const_iterator origin = origins.begin(); |
| 118 | origin != origins.end(); ++origin) { |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 119 | quota_manager->DeleteOriginData( |
| 120 | *origin, quota_storage_type, |
| 121 | GenerateQuotaClientMask(remove_mask), |
| 122 | base::Bind(&OnQuotaManagedOriginDeleted, |
| 123 | origin->GetOrigin(), quota_storage_type, |
| 124 | origins_to_delete_count, callback)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 128 | void ClearedShaderCache(const base::Closure& callback) { |
| 129 | if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 130 | BrowserThread::PostTask( |
| 131 | BrowserThread::UI, FROM_HERE, |
| 132 | base::Bind(&ClearedShaderCache, callback)); |
| 133 | return; |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 134 | } |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 135 | callback.Run(); |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 136 | } |
| 137 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 138 | void ClearShaderCacheOnIOThread(const base::FilePath& path, |
| 139 | const base::Time begin, |
| 140 | const base::Time end, |
| 141 | const base::Closure& callback) { |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 142 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 143 | ShaderCacheFactory::GetInstance()->ClearByPath( |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 144 | path, begin, end, base::Bind(&ClearedShaderCache, callback)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | void OnLocalStorageUsageInfo( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 148 | const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 149 | const base::Time delete_begin, |
| 150 | const base::Time delete_end, |
| 151 | const base::Closure& callback, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 152 | const std::vector<LocalStorageUsageInfo>& infos) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 153 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 154 | |
| 155 | for (size_t i = 0; i < infos.size(); ++i) { |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 156 | if (infos[i].last_modified >= delete_begin && |
| 157 | infos[i].last_modified <= delete_end) { |
| 158 | dom_storage_context->DeleteLocalStorage(infos[i].origin); |
| 159 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 160 | } |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 161 | callback.Run(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | void OnSessionStorageUsageInfo( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 165 | const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 166 | const base::Closure& callback, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 167 | const std::vector<SessionStorageUsageInfo>& infos) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 168 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 169 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 170 | for (size_t i = 0; i < infos.size(); ++i) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 171 | dom_storage_context->DeleteSessionStorage(infos[i]); |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 172 | |
| 173 | callback.Run(); |
| 174 | } |
| 175 | |
| 176 | void ClearLocalStorageOnUIThread( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 177 | const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 178 | const GURL& remove_origin, |
| 179 | const base::Time begin, |
| 180 | const base::Time end, |
| 181 | const base::Closure& callback) { |
| 182 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 183 | |
| 184 | if (!remove_origin.is_empty()) { |
| 185 | dom_storage_context->DeleteLocalStorage(remove_origin); |
| 186 | callback.Run(); |
| 187 | return; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 188 | } |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 189 | |
| 190 | dom_storage_context->GetLocalStorageUsage( |
| 191 | base::Bind(&OnLocalStorageUsageInfo, |
| 192 | dom_storage_context, begin, end, callback)); |
| 193 | } |
| 194 | |
| 195 | void ClearSessionStorageOnUIThread( |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 196 | const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 197 | const base::Closure& callback) { |
| 198 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 199 | |
| 200 | dom_storage_context->GetSessionStorageUsage( |
| 201 | base::Bind(&OnSessionStorageUsageInfo, dom_storage_context, callback)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 202 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 203 | |
| 204 | } // namespace |
| 205 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 206 | // Helper for deleting quota managed data from a partition. |
| 207 | // |
| 208 | // Most of the operations in this class are done on IO thread. |
| 209 | struct StoragePartitionImpl::QuotaManagedDataDeletionHelper { |
| 210 | QuotaManagedDataDeletionHelper(const base::Closure& callback) |
| 211 | : callback(callback), task_count(0) { |
| 212 | } |
| 213 | |
| 214 | void IncrementTaskCountOnIO(); |
| 215 | void DecrementTaskCountOnIO(); |
| 216 | |
| 217 | void ClearDataOnIOThread( |
| 218 | const scoped_refptr<quota::QuotaManager>& quota_manager, |
| 219 | const base::Time begin, |
| 220 | uint32 remove_mask, |
| 221 | uint32 quota_storage_remove_mask, |
| 222 | const GURL& remove_origin); |
| 223 | |
| 224 | // Accessed on IO thread. |
| 225 | const base::Closure callback; |
| 226 | // Accessed on IO thread. |
| 227 | int task_count; |
| 228 | }; |
| 229 | |
| 230 | // Helper for deleting all sorts of data from a partition, keeps track of |
| 231 | // deletion status. |
| 232 | // |
| 233 | // StoragePartitionImpl creates an instance of this class to keep track of |
| 234 | // data deletion progress. Deletion requires deleting multiple bits of data |
| 235 | // (e.g. cookies, local storage, session storage etc.) and hopping between UI |
| 236 | // and IO thread. An instance of this class is created in the beginning of |
| 237 | // deletion process (StoragePartitionImpl::ClearDataImpl) and the instance is |
| 238 | // forwarded and updated on each (sub) deletion's callback. The instance is |
| 239 | // finally destroyed when deletion completes (and |callback| is invoked). |
| 240 | struct StoragePartitionImpl::DataDeletionHelper { |
| 241 | DataDeletionHelper(const base::Closure& callback) |
| 242 | : callback(callback), task_count(0) { |
| 243 | } |
| 244 | |
| 245 | void IncrementTaskCountOnUI(); |
| 246 | void DecrementTaskCountOnUI(); |
| 247 | |
| 248 | void ClearDataOnUIThread(uint32 remove_mask, |
| 249 | uint32 quota_storage_remove_mask, |
| 250 | const GURL& remove_origin, |
| 251 | const base::FilePath& path, |
| 252 | net::URLRequestContextGetter* rq_context, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 253 | DOMStorageContextWrapper* dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 254 | quota::QuotaManager* quota_manager, |
| 255 | const base::Time begin, |
| 256 | const base::Time end); |
| 257 | |
| 258 | // Accessed on UI thread. |
| 259 | const base::Closure callback; |
| 260 | // Accessed on UI thread. |
| 261 | int task_count; |
| 262 | }; |
| 263 | |
| 264 | void ClearQuotaManagedDataOnIOThread( |
| 265 | const scoped_refptr<quota::QuotaManager>& quota_manager, |
| 266 | const base::Time begin, |
| 267 | uint32 remove_mask, |
| 268 | uint32 quota_storage_remove_mask, |
| 269 | const GURL& remove_origin, |
| 270 | const base::Closure& callback) { |
| 271 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 272 | |
| 273 | StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper = |
| 274 | new StoragePartitionImpl::QuotaManagedDataDeletionHelper(callback); |
| 275 | helper->ClearDataOnIOThread(quota_manager, begin, |
| 276 | remove_mask, quota_storage_remove_mask, remove_origin); |
| 277 | } |
| 278 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 279 | StoragePartitionImpl::StoragePartitionImpl( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 280 | const base::FilePath& partition_path, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 281 | quota::QuotaManager* quota_manager, |
| 282 | ChromeAppCacheService* appcache_service, |
| 283 | fileapi::FileSystemContext* filesystem_context, |
| 284 | webkit_database::DatabaseTracker* database_tracker, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 285 | DOMStorageContextWrapper* dom_storage_context, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 286 | IndexedDBContextImpl* indexed_db_context, |
| 287 | scoped_ptr<WebRTCIdentityStore> webrtc_identity_store) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 288 | : partition_path_(partition_path), |
| 289 | quota_manager_(quota_manager), |
| 290 | appcache_service_(appcache_service), |
| 291 | filesystem_context_(filesystem_context), |
| 292 | database_tracker_(database_tracker), |
| 293 | dom_storage_context_(dom_storage_context), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 294 | indexed_db_context_(indexed_db_context), |
| 295 | webrtc_identity_store_(webrtc_identity_store.Pass()) {} |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 296 | |
| 297 | StoragePartitionImpl::~StoragePartitionImpl() { |
| 298 | // These message loop checks are just to avoid leaks in unittests. |
| 299 | if (GetDatabaseTracker() && |
| 300 | BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { |
| 301 | BrowserThread::PostTask( |
| 302 | BrowserThread::FILE, FROM_HERE, |
| 303 | base::Bind(&webkit_database::DatabaseTracker::Shutdown, |
| 304 | GetDatabaseTracker())); |
| 305 | } |
| 306 | |
| 307 | if (GetDOMStorageContext()) |
| 308 | GetDOMStorageContext()->Shutdown(); |
| 309 | } |
| 310 | |
| 311 | // TODO(ajwong): Break the direct dependency on |context|. We only |
| 312 | // need 3 pieces of info from it. |
| 313 | StoragePartitionImpl* StoragePartitionImpl::Create( |
| 314 | BrowserContext* context, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 315 | bool in_memory, |
| 316 | const base::FilePath& partition_path) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 317 | // Ensure that these methods are called on the UI thread, except for |
| 318 | // unittests where a UI thread might not have been created. |
| 319 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
| 320 | !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); |
| 321 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 322 | // All of the clients have to be created and registered with the |
| 323 | // QuotaManager prior to the QuotaManger being used. We do them |
| 324 | // all together here prior to handing out a reference to anything |
| 325 | // that utilizes the QuotaManager. |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 326 | scoped_refptr<quota::QuotaManager> quota_manager = new quota::QuotaManager( |
| 327 | in_memory, |
| 328 | partition_path, |
| 329 | BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), |
| 330 | BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(), |
| 331 | context->GetSpecialStoragePolicy()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 332 | |
| 333 | // Each consumer is responsible for registering its QuotaClient during |
| 334 | // its construction. |
| 335 | scoped_refptr<fileapi::FileSystemContext> filesystem_context = |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 336 | CreateFileSystemContext(context, |
| 337 | partition_path, in_memory, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 338 | quota_manager->proxy()); |
| 339 | |
| 340 | scoped_refptr<webkit_database::DatabaseTracker> database_tracker = |
| 341 | new webkit_database::DatabaseTracker( |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 342 | partition_path, |
| 343 | in_memory, |
| 344 | context->GetSpecialStoragePolicy(), |
| 345 | quota_manager->proxy(), |
| 346 | BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) |
| 347 | .get()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 348 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 349 | base::FilePath path = in_memory ? base::FilePath() : partition_path; |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 350 | scoped_refptr<DOMStorageContextWrapper> dom_storage_context = |
| 351 | new DOMStorageContextWrapper(path, context->GetSpecialStoragePolicy()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 352 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 353 | // BrowserMainLoop may not be initialized in unit tests. Tests will |
| 354 | // need to inject their own task runner into the IndexedDBContext. |
| 355 | base::SequencedTaskRunner* idb_task_runner = |
| 356 | BrowserThread::CurrentlyOn(BrowserThread::UI) && |
| 357 | BrowserMainLoop::GetInstance() |
| 358 | ? BrowserMainLoop::GetInstance()->indexed_db_thread() |
| 359 | ->message_loop_proxy().get() |
| 360 | : NULL; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 361 | scoped_refptr<IndexedDBContextImpl> indexed_db_context = |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 362 | new IndexedDBContextImpl(path, |
| 363 | context->GetSpecialStoragePolicy(), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 364 | quota_manager->proxy(), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 365 | idb_task_runner); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 366 | |
| 367 | scoped_refptr<ChromeAppCacheService> appcache_service = |
| 368 | new ChromeAppCacheService(quota_manager->proxy()); |
| 369 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 370 | scoped_ptr<WebRTCIdentityStore> webrtc_identity_store( |
| 371 | new WebRTCIdentityStore()); |
| 372 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 373 | return new StoragePartitionImpl(partition_path, |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 374 | quota_manager.get(), |
| 375 | appcache_service.get(), |
| 376 | filesystem_context.get(), |
| 377 | database_tracker.get(), |
| 378 | dom_storage_context.get(), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 379 | indexed_db_context.get(), |
| 380 | webrtc_identity_store.Pass()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 381 | } |
| 382 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 383 | base::FilePath StoragePartitionImpl::GetPath() { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 384 | return partition_path_; |
| 385 | } |
| 386 | |
| 387 | net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 388 | return url_request_context_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 389 | } |
| 390 | |
| 391 | net::URLRequestContextGetter* |
| 392 | StoragePartitionImpl::GetMediaURLRequestContext() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 393 | return media_url_request_context_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 397 | return quota_manager_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 398 | } |
| 399 | |
| 400 | ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 401 | return appcache_service_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 402 | } |
| 403 | |
| 404 | fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 405 | return filesystem_context_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 409 | return database_tracker_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 410 | } |
| 411 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 412 | DOMStorageContextWrapper* StoragePartitionImpl::GetDOMStorageContext() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 413 | return dom_storage_context_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 414 | } |
| 415 | |
| 416 | IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 417 | return indexed_db_context_.get(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 418 | } |
| 419 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 420 | void StoragePartitionImpl::ClearDataImpl( |
| 421 | uint32 remove_mask, |
| 422 | uint32 quota_storage_remove_mask, |
| 423 | const GURL& remove_origin, |
| 424 | net::URLRequestContextGetter* rq_context, |
| 425 | const base::Time begin, |
| 426 | const base::Time end, |
| 427 | const base::Closure& callback) { |
| 428 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 429 | DataDeletionHelper* helper = new DataDeletionHelper(callback); |
| 430 | // |helper| deletes itself when done in |
| 431 | // DataDeletionHelper::DecrementTaskCountOnUI(). |
| 432 | helper->ClearDataOnUIThread( |
| 433 | remove_mask, quota_storage_remove_mask, remove_origin, |
| 434 | GetPath(), rq_context, dom_storage_context_, quota_manager_, begin, end); |
| 435 | } |
| 436 | |
| 437 | void StoragePartitionImpl:: |
| 438 | QuotaManagedDataDeletionHelper::IncrementTaskCountOnIO() { |
| 439 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 440 | ++task_count; |
| 441 | } |
| 442 | |
| 443 | void StoragePartitionImpl:: |
| 444 | QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO() { |
| 445 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 446 | DCHECK_GT(task_count, 0); |
| 447 | --task_count; |
| 448 | if (task_count) |
| 449 | return; |
| 450 | |
| 451 | callback.Run(); |
| 452 | delete this; |
| 453 | } |
| 454 | |
| 455 | void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread( |
| 456 | const scoped_refptr<quota::QuotaManager>& quota_manager, |
| 457 | const base::Time begin, |
| 458 | uint32 remove_mask, |
| 459 | uint32 quota_storage_remove_mask, |
| 460 | const GURL& remove_origin) { |
| 461 | std::set<GURL> origins; |
| 462 | if (!remove_origin.is_empty()) |
| 463 | origins.insert(remove_origin); |
| 464 | |
| 465 | IncrementTaskCountOnIO(); |
| 466 | base::Closure decrement_callback = base::Bind( |
| 467 | &QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO, |
| 468 | base::Unretained(this)); |
| 469 | |
| 470 | if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_PERSISTENT) { |
| 471 | IncrementTaskCountOnIO(); |
| 472 | if (origins.empty()) { // Remove for all origins. |
| 473 | // Ask the QuotaManager for all origins with temporary quota modified |
| 474 | // within the user-specified timeframe, and deal with the resulting set in |
| 475 | // ClearQuotaManagedOriginsOnIOThread(). |
| 476 | quota_manager->GetOriginsModifiedSince( |
| 477 | quota::kStorageTypePersistent, begin, |
| 478 | base::Bind(&ClearQuotaManagedOriginsOnIOThread, |
| 479 | quota_manager, remove_mask, decrement_callback)); |
| 480 | } else { |
| 481 | ClearQuotaManagedOriginsOnIOThread( |
| 482 | quota_manager, remove_mask, decrement_callback, |
| 483 | origins, quota::kStorageTypePersistent); |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | // Do the same for temporary quota. |
| 488 | if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) { |
| 489 | IncrementTaskCountOnIO(); |
| 490 | if (origins.empty()) { // Remove for all origins. |
| 491 | quota_manager->GetOriginsModifiedSince( |
| 492 | quota::kStorageTypeTemporary, begin, |
| 493 | base::Bind(&ClearQuotaManagedOriginsOnIOThread, |
| 494 | quota_manager, remove_mask, decrement_callback)); |
| 495 | } else { |
| 496 | ClearQuotaManagedOriginsOnIOThread( |
| 497 | quota_manager, remove_mask, decrement_callback, |
| 498 | origins, quota::kStorageTypeTemporary); |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | // Do the same for syncable quota. |
| 503 | if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) { |
| 504 | IncrementTaskCountOnIO(); |
| 505 | if (origins.empty()) { // Remove for all origins. |
| 506 | quota_manager->GetOriginsModifiedSince( |
| 507 | quota::kStorageTypeSyncable, begin, |
| 508 | base::Bind(&ClearQuotaManagedOriginsOnIOThread, |
| 509 | quota_manager, remove_mask, decrement_callback)); |
| 510 | } else { |
| 511 | ClearQuotaManagedOriginsOnIOThread( |
| 512 | quota_manager, remove_mask, decrement_callback, |
| 513 | origins, quota::kStorageTypeSyncable); |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | DecrementTaskCountOnIO(); |
| 518 | } |
| 519 | |
| 520 | void StoragePartitionImpl::DataDeletionHelper::IncrementTaskCountOnUI() { |
| 521 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 522 | ++task_count; |
| 523 | } |
| 524 | |
| 525 | void StoragePartitionImpl::DataDeletionHelper::DecrementTaskCountOnUI() { |
| 526 | if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 527 | BrowserThread::PostTask( |
| 528 | BrowserThread::UI, FROM_HERE, |
| 529 | base::Bind(&DataDeletionHelper::DecrementTaskCountOnUI, |
| 530 | base::Unretained(this))); |
| 531 | return; |
| 532 | } |
| 533 | DCHECK_GT(task_count, 0); |
| 534 | --task_count; |
| 535 | if (!task_count) { |
| 536 | callback.Run(); |
| 537 | delete this; |
| 538 | } |
| 539 | } |
| 540 | |
| 541 | void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread( |
| 542 | uint32 remove_mask, |
| 543 | uint32 quota_storage_remove_mask, |
| 544 | const GURL& remove_origin, |
| 545 | const base::FilePath& path, |
| 546 | net::URLRequestContextGetter* rq_context, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 547 | DOMStorageContextWrapper* dom_storage_context, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 548 | quota::QuotaManager* quota_manager, |
| 549 | const base::Time begin, |
| 550 | const base::Time end) { |
| 551 | DCHECK_NE(remove_mask, 0u); |
| 552 | DCHECK(!callback.is_null()); |
| 553 | |
| 554 | IncrementTaskCountOnUI(); |
| 555 | base::Closure decrement_callback = base::Bind( |
| 556 | &DataDeletionHelper::DecrementTaskCountOnUI, base::Unretained(this)); |
| 557 | |
| 558 | if (remove_mask & REMOVE_DATA_MASK_COOKIES) { |
| 559 | // Handle the cookies. |
| 560 | IncrementTaskCountOnUI(); |
| 561 | BrowserThread::PostTask( |
| 562 | BrowserThread::IO, FROM_HERE, |
| 563 | base::Bind(&ClearCookiesOnIOThread, |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 564 | make_scoped_refptr(rq_context), begin, end, remove_origin, |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 565 | decrement_callback)); |
| 566 | } |
| 567 | |
| 568 | if (remove_mask & REMOVE_DATA_MASK_INDEXEDDB || |
| 569 | remove_mask & REMOVE_DATA_MASK_WEBSQL || |
| 570 | remove_mask & REMOVE_DATA_MASK_APPCACHE || |
| 571 | remove_mask & REMOVE_DATA_MASK_FILE_SYSTEMS) { |
| 572 | IncrementTaskCountOnUI(); |
| 573 | BrowserThread::PostTask( |
| 574 | BrowserThread::IO, FROM_HERE, |
| 575 | base::Bind(&ClearQuotaManagedDataOnIOThread, |
| 576 | make_scoped_refptr(quota_manager), begin, |
| 577 | remove_mask, quota_storage_remove_mask, remove_origin, |
| 578 | decrement_callback)); |
| 579 | } |
| 580 | |
| 581 | if (remove_mask & REMOVE_DATA_MASK_LOCAL_STORAGE) { |
| 582 | IncrementTaskCountOnUI(); |
| 583 | ClearLocalStorageOnUIThread( |
| 584 | make_scoped_refptr(dom_storage_context), |
| 585 | remove_origin, begin, end, decrement_callback); |
| 586 | |
| 587 | // ClearDataImpl cannot clear session storage data when a particular origin |
| 588 | // is specified. Therefore we ignore clearing session storage in this case. |
| 589 | // TODO(lazyboy): Fix. |
| 590 | if (remove_origin.is_empty()) { |
| 591 | IncrementTaskCountOnUI(); |
| 592 | ClearSessionStorageOnUIThread( |
| 593 | make_scoped_refptr(dom_storage_context), decrement_callback); |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | if (remove_mask & REMOVE_DATA_MASK_SHADER_CACHE) { |
| 598 | IncrementTaskCountOnUI(); |
| 599 | BrowserThread::PostTask( |
| 600 | BrowserThread::IO, FROM_HERE, |
| 601 | base::Bind(&ClearShaderCacheOnIOThread, |
| 602 | path, begin, end, decrement_callback)); |
| 603 | } |
| 604 | |
| 605 | DecrementTaskCountOnUI(); |
| 606 | } |
| 607 | |
| 608 | |
| 609 | void StoragePartitionImpl::ClearDataForOrigin( |
| 610 | uint32 remove_mask, |
| 611 | uint32 quota_storage_remove_mask, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 612 | const GURL& storage_origin, |
| 613 | net::URLRequestContextGetter* request_context_getter) { |
| 614 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 615 | ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin, |
| 616 | request_context_getter, base::Time(), base::Time::Max(), |
| 617 | base::Bind(&base::DoNothing)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 618 | } |
| 619 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 620 | void StoragePartitionImpl::ClearDataForUnboundedRange( |
| 621 | uint32 remove_mask, |
| 622 | uint32 quota_storage_remove_mask) { |
| 623 | ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(), |
| 624 | GetURLRequestContext(), base::Time(), base::Time::Max(), |
| 625 | base::Bind(&base::DoNothing)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 626 | } |
| 627 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 628 | void StoragePartitionImpl::ClearDataForRange(uint32 remove_mask, |
| 629 | uint32 quota_storage_remove_mask, |
| 630 | const base::Time& begin, |
| 631 | const base::Time& end, |
| 632 | const base::Closure& callback) { |
| 633 | ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(), |
| 634 | GetURLRequestContext(), begin, end, callback); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 635 | } |
| 636 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 637 | WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() { |
| 638 | return webrtc_identity_store_.get(); |
| 639 | } |
| 640 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 641 | void StoragePartitionImpl::SetURLRequestContext( |
| 642 | net::URLRequestContextGetter* url_request_context) { |
| 643 | url_request_context_ = url_request_context; |
| 644 | } |
| 645 | |
| 646 | void StoragePartitionImpl::SetMediaURLRequestContext( |
| 647 | net::URLRequestContextGetter* media_url_request_context) { |
| 648 | media_url_request_context_ = media_url_request_context; |
| 649 | } |
| 650 | |
| 651 | } // namespace content |