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