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