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