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 kMountPointsKey[] = "mount_points"; 40 const char kStorageParitionMapKeyName[] = "content_storage_partition_map"; 41 42 StoragePartitionImplMap* 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 54 StoragePartition* 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|. 69 void PurgeDOMStorageContextInPartition(StoragePartition* storage_partition) { 70 static_cast<StoragePartitionImpl*>(storage_partition)-> 71 GetDOMStorageContext()->PurgeMemory(); 72 } 73 74 void 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 85 void SaveSessionStateOnIndexedDBThread( 86 scoped_refptr<IndexedDBContextImpl> indexed_db_context) { 87 indexed_db_context->SetForceKeepSessionState(); 88 } 89 90 void PurgeMemoryOnIOThread(appcache::AppCacheService* appcache_service) { 91 appcache_service->PurgeMemory(); 92 } 93 94 } // namespace 95 96 // static 97 void 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 106 void 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 114 DownloadManager* 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 135 fileapi::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 158 StoragePartition* 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 177 StoragePartition* 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 192 void 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 204 StoragePartition* BrowserContext::GetDefaultStoragePartition( 205 BrowserContext* browser_context) { 206 return GetStoragePartition(browser_context, NULL); 207 } 208 209 void 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 221 void 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 253 void 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 269 BrowserContext::~BrowserContext() { 270 #if !defined(OS_IOS) 271 if (GetUserData(kDownloadManagerKeyName)) 272 GetDownloadManager(this)->Shutdown(); 273 #endif 274 } 275 276 } // namespace content 277