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