storage_partition_impl.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/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_getter.h" 18#include "net/url_request/url_request_context.h" 19#include "webkit/browser/database/database_tracker.h" 20#include "webkit/dom_storage/dom_storage_types.h" 21#include "webkit/quota/quota_manager.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 = 200 new quota::QuotaManager( 201 in_memory, partition_path, 202 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), 203 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), 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, in_memory, 217 context->GetSpecialStoragePolicy(), quota_manager->proxy(), 218 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 219 220 base::FilePath path = in_memory ? base::FilePath() : partition_path; 221 scoped_refptr<DOMStorageContextImpl> dom_storage_context = 222 new DOMStorageContextImpl(path, context->GetSpecialStoragePolicy()); 223 224 scoped_refptr<IndexedDBContextImpl> indexed_db_context = 225 new IndexedDBContextImpl(path, context->GetSpecialStoragePolicy(), 226 quota_manager->proxy(), 227 BrowserThread::GetMessageLoopProxyForThread( 228 BrowserThread::WEBKIT_DEPRECATED)); 229 230 scoped_refptr<ChromeAppCacheService> appcache_service = 231 new ChromeAppCacheService(quota_manager->proxy()); 232 233 return new StoragePartitionImpl(partition_path, 234 quota_manager, 235 appcache_service, 236 filesystem_context, 237 database_tracker, 238 dom_storage_context, 239 indexed_db_context); 240} 241 242base::FilePath StoragePartitionImpl::GetPath() { 243 return partition_path_; 244} 245 246net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() { 247 return url_request_context_; 248} 249 250net::URLRequestContextGetter* 251StoragePartitionImpl::GetMediaURLRequestContext() { 252 return media_url_request_context_; 253} 254 255quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() { 256 return quota_manager_; 257} 258 259ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() { 260 return appcache_service_; 261} 262 263fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() { 264 return filesystem_context_; 265} 266 267webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() { 268 return database_tracker_; 269} 270 271DOMStorageContextImpl* StoragePartitionImpl::GetDOMStorageContext() { 272 return dom_storage_context_; 273} 274 275IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() { 276 return indexed_db_context_; 277} 278 279void StoragePartitionImpl::AsyncClearDataForOrigin( 280 uint32 storage_mask, 281 const GURL& storage_origin, 282 net::URLRequestContextGetter* request_context_getter) { 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 284 285 BrowserThread::PostTask( 286 BrowserThread::IO, FROM_HERE, 287 base::Bind(&ClearOriginOnIOThread, 288 storage_mask, 289 storage_origin, 290 make_scoped_refptr(request_context_getter), 291 quota_manager_)); 292 293 if (storage_mask & kLocalDomStorage) 294 GetDOMStorageContext()->DeleteLocalStorage(storage_origin); 295} 296 297void StoragePartitionImpl::AsyncClearData(uint32 storage_mask) { 298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 299 300 // We ignore the media request context because it shares the same cookie store 301 // as the main request context. 302 BrowserThread::PostTask( 303 BrowserThread::IO, FROM_HERE, 304 base::Bind(&ClearAllDataOnIOThread, 305 storage_mask, 306 url_request_context_, 307 quota_manager_)); 308 309 if (storage_mask & kLocalDomStorage) { 310 dom_storage_context_->GetLocalStorageUsage( 311 base::Bind(&OnLocalStorageUsageInfo, dom_storage_context_)); 312 } 313 314 if (storage_mask & kSessionDomStorage) { 315 dom_storage_context_->GetSessionStorageUsage( 316 base::Bind(&OnSessionStorageUsageInfo, dom_storage_context_)); 317 } 318} 319 320void StoragePartitionImpl::AsyncClearDataBetween(uint32 storage_mask, 321 const base::Time& begin, const base::Time& end, 322 const base::Closure& callback) { 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 324 DCHECK(storage_mask == kShaderStorage); 325 326 if (storage_mask & kShaderStorage) { 327 BrowserThread::PostTask( 328 BrowserThread::IO, FROM_HERE, 329 base::Bind(&ClearShaderCacheOnIOThread, GetPath(), begin, end, 330 callback)); 331 } 332} 333 334void StoragePartitionImpl::SetURLRequestContext( 335 net::URLRequestContextGetter* url_request_context) { 336 url_request_context_ = url_request_context; 337} 338 339void StoragePartitionImpl::SetMediaURLRequestContext( 340 net::URLRequestContextGetter* media_url_request_context) { 341 media_url_request_context_ = media_url_request_context; 342} 343 344} // namespace content 345