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/callback.h"
     13 #include "base/command_line.h"
     14 #include "base/compiler_specific.h"
     15 #include "base/debug/alias.h"
     16 #include "base/logging.h"
     17 #include "base/path_service.h"
     18 #include "base/prefs/pref_service.h"
     19 #include "base/stl_util.h"
     20 #include "base/strings/string_number_conversions.h"
     21 #include "base/strings/string_util.h"
     22 #include "base/strings/stringprintf.h"
     23 #include "base/threading/sequenced_worker_pool.h"
     24 #include "chrome/browser/browser_process.h"
     25 #include "chrome/browser/chrome_notification_types.h"
     26 #include "chrome/browser/content_settings/content_settings_provider.h"
     27 #include "chrome/browser/content_settings/cookie_settings.h"
     28 #include "chrome/browser/content_settings/host_content_settings_map.h"
     29 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
     30 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
     31 #include "chrome/browser/download/download_service.h"
     32 #include "chrome/browser/download/download_service_factory.h"
     33 #include "chrome/browser/extensions/extension_protocols.h"
     34 #include "chrome/browser/extensions/extension_resource_protocols.h"
     35 #include "chrome/browser/extensions/extension_system.h"
     36 #include "chrome/browser/io_thread.h"
     37 #include "chrome/browser/media/media_device_id_salt.h"
     38 #include "chrome/browser/net/about_protocol_handler.h"
     39 #include "chrome/browser/net/chrome_cookie_notification_details.h"
     40 #include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h"
     41 #include "chrome/browser/net/chrome_http_user_agent_settings.h"
     42 #include "chrome/browser/net/chrome_net_log.h"
     43 #include "chrome/browser/net/chrome_network_delegate.h"
     44 #include "chrome/browser/net/evicted_domain_cookie_counter.h"
     45 #include "chrome/browser/net/load_time_stats.h"
     46 #include "chrome/browser/net/proxy_service_factory.h"
     47 #include "chrome/browser/net/resource_prefetch_predictor_observer.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/url_constants.h"
     58 #include "components/startup_metric_utils/startup_metric_utils.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/browser/info_map.h"
     64 #include "extensions/common/constants.h"
     65 #include "net/base/keygen_handler.h"
     66 #include "net/cookies/canonical_cookie.h"
     67 #include "net/cookies/cookie_monster.h"
     68 #include "net/http/http_transaction_factory.h"
     69 #include "net/http/http_util.h"
     70 #include "net/http/transport_security_persister.h"
     71 #include "net/proxy/proxy_config_service_fixed.h"
     72 #include "net/proxy/proxy_script_fetcher_impl.h"
     73 #include "net/proxy/proxy_service.h"
     74 #include "net/ssl/client_cert_store.h"
     75 #include "net/ssl/server_bound_cert_service.h"
     76 #include "net/url_request/data_protocol_handler.h"
     77 #include "net/url_request/file_protocol_handler.h"
     78 #include "net/url_request/ftp_protocol_handler.h"
     79 #include "net/url_request/protocol_intercept_job_factory.h"
     80 #include "net/url_request/url_request.h"
     81 #include "net/url_request/url_request_file_job.h"
     82 #include "net/url_request/url_request_job_factory_impl.h"
     83 
     84 #if defined(ENABLE_CONFIGURATION_POLICY)
     85 #include "chrome/browser/policy/cloud/policy_header_service_factory.h"
     86 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
     87 #include "components/policy/core/common/cloud/policy_header_io_helper.h"
     88 #include "components/policy/core/common/cloud/policy_header_service.h"
     89 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
     90 #endif
     91 
     92 #if defined(ENABLE_MANAGED_USERS)
     93 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
     94 #include "chrome/browser/managed_mode/managed_user_service.h"
     95 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
     96 #endif
     97 
     98 #if defined(OS_CHROMEOS)
     99 #include "chrome/browser/chromeos/drive/drive_protocol_handler.h"
    100 #include "chrome/browser/chromeos/login/user.h"
    101 #include "chrome/browser/chromeos/login/user_manager.h"
    102 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
    103 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
    104 #include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
    105 #include "chrome/browser/chromeos/settings/cros_settings.h"
    106 #include "chromeos/dbus/cryptohome_client.h"
    107 #include "chromeos/dbus/dbus_thread_manager.h"
    108 #include "chromeos/settings/cros_settings_names.h"
    109 #include "crypto/nss_util.h"
    110 #include "crypto/nss_util_internal.h"
    111 #endif  // defined(OS_CHROMEOS)
    112 
    113 #if defined(USE_NSS)
    114 #include "chrome/browser/ui/crypto_module_delegate_nss.h"
    115 #include "net/ssl/client_cert_store_nss.h"
    116 #endif
    117 
    118 #if defined(OS_WIN)
    119 #include "net/ssl/client_cert_store_win.h"
    120 #endif
    121 
    122 #if defined(OS_MACOSX)
    123 #include "net/ssl/client_cert_store_mac.h"
    124 #endif
    125 
    126 using content::BrowserContext;
    127 using content::BrowserThread;
    128 using content::ResourceContext;
    129 
    130 namespace {
    131 
    132 // ----------------------------------------------------------------------------
    133 // CookieMonster::Delegate implementation
    134 // ----------------------------------------------------------------------------
    135 class ChromeCookieMonsterDelegate : public net::CookieMonster::Delegate {
    136  public:
    137   explicit ChromeCookieMonsterDelegate(
    138       const base::Callback<Profile*(void)>& profile_getter)
    139       : profile_getter_(profile_getter) {
    140     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    141   }
    142 
    143   // net::CookieMonster::Delegate implementation.
    144   virtual void OnCookieChanged(
    145       const net::CanonicalCookie& cookie,
    146       bool removed,
    147       net::CookieMonster::Delegate::ChangeCause cause) OVERRIDE {
    148     BrowserThread::PostTask(
    149         BrowserThread::UI, FROM_HERE,
    150         base::Bind(&ChromeCookieMonsterDelegate::OnCookieChangedAsyncHelper,
    151                    this, cookie, removed, cause));
    152   }
    153 
    154  private:
    155   virtual ~ChromeCookieMonsterDelegate() {}
    156 
    157   void OnCookieChangedAsyncHelper(
    158       const net::CanonicalCookie& cookie,
    159       bool removed,
    160       net::CookieMonster::Delegate::ChangeCause cause) {
    161     Profile* profile = profile_getter_.Run();
    162     if (profile) {
    163       ChromeCookieDetails cookie_details(&cookie, removed, cause);
    164       content::NotificationService::current()->Notify(
    165           chrome::NOTIFICATION_COOKIE_CHANGED,
    166           content::Source<Profile>(profile),
    167           content::Details<ChromeCookieDetails>(&cookie_details));
    168     }
    169   }
    170 
    171   const base::Callback<Profile*(void)> profile_getter_;
    172 };
    173 
    174 Profile* GetProfileOnUI(ProfileManager* profile_manager, Profile* profile) {
    175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    176   DCHECK(profile);
    177   if (profile_manager->IsValidProfile(profile))
    178     return profile;
    179   return NULL;
    180 }
    181 
    182 #if defined(DEBUG_DEVTOOLS)
    183 bool IsSupportedDevToolsURL(const GURL& url, base::FilePath* path) {
    184   std::string bundled_path_prefix(chrome::kChromeUIDevToolsBundledPath);
    185   bundled_path_prefix = "/" + bundled_path_prefix + "/";
    186 
    187   if (!url.SchemeIs(chrome::kChromeDevToolsScheme) ||
    188       url.host() != chrome::kChromeUIDevToolsHost ||
    189       !StartsWithASCII(url.path(), bundled_path_prefix, false)) {
    190     return false;
    191   }
    192 
    193   if (!url.is_valid()) {
    194     NOTREACHED();
    195     return false;
    196   }
    197 
    198   // Remove Query and Ref from URL.
    199   GURL stripped_url;
    200   GURL::Replacements replacements;
    201   replacements.ClearQuery();
    202   replacements.ClearRef();
    203   stripped_url = url.ReplaceComponents(replacements);
    204 
    205   std::string relative_path;
    206   const std::string& spec = stripped_url.possibly_invalid_spec();
    207   const url_parse::Parsed& parsed =
    208       stripped_url.parsed_for_possibly_invalid_spec();
    209   int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
    210   if (offset < static_cast<int>(spec.size()))
    211     relative_path.assign(spec.substr(offset + bundled_path_prefix.length()));
    212 
    213   // Check that |relative_path| is not an absolute path (otherwise
    214   // AppendASCII() will DCHECK).  The awkward use of StringType is because on
    215   // some systems FilePath expects a std::string, but on others a std::wstring.
    216   base::FilePath p(
    217       base::FilePath::StringType(relative_path.begin(), relative_path.end()));
    218   if (p.IsAbsolute())
    219     return false;
    220 
    221   base::FilePath inspector_dir;
    222   if (!PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir))
    223     return false;
    224 
    225   if (inspector_dir.empty())
    226     return false;
    227 
    228   *path = inspector_dir.AppendASCII(relative_path);
    229   return true;
    230 }
    231 
    232 class DebugDevToolsInterceptor
    233     : public net::URLRequestJobFactory::ProtocolHandler {
    234  public:
    235   DebugDevToolsInterceptor() {}
    236   virtual ~DebugDevToolsInterceptor() {}
    237 
    238   virtual net::URLRequestJob* MaybeCreateJob(
    239       net::URLRequest* request,
    240       net::NetworkDelegate* network_delegate) const OVERRIDE {
    241     base::FilePath path;
    242     if (IsSupportedDevToolsURL(request->url(), &path))
    243       return new net::URLRequestFileJob(
    244           request, network_delegate, path,
    245           content::BrowserThread::GetBlockingPool()->
    246               GetTaskRunnerWithShutdownBehavior(
    247                   base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
    248 
    249     return NULL;
    250   }
    251 };
    252 #endif  // defined(DEBUG_DEVTOOLS)
    253 
    254 #if defined(OS_CHROMEOS)
    255 // The following four functions are responsible for initializing NSS for each
    256 // profile on ChromeOS, which has a separate NSS database and TPM slot
    257 // per-profile.
    258 //
    259 // Initialization basically follows these steps:
    260 // 1) Get some info from chromeos::UserManager about the User for this profile.
    261 // 2) Tell nss_util to initialize the software slot for this profile.
    262 // 3) Wait for the TPM module to be loaded by nss_util if it isn't already.
    263 // 4) Ask CryptohomeClient which TPM slot id corresponds to this profile.
    264 // 5) Tell nss_util to use that slot id on the TPM module.
    265 //
    266 // Some of these steps must happen on the UI thread, others must happen on the
    267 // IO thread:
    268 //               UI thread                              IO Thread
    269 //
    270 //  ProfileIOData::InitializeOnUIThread
    271 //                   |
    272 // chromeos::UserManager::GetUserByProfile
    273 //                   \---------------------------------------v
    274 //                                                 StartNSSInitOnIOThread
    275 //                                                           |
    276 //                                          crypto::InitializeNSSForChromeOSUser
    277 //                                                           |
    278 //                                                crypto::IsTPMTokenReady
    279 //                                                           |
    280 //                                          StartTPMSlotInitializationOnIOThread
    281 //                   v---------------------------------------/
    282 //     GetTPMInfoForUserOnUIThread
    283 //                   |
    284 // CryptohomeClient::Pkcs11GetTpmTokenInfoForUser
    285 //                   |
    286 //     DidGetTPMInfoForUserOnUIThread
    287 //                   \---------------------------------------v
    288 //                                          crypto::InitializeTPMForChromeOSUser
    289 
    290 void DidGetTPMInfoForUserOnUIThread(const std::string& username_hash,
    291                                     chromeos::DBusMethodCallStatus call_status,
    292                                     const std::string& label,
    293                                     const std::string& user_pin,
    294                                     int slot_id) {
    295   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    296   if (call_status == chromeos::DBUS_METHOD_CALL_FAILURE) {
    297     NOTREACHED() << "dbus error getting TPM info for " << username_hash;
    298     return;
    299   }
    300   DVLOG(1) << "Got TPM slot for " << username_hash << ": " << slot_id;
    301   BrowserThread::PostTask(
    302       BrowserThread::IO,
    303       FROM_HERE,
    304       base::Bind(
    305           &crypto::InitializeTPMForChromeOSUser, username_hash, slot_id));
    306 }
    307 
    308 void GetTPMInfoForUserOnUIThread(const std::string& username,
    309                                  const std::string& username_hash) {
    310   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    311   DVLOG(1) << "Getting TPM info from cryptohome for "
    312            << " " << username << " " << username_hash;
    313   chromeos::DBusThreadManager::Get()
    314       ->GetCryptohomeClient()
    315       ->Pkcs11GetTpmTokenInfoForUser(
    316             username,
    317             base::Bind(&DidGetTPMInfoForUserOnUIThread, username_hash));
    318 }
    319 
    320 void StartTPMSlotInitializationOnIOThread(const std::string& username,
    321                                           const std::string& username_hash) {
    322   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    323 
    324   BrowserThread::PostTask(
    325       BrowserThread::UI,
    326       FROM_HERE,
    327       base::Bind(&GetTPMInfoForUserOnUIThread, username, username_hash));
    328 }
    329 
    330 void StartNSSInitOnIOThread(const std::string& username,
    331                             const std::string& username_hash,
    332                             const base::FilePath& path,
    333                             bool is_primary_user) {
    334   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    335   DVLOG(1) << "Starting NSS init for " << username
    336            << "  hash:" << username_hash
    337            << "  is_primary_user:" << is_primary_user;
    338 
    339   if (!crypto::InitializeNSSForChromeOSUser(
    340            username, username_hash, is_primary_user, path)) {
    341     // If the user already exists in nss_util's map, it is already initialized
    342     // or in the process of being initialized. In either case, there's no need
    343     // to do anything.
    344     return;
    345   }
    346 
    347   if (crypto::IsTPMTokenEnabledForNSS()) {
    348     if (crypto::IsTPMTokenReady(base::Bind(
    349             &StartTPMSlotInitializationOnIOThread, username, username_hash))) {
    350       StartTPMSlotInitializationOnIOThread(username, username_hash);
    351     } else {
    352       DVLOG(1) << "Waiting for tpm ready ...";
    353     }
    354   } else {
    355     crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash);
    356   }
    357 }
    358 #endif  // defined(OS_CHROMEOS)
    359 
    360 }  // namespace
    361 
    362 void ProfileIOData::InitializeOnUIThread(Profile* profile) {
    363   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    364   PrefService* pref_service = profile->GetPrefs();
    365   PrefService* local_state_pref_service = g_browser_process->local_state();
    366 
    367   scoped_ptr<ProfileParams> params(new ProfileParams);
    368   params->path = profile->GetPath();
    369 
    370   params->io_thread = g_browser_process->io_thread();
    371 
    372   params->cookie_settings = CookieSettings::Factory::GetForProfile(profile);
    373   params->host_content_settings_map = profile->GetHostContentSettingsMap();
    374   params->ssl_config_service = profile->GetSSLConfigService();
    375   base::Callback<Profile*(void)> profile_getter =
    376       base::Bind(&GetProfileOnUI, g_browser_process->profile_manager(),
    377                  profile);
    378   params->cookie_monster_delegate =
    379       new chrome_browser_net::EvictedDomainCookieCounter(
    380           new ChromeCookieMonsterDelegate(profile_getter));
    381   params->extension_info_map =
    382       extensions::ExtensionSystem::Get(profile)->info_map();
    383 
    384   if (predictors::ResourcePrefetchPredictor* predictor =
    385           predictors::ResourcePrefetchPredictorFactory::GetForProfile(
    386               profile)) {
    387     resource_prefetch_predictor_observer_.reset(
    388         new chrome_browser_net::ResourcePrefetchPredictorObserver(predictor));
    389   }
    390 
    391   ProtocolHandlerRegistry* protocol_handler_registry =
    392       ProtocolHandlerRegistryFactory::GetForProfile(profile);
    393   DCHECK(protocol_handler_registry);
    394 
    395   // The profile instance is only available here in the InitializeOnUIThread
    396   // method, so we create the url job factory here, then save it for
    397   // later delivery to the job factory in Init().
    398   params->protocol_handler_interceptor =
    399       protocol_handler_registry->CreateJobInterceptorFactory();
    400 
    401   params->proxy_config_service
    402       .reset(ProxyServiceFactory::CreateProxyConfigService(
    403            profile->GetProxyConfigTracker()));
    404 #if defined(ENABLE_MANAGED_USERS)
    405   ManagedUserService* managed_user_service =
    406       ManagedUserServiceFactory::GetForProfile(profile);
    407   params->managed_mode_url_filter =
    408       managed_user_service->GetURLFilterForIOThread();
    409 #endif
    410 #if defined(OS_CHROMEOS)
    411   chromeos::UserManager* user_manager = chromeos::UserManager::Get();
    412   if (user_manager) {
    413     chromeos::User* user = user_manager->GetUserByProfile(profile);
    414     if (user) {
    415       params->username_hash = user->username_hash();
    416       bool is_primary_user = (user_manager->GetPrimaryUser() == user);
    417       BrowserThread::PostTask(BrowserThread::IO,
    418                               FROM_HERE,
    419                               base::Bind(&StartNSSInitOnIOThread,
    420                                          user->email(),
    421                                          user->username_hash(),
    422                                          profile->GetPath(),
    423                                          is_primary_user));
    424     }
    425   }
    426   if (params->username_hash.empty())
    427     LOG(WARNING) << "no username_hash";
    428 #endif
    429 
    430   params->profile = profile;
    431   profile_params_.reset(params.release());
    432 
    433   ChromeNetworkDelegate::InitializePrefsOnUIThread(
    434       &enable_referrers_,
    435       &enable_do_not_track_,
    436       &force_safesearch_,
    437       pref_service);
    438 
    439   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy =
    440       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    441 #if defined(ENABLE_PRINTING)
    442   printing_enabled_.Init(prefs::kPrintingEnabled, pref_service);
    443   printing_enabled_.MoveToThread(io_message_loop_proxy);
    444 #endif
    445 
    446   chrome_http_user_agent_settings_.reset(
    447       new ChromeHttpUserAgentSettings(pref_service));
    448 
    449   // These members are used only for one click sign in, which is not enabled
    450   // in incognito mode.  So no need to initialize them.
    451   if (!is_incognito()) {
    452     signin_names_.reset(new SigninNamesOnIOThread());
    453 
    454     google_services_user_account_id_.Init(
    455         prefs::kGoogleServicesUserAccountId, pref_service);
    456     google_services_user_account_id_.MoveToThread(io_message_loop_proxy);
    457 
    458     google_services_username_.Init(
    459         prefs::kGoogleServicesUsername, pref_service);
    460     google_services_username_.MoveToThread(io_message_loop_proxy);
    461 
    462     google_services_username_pattern_.Init(
    463         prefs::kGoogleServicesUsernamePattern, local_state_pref_service);
    464     google_services_username_pattern_.MoveToThread(io_message_loop_proxy);
    465 
    466     reverse_autologin_enabled_.Init(
    467         prefs::kReverseAutologinEnabled, pref_service);
    468     reverse_autologin_enabled_.MoveToThread(io_message_loop_proxy);
    469 
    470     one_click_signin_rejected_email_list_.Init(
    471         prefs::kReverseAutologinRejectedEmailList, pref_service);
    472     one_click_signin_rejected_email_list_.MoveToThread(io_message_loop_proxy);
    473 
    474     sync_disabled_.Init(prefs::kSyncManaged, pref_service);
    475     sync_disabled_.MoveToThread(io_message_loop_proxy);
    476 
    477     signin_allowed_.Init(prefs::kSigninAllowed, pref_service);
    478     signin_allowed_.MoveToThread(io_message_loop_proxy);
    479   }
    480 
    481   media_device_id_salt_ = new MediaDeviceIDSalt(pref_service, is_incognito());
    482 
    483 #if defined(OS_CHROMEOS)
    484   cert_verifier_ = policy::PolicyCertServiceFactory::CreateForProfile(profile);
    485 #endif
    486   // The URLBlacklistManager has to be created on the UI thread to register
    487   // observers of |pref_service|, and it also has to clean up on
    488   // ShutdownOnUIThread to release these observers on the right thread.
    489   // Don't pass it in |profile_params_| to make sure it is correctly cleaned up,
    490   // in particular when this ProfileIOData isn't |initialized_| during deletion.
    491 #if defined(ENABLE_CONFIGURATION_POLICY)
    492   url_blacklist_manager_.reset(new policy::URLBlacklistManager(pref_service));
    493 
    494   if (!is_incognito()) {
    495     // Add policy headers for non-incognito requests.
    496     policy::PolicyHeaderService* policy_header_service =
    497         policy::PolicyHeaderServiceFactory::GetForBrowserContext(profile);
    498     if (policy_header_service) {
    499       policy_header_helper_ = policy_header_service->CreatePolicyHeaderIOHelper(
    500           io_message_loop_proxy);
    501     }
    502   }
    503 #endif
    504 
    505   initialized_on_UI_thread_ = true;
    506 
    507   // We need to make sure that content initializes its own data structures that
    508   // are associated with each ResourceContext because we might post this
    509   // object to the IO thread after this function.
    510   BrowserContext::EnsureResourceContextInitialized(profile);
    511 }
    512 
    513 ProfileIOData::MediaRequestContext::MediaRequestContext(
    514     chrome_browser_net::LoadTimeStats* load_time_stats)
    515     : ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_MEDIA,
    516                               load_time_stats) {
    517 }
    518 
    519 void ProfileIOData::MediaRequestContext::SetHttpTransactionFactory(
    520     scoped_ptr<net::HttpTransactionFactory> http_factory) {
    521   http_factory_ = http_factory.Pass();
    522   set_http_transaction_factory(http_factory_.get());
    523 }
    524 
    525 ProfileIOData::MediaRequestContext::~MediaRequestContext() {}
    526 
    527 ProfileIOData::AppRequestContext::AppRequestContext(
    528     chrome_browser_net::LoadTimeStats* load_time_stats)
    529     : ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_APP,
    530                               load_time_stats) {
    531 }
    532 
    533 void ProfileIOData::AppRequestContext::SetCookieStore(
    534     net::CookieStore* cookie_store) {
    535   cookie_store_ = cookie_store;
    536   set_cookie_store(cookie_store);
    537 }
    538 
    539 void ProfileIOData::AppRequestContext::SetHttpTransactionFactory(
    540     scoped_ptr<net::HttpTransactionFactory> http_factory) {
    541   http_factory_ = http_factory.Pass();
    542   set_http_transaction_factory(http_factory_.get());
    543 }
    544 
    545 void ProfileIOData::AppRequestContext::SetJobFactory(
    546     scoped_ptr<net::URLRequestJobFactory> job_factory) {
    547   job_factory_ = job_factory.Pass();
    548   set_job_factory(job_factory_.get());
    549 }
    550 
    551 ProfileIOData::AppRequestContext::~AppRequestContext() {}
    552 
    553 ProfileIOData::ProfileParams::ProfileParams()
    554     : io_thread(NULL),
    555       profile(NULL) {
    556 }
    557 
    558 ProfileIOData::ProfileParams::~ProfileParams() {}
    559 
    560 ProfileIOData::ProfileIOData(bool is_incognito)
    561     : initialized_(false),
    562       resource_context_(new ResourceContext(this)),
    563       load_time_stats_(NULL),
    564       initialized_on_UI_thread_(false),
    565       is_incognito_(is_incognito) {
    566   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    567 }
    568 
    569 ProfileIOData::~ProfileIOData() {
    570   if (BrowserThread::IsMessageLoopValid(BrowserThread::IO))
    571     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    572 
    573   // Pull the contents of the request context maps onto the stack for sanity
    574   // checking of values in a minidump. http://crbug.com/260425
    575   size_t num_app_contexts = app_request_context_map_.size();
    576   size_t num_media_contexts = isolated_media_request_context_map_.size();
    577   size_t current_context = 0;
    578   static const size_t kMaxCachedContexts = 20;
    579   ChromeURLRequestContext* app_context_cache[kMaxCachedContexts] = {0};
    580   void* app_context_vtable_cache[kMaxCachedContexts] = {0};
    581   ChromeURLRequestContext* media_context_cache[kMaxCachedContexts] = {0};
    582   void* media_context_vtable_cache[kMaxCachedContexts] = {0};
    583   void* tmp_vtable = NULL;
    584   base::debug::Alias(&num_app_contexts);
    585   base::debug::Alias(&num_media_contexts);
    586   base::debug::Alias(&current_context);
    587   base::debug::Alias(app_context_cache);
    588   base::debug::Alias(app_context_vtable_cache);
    589   base::debug::Alias(media_context_cache);
    590   base::debug::Alias(media_context_vtable_cache);
    591   base::debug::Alias(&tmp_vtable);
    592 
    593   current_context = 0;
    594   for (URLRequestContextMap::const_iterator it =
    595            app_request_context_map_.begin();
    596        current_context < kMaxCachedContexts &&
    597            it != app_request_context_map_.end();
    598        ++it, ++current_context) {
    599     app_context_cache[current_context] = it->second;
    600     memcpy(&app_context_vtable_cache[current_context],
    601            static_cast<void*>(it->second), sizeof(void*));
    602   }
    603 
    604   current_context = 0;
    605   for (URLRequestContextMap::const_iterator it =
    606            isolated_media_request_context_map_.begin();
    607        current_context < kMaxCachedContexts &&
    608            it != isolated_media_request_context_map_.end();
    609        ++it, ++current_context) {
    610     media_context_cache[current_context] = it->second;
    611     memcpy(&media_context_vtable_cache[current_context],
    612            static_cast<void*>(it->second), sizeof(void*));
    613   }
    614 
    615   // TODO(ajwong): These AssertNoURLRequests() calls are unnecessary since they
    616   // are already done in the URLRequestContext destructor.
    617   if (main_request_context_)
    618     main_request_context_->AssertNoURLRequests();
    619   if (extensions_request_context_)
    620     extensions_request_context_->AssertNoURLRequests();
    621 
    622   current_context = 0;
    623   for (URLRequestContextMap::iterator it = app_request_context_map_.begin();
    624        it != app_request_context_map_.end(); ++it) {
    625     if (current_context < kMaxCachedContexts) {
    626       CHECK_EQ(app_context_cache[current_context], it->second);
    627       memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
    628       CHECK_EQ(app_context_vtable_cache[current_context], tmp_vtable);
    629     }
    630     it->second->AssertNoURLRequests();
    631     delete it->second;
    632     current_context++;
    633   }
    634 
    635   current_context = 0;
    636   for (URLRequestContextMap::iterator it =
    637            isolated_media_request_context_map_.begin();
    638        it != isolated_media_request_context_map_.end(); ++it) {
    639     if (current_context < kMaxCachedContexts) {
    640       CHECK_EQ(media_context_cache[current_context], it->second);
    641       memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*));
    642       CHECK_EQ(media_context_vtable_cache[current_context], tmp_vtable);
    643     }
    644     it->second->AssertNoURLRequests();
    645     delete it->second;
    646     current_context++;
    647   }
    648 }
    649 
    650 // static
    651 ProfileIOData* ProfileIOData::FromResourceContext(
    652     content::ResourceContext* rc) {
    653   return (static_cast<ResourceContext*>(rc))->io_data_;
    654 }
    655 
    656 // static
    657 bool ProfileIOData::IsHandledProtocol(const std::string& scheme) {
    658   DCHECK_EQ(scheme, StringToLowerASCII(scheme));
    659   static const char* const kProtocolList[] = {
    660     chrome::kFileScheme,
    661     chrome::kChromeDevToolsScheme,
    662     extensions::kExtensionScheme,
    663     chrome::kExtensionResourceScheme,
    664     chrome::kChromeUIScheme,
    665     chrome::kDataScheme,
    666 #if defined(OS_CHROMEOS)
    667     chrome::kDriveScheme,
    668 #endif  // defined(OS_CHROMEOS)
    669     chrome::kAboutScheme,
    670 #if !defined(DISABLE_FTP_SUPPORT)
    671     content::kFtpScheme,
    672 #endif  // !defined(DISABLE_FTP_SUPPORT)
    673     chrome::kBlobScheme,
    674     chrome::kFileSystemScheme,
    675     chrome::kChromeSearchScheme,
    676   };
    677   for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
    678     if (scheme == kProtocolList[i])
    679       return true;
    680   }
    681   return net::URLRequest::IsHandledProtocol(scheme);
    682 }
    683 
    684 // static
    685 bool ProfileIOData::IsHandledURL(const GURL& url) {
    686   if (!url.is_valid()) {
    687     // We handle error cases.
    688     return true;
    689   }
    690 
    691   return IsHandledProtocol(url.scheme());
    692 }
    693 
    694 // static
    695 void ProfileIOData::InstallProtocolHandlers(
    696     net::URLRequestJobFactoryImpl* job_factory,
    697     content::ProtocolHandlerMap* protocol_handlers) {
    698   for (content::ProtocolHandlerMap::iterator it =
    699            protocol_handlers->begin();
    700        it != protocol_handlers->end();
    701        ++it) {
    702     bool set_protocol = job_factory->SetProtocolHandler(
    703         it->first, it->second.release());
    704     DCHECK(set_protocol);
    705   }
    706   protocol_handlers->clear();
    707 }
    708 
    709 content::ResourceContext* ProfileIOData::GetResourceContext() const {
    710   return resource_context_.get();
    711 }
    712 
    713 ChromeURLRequestContext* ProfileIOData::GetMainRequestContext() const {
    714   DCHECK(initialized_);
    715   return main_request_context_.get();
    716 }
    717 
    718 ChromeURLRequestContext* ProfileIOData::GetMediaRequestContext() const {
    719   DCHECK(initialized_);
    720   ChromeURLRequestContext* context = AcquireMediaRequestContext();
    721   DCHECK(context);
    722   return context;
    723 }
    724 
    725 ChromeURLRequestContext* ProfileIOData::GetExtensionsRequestContext() const {
    726   DCHECK(initialized_);
    727   return extensions_request_context_.get();
    728 }
    729 
    730 ChromeURLRequestContext* ProfileIOData::GetIsolatedAppRequestContext(
    731     ChromeURLRequestContext* main_context,
    732     const StoragePartitionDescriptor& partition_descriptor,
    733     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
    734         protocol_handler_interceptor,
    735     content::ProtocolHandlerMap* protocol_handlers) const {
    736   DCHECK(initialized_);
    737   ChromeURLRequestContext* context = NULL;
    738   if (ContainsKey(app_request_context_map_, partition_descriptor)) {
    739     context = app_request_context_map_[partition_descriptor];
    740   } else {
    741     context = AcquireIsolatedAppRequestContext(
    742         main_context, partition_descriptor, protocol_handler_interceptor.Pass(),
    743         protocol_handlers);
    744     app_request_context_map_[partition_descriptor] = context;
    745   }
    746   DCHECK(context);
    747   return context;
    748 }
    749 
    750 ChromeURLRequestContext* ProfileIOData::GetIsolatedMediaRequestContext(
    751     ChromeURLRequestContext* app_context,
    752     const StoragePartitionDescriptor& partition_descriptor) const {
    753   DCHECK(initialized_);
    754   ChromeURLRequestContext* context = NULL;
    755   if (ContainsKey(isolated_media_request_context_map_, partition_descriptor)) {
    756     context = isolated_media_request_context_map_[partition_descriptor];
    757   } else {
    758     context = AcquireIsolatedMediaRequestContext(app_context,
    759                                                  partition_descriptor);
    760     isolated_media_request_context_map_[partition_descriptor] = context;
    761   }
    762   DCHECK(context);
    763   return context;
    764 }
    765 
    766 extensions::InfoMap* ProfileIOData::GetExtensionInfoMap() const {
    767   DCHECK(initialized_) << "ExtensionSystem not initialized";
    768   return extension_info_map_.get();
    769 }
    770 
    771 CookieSettings* ProfileIOData::GetCookieSettings() const {
    772   // Allow either Init() or SetCookieSettingsForTesting() to initialize.
    773   DCHECK(initialized_ || cookie_settings_.get());
    774   return cookie_settings_.get();
    775 }
    776 
    777 HostContentSettingsMap* ProfileIOData::GetHostContentSettingsMap() const {
    778   DCHECK(initialized_);
    779   return host_content_settings_map_.get();
    780 }
    781 
    782 ResourceContext::SaltCallback ProfileIOData::GetMediaDeviceIDSalt() const {
    783   return base::Bind(&MediaDeviceIDSalt::GetSalt, media_device_id_salt_);
    784 }
    785 
    786 void ProfileIOData::InitializeMetricsEnabledStateOnUIThread() {
    787   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    788 #if defined(OS_CHROMEOS)
    789   // Just fetch the value from ChromeOS' settings while we're on the UI thread.
    790   // TODO(stevet): For now, this value is only set on profile initialization.
    791   // We will want to do something similar to the PrefMember method below in the
    792   // future to more accurately capture this state.
    793   chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
    794                                             &enable_metrics_);
    795 #elif defined(OS_ANDROID)
    796   // TODO(dwkang): rename or unify the pref for UMA once we have conclusion
    797   // in crbugs.com/246495.
    798   // Android has it's own preferences for metrics / crash uploading.
    799   enable_metrics_.Init(prefs::kCrashReportingEnabled,
    800                        g_browser_process->local_state());
    801   enable_metrics_.MoveToThread(
    802       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    803 #else
    804   // Prep the PrefMember and send it to the IO thread, since this value will be
    805   // read from there.
    806   enable_metrics_.Init(prefs::kMetricsReportingEnabled,
    807                        g_browser_process->local_state());
    808   enable_metrics_.MoveToThread(
    809       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
    810 #endif  // defined(OS_CHROMEOS)
    811 }
    812 
    813 bool ProfileIOData::GetMetricsEnabledStateOnIOThread() const {
    814   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    815 #if defined(OS_CHROMEOS)
    816   return enable_metrics_;
    817 #else
    818   return enable_metrics_.GetValue();
    819 #endif  // defined(OS_CHROMEOS)
    820 }
    821 
    822 base::WeakPtr<net::HttpServerProperties>
    823 ProfileIOData::http_server_properties() const {
    824   return http_server_properties_->GetWeakPtr();
    825 }
    826 
    827 void ProfileIOData::set_http_server_properties(
    828     scoped_ptr<net::HttpServerProperties> http_server_properties) const {
    829   http_server_properties_ = http_server_properties.Pass();
    830 }
    831 
    832 ProfileIOData::ResourceContext::ResourceContext(ProfileIOData* io_data)
    833     : io_data_(io_data),
    834       host_resolver_(NULL),
    835       request_context_(NULL) {
    836   DCHECK(io_data);
    837 }
    838 
    839 ProfileIOData::ResourceContext::~ResourceContext() {}
    840 
    841 net::HostResolver* ProfileIOData::ResourceContext::GetHostResolver()  {
    842   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    843   DCHECK(io_data_->initialized_);
    844   return host_resolver_;
    845 }
    846 
    847 net::URLRequestContext* ProfileIOData::ResourceContext::GetRequestContext()  {
    848   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    849   DCHECK(io_data_->initialized_);
    850   return request_context_;
    851 }
    852 
    853 scoped_ptr<net::ClientCertStore>
    854 ProfileIOData::ResourceContext::CreateClientCertStore() {
    855 #if defined(USE_NSS)
    856   return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
    857       base::Bind(&CreateCryptoModuleBlockingPasswordDelegate,
    858                  chrome::kCryptoModulePasswordClientAuth)));
    859 #elif defined(OS_WIN)
    860   return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
    861 #elif defined(OS_MACOSX)
    862   return scoped_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
    863 #elif defined(USE_OPENSSL)
    864   // OpenSSL does not use the ClientCertStore infrastructure. On Android client
    865   // cert matching is done by the OS as part of the call to show the cert
    866   // selection dialog.
    867   return scoped_ptr<net::ClientCertStore>();
    868 #else
    869 #error Unknown platform.
    870 #endif
    871 }
    872 
    873 void ProfileIOData::ResourceContext::CreateKeygenHandler(
    874     uint32 key_size_in_bits,
    875     const std::string& challenge_string,
    876     const GURL& url,
    877     const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback) {
    878   DCHECK(!callback.is_null());
    879 #if defined(USE_NSS)
    880   scoped_ptr<net::KeygenHandler> keygen_handler(
    881       new net::KeygenHandler(key_size_in_bits, challenge_string, url));
    882 
    883   scoped_ptr<ChromeNSSCryptoModuleDelegate> delegate(
    884       new ChromeNSSCryptoModuleDelegate(chrome::kCryptoModulePasswordKeygen,
    885                                         url.host()));
    886   ChromeNSSCryptoModuleDelegate* delegate_ptr = delegate.get();
    887   keygen_handler->set_crypto_module_delegate(
    888       delegate.PassAs<crypto::NSSCryptoModuleDelegate>());
    889 
    890   base::Closure bound_callback =
    891       base::Bind(callback, base::Passed(&keygen_handler));
    892   if (delegate_ptr->InitializeSlot(this, bound_callback)) {
    893     // Initialization complete, run the callback synchronously.
    894     bound_callback.Run();
    895     return;
    896   }
    897   // Otherwise, the InitializeSlot will run the callback asynchronously.
    898 #else
    899   callback.Run(make_scoped_ptr(
    900       new net::KeygenHandler(key_size_in_bits, challenge_string, url)));
    901 #endif
    902 }
    903 
    904 bool ProfileIOData::ResourceContext::AllowMicAccess(const GURL& origin) {
    905   return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
    906 }
    907 
    908 bool ProfileIOData::ResourceContext::AllowCameraAccess(const GURL& origin) {
    909   return AllowContentAccess(origin, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
    910 }
    911 
    912 bool ProfileIOData::ResourceContext::AllowContentAccess(
    913     const GURL& origin, ContentSettingsType type) {
    914   HostContentSettingsMap* content_settings =
    915       io_data_->GetHostContentSettingsMap();
    916   ContentSetting setting = content_settings->GetContentSetting(
    917       origin, origin, type, NO_RESOURCE_IDENTIFIER);
    918   return setting == CONTENT_SETTING_ALLOW;
    919 }
    920 
    921 ResourceContext::SaltCallback
    922 ProfileIOData::ResourceContext::GetMediaDeviceIDSalt() {
    923   return io_data_->GetMediaDeviceIDSalt();
    924 }
    925 
    926 // static
    927 std::string ProfileIOData::GetSSLSessionCacheShard() {
    928   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    929   // The SSL session cache is partitioned by setting a string. This returns a
    930   // unique string to partition the SSL session cache. Each time we create a
    931   // new profile, we'll get a fresh SSL session cache which is separate from
    932   // the other profiles.
    933   static unsigned ssl_session_cache_instance = 0;
    934   return base::StringPrintf("profile/%u", ssl_session_cache_instance++);
    935 }
    936 
    937 void ProfileIOData::Init(content::ProtocolHandlerMap* protocol_handlers) const {
    938   // The basic logic is implemented here. The specific initialization
    939   // is done in InitializeInternal(), implemented by subtypes. Static helper
    940   // functions have been provided to assist in common operations.
    941   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    942   DCHECK(!initialized_);
    943 
    944   startup_metric_utils::ScopedSlowStartupUMA
    945       scoped_timer("Startup.SlowStartupProfileIODataInit");
    946 
    947   // TODO(jhawkins): Remove once crbug.com/102004 is fixed.
    948   CHECK(initialized_on_UI_thread_);
    949 
    950   // TODO(jhawkins): Return to DCHECK once crbug.com/102004 is fixed.
    951   CHECK(profile_params_.get());
    952 
    953   IOThread* const io_thread = profile_params_->io_thread;
    954   IOThread::Globals* const io_thread_globals = io_thread->globals();
    955   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    956   load_time_stats_ = GetLoadTimeStats(io_thread_globals);
    957 
    958   // Create the common request contexts.
    959   main_request_context_.reset(
    960       new ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_MAIN,
    961                                   load_time_stats_));
    962   extensions_request_context_.reset(
    963       new ChromeURLRequestContext(
    964           ChromeURLRequestContext::CONTEXT_TYPE_EXTENSIONS,
    965           load_time_stats_));
    966 
    967   ChromeNetworkDelegate* network_delegate =
    968       new ChromeNetworkDelegate(
    969           io_thread_globals->extension_event_router_forwarder.get(),
    970           &enable_referrers_);
    971   if (command_line.HasSwitch(switches::kEnableClientHints))
    972     network_delegate->SetEnableClientHints();
    973   network_delegate->set_extension_info_map(
    974       profile_params_->extension_info_map.get());
    975   network_delegate->set_url_blacklist_manager(url_blacklist_manager_.get());
    976   network_delegate->set_profile(profile_params_->profile);
    977   network_delegate->set_profile_path(profile_params_->path);
    978   network_delegate->set_cookie_settings(profile_params_->cookie_settings.get());
    979   network_delegate->set_enable_do_not_track(&enable_do_not_track_);
    980   network_delegate->set_force_google_safe_search(&force_safesearch_);
    981   network_delegate->set_load_time_stats(load_time_stats_);
    982   network_delegate_.reset(network_delegate);
    983 
    984   fraudulent_certificate_reporter_.reset(
    985       new chrome_browser_net::ChromeFraudulentCertificateReporter(
    986           main_request_context_.get()));
    987 
    988   // NOTE: Proxy service uses the default io thread network delegate, not the
    989   // delegate just created.
    990   proxy_service_.reset(
    991       ProxyServiceFactory::CreateProxyService(
    992           io_thread->net_log(),
    993           io_thread_globals->proxy_script_fetcher_context.get(),
    994           io_thread_globals->system_network_delegate.get(),
    995           profile_params_->proxy_config_service.release(),
    996           command_line));
    997 
    998   transport_security_state_.reset(new net::TransportSecurityState());
    999   transport_security_persister_.reset(
   1000       new net::TransportSecurityPersister(
   1001           transport_security_state_.get(),
   1002           profile_params_->path,
   1003           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
   1004           is_incognito()));
   1005 
   1006   // Take ownership over these parameters.
   1007   cookie_settings_ = profile_params_->cookie_settings;
   1008   host_content_settings_map_ = profile_params_->host_content_settings_map;
   1009   extension_info_map_ = profile_params_->extension_info_map;
   1010 
   1011   resource_context_->host_resolver_ = io_thread_globals->host_resolver.get();
   1012   resource_context_->request_context_ = main_request_context_.get();
   1013 
   1014   if (profile_params_->resource_prefetch_predictor_observer_) {
   1015     resource_prefetch_predictor_observer_.reset(
   1016         profile_params_->resource_prefetch_predictor_observer_.release());
   1017   }
   1018 
   1019 #if defined(ENABLE_MANAGED_USERS)
   1020   managed_mode_url_filter_ = profile_params_->managed_mode_url_filter;
   1021 #endif
   1022 
   1023 #if defined(OS_CHROMEOS)
   1024   if (cert_verifier_) {
   1025     cert_verifier_->InitializeOnIOThread();
   1026     main_request_context_->set_cert_verifier(cert_verifier_.get());
   1027   } else {
   1028     main_request_context_->set_cert_verifier(
   1029         io_thread_globals->cert_verifier.get());
   1030   }
   1031   username_hash_ = profile_params_->username_hash;
   1032 #else
   1033   main_request_context_->set_cert_verifier(
   1034       io_thread_globals->cert_verifier.get());
   1035 #endif
   1036 
   1037   InitializeInternal(profile_params_.get(), protocol_handlers);
   1038 
   1039   profile_params_.reset();
   1040   initialized_ = true;
   1041 }
   1042 
   1043 void ProfileIOData::ApplyProfileParamsToContext(
   1044     ChromeURLRequestContext* context) const {
   1045   context->set_http_user_agent_settings(
   1046       chrome_http_user_agent_settings_.get());
   1047   context->set_ssl_config_service(profile_params_->ssl_config_service.get());
   1048 }
   1049 
   1050 scoped_ptr<net::URLRequestJobFactory> ProfileIOData::SetUpJobFactoryDefaults(
   1051     scoped_ptr<net::URLRequestJobFactoryImpl> job_factory,
   1052     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
   1053         protocol_handler_interceptor,
   1054     net::NetworkDelegate* network_delegate,
   1055     net::FtpTransactionFactory* ftp_transaction_factory) const {
   1056   // NOTE(willchan): Keep these protocol handlers in sync with
   1057   // ProfileIOData::IsHandledProtocol().
   1058   bool set_protocol = job_factory->SetProtocolHandler(
   1059       chrome::kFileScheme,
   1060       new net::FileProtocolHandler(
   1061           content::BrowserThread::GetBlockingPool()->
   1062               GetTaskRunnerWithShutdownBehavior(
   1063                   base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
   1064   DCHECK(set_protocol);
   1065 
   1066   DCHECK(extension_info_map_.get());
   1067   set_protocol = job_factory->SetProtocolHandler(
   1068       extensions::kExtensionScheme,
   1069       CreateExtensionProtocolHandler(is_incognito(),
   1070                                      extension_info_map_.get()));
   1071   DCHECK(set_protocol);
   1072   set_protocol = job_factory->SetProtocolHandler(
   1073       chrome::kExtensionResourceScheme,
   1074       CreateExtensionResourceProtocolHandler());
   1075   DCHECK(set_protocol);
   1076   set_protocol = job_factory->SetProtocolHandler(
   1077       chrome::kDataScheme, new net::DataProtocolHandler());
   1078   DCHECK(set_protocol);
   1079 #if defined(OS_CHROMEOS)
   1080   if (!is_incognito() && profile_params_) {
   1081     set_protocol = job_factory->SetProtocolHandler(
   1082         chrome::kDriveScheme,
   1083         new drive::DriveProtocolHandler(profile_params_->profile));
   1084     DCHECK(set_protocol);
   1085   }
   1086 #endif  // defined(OS_CHROMEOS)
   1087 
   1088   job_factory->SetProtocolHandler(
   1089       chrome::kAboutScheme,
   1090       new chrome_browser_net::AboutProtocolHandler());
   1091 #if !defined(DISABLE_FTP_SUPPORT)
   1092   DCHECK(ftp_transaction_factory);
   1093   job_factory->SetProtocolHandler(
   1094       content::kFtpScheme,
   1095       new net::FtpProtocolHandler(ftp_transaction_factory));
   1096 #endif  // !defined(DISABLE_FTP_SUPPORT)
   1097 
   1098   scoped_ptr<net::URLRequestJobFactory> top_job_factory =
   1099       job_factory.PassAs<net::URLRequestJobFactory>();
   1100 #if defined(DEBUG_DEVTOOLS)
   1101   top_job_factory.reset(new net::ProtocolInterceptJobFactory(
   1102       top_job_factory.Pass(),
   1103       scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
   1104           new DebugDevToolsInterceptor)));
   1105 #endif
   1106 
   1107   if (protocol_handler_interceptor) {
   1108     protocol_handler_interceptor->Chain(top_job_factory.Pass());
   1109     return protocol_handler_interceptor.PassAs<net::URLRequestJobFactory>();
   1110   } else {
   1111     return top_job_factory.Pass();
   1112   }
   1113 }
   1114 
   1115 void ProfileIOData::ShutdownOnUIThread() {
   1116   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   1117 
   1118   if (signin_names_)
   1119     signin_names_->ReleaseResourcesOnUIThread();
   1120 
   1121   google_services_user_account_id_.Destroy();
   1122   google_services_username_.Destroy();
   1123   google_services_username_pattern_.Destroy();
   1124   reverse_autologin_enabled_.Destroy();
   1125   one_click_signin_rejected_email_list_.Destroy();
   1126   enable_referrers_.Destroy();
   1127   enable_do_not_track_.Destroy();
   1128   force_safesearch_.Destroy();
   1129 #if !defined(OS_CHROMEOS)
   1130   enable_metrics_.Destroy();
   1131 #endif
   1132   safe_browsing_enabled_.Destroy();
   1133   printing_enabled_.Destroy();
   1134   sync_disabled_.Destroy();
   1135   signin_allowed_.Destroy();
   1136   if (media_device_id_salt_)
   1137     media_device_id_salt_->ShutdownOnUIThread();
   1138   session_startup_pref_.Destroy();
   1139 #if defined(ENABLE_CONFIGURATION_POLICY)
   1140   if (url_blacklist_manager_)
   1141     url_blacklist_manager_->ShutdownOnUIThread();
   1142 #endif
   1143   if (chrome_http_user_agent_settings_)
   1144     chrome_http_user_agent_settings_->CleanupOnUIThread();
   1145   bool posted = BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
   1146   if (!posted)
   1147     delete this;
   1148 }
   1149 
   1150 void ProfileIOData::set_server_bound_cert_service(
   1151     net::ServerBoundCertService* server_bound_cert_service) const {
   1152   server_bound_cert_service_.reset(server_bound_cert_service);
   1153 }
   1154 
   1155 void ProfileIOData::DestroyResourceContext() {
   1156   resource_context_.reset();
   1157 }
   1158 
   1159 void ProfileIOData::PopulateNetworkSessionParams(
   1160     const ProfileParams* profile_params,
   1161     net::HttpNetworkSession::Params* params) const {
   1162 
   1163   ChromeURLRequestContext* context = main_request_context();
   1164 
   1165   IOThread* const io_thread = profile_params->io_thread;
   1166 
   1167   io_thread->InitializeNetworkSessionParams(params);
   1168 
   1169   params->host_resolver = context->host_resolver();
   1170   params->cert_verifier = context->cert_verifier();
   1171   params->server_bound_cert_service = context->server_bound_cert_service();
   1172   params->transport_security_state = context->transport_security_state();
   1173   params->cert_transparency_verifier = context->cert_transparency_verifier();
   1174   params->proxy_service = context->proxy_service();
   1175   params->ssl_session_cache_shard = GetSSLSessionCacheShard();
   1176   params->ssl_config_service = context->ssl_config_service();
   1177   params->http_auth_handler_factory = context->http_auth_handler_factory();
   1178   params->network_delegate = network_delegate();
   1179   params->http_server_properties = context->http_server_properties();
   1180   params->net_log = context->net_log();
   1181 }
   1182 
   1183 void ProfileIOData::SetCookieSettingsForTesting(
   1184     CookieSettings* cookie_settings) {
   1185   DCHECK(!cookie_settings_.get());
   1186   cookie_settings_ = cookie_settings;
   1187 }
   1188 
   1189 void ProfileIOData::set_signin_names_for_testing(
   1190     SigninNamesOnIOThread* signin_names) {
   1191   signin_names_.reset(signin_names);
   1192 }
   1193