Home | History | Annotate | Download | only in profiles
      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 "chrome/browser/profiles/profile_io_data.h"
      6 
      7 #include <string>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/command_line.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/debug/alias.h"
     15 #include "base/logging.h"
     16 #include "base/path_service.h"
     17 #include "base/prefs/pref_service.h"
     18 #include "base/stl_util.h"
     19 #include "base/strings/string_number_conversions.h"
     20 #include "base/strings/string_util.h"
     21 #include "base/strings/stringprintf.h"
     22 #include "chrome/browser/browser_process.h"
     23 #include "chrome/browser/chrome_notification_types.h"
     24 #include "chrome/browser/content_settings/content_settings_provider.h"
     25 #include "chrome/browser/content_settings/cookie_settings.h"
     26 #include "chrome/browser/content_settings/host_content_settings_map.h"
     27 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
     28 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
     29 #include "chrome/browser/download/download_service.h"
     30 #include "chrome/browser/download/download_service_factory.h"
     31 #include "chrome/browser/extensions/extension_info_map.h"
     32 #include "chrome/browser/extensions/extension_protocols.h"
     33 #include "chrome/browser/extensions/extension_resource_protocols.h"
     34 #include "chrome/browser/extensions/extension_system.h"
     35 #include "chrome/browser/io_thread.h"
     36 #include "chrome/browser/net/about_protocol_handler.h"
     37 #include "chrome/browser/net/chrome_cookie_notification_details.h"
     38 #include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h"
     39 #include "chrome/browser/net/chrome_http_user_agent_settings.h"
     40 #include "chrome/browser/net/chrome_net_log.h"
     41 #include "chrome/browser/net/chrome_network_delegate.h"
     42 #include "chrome/browser/net/evicted_domain_cookie_counter.h"
     43 #include "chrome/browser/net/load_time_stats.h"
     44 #include "chrome/browser/net/proxy_service_factory.h"
     45 #include "chrome/browser/net/resource_prefetch_predictor_observer.h"
     46 #include "chrome/browser/net/transport_security_persister.h"
     47 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
     48 #include "chrome/browser/policy/url_blacklist_manager.h"
     49 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
     50 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
     51 #include "chrome/browser/profiles/profile.h"
     52 #include "chrome/browser/profiles/profile_manager.h"
     53 #include "chrome/browser/signin/signin_names_io_thread.h"
     54 #include "chrome/common/chrome_paths.h"
     55 #include "chrome/common/chrome_switches.h"
     56 #include "chrome/common/pref_names.h"
     57 #include "chrome/common/startup_metric_utils.h"
     58 #include "chrome/common/url_constants.h"
     59 #include "content/public/browser/browser_thread.h"
     60 #include "content/public/browser/host_zoom_map.h"
     61 #include "content/public/browser/notification_service.h"
     62 #include "content/public/browser/resource_context.h"
     63 #include "extensions/common/constants.h"
     64 #include "net/cert/cert_verifier.h"
     65 #include "net/cookies/canonical_cookie.h"
     66 #include "net/cookies/cookie_monster.h"
     67 #include "net/http/http_transaction_factory.h"
     68 #include "net/http/http_util.h"
     69 #include "net/proxy/proxy_config_service_fixed.h"
     70 #include "net/proxy/proxy_script_fetcher_impl.h"
     71 #include "net/proxy/proxy_service.h"
     72 #include "net/ssl/server_bound_cert_service.h"
     73 #include "net/url_request/data_protocol_handler.h"
     74 #include "net/url_request/file_protocol_handler.h"
     75 #include "net/url_request/ftp_protocol_handler.h"
     76 #include "net/url_request/protocol_intercept_job_factory.h"
     77 #include "net/url_request/url_request.h"
     78 #include "net/url_request/url_request_file_job.h"
     79 #include "net/url_request/url_request_job_factory_impl.h"
     80 
     81 #if defined(ENABLE_MANAGED_USERS)
     82 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
     83 #include "chrome/browser/managed_mode/managed_user_service.h"
     84 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
     85 #endif
     86 
     87 #if defined(OS_CHROMEOS)
     88 #include "chrome/browser/chromeos/drive/drive_protocol_handler.h"
     89 #include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
     90 #include "chrome/browser/chromeos/settings/cros_settings.h"
     91 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
     92 #include "chrome/browser/policy/browser_policy_connector.h"
     93 #endif  // defined(OS_CHROMEOS)
     94 
     95 using content::BrowserContext;
     96 using content::BrowserThread;
     97 using content::ResourceContext;
     98 
     99 namespace {
    100 
    101 // ----------------------------------------------------------------------------
    102 // CookieMonster::Delegate implementation
    103 // ----------------------------------------------------------------------------
    104 class ChromeCookieMonsterDelegate : public net::CookieMonster::Delegate {
    105  public:
    106   explicit ChromeCookieMonsterDelegate(
    107       const base::Callback<Profile*(void)>& profile_getter)
    108       : profile_getter_(profile_getter) {
    109     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    110   }
    111 
    112   // net::CookieMonster::Delegate implementation.
    113   virtual void OnCookieChanged(
    114       const net::CanonicalCookie& cookie,
    115       bool removed,
    116       net::CookieMonster::Delegate::ChangeCause cause) OVERRIDE {
    117     BrowserThread::PostTask(
    118         BrowserThread::UI, FROM_HERE,
    119         base::Bind(&ChromeCookieMonsterDelegate::OnCookieChangedAsyncHelper,
    120                    this, cookie, removed, cause));
    121   }
    122 
    123  private:
    124   virtual ~ChromeCookieMonsterDelegate() {}
    125 
    126   void OnCookieChangedAsyncHelper(
    127       const net::CanonicalCookie& cookie,
    128       bool removed,
    129       net::CookieMonster::Delegate::ChangeCause cause) {
    130     Profile* profile = profile_getter_.Run();
    131     if (profile) {
    132       ChromeCookieDetails cookie_details(&cookie, removed, cause);
    133       content::NotificationService::current()->Notify(
    134           chrome::NOTIFICATION_COOKIE_CHANGED,
    135           content::Source<Profile>(profile),
    136           content::Details<ChromeCookieDetails>(&cookie_details));
    137     }
    138   }
    139 
    140   const base::Callback<Profile*(void)> profile_getter_;
    141 };
    142 
    143 Profile* GetProfileOnUI(ProfileManager* profile_manager, Profile* profile) {
    144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    145   DCHECK(profile);
    146   if (profile_manager->IsValidProfile(profile))
    147     return profile;
    148   return NULL;
    149 }
    150 
    151 #if defined(DEBUG_DEVTOOLS)
    152 bool IsSupportedDevToolsURL(const GURL& url, base::FilePath* path) {
    153   std::string bundled_path_prefix(chrome::kChromeUIDevToolsBundledPath);
    154   bundled_path_prefix = "/" + bundled_path_prefix + "/";
    155 
    156   if (!url.SchemeIs(chrome::kChromeDevToolsScheme) ||
    157       url.host() != chrome::kChromeUIDevToolsHost ||
    158       !StartsWithASCII(url.path(), bundled_path_prefix, false)) {
    159     return false;
    160   }
    161 
    162   if (!url.is_valid()) {
    163     NOTREACHED();
    164     return false;
    165   }
    166 
    167   // Remove Query and Ref from URL.
    168   GURL stripped_url;
    169   GURL::Replacements replacements;
    170   replacements.ClearQuery();
    171   replacements.ClearRef();
    172   stripped_url = url.ReplaceComponents(replacements);
    173 
    174   std::string relative_path;
    175   const std::string& spec = stripped_url.possibly_invalid_spec();
    176   const url_parse::Parsed& parsed =
    177       stripped_url.parsed_for_possibly_invalid_spec();
    178   int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
    179   if (offset < static_cast<int>(spec.size()))
    180     relative_path.assign(spec.substr(offset + bundled_path_prefix.length()));
    181 
    182   // Check that |relative_path| is not an absolute path (otherwise
    183   // AppendASCII() will DCHECK).  The awkward use of StringType is because on
    184   // some systems FilePath expects a std::string, but on others a std::wstring.
    185   base::FilePath p(
    186       base::FilePath::StringType(relative_path.begin(), relative_path.end()));
    187   if (p.IsAbsolute())
    188     return false;
    189 
    190   base::FilePath inspector_dir;
    191   if (!PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    192     return false;
    193 
    194   if (inspector_dir.empty())
    195     return false;
    196 
    197   *path = inspector_dir.AppendASCII(relative_path);
    198   return true;
    199 }
    200 
    201 class DebugDevToolsInterceptor
    202     : public net::URLRequestJobFactory::ProtocolHandler {
    203  public:
    204   DebugDevToolsInterceptor() {}
    205   virtual ~DebugDevToolsInterceptor() {}
    206 
    207   virtual net::URLRequestJob* MaybeCreateJob(
    208       net::URLRequest* request,
    209       net::NetworkDelegate* network_delegate) const OVERRIDE {
    210     base::FilePath path;
    211     if (IsSupportedDevToolsURL(request->url(), &path))
    212       return new net::URLRequestFileJob(request, network_delegate, path);
    213 
    214     return NULL;
    215   }
    216 };
    217 #endif  // defined(DEBUG_DEVTOOLS)
    218 
    219 }  // namespace
    220 
    221 void ProfileIOData::InitializeOnUIThread(Profile* profile) {
    222   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    223   PrefService* pref_service = profile->GetPrefs();
    224   PrefService* local_state_pref_service = g_browser_process->local_state();
    225 
    226   scoped_ptr<ProfileParams> params(new ProfileParams);
    227   params->path = profile->GetPath();
    228 
    229   params->io_thread = g_browser_process->io_thread();
    230 
    231   params->cookie_settings = CookieSettings::Factory::GetForProfile(profile);
    232   params->host_content_settings_map = profile->GetHostContentSettingsMap();
    233   params->ssl_config_service = profile->GetSSLConfigService();
    234   base::Callback<Profile*(void)> profile_getter =
    235       base::Bind(&GetProfileOnUI, g_browser_process->profile_manager(),
    236                  profile);
    237   params->cookie_monster_delegate =
    238       new chrome_browser_net::EvictedDomainCookieCounter(
    239           new ChromeCookieMonsterDelegate(profile_getter));
    240   params->extension_info_map =
    241       extensions::ExtensionSystem::Get(profile)->info_map();
    242 
    243   if (predictors::ResourcePrefetchPredictor* predictor =
    244           predictors::ResourcePrefetchPredictorFactory::GetForProfile(
    245               profile)) {
    246     resource_prefetch_predictor_observer_.reset(
    247         new chrome_browser_net::ResourcePrefetchPredictorObserver(predictor));
    248   }
    249 
    250 #if defined(ENABLE_NOTIFICATIONS)
    251   params->notification_service =
    252       DesktopNotificationServiceFactory::GetForProfile(profile);
    253 #endif
    254 
    255   ProtocolHandlerRegistry* protocol_handler_registry =
    256       ProtocolHandlerRegistryFactory::GetForProfile(profile);
    257   DCHECK(protocol_handler_registry);
    258 
    259   // The profile instance is only available here in the InitializeOnUIThread
    260   // method, so we create the url job factory here, then save it for
    261   // later delivery to the job factory in Init().
    262   params->protocol_handler_interceptor =
    263       protocol_handler_registry->CreateJobInterceptorFactory();
    264 
    265   params->proxy_config_service
    266       .reset(ProxyServiceFactory::CreateProxyConfigService(
    267            profile->GetProxyConfigTracker()));
    268 #if defined(ENABLE_MANAGED_USERS)
    269   ManagedUserService* managed_user_service =
    270       ManagedUserServiceFactory::GetForProfile(profile);
    271   params->managed_mode_url_filter =
    272       managed_user_service->GetURLFilterForIOThread();
    273 #endif
    274 #if defined(OS_CHROMEOS)
    275   policy::BrowserPolicyConnector* connector =
    276       g_browser_process->browser_policy_connector();
    277   params->trust_anchor_provider = connector->GetCertTrustAnchorProvider();
    278 #endif
    279 
    280   params->profile = profile;
    281   profile_params_.reset(params.release());
    282 
    283   ChromeNetworkDelegate::InitializePrefsOnUIThread(
    284       &enable_referrers_,
    285       &enable_do_not_track_,
    286       &force_safesearch_,
    287       pref_service);
    288 
    289   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy =
    290       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    291 #if defined(ENABLE_PRINTING)
    292   printing_enabled_.Init(prefs::kPrintingEnabled, pref_service);
    293   printing_enabled_.MoveToThread(io_message_loop_proxy);
    294 #endif
    295   chrome_http_user_agent_settings_.reset(
    296       new ChromeHttpUserAgentSettings(pref_service));
    297 
    298   // These members are used only for one click sign in, which is not enabled
    299   // in incognito mode.  So no need to initialize them.
    300   if (!is_incognito()) {
    301     signin_names_.reset(new SigninNamesOnIOThread());
    302 
    303     google_services_username_.Init(
    304         prefs::kGoogleServicesUsername, pref_service);
    305     google_services_username_.MoveToThread(io_message_loop_proxy);
    306 
    307     google_services_username_pattern_.Init(
    308         prefs::kGoogleServicesUsernamePattern, local_state_pref_service);
    309     google_services_username_pattern_.MoveToThread(io_message_loop_proxy);
    310 
    311     reverse_autologin_enabled_.Init(
    312         prefs::kReverseAutologinEnabled, pref_service);
    313     reverse_autologin_enabled_.MoveToThread(io_message_loop_proxy);
    314 
    315     one_click_signin_rejected_email_list_.Init(
    316         prefs::kReverseAutologinRejectedEmailList, pref_service);
    317     one_click_signin_rejected_email_list_.MoveToThread(io_message_loop_proxy);
    318 
    319     sync_disabled_.Init(prefs::kSyncManaged, pref_service);
    320     sync_disabled_.MoveToThread(io_message_loop_proxy);
    321 
    322     signin_allowed_.Init(prefs::kSigninAllowed, pref_service);
    323     signin_allowed_.MoveToThread(io_message_loop_proxy);
    324   }
    325 
    326   // The URLBlacklistManager has to be created on the UI thread to register
    327   // observers of |pref_service|, and it also has to clean up on
    328   // ShutdownOnUIThread to release these observers on the right thread.
    329   // Don't pass it in |profile_params_| to make sure it is correctly cleaned up,
    330   // in particular when this ProfileIOData isn't |initialized_| during deletion.
    331 #if defined(ENABLE_CONFIGURATION_POLICY)
    332   url_blacklist_manager_.reset(new policy::URLBlacklistManager(pref_service));
    333 #endif
    334 
    335   initialized_on_UI_thread_ = true;
    336 
    337   // We need to make sure that content initializes its own data structures that
    338   // are associated with each ResourceContext because we might post this
    339   // object to the IO thread after this function.
    340   BrowserContext::EnsureResourceContextInitialized(profile);
    341 }
    342 
    343 ProfileIOData::MediaRequestContext::MediaRequestContext(
    344     chrome_browser_net::LoadTimeStats* load_time_stats)
    345     : ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_MEDIA,
    346                               load_time_stats) {
    347 }
    348 
    349 void ProfileIOData::MediaRequestContext::SetHttpTransactionFactory(
    350     scoped_ptr<net::HttpTransactionFactory> http_factory) {
    351   http_factory_ = http_factory.Pass();
    352   set_http_transaction_factory(http_factory_.get());
    353 }
    354 
    355 ProfileIOData::MediaRequestContext::~MediaRequestContext() {}
    356 
    357 ProfileIOData::AppRequestContext::AppRequestContext(
    358     chrome_browser_net::LoadTimeStats* load_time_stats)
    359     : ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_APP,
    360                               load_time_stats) {
    361 }
    362 
    363 void ProfileIOData::AppRequestContext::SetCookieStore(
    364     net::CookieStore* cookie_store) {
    365   cookie_store_ = cookie_store;
    366   set_cookie_store(cookie_store);
    367 }
    368 
    369 void ProfileIOData::AppRequestContext::SetHttpTransactionFactory(
    370     scoped_ptr<net::HttpTransactionFactory> http_factory) {
    371   http_factory_ = http_factory.Pass();
    372   set_http_transaction_factory(http_factory_.get());
    373 }
    374 
    375 void ProfileIOData::AppRequestContext::SetJobFactory(
    376     scoped_ptr<net::URLRequestJobFactory> job_factory) {
    377   job_factory_ = job_factory.Pass();
    378   set_job_factory(job_factory_.get());
    379 }
    380 
    381 ProfileIOData::AppRequestContext::~AppRequestContext() {}
    382 
    383 ProfileIOData::ProfileParams::ProfileParams()
    384     : io_thread(NULL),
    385 #if defined(ENABLE_NOTIFICATIONS)
    386       notification_service(NULL),
    387 #endif
    388 #if defined(OS_CHROMEOS)
    389       trust_anchor_provider(NULL),
    390 #endif
    391       profile(NULL) {
    392 }
    393 
    394 ProfileIOData::ProfileParams::~ProfileParams() {}
    395 
    396 ProfileIOData::ProfileIOData(bool is_incognito)
    397     : initialized_(false),
    398 #if defined(ENABLE_NOTIFICATIONS)
    399       notification_service_(NULL),
    400 #endif
    401       resource_context_(new ResourceContext(this)),
    402       load_time_stats_(NULL),
    403       initialized_on_UI_thread_(false),
    404       is_incognito_(is_incognito) {
    405   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    406 }
    407 
    408 ProfileIOData::~ProfileIOData() {
    409   if (BrowserThread::IsMessageLoopValid(BrowserThread::IO))
    410     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    411 
    412   // Pull the contents of the request context maps onto the stack for sanity
    413   // checking of values in a minidump. http://crbug.com/260425
    414   size_t num_app_contexts = app_request_context_map_.size();
    415   size_t num_media_contexts = isolated_media_request_context_map_.size();
    416   size_t current_context = 0;
    417   static const size_t kMaxCachedContexts = 20;
    418   ChromeURLRequestContext* app_context_cache[kMaxCachedContexts] = {0};
    419   void* app_context_vtable_cache[kMaxCachedContexts] = {0};
    420   ChromeURLRequestContext* media_context_cache[kMaxCachedContexts] = {0};
    421   void* media_context_vtable_cache[kMaxCachedContexts] = {0};
    422   void* tmp_vtable = NULL;
    423   base::debug::Alias(&num_app_contexts);
    424   base::debug::Alias(&num_media_contexts);
    425   base::debug::Alias(&current_context);
    426   base::debug::Alias(app_context_cache);
    427   base::debug::Alias(app_context_vtable_cache);
    428   base::debug::Alias(media_context_cache);
    429   base::debug::Alias(media_context_vtable_cache);
    430   base::debug::Alias(&tmp_vtable);
    431 
    432   current_context = 0;
    433   for (URLRequestContextMap::const_iterator it =
    434            app_request_context_map_.begin();
    435        current_context < kMaxCachedContexts &&
    436            it != app_request_context_map_.end();
    437        ++it, ++current_context) {
    438     app_context_cache[current_context] = it->second;
    439     memcpy(&app_context_vtable_cache[current_context],
    440            static_cast<void*>(it->second), sizeof(void*));
    441   }
    442 
    443   current_context = 0;
    444   for (URLRequestContextMap::const_iterator it =
    445            isolated_media_request_context_map_.begin();
    446        current_context < kMaxCachedContexts &&
    447            it != isolated_media_request_context_map_.end();
    448        ++it, ++current_context) {
    449     media_context_cache[current_context] = it->second;
    450     memcpy(&media_context_vtable_cache[current_context],
    451            static_cast<void*>(it->second), sizeof(void*));
    452   }
    453 
    454   // TODO(ajwong): These AssertNoURLRequests() calls are unnecessary since they
    455   // are already done in the URLRequestContext destructor.
    456   if (main_request_context_)
    457     main_request_context_->AssertNoURLRequests();
    458   if (extensions_request_context_)
    459     extensions_request_context_->AssertNoURLRequests();
    460 
    461   current_context = 0;
    462   for (URLRequestContextMap::iterator it = app_request_context_map_.begin();
    463        it != app_request_context_map_.end(); ++it) {
    464     if (current_context < kMaxCachedContexts) {
    465       CHECK_EQ(app_context_cache[current_context], it->second);
    466       memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
    467       CHECK_EQ(app_context_vtable_cache[current_context], tmp_vtable);
    468     }
    469     it->second->AssertNoURLRequests();
    470     delete it->second;
    471     current_context++;
    472   }
    473 
    474   current_context = 0;
    475   for (URLRequestContextMap::iterator it =
    476            isolated_media_request_context_map_.begin();
    477        it != isolated_media_request_context_map_.end(); ++it) {
    478     if (current_context < kMaxCachedContexts) {
    479       CHECK_EQ(media_context_cache[current_context], it->second);
    480       memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
    481       CHECK_EQ(media_context_vtable_cache[current_context], tmp_vtable);
    482     }
    483     it->second->AssertNoURLRequests();
    484     delete it->second;
    485     current_context++;
    486   }
    487 }
    488 
    489 // static
    490 ProfileIOData* ProfileIOData::FromResourceContext(
    491     content::ResourceContext* rc) {
    492   return (static_cast<ResourceContext*>(rc))->io_data_;
    493 }
    494 
    495 // static
    496 bool ProfileIOData::IsHandledProtocol(const std::string& scheme) {
    497   DCHECK_EQ(scheme, StringToLowerASCII(scheme));
    498   static const char* const kProtocolList[] = {
    499     chrome::kFileScheme,
    500     chrome::kChromeDevToolsScheme,
    501     extensions::kExtensionScheme,
    502     chrome::kExtensionResourceScheme,
    503     chrome::kChromeUIScheme,
    504     chrome::kDataScheme,
    505 #if defined(OS_CHROMEOS)
    506     chrome::kDriveScheme,
    507 #endif  // defined(OS_CHROMEOS)
    508     chrome::kAboutScheme,
    509 #if !defined(DISABLE_FTP_SUPPORT)
    510     chrome::kFtpScheme,
    511 #endif  // !defined(DISABLE_FTP_SUPPORT)
    512     chrome::kBlobScheme,
    513     chrome::kFileSystemScheme,
    514     chrome::kChromeSearchScheme,
    515   };
    516   for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
    517     if (scheme == kProtocolList[i])
    518       return true;
    519   }
    520   return net::URLRequest::IsHandledProtocol(scheme);
    521 }
    522 
    523 // static
    524 bool ProfileIOData::IsHandledURL(const GURL& url) {
    525   if (!url.is_valid()) {
    526     // We handle error cases.
    527     return true;
    528   }
    529 
    530   return IsHandledProtocol(url.scheme());
    531 }
    532 
    533 // static
    534 void ProfileIOData::InstallProtocolHandlers(
    535     net::URLRequestJobFactoryImpl* job_factory,
    536     content::ProtocolHandlerMap* protocol_handlers) {
    537   for (content::ProtocolHandlerMap::iterator it =
    538            protocol_handlers->begin();
    539        it != protocol_handlers->end();
    540        ++it) {
    541     bool set_protocol = job_factory->SetProtocolHandler(
    542         it->first, it->second.release());
    543     DCHECK(set_protocol);
    544   }
    545   protocol_handlers->clear();
    546 }
    547 
    548 content::ResourceContext* ProfileIOData::GetResourceContext() const {
    549   return resource_context_.get();
    550 }
    551 
    552 ChromeURLRequestContext* ProfileIOData::GetMainRequestContext() const {
    553   DCHECK(initialized_);
    554   return main_request_context_.get();
    555 }
    556 
    557 ChromeURLRequestContext* ProfileIOData::GetMediaRequestContext() const {
    558   DCHECK(initialized_);
    559   ChromeURLRequestContext* context = AcquireMediaRequestContext();
    560   DCHECK(context);
    561   return context;
    562 }
    563 
    564 ChromeURLRequestContext* ProfileIOData::GetExtensionsRequestContext() const {
    565   DCHECK(initialized_);
    566   return extensions_request_context_.get();
    567 }
    568 
    569 ChromeURLRequestContext* ProfileIOData::GetIsolatedAppRequestContext(
    570     ChromeURLRequestContext* main_context,
    571     const StoragePartitionDescriptor& partition_descriptor,
    572     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    573         protocol_handler_interceptor,
    574     content::ProtocolHandlerMap* protocol_handlers) const {
    575   DCHECK(initialized_);
    576   ChromeURLRequestContext* context = NULL;
    577   if (ContainsKey(app_request_context_map_, partition_descriptor)) {
    578     context = app_request_context_map_[partition_descriptor];
    579   } else {
    580     context = AcquireIsolatedAppRequestContext(
    581         main_context, partition_descriptor, protocol_handler_interceptor.Pass(),
    582         protocol_handlers);
    583     app_request_context_map_[partition_descriptor] = context;
    584   }
    585   DCHECK(context);
    586   return context;
    587 }
    588 
    589 ChromeURLRequestContext* ProfileIOData::GetIsolatedMediaRequestContext(
    590     ChromeURLRequestContext* app_context,
    591     const StoragePartitionDescriptor& partition_descriptor) const {
    592   DCHECK(initialized_);
    593   ChromeURLRequestContext* context = NULL;
    594   if (ContainsKey(isolated_media_request_context_map_, partition_descriptor)) {
    595     context = isolated_media_request_context_map_[partition_descriptor];
    596   } else {
    597     context = AcquireIsolatedMediaRequestContext(app_context,
    598                                                  partition_descriptor);
    599     isolated_media_request_context_map_[partition_descriptor] = context;
    600   }
    601   DCHECK(context);
    602   return context;
    603 }
    604 
    605 ExtensionInfoMap* ProfileIOData::GetExtensionInfoMap() const {
    606   DCHECK(initialized_) << "ExtensionSystem not initialized";
    607   return extension_info_map_.get();
    608 }
    609 
    610 CookieSettings* ProfileIOData::GetCookieSettings() const {
    611   // Allow either Init() or SetCookieSettingsForTesting() to initialize.
    612   DCHECK(initialized_ || cookie_settings_.get());
    613   return cookie_settings_.get();
    614 }
    615 
    616 HostContentSettingsMap* ProfileIOData::GetHostContentSettingsMap() const {
    617   DCHECK(initialized_);
    618   return host_content_settings_map_.get();
    619 }
    620 
    621 #if defined(ENABLE_NOTIFICATIONS)
    622 DesktopNotificationService* ProfileIOData::GetNotificationService() const {
    623   DCHECK(initialized_);
    624   return notification_service_;
    625 }
    626 #endif
    627 
    628 void ProfileIOData::InitializeMetricsEnabledStateOnUIThread() {
    629   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    630 #if defined(OS_CHROMEOS)
    631   // Just fetch the value from ChromeOS' settings while we're on the UI thread.
    632   // TODO(stevet): For now, this value is only set on profile initialization.
    633   // We will want to do something similar to the PrefMember method below in the
    634   // future to more accurately capture this state.
    635   chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
    636                                             &enable_metrics_);
    637 #elif defined(OS_ANDROID)
    638   // TODO(dwkang): rename or unify the pref for UMA once we have conclusion
    639   // in crbugs.com/246495.
    640   // Android has it's own preferences for metrics / crash uploading.
    641   enable_metrics_.Init(prefs::kCrashReportingEnabled,
    642                        g_browser_process->local_state());
    643   enable_metrics_.MoveToThread(
    644       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    645 #else
    646   // Prep the PrefMember and send it to the IO thread, since this value will be
    647   // read from there.
    648   enable_metrics_.Init(prefs::kMetricsReportingEnabled,
    649                        g_browser_process->local_state());
    650   enable_metrics_.MoveToThread(
    651       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    652 #endif  // defined(OS_CHROMEOS)
    653 }
    654 
    655 bool ProfileIOData::GetMetricsEnabledStateOnIOThread() const {
    656   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    657 #if defined(OS_CHROMEOS)
    658   return enable_metrics_;
    659 #else
    660   return enable_metrics_.GetValue();
    661 #endif  // defined(OS_CHROMEOS)
    662 }
    663 
    664 base::WeakPtr<net::HttpServerProperties>
    665 ProfileIOData::http_server_properties() const {
    666   return http_server_properties_->GetWeakPtr();
    667 }
    668 
    669 void ProfileIOData::set_http_server_properties(
    670     scoped_ptr<net::HttpServerProperties> http_server_properties) const {
    671   http_server_properties_ = http_server_properties.Pass();
    672 }
    673 
    674 ProfileIOData::ResourceContext::ResourceContext(ProfileIOData* io_data)
    675     : io_data_(io_data),
    676       host_resolver_(NULL),
    677       request_context_(NULL) {
    678   DCHECK(io_data);
    679 }
    680 
    681 ProfileIOData::ResourceContext::~ResourceContext() {}
    682 
    683 net::HostResolver* ProfileIOData::ResourceContext::GetHostResolver()  {
    684   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    685   DCHECK(io_data_->initialized_);
    686   return host_resolver_;
    687 }
    688 
    689 net::URLRequestContext* ProfileIOData::ResourceContext::GetRequestContext()  {
    690   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    691   DCHECK(io_data_->initialized_);
    692   return request_context_;
    693 }
    694 
    695 bool ProfileIOData::ResourceContext::AllowMicAccess(const GURL& origin) {
    696   return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
    697 }
    698 
    699 bool ProfileIOData::ResourceContext::AllowCameraAccess(const GURL& origin) {
    700   return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
    701 }
    702 
    703 bool ProfileIOData::ResourceContext::AllowContentAccess(
    704     const GURL& origin, ContentSettingsType type) {
    705   HostContentSettingsMap* content_settings =
    706       io_data_->GetHostContentSettingsMap();
    707   ContentSetting setting = content_settings->GetContentSetting(
    708       origin, origin, type, NO_RESOURCE_IDENTIFIER);
    709   return setting == CONTENT_SETTING_ALLOW;
    710 }
    711 
    712 // static
    713 std::string ProfileIOData::GetSSLSessionCacheShard() {
    714   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    715   // The SSL session cache is partitioned by setting a string. This returns a
    716   // unique string to partition the SSL session cache. Each time we create a
    717   // new profile, we'll get a fresh SSL session cache which is separate from
    718   // the other profiles.
    719   static unsigned ssl_session_cache_instance = 0;
    720   return base::StringPrintf("profile/%u", ssl_session_cache_instance++);
    721 }
    722 
    723 void ProfileIOData::Init(content::ProtocolHandlerMap* protocol_handlers) const {
    724   // The basic logic is implemented here. The specific initialization
    725   // is done in InitializeInternal(), implemented by subtypes. Static helper
    726   // functions have been provided to assist in common operations.
    727   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    728   DCHECK(!initialized_);
    729 
    730   startup_metric_utils::ScopedSlowStartupUMA
    731       scoped_timer("Startup.SlowStartupProfileIODataInit");
    732 
    733   // TODO(jhawkins): Remove once crbug.com/102004 is fixed.
    734   CHECK(initialized_on_UI_thread_);
    735 
    736   // TODO(jhawkins): Return to DCHECK once crbug.com/102004 is fixed.
    737   CHECK(profile_params_.get());
    738 
    739   IOThread* const io_thread = profile_params_->io_thread;
    740   IOThread::Globals* const io_thread_globals = io_thread->globals();
    741   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    742   load_time_stats_ = GetLoadTimeStats(io_thread_globals);
    743 
    744   // Create the common request contexts.
    745   main_request_context_.reset(
    746       new ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_MAIN,
    747                                   load_time_stats_));
    748   extensions_request_context_.reset(
    749       new ChromeURLRequestContext(
    750           ChromeURLRequestContext::CONTEXT_TYPE_EXTENSIONS,
    751           load_time_stats_));
    752 
    753   ChromeNetworkDelegate* network_delegate =
    754       new ChromeNetworkDelegate(
    755           io_thread_globals->extension_event_router_forwarder.get(),
    756           &enable_referrers_);
    757   network_delegate->set_extension_info_map(
    758       profile_params_->extension_info_map.get());
    759   network_delegate->set_url_blacklist_manager(url_blacklist_manager_.get());
    760   network_delegate->set_profile(profile_params_->profile);
    761   network_delegate->set_cookie_settings(profile_params_->cookie_settings.get());
    762   network_delegate->set_enable_do_not_track(&enable_do_not_track_);
    763   network_delegate->set_force_google_safe_search(&force_safesearch_);
    764   network_delegate->set_load_time_stats(load_time_stats_);
    765   network_delegate_.reset(network_delegate);
    766 
    767   fraudulent_certificate_reporter_.reset(
    768       new chrome_browser_net::ChromeFraudulentCertificateReporter(
    769           main_request_context_.get()));
    770 
    771   // NOTE: Proxy service uses the default io thread network delegate, not the
    772   // delegate just created.
    773   proxy_service_.reset(
    774       ProxyServiceFactory::CreateProxyService(
    775           io_thread->net_log(),
    776           io_thread_globals->proxy_script_fetcher_context.get(),
    777           io_thread_globals->system_network_delegate.get(),
    778           profile_params_->proxy_config_service.release(),
    779           command_line));
    780 
    781   transport_security_state_.reset(new net::TransportSecurityState());
    782   transport_security_persister_.reset(
    783       new TransportSecurityPersister(transport_security_state_.get(),
    784                                      profile_params_->path,
    785                                      is_incognito()));
    786 
    787   // Take ownership over these parameters.
    788   cookie_settings_ = profile_params_->cookie_settings;
    789   host_content_settings_map_ = profile_params_->host_content_settings_map;
    790 #if defined(ENABLE_NOTIFICATIONS)
    791   notification_service_ = profile_params_->notification_service;
    792 #endif
    793   extension_info_map_ = profile_params_->extension_info_map;
    794 
    795   resource_context_->host_resolver_ = io_thread_globals->host_resolver.get();
    796   resource_context_->request_context_ = main_request_context_.get();
    797 
    798   if (profile_params_->resource_prefetch_predictor_observer_) {
    799     resource_prefetch_predictor_observer_.reset(
    800         profile_params_->resource_prefetch_predictor_observer_.release());
    801   }
    802 
    803 #if defined(ENABLE_MANAGED_USERS)
    804   managed_mode_url_filter_ = profile_params_->managed_mode_url_filter;
    805 #endif
    806 
    807 #if defined(OS_CHROMEOS)
    808   cert_verifier_.reset(new policy::PolicyCertVerifier(
    809       profile_params_->profile, profile_params_->trust_anchor_provider));
    810   main_request_context_->set_cert_verifier(cert_verifier_.get());
    811 #else
    812   main_request_context_->set_cert_verifier(
    813       io_thread_globals->cert_verifier.get());
    814 #endif
    815 
    816   InitializeInternal(profile_params_.get(), protocol_handlers);
    817 
    818   profile_params_.reset();
    819   initialized_ = true;
    820 }
    821 
    822 void ProfileIOData::ApplyProfileParamsToContext(
    823     ChromeURLRequestContext* context) const {
    824   context->set_http_user_agent_settings(
    825       chrome_http_user_agent_settings_.get());
    826   context->set_ssl_config_service(profile_params_->ssl_config_service.get());
    827 }
    828 
    829 scoped_ptr<net::URLRequestJobFactory> ProfileIOData::SetUpJobFactoryDefaults(
    830     scoped_ptr<net::URLRequestJobFactoryImpl> job_factory,
    831     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    832         protocol_handler_interceptor,
    833     net::NetworkDelegate* network_delegate,
    834     net::FtpTransactionFactory* ftp_transaction_factory) const {
    835   // NOTE(willchan): Keep these protocol handlers in sync with
    836   // ProfileIOData::IsHandledProtocol().
    837   bool set_protocol = job_factory->SetProtocolHandler(
    838       chrome::kFileScheme, new net::FileProtocolHandler());
    839   DCHECK(set_protocol);
    840 
    841   DCHECK(extension_info_map_.get());
    842   set_protocol = job_factory->SetProtocolHandler(
    843       extensions::kExtensionScheme,
    844       CreateExtensionProtocolHandler(is_incognito(),
    845                                      extension_info_map_.get()));
    846   DCHECK(set_protocol);
    847   set_protocol = job_factory->SetProtocolHandler(
    848       chrome::kExtensionResourceScheme,
    849       CreateExtensionResourceProtocolHandler());
    850   DCHECK(set_protocol);
    851   set_protocol = job_factory->SetProtocolHandler(
    852       chrome::kDataScheme, new net::DataProtocolHandler());
    853   DCHECK(set_protocol);
    854 #if defined(OS_CHROMEOS)
    855   if (!is_incognito() && profile_params_) {
    856     set_protocol = job_factory->SetProtocolHandler(
    857         chrome::kDriveScheme,
    858         new drive::DriveProtocolHandler(profile_params_->profile));
    859     DCHECK(set_protocol);
    860   }
    861 #endif  // defined(OS_CHROMEOS)
    862 
    863   job_factory->SetProtocolHandler(
    864       chrome::kAboutScheme,
    865       new chrome_browser_net::AboutProtocolHandler());
    866 #if !defined(DISABLE_FTP_SUPPORT)
    867   DCHECK(ftp_transaction_factory);
    868   job_factory->SetProtocolHandler(
    869       chrome::kFtpScheme,
    870       new net::FtpProtocolHandler(ftp_transaction_factory));
    871 #endif  // !defined(DISABLE_FTP_SUPPORT)
    872 
    873   scoped_ptr<net::URLRequestJobFactory> top_job_factory =
    874       job_factory.PassAs<net::URLRequestJobFactory>();
    875 #if defined(DEBUG_DEVTOOLS)
    876   top_job_factory.reset(new net::ProtocolInterceptJobFactory(
    877       top_job_factory.Pass(),
    878       scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
    879           new DebugDevToolsInterceptor)));
    880 #endif
    881 
    882   if (protocol_handler_interceptor) {
    883     protocol_handler_interceptor->Chain(top_job_factory.Pass());
    884     return protocol_handler_interceptor.PassAs<net::URLRequestJobFactory>();
    885   } else {
    886     return top_job_factory.Pass();
    887   }
    888 }
    889 
    890 void ProfileIOData::ShutdownOnUIThread() {
    891   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    892 
    893   if (signin_names_)
    894     signin_names_->ReleaseResourcesOnUIThread();
    895 
    896   google_services_username_.Destroy();
    897   google_services_username_pattern_.Destroy();
    898   reverse_autologin_enabled_.Destroy();
    899   one_click_signin_rejected_email_list_.Destroy();
    900   enable_referrers_.Destroy();
    901   enable_do_not_track_.Destroy();
    902   force_safesearch_.Destroy();
    903 #if !defined(OS_CHROMEOS)
    904   enable_metrics_.Destroy();
    905 #endif
    906   safe_browsing_enabled_.Destroy();
    907   printing_enabled_.Destroy();
    908   sync_disabled_.Destroy();
    909   signin_allowed_.Destroy();
    910   session_startup_pref_.Destroy();
    911 #if defined(ENABLE_CONFIGURATION_POLICY)
    912   if (url_blacklist_manager_)
    913     url_blacklist_manager_->ShutdownOnUIThread();
    914 #endif
    915   if (chrome_http_user_agent_settings_)
    916     chrome_http_user_agent_settings_->CleanupOnUIThread();
    917   bool posted = BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
    918   if (!posted)
    919     delete this;
    920 }
    921 
    922 void ProfileIOData::set_server_bound_cert_service(
    923     net::ServerBoundCertService* server_bound_cert_service) const {
    924   server_bound_cert_service_.reset(server_bound_cert_service);
    925 }
    926 
    927 void ProfileIOData::DestroyResourceContext() {
    928   resource_context_.reset();
    929 }
    930 
    931 void ProfileIOData::PopulateNetworkSessionParams(
    932     const ProfileParams* profile_params,
    933     net::HttpNetworkSession::Params* params) const {
    934 
    935   ChromeURLRequestContext* context = main_request_context();
    936 
    937   IOThread* const io_thread = profile_params->io_thread;
    938 
    939   io_thread->InitializeNetworkSessionParams(params);
    940 
    941   params->host_resolver = context->host_resolver();
    942   params->cert_verifier = context->cert_verifier();
    943   params->server_bound_cert_service = context->server_bound_cert_service();
    944   params->transport_security_state = context->transport_security_state();
    945   params->proxy_service = context->proxy_service();
    946   params->ssl_session_cache_shard = GetSSLSessionCacheShard();
    947   params->ssl_config_service = context->ssl_config_service();
    948   params->http_auth_handler_factory = context->http_auth_handler_factory();
    949   params->network_delegate = network_delegate();
    950   params->http_server_properties = context->http_server_properties();
    951   params->net_log = context->net_log();
    952 }
    953 
    954 void ProfileIOData::SetCookieSettingsForTesting(
    955     CookieSettings* cookie_settings) {
    956   DCHECK(!cookie_settings_.get());
    957   cookie_settings_ = cookie_settings;
    958 }
    959 
    960 void ProfileIOData::set_signin_names_for_testing(
    961     SigninNamesOnIOThread* signin_names) {
    962   signin_names_.reset(signin_names);
    963 }
    964