Home | History | Annotate | Download | only in browser
      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