storage_partition_impl.cc revision 58e6fbe4ee35d65e14b626c557d37565bf8ad179
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 7#include "base/sequenced_task_runner.h" 8#include "base/strings/utf_string_conversions.h" 9#include "content/browser/browser_main_loop.h" 10#include "content/browser/fileapi/browser_file_system_helper.h" 11#include "content/browser/gpu/shader_disk_cache.h" 12#include "content/public/browser/browser_context.h" 13#include "content/public/browser/browser_thread.h" 14#include "content/public/browser/dom_storage_context.h" 15#include "content/public/browser/indexed_db_context.h" 16#include "net/base/completion_callback.h" 17#include "net/base/net_errors.h" 18#include "net/cookies/cookie_monster.h" 19#include "net/url_request/url_request_context.h" 20#include "net/url_request/url_request_context_getter.h" 21#include "webkit/browser/database/database_tracker.h" 22#include "webkit/browser/quota/quota_manager.h" 23#include "webkit/common/dom_storage/dom_storage_types.h" 24 25namespace content { 26 27namespace { 28 29void DoNothingStatusCallback(quota::QuotaStatusCode status) { 30 // Do nothing. 31} 32 33void ClearQuotaManagedOriginsOnIOThread( 34 const scoped_refptr<quota::QuotaManager>& quota_manager, 35 const std::set<GURL>& origins, 36 quota::StorageType quota_storage_type) { 37 // The QuotaManager manages all storage other than cookies, LocalStorage, 38 // and SessionStorage. This loop wipes out most HTML5 storage for the given 39 // origins. 40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 41 std::set<GURL>::const_iterator origin; 42 for (std::set<GURL>::const_iterator origin = origins.begin(); 43 origin != origins.end(); ++origin) { 44 quota_manager->DeleteOriginData(*origin, quota_storage_type, 45 quota::QuotaClient::kAllClientsMask, 46 base::Bind(&DoNothingStatusCallback)); 47 } 48} 49 50void ClearOriginOnIOThread( 51 uint32 storage_mask, 52 const GURL& storage_origin, 53 const scoped_refptr<net::URLRequestContextGetter>& request_context, 54 const scoped_refptr<quota::QuotaManager>& quota_manager) { 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 56 57 if (storage_mask & StoragePartition::kCookies) { 58 // Handle the cookies. 59 net::CookieMonster* cookie_monster = 60 request_context->GetURLRequestContext()->cookie_store()-> 61 GetCookieMonster(); 62 if (cookie_monster) 63 cookie_monster->DeleteAllForHostAsync( 64 storage_origin, net::CookieMonster::DeleteCallback()); 65 } 66 67 // Handle all HTML5 storage other than DOMStorageContext. 68 std::set<GURL> origins; 69 origins.insert(storage_origin); 70 if (storage_mask & StoragePartition::kQuotaManagedTemporaryStorage) { 71 ClearQuotaManagedOriginsOnIOThread(quota_manager, 72 origins, 73 quota::kStorageTypeTemporary); 74 } 75 if (storage_mask & StoragePartition::kQuotaManagedPersistentStorage) { 76 ClearQuotaManagedOriginsOnIOThread(quota_manager, 77 origins, 78 quota::kStorageTypePersistent); 79 } 80 if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) { 81 ClearQuotaManagedOriginsOnIOThread(quota_manager, 82 origins, 83 quota::kStorageTypeSyncable); 84 } 85} 86 87void ClearAllDataOnIOThread( 88 uint32 storage_mask, 89 const scoped_refptr<net::URLRequestContextGetter>& request_context, 90 const scoped_refptr<quota::QuotaManager>& quota_manager) { 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 92 93 if (storage_mask & StoragePartition::kCookies) { 94 // Handle the cookies. 95 net::CookieMonster* cookie_monster = 96 request_context->GetURLRequestContext()->cookie_store()-> 97 GetCookieMonster(); 98 if (cookie_monster) 99 cookie_monster->DeleteAllAsync(net::CookieMonster::DeleteCallback()); 100 } 101 102 // Handle all HTML5 storage other than DOMStorageContext. 103 if (storage_mask & StoragePartition::kQuotaManagedTemporaryStorage) { 104 quota_manager->GetOriginsModifiedSince( 105 quota::kStorageTypeTemporary, base::Time(), 106 base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager)); 107 } 108 if (storage_mask & StoragePartition::kQuotaManagedPersistentStorage) { 109 quota_manager->GetOriginsModifiedSince( 110 quota::kStorageTypePersistent, base::Time(), 111 base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager)); 112 } 113 if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) { 114 quota_manager->GetOriginsModifiedSince( 115 quota::kStorageTypeSyncable, base::Time(), 116 base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager)); 117 } 118} 119 120void ClearedShaderCacheOnIOThread(base::Closure callback) { 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 122 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); 123} 124 125void ClearShaderCacheOnIOThread(base::FilePath path, 126 base::Time begin, base::Time end, base::Closure callback) { 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 128 ShaderCacheFactory::GetInstance()->ClearByPath( 129 path, begin, end, 130 base::Bind(&ClearedShaderCacheOnIOThread, callback)); 131} 132 133void OnLocalStorageUsageInfo( 134 const scoped_refptr<DOMStorageContextImpl>& dom_storage_context, 135 const std::vector<dom_storage::LocalStorageUsageInfo>& infos) { 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 137 138 for (size_t i = 0; i < infos.size(); ++i) { 139 dom_storage_context->DeleteLocalStorage(infos[i].origin); 140 } 141} 142 143void OnSessionStorageUsageInfo( 144 const scoped_refptr<DOMStorageContextImpl>& dom_storage_context, 145 const std::vector<dom_storage::SessionStorageUsageInfo>& infos) { 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 147 148 for (size_t i = 0; i < infos.size(); ++i) { 149 dom_storage_context->DeleteSessionStorage(infos[i]); 150 } 151} 152 153} // namespace 154 155StoragePartitionImpl::StoragePartitionImpl( 156 const base::FilePath& partition_path, 157 quota::QuotaManager* quota_manager, 158 ChromeAppCacheService* appcache_service, 159 fileapi::FileSystemContext* filesystem_context, 160 webkit_database::DatabaseTracker* database_tracker, 161 DOMStorageContextImpl* dom_storage_context, 162 IndexedDBContextImpl* indexed_db_context, 163 scoped_ptr<WebRTCIdentityStore> webrtc_identity_store) 164 : partition_path_(partition_path), 165 quota_manager_(quota_manager), 166 appcache_service_(appcache_service), 167 filesystem_context_(filesystem_context), 168 database_tracker_(database_tracker), 169 dom_storage_context_(dom_storage_context), 170 indexed_db_context_(indexed_db_context), 171 webrtc_identity_store_(webrtc_identity_store.Pass()) {} 172 173StoragePartitionImpl::~StoragePartitionImpl() { 174 // These message loop checks are just to avoid leaks in unittests. 175 if (GetDatabaseTracker() && 176 BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { 177 BrowserThread::PostTask( 178 BrowserThread::FILE, FROM_HERE, 179 base::Bind(&webkit_database::DatabaseTracker::Shutdown, 180 GetDatabaseTracker())); 181 } 182 183 if (GetDOMStorageContext()) 184 GetDOMStorageContext()->Shutdown(); 185} 186 187// TODO(ajwong): Break the direct dependency on |context|. We only 188// need 3 pieces of info from it. 189StoragePartitionImpl* StoragePartitionImpl::Create( 190 BrowserContext* context, 191 bool in_memory, 192 const base::FilePath& partition_path) { 193 // Ensure that these methods are called on the UI thread, except for 194 // unittests where a UI thread might not have been created. 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 196 !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); 197 198 // All of the clients have to be created and registered with the 199 // QuotaManager prior to the QuotaManger being used. We do them 200 // all together here prior to handing out a reference to anything 201 // that utilizes the QuotaManager. 202 scoped_refptr<quota::QuotaManager> quota_manager = new quota::QuotaManager( 203 in_memory, 204 partition_path, 205 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), 206 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(), 207 context->GetSpecialStoragePolicy()); 208 209 // Each consumer is responsible for registering its QuotaClient during 210 // its construction. 211 scoped_refptr<fileapi::FileSystemContext> filesystem_context = 212 CreateFileSystemContext(context, 213 partition_path, in_memory, 214 quota_manager->proxy()); 215 216 scoped_refptr<webkit_database::DatabaseTracker> database_tracker = 217 new webkit_database::DatabaseTracker( 218 partition_path, 219 in_memory, 220 context->GetSpecialStoragePolicy(), 221 quota_manager->proxy(), 222 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) 223 .get()); 224 225 base::FilePath path = in_memory ? base::FilePath() : partition_path; 226 scoped_refptr<DOMStorageContextImpl> dom_storage_context = 227 new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy()); 228 229 // BrowserMainLoop may not be initialized in unit tests. Tests will 230 // need to inject their own task runner into the IndexedDBContext. 231 base::SequencedTaskRunner* idb_task_runner = 232 BrowserThread::CurrentlyOn(BrowserThread::UI) && 233 BrowserMainLoop::GetInstance() 234 ? BrowserMainLoop::GetInstance()->indexed_db_thread() 235 ->message_loop_proxy().get() 236 : NULL; 237 scoped_refptr<IndexedDBContextImpl> indexed_db_context = 238 new IndexedDBContextImpl(path, 239 context->GetSpecialStoragePolicy(), 240 quota_manager->proxy(), 241 idb_task_runner); 242 243 scoped_refptr<ChromeAppCacheService> appcache_service = 244 new ChromeAppCacheService(quota_manager->proxy()); 245 246 scoped_ptr<WebRTCIdentityStore> webrtc_identity_store( 247 new WebRTCIdentityStore()); 248 249 return new StoragePartitionImpl(partition_path, 250 quota_manager.get(), 251 appcache_service.get(), 252 filesystem_context.get(), 253 database_tracker.get(), 254 dom_storage_context.get(), 255 indexed_db_context.get(), 256 webrtc_identity_store.Pass()); 257} 258 259base::FilePath StoragePartitionImpl::GetPath() { 260 return partition_path_; 261} 262 263net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() { 264 return url_request_context_.get(); 265} 266 267net::URLRequestContextGetter* 268StoragePartitionImpl::GetMediaURLRequestContext() { 269 return media_url_request_context_.get(); 270} 271 272quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() { 273 return quota_manager_.get(); 274} 275 276ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() { 277 return appcache_service_.get(); 278} 279 280fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() { 281 return filesystem_context_.get(); 282} 283 284webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() { 285 return database_tracker_.get(); 286} 287 288DOMStorageContextImpl* StoragePartitionImpl::GetDOMStorageContext() { 289 return dom_storage_context_.get(); 290} 291 292IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() { 293 return indexed_db_context_.get(); 294} 295 296void StoragePartitionImpl::AsyncClearDataForOrigin( 297 uint32 storage_mask, 298 const GURL& storage_origin, 299 net::URLRequestContextGetter* request_context_getter) { 300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 301 302 BrowserThread::PostTask( 303 BrowserThread::IO, FROM_HERE, 304 base::Bind(&ClearOriginOnIOThread, 305 storage_mask, 306 storage_origin, 307 make_scoped_refptr(request_context_getter), 308 quota_manager_)); 309 310 if (storage_mask & kLocalDomStorage) 311 GetDOMStorageContext()->DeleteLocalStorage(storage_origin); 312} 313 314void StoragePartitionImpl::AsyncClearData(uint32 storage_mask) { 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 316 317 // We ignore the media request context because it shares the same cookie store 318 // as the main request context. 319 BrowserThread::PostTask( 320 BrowserThread::IO, FROM_HERE, 321 base::Bind(&ClearAllDataOnIOThread, 322 storage_mask, 323 url_request_context_, 324 quota_manager_)); 325 326 if (storage_mask & kLocalDomStorage) { 327 dom_storage_context_->GetLocalStorageUsage( 328 base::Bind(&OnLocalStorageUsageInfo, dom_storage_context_)); 329 } 330 331 if (storage_mask & kSessionDomStorage) { 332 dom_storage_context_->GetSessionStorageUsage( 333 base::Bind(&OnSessionStorageUsageInfo, dom_storage_context_)); 334 } 335} 336 337void StoragePartitionImpl::AsyncClearDataBetween(uint32 storage_mask, 338 const base::Time& begin, const base::Time& end, 339 const base::Closure& callback) { 340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 341 DCHECK(storage_mask == kShaderStorage); 342 343 if (storage_mask & kShaderStorage) { 344 BrowserThread::PostTask( 345 BrowserThread::IO, FROM_HERE, 346 base::Bind(&ClearShaderCacheOnIOThread, GetPath(), begin, end, 347 callback)); 348 } 349} 350 351WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() { 352 return webrtc_identity_store_.get(); 353} 354 355void StoragePartitionImpl::SetURLRequestContext( 356 net::URLRequestContextGetter* url_request_context) { 357 url_request_context_ = url_request_context; 358} 359 360void StoragePartitionImpl::SetMediaURLRequestContext( 361 net::URLRequestContextGetter* media_url_request_context) { 362 media_url_request_context_ = media_url_request_context; 363} 364 365} // namespace content 366