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