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/public/browser/browser_context.h" 6 7#if !defined(OS_IOS) 8#include "content/browser/appcache/chrome_appcache_service.h" 9#include "content/browser/dom_storage/dom_storage_context_wrapper.h" 10#include "content/browser/download/download_manager_impl.h" 11#include "content/browser/indexed_db/indexed_db_context_impl.h" 12#include "content/browser/loader/resource_dispatcher_host_impl.h" 13#include "content/browser/storage_partition_impl.h" 14#include "content/browser/storage_partition_impl_map.h" 15#include "content/common/child_process_host_impl.h" 16#include "content/public/browser/browser_thread.h" 17#include "content/public/browser/content_browser_client.h" 18#include "content/public/browser/site_instance.h" 19#include "net/cookies/cookie_monster.h" 20#include "net/cookies/cookie_store.h" 21#include "net/ssl/server_bound_cert_service.h" 22#include "net/ssl/server_bound_cert_store.h" 23#include "net/url_request/url_request_context.h" 24#include "net/url_request/url_request_context_getter.h" 25#include "webkit/browser/database/database_tracker.h" 26#include "webkit/browser/fileapi/external_mount_points.h" 27#endif // !OS_IOS 28 29using base::UserDataAdapter; 30 31namespace content { 32 33// Only ~BrowserContext() is needed on iOS. 34#if !defined(OS_IOS) 35namespace { 36 37// Key names on BrowserContext. 38const char kDownloadManagerKeyName[] = "download_manager"; 39const char kMountPointsKey[] = "mount_points"; 40const char kStorageParitionMapKeyName[] = "content_storage_partition_map"; 41 42StoragePartitionImplMap* GetStoragePartitionMap( 43 BrowserContext* browser_context) { 44 StoragePartitionImplMap* partition_map = 45 static_cast<StoragePartitionImplMap*>( 46 browser_context->GetUserData(kStorageParitionMapKeyName)); 47 if (!partition_map) { 48 partition_map = new StoragePartitionImplMap(browser_context); 49 browser_context->SetUserData(kStorageParitionMapKeyName, partition_map); 50 } 51 return partition_map; 52} 53 54StoragePartition* GetStoragePartitionFromConfig( 55 BrowserContext* browser_context, 56 const std::string& partition_domain, 57 const std::string& partition_name, 58 bool in_memory) { 59 StoragePartitionImplMap* partition_map = 60 GetStoragePartitionMap(browser_context); 61 62 if (browser_context->IsOffTheRecord()) 63 in_memory = true; 64 65 return partition_map->Get(partition_domain, partition_name, in_memory); 66} 67 68// Run |callback| on each DOMStorageContextWrapper in |browser_context|. 69void PurgeDOMStorageContextInPartition(StoragePartition* storage_partition) { 70 static_cast<StoragePartitionImpl*>(storage_partition)-> 71 GetDOMStorageContext()->PurgeMemory(); 72} 73 74void SaveSessionStateOnIOThread( 75 const scoped_refptr<net::URLRequestContextGetter>& context_getter, 76 appcache::AppCacheService* appcache_service) { 77 net::URLRequestContext* context = context_getter->GetURLRequestContext(); 78 context->cookie_store()->GetCookieMonster()-> 79 SetForceKeepSessionState(); 80 context->server_bound_cert_service()->GetCertStore()-> 81 SetForceKeepSessionState(); 82 appcache_service->set_force_keep_session_state(); 83} 84 85void SaveSessionStateOnIndexedDBThread( 86 scoped_refptr<IndexedDBContextImpl> indexed_db_context) { 87 indexed_db_context->SetForceKeepSessionState(); 88} 89 90void PurgeMemoryOnIOThread(appcache::AppCacheService* appcache_service) { 91 appcache_service->PurgeMemory(); 92} 93 94} // namespace 95 96// static 97void BrowserContext::AsyncObliterateStoragePartition( 98 BrowserContext* browser_context, 99 const GURL& site, 100 const base::Closure& on_gc_required) { 101 GetStoragePartitionMap(browser_context)->AsyncObliterate(site, 102 on_gc_required); 103} 104 105// static 106void BrowserContext::GarbageCollectStoragePartitions( 107 BrowserContext* browser_context, 108 scoped_ptr<base::hash_set<base::FilePath> > active_paths, 109 const base::Closure& done) { 110 GetStoragePartitionMap(browser_context)->GarbageCollect( 111 active_paths.Pass(), done); 112} 113 114DownloadManager* BrowserContext::GetDownloadManager( 115 BrowserContext* context) { 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 117 if (!context->GetUserData(kDownloadManagerKeyName)) { 118 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 119 DCHECK(rdh); 120 DownloadManager* download_manager = 121 new DownloadManagerImpl( 122 GetContentClient()->browser()->GetNetLog(), context); 123 124 context->SetUserData( 125 kDownloadManagerKeyName, 126 download_manager); 127 download_manager->SetDelegate(context->GetDownloadManagerDelegate()); 128 } 129 130 return static_cast<DownloadManager*>( 131 context->GetUserData(kDownloadManagerKeyName)); 132} 133 134// static 135fileapi::ExternalMountPoints* BrowserContext::GetMountPoints( 136 BrowserContext* context) { 137 // Ensure that these methods are called on the UI thread, except for 138 // unittests where a UI thread might not have been created. 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 140 !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); 141 142#if defined(OS_CHROMEOS) 143 if (!context->GetUserData(kMountPointsKey)) { 144 scoped_refptr<fileapi::ExternalMountPoints> mount_points = 145 fileapi::ExternalMountPoints::CreateRefCounted(); 146 context->SetUserData( 147 kMountPointsKey, 148 new UserDataAdapter<fileapi::ExternalMountPoints>(mount_points.get())); 149 } 150 151 return UserDataAdapter<fileapi::ExternalMountPoints>::Get( 152 context, kMountPointsKey); 153#else 154 return NULL; 155#endif 156} 157 158StoragePartition* BrowserContext::GetStoragePartition( 159 BrowserContext* browser_context, 160 SiteInstance* site_instance) { 161 std::string partition_domain; 162 std::string partition_name; 163 bool in_memory = false; 164 165 // TODO(ajwong): After GetDefaultStoragePartition() is removed, get rid of 166 // this conditional and require that |site_instance| is non-NULL. 167 if (site_instance) { 168 GetContentClient()->browser()->GetStoragePartitionConfigForSite( 169 browser_context, site_instance->GetSiteURL(), true, 170 &partition_domain, &partition_name, &in_memory); 171 } 172 173 return GetStoragePartitionFromConfig( 174 browser_context, partition_domain, partition_name, in_memory); 175} 176 177StoragePartition* BrowserContext::GetStoragePartitionForSite( 178 BrowserContext* browser_context, 179 const GURL& site) { 180 std::string partition_domain; 181 std::string partition_name; 182 bool in_memory; 183 184 GetContentClient()->browser()->GetStoragePartitionConfigForSite( 185 browser_context, site, true, &partition_domain, &partition_name, 186 &in_memory); 187 188 return GetStoragePartitionFromConfig( 189 browser_context, partition_domain, partition_name, in_memory); 190} 191 192void BrowserContext::ForEachStoragePartition( 193 BrowserContext* browser_context, 194 const StoragePartitionCallback& callback) { 195 StoragePartitionImplMap* partition_map = 196 static_cast<StoragePartitionImplMap*>( 197 browser_context->GetUserData(kStorageParitionMapKeyName)); 198 if (!partition_map) 199 return; 200 201 partition_map->ForEach(callback); 202} 203 204StoragePartition* BrowserContext::GetDefaultStoragePartition( 205 BrowserContext* browser_context) { 206 return GetStoragePartition(browser_context, NULL); 207} 208 209void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) { 210 // This will be enough to tickle initialization of BrowserContext if 211 // necessary, which initializes ResourceContext. The reason we don't call 212 // ResourceContext::InitializeResourceContext() directly here is that 213 // ResourceContext initialization may call back into BrowserContext 214 // and when that call returns it'll end rewriting its UserData map. It will 215 // end up rewriting the same value but this still causes a race condition. 216 // 217 // See http://crbug.com/115678. 218 GetDefaultStoragePartition(context); 219} 220 221void BrowserContext::SaveSessionState(BrowserContext* browser_context) { 222 GetDefaultStoragePartition(browser_context)->GetDatabaseTracker()-> 223 SetForceKeepSessionState(); 224 StoragePartition* storage_partition = 225 BrowserContext::GetDefaultStoragePartition(browser_context); 226 227 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { 228 BrowserThread::PostTask( 229 BrowserThread::IO, FROM_HERE, 230 base::Bind( 231 &SaveSessionStateOnIOThread, 232 make_scoped_refptr(browser_context->GetRequestContext()), 233 storage_partition->GetAppCacheService())); 234 } 235 236 DOMStorageContextWrapper* dom_storage_context_proxy = 237 static_cast<DOMStorageContextWrapper*>( 238 storage_partition->GetDOMStorageContext()); 239 dom_storage_context_proxy->SetForceKeepSessionState(); 240 241 IndexedDBContextImpl* indexed_db_context_impl = 242 static_cast<IndexedDBContextImpl*>( 243 storage_partition->GetIndexedDBContext()); 244 // No task runner in unit tests. 245 if (indexed_db_context_impl->TaskRunner()) { 246 indexed_db_context_impl->TaskRunner()->PostTask( 247 FROM_HERE, 248 base::Bind(&SaveSessionStateOnIndexedDBThread, 249 make_scoped_refptr(indexed_db_context_impl))); 250 } 251} 252 253void BrowserContext::PurgeMemory(BrowserContext* browser_context) { 254 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { 255 BrowserThread::PostTask( 256 BrowserThread::IO, FROM_HERE, 257 base::Bind( 258 &PurgeMemoryOnIOThread, 259 BrowserContext::GetDefaultStoragePartition(browser_context)-> 260 GetAppCacheService())); 261 } 262 263 ForEachStoragePartition(browser_context, 264 base::Bind(&PurgeDOMStorageContextInPartition)); 265} 266 267#endif // !OS_IOS 268 269BrowserContext::~BrowserContext() { 270#if !defined(OS_IOS) 271 if (GetUserData(kDownloadManagerKeyName)) 272 GetDownloadManager(this)->Shutdown(); 273#endif 274} 275 276} // namespace content 277