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