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_impl.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/callback.h"
11#include "base/command_line.h"
12#include "base/compiler_specific.h"
13#include "base/debug/trace_event.h"
14#include "base/environment.h"
15#include "base/files/file_path.h"
16#include "base/files/file_util.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/path_service.h"
19#include "base/prefs/json_pref_store.h"
20#include "base/prefs/scoped_user_pref_update.h"
21#include "base/strings/string_number_conversions.h"
22#include "base/strings/string_util.h"
23#include "base/strings/stringprintf.h"
24#include "base/strings/utf_string_conversions.h"
25#include "base/synchronization/waitable_event.h"
26#include "base/threading/sequenced_worker_pool.h"
27#include "base/version.h"
28#include "chrome/browser/autocomplete/autocomplete_classifier.h"
29#include "chrome/browser/autocomplete/shortcuts_backend.h"
30#include "chrome/browser/background/background_contents_service_factory.h"
31#include "chrome/browser/background/background_mode_manager.h"
32#include "chrome/browser/bookmarks/bookmark_model_factory.h"
33#include "chrome/browser/browser_process.h"
34#include "chrome/browser/chrome_notification_types.h"
35#include "chrome/browser/content_settings/cookie_settings.h"
36#include "chrome/browser/content_settings/host_content_settings_map.h"
37#include "chrome/browser/dom_distiller/profile_utils.h"
38#include "chrome/browser/domain_reliability/service_factory.h"
39#include "chrome/browser/download/chrome_download_manager_delegate.h"
40#include "chrome/browser/download/download_service.h"
41#include "chrome/browser/download/download_service_factory.h"
42#include "chrome/browser/history/top_sites.h"
43#include "chrome/browser/net/net_pref_observer.h"
44#include "chrome/browser/net/predictor.h"
45#include "chrome/browser/net/pref_proxy_config_tracker.h"
46#include "chrome/browser/net/proxy_service_factory.h"
47#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_configurator.h"
48#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
49#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
50#include "chrome/browser/net/ssl_config_service_manager.h"
51#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
52#include "chrome/browser/plugins/plugin_prefs.h"
53#include "chrome/browser/policy/profile_policy_connector.h"
54#include "chrome/browser/policy/profile_policy_connector_factory.h"
55#include "chrome/browser/prefs/browser_prefs.h"
56#include "chrome/browser/prefs/chrome_pref_service_factory.h"
57#include "chrome/browser/prefs/pref_service_syncable.h"
58#include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h"
59#include "chrome/browser/prerender/prerender_manager_factory.h"
60#include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
61#include "chrome/browser/profiles/chrome_version_service.h"
62#include "chrome/browser/profiles/gaia_info_update_service_factory.h"
63#include "chrome/browser/profiles/profile_destroyer.h"
64#include "chrome/browser/profiles/profile_info_cache.h"
65#include "chrome/browser/profiles/profile_manager.h"
66#include "chrome/browser/profiles/profile_metrics.h"
67#include "chrome/browser/safe_browsing/safe_browsing_service.h"
68#include "chrome/browser/services/gcm/gcm_profile_service.h"
69#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
70#include "chrome/browser/services/gcm/push_messaging_service_impl.h"
71#include "chrome/browser/sessions/session_service_factory.h"
72#include "chrome/browser/signin/signin_ui_util.h"
73#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
74#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
75#include "chrome/browser/ui/startup/startup_browser_creator.h"
76#include "chrome/common/chrome_constants.h"
77#include "chrome/common/chrome_paths_internal.h"
78#include "chrome/common/chrome_switches.h"
79#include "chrome/common/chrome_version_info.h"
80#include "chrome/common/pref_names.h"
81#include "chrome/common/url_constants.h"
82#include "chrome/grit/chromium_strings.h"
83#include "components/bookmarks/browser/bookmark_model.h"
84#include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
85#include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
86#include "components/data_reduction_proxy/browser/data_reduction_proxy_statistics_prefs.h"
87#include "components/domain_reliability/monitor.h"
88#include "components/domain_reliability/service.h"
89#include "components/keyed_service/content/browser_context_dependency_manager.h"
90#include "components/metrics/metrics_service.h"
91#include "components/pref_registry/pref_registry_syncable.h"
92#include "components/startup_metric_utils/startup_metric_utils.h"
93#include "components/url_fixer/url_fixer.h"
94#include "components/user_prefs/user_prefs.h"
95#include "content/public/browser/browser_thread.h"
96#include "content/public/browser/dom_storage_context.h"
97#include "content/public/browser/host_zoom_map.h"
98#include "content/public/browser/notification_service.h"
99#include "content/public/browser/render_process_host.h"
100#include "content/public/browser/storage_partition.h"
101#include "content/public/browser/url_data_source.h"
102#include "content/public/browser/user_metrics.h"
103#include "content/public/common/content_constants.h"
104#include "content/public/common/page_zoom.h"
105#include "ui/base/l10n/l10n_util.h"
106
107#if defined(OS_ANDROID)
108#include "chrome/browser/media/protected_media_identifier_permission_context.h"
109#include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
110#endif
111
112#if defined(OS_CHROMEOS)
113#include "chrome/browser/chromeos/locale_change_guard.h"
114#include "chrome/browser/chromeos/preferences.h"
115#include "chrome/browser/chromeos/profiles/profile_helper.h"
116#include "components/user_manager/user_manager.h"
117#endif
118
119#if defined(ENABLE_CONFIGURATION_POLICY)
120#include "chrome/browser/policy/schema_registry_service.h"
121#include "chrome/browser/policy/schema_registry_service_factory.h"
122#include "components/policy/core/browser/browser_policy_connector.h"
123#if defined(OS_CHROMEOS)
124#include "chrome/browser/chromeos/login/login_utils.h"
125#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
126#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
127#else
128#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
129#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
130#endif
131#endif
132
133#if defined(ENABLE_EXTENSIONS)
134#include "chrome/browser/extensions/extension_service.h"
135#include "chrome/browser/extensions/extension_special_storage_policy.h"
136#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
137#include "extensions/browser/extension_pref_store.h"
138#include "extensions/browser/extension_pref_value_map.h"
139#include "extensions/browser/extension_pref_value_map_factory.h"
140#include "extensions/browser/extension_system.h"
141#include "extensions/browser/guest_view/guest_view_manager.h"
142#endif
143
144#if defined(ENABLE_MANAGED_USERS)
145#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
146#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
147#endif
148
149using base::Time;
150using base::TimeDelta;
151using base::UserMetricsAction;
152using content::BrowserThread;
153using content::DownloadManagerDelegate;
154using content::HostZoomMap;
155
156namespace {
157
158#if defined(ENABLE_SESSION_SERVICE)
159// Delay, in milliseconds, before we explicitly create the SessionService.
160const int kCreateSessionServiceDelayMS = 500;
161#endif
162
163// Text content of README file created in each profile directory. Both %s
164// placeholders must contain the product name. This is not localizable and hence
165// not in resources.
166const char kReadmeText[] =
167    "%s settings and storage represent user-selected preferences and "
168    "information and MUST not be extracted, overwritten or modified except "
169    "through %s defined APIs.";
170
171// Value written to prefs for EXIT_CRASHED and EXIT_SESSION_ENDED.
172const char kPrefExitTypeCrashed[] = "Crashed";
173const char kPrefExitTypeSessionEnded[] = "SessionEnded";
174
175// Helper method needed because PostTask cannot currently take a Callback
176// function with non-void return type.
177void CreateDirectoryAndSignal(const base::FilePath& path,
178                              base::WaitableEvent* done_creating) {
179  DVLOG(1) << "Creating directory " << path.value();
180  base::CreateDirectory(path);
181  done_creating->Signal();
182}
183
184// Task that blocks the FILE thread until CreateDirectoryAndSignal() finishes on
185// blocking I/O pool.
186void BlockFileThreadOnDirectoryCreate(base::WaitableEvent* done_creating) {
187  done_creating->Wait();
188}
189
190// Initiates creation of profile directory on |sequenced_task_runner| and
191// ensures that FILE thread is blocked until that operation finishes.
192void CreateProfileDirectory(base::SequencedTaskRunner* sequenced_task_runner,
193                            const base::FilePath& path) {
194  base::WaitableEvent* done_creating = new base::WaitableEvent(false, false);
195  sequenced_task_runner->PostTask(FROM_HERE,
196                                  base::Bind(&CreateDirectoryAndSignal,
197                                             path,
198                                             done_creating));
199  // Block the FILE thread until directory is created on I/O pool to make sure
200  // that we don't attempt any operation until that part completes.
201  BrowserThread::PostTask(
202      BrowserThread::FILE, FROM_HERE,
203      base::Bind(&BlockFileThreadOnDirectoryCreate,
204                 base::Owned(done_creating)));
205}
206
207base::FilePath GetCachePath(const base::FilePath& base) {
208  return base.Append(chrome::kCacheDirname);
209}
210
211base::FilePath GetMediaCachePath(const base::FilePath& base) {
212  return base.Append(chrome::kMediaCacheDirname);
213}
214
215void EnsureReadmeFile(const base::FilePath& base) {
216  base::FilePath readme_path = base.Append(chrome::kReadmeFilename);
217  if (base::PathExists(readme_path))
218    return;
219  std::string product_name = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
220  std::string readme_text = base::StringPrintf(
221      kReadmeText, product_name.c_str(), product_name.c_str());
222  if (base::WriteFile(readme_path, readme_text.data(), readme_text.size()) ==
223      -1) {
224    LOG(ERROR) << "Could not create README file.";
225  }
226}
227
228// Converts the kSessionExitedCleanly pref to the corresponding EXIT_TYPE.
229Profile::ExitType SessionTypePrefValueToExitType(const std::string& value) {
230  if (value == kPrefExitTypeSessionEnded)
231    return Profile::EXIT_SESSION_ENDED;
232  if (value == kPrefExitTypeCrashed)
233    return Profile::EXIT_CRASHED;
234  return Profile::EXIT_NORMAL;
235}
236
237// Converts an ExitType into a string that is written to prefs.
238std::string ExitTypeToSessionTypePrefValue(Profile::ExitType type) {
239  switch (type) {
240    case Profile::EXIT_NORMAL:
241        return ProfileImpl::kPrefExitTypeNormal;
242    case Profile::EXIT_SESSION_ENDED:
243      return kPrefExitTypeSessionEnded;
244    case Profile::EXIT_CRASHED:
245      return kPrefExitTypeCrashed;
246  }
247  NOTREACHED();
248  return std::string();
249}
250
251PrefStore* CreateExtensionPrefStore(Profile* profile,
252                                    bool incognito_pref_store) {
253#if defined(ENABLE_EXTENSIONS)
254  return new ExtensionPrefStore(
255      ExtensionPrefValueMapFactory::GetForBrowserContext(profile),
256      incognito_pref_store);
257#else
258  return NULL;
259#endif
260}
261
262}  // namespace
263
264// static
265Profile* Profile::CreateProfile(const base::FilePath& path,
266                                Delegate* delegate,
267                                CreateMode create_mode) {
268  TRACE_EVENT_BEGIN1("browser",
269                     "Profile::CreateProfile",
270                     "profile_path",
271                     path.value().c_str());
272
273  // Get sequenced task runner for making sure that file operations of
274  // this profile (defined by |path|) are executed in expected order
275  // (what was previously assured by the FILE thread).
276  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
277      JsonPrefStore::GetTaskRunnerForFile(path,
278                                          BrowserThread::GetBlockingPool());
279  if (create_mode == CREATE_MODE_ASYNCHRONOUS) {
280    DCHECK(delegate);
281    CreateProfileDirectory(sequenced_task_runner.get(), path);
282  } else if (create_mode == CREATE_MODE_SYNCHRONOUS) {
283    if (!base::PathExists(path)) {
284      // TODO(tc): http://b/1094718 Bad things happen if we can't write to the
285      // profile directory.  We should eventually be able to run in this
286      // situation.
287      if (!base::CreateDirectory(path))
288        return NULL;
289    }
290  } else {
291    NOTREACHED();
292  }
293
294  return new ProfileImpl(
295      path, delegate, create_mode, sequenced_task_runner.get());
296}
297
298// static
299int ProfileImpl::create_readme_delay_ms = 60000;
300
301// static
302const char* const ProfileImpl::kPrefExitTypeNormal = "Normal";
303
304// static
305void ProfileImpl::RegisterProfilePrefs(
306    user_prefs::PrefRegistrySyncable* registry) {
307  registry->RegisterBooleanPref(
308      prefs::kSavingBrowserHistoryDisabled,
309      false,
310      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
311  registry->RegisterBooleanPref(
312      prefs::kAllowDeletingBrowserHistory,
313      true,
314      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
315  registry->RegisterBooleanPref(
316      prefs::kSigninAllowed,
317      true,
318      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
319  registry->RegisterBooleanPref(
320      prefs::kForceSafeSearch,
321      false,
322      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
323  registry->RegisterIntegerPref(
324      prefs::kProfileAvatarIndex,
325      -1,
326      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
327  // Whether a profile is using an avatar without having explicitely chosen it
328  // (i.e. was assigned by default by legacy profile creation).
329  registry->RegisterBooleanPref(
330      prefs::kProfileUsingDefaultAvatar,
331      true,
332      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
333  registry->RegisterBooleanPref(
334      prefs::kProfileUsingGAIAAvatar,
335      false,
336      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
337  // Whether a profile is using a default avatar name (eg. Pickles or Person 1).
338  registry->RegisterBooleanPref(
339      prefs::kProfileUsingDefaultName,
340      true,
341      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
342  registry->RegisterStringPref(
343      prefs::kSupervisedUserId,
344      std::string(),
345      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
346  registry->RegisterStringPref(prefs::kProfileName,
347                               std::string(),
348                               user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
349  registry->RegisterStringPref(prefs::kHomePage,
350                               std::string(),
351                               user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
352#if defined(ENABLE_PRINTING)
353  registry->RegisterBooleanPref(
354      prefs::kPrintingEnabled,
355      true,
356      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
357#endif
358  registry->RegisterBooleanPref(
359      prefs::kPrintPreviewDisabled,
360      false,
361      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
362  registry->RegisterBooleanPref(
363      prefs::kForceEphemeralProfiles,
364      false,
365      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
366
367  // Initialize the cache prefs.
368  registry->RegisterFilePathPref(
369      prefs::kDiskCacheDir,
370      base::FilePath(),
371      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
372  registry->RegisterIntegerPref(
373      prefs::kDiskCacheSize,
374      0,
375      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
376  registry->RegisterIntegerPref(
377      prefs::kMediaCacheSize,
378      0,
379      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
380
381  // Deprecated. Kept around for migration.
382  registry->RegisterBooleanPref(
383      prefs::kClearSiteDataOnExit,
384      false,
385      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
386}
387
388ProfileImpl::ProfileImpl(
389    const base::FilePath& path,
390    Delegate* delegate,
391    CreateMode create_mode,
392    base::SequencedTaskRunner* sequenced_task_runner)
393    : path_(path),
394      pref_registry_(new user_prefs::PrefRegistrySyncable),
395      io_data_(this),
396      host_content_settings_map_(NULL),
397      last_session_exit_type_(EXIT_NORMAL),
398      start_time_(Time::Now()),
399      delegate_(delegate),
400      predictor_(NULL) {
401  TRACE_EVENT0("browser", "ProfileImpl::ctor")
402  DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
403                            "profile files to the root directory!";
404
405#if defined(ENABLE_SESSION_SERVICE)
406  create_session_service_timer_.Start(FROM_HERE,
407      TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
408      &ProfileImpl::EnsureSessionServiceCreated);
409#endif
410
411  // Determine if prefetch is enabled for this profile.
412  // If not profile_manager is present, it means we are in a unittest.
413  const CommandLine* command_line = CommandLine::ForCurrentProcess();
414  predictor_ = chrome_browser_net::Predictor::CreatePredictor(
415      !command_line->HasSwitch(switches::kDisablePreconnect),
416      !command_line->HasSwitch(switches::kDnsPrefetchDisable),
417      g_browser_process->profile_manager() == NULL);
418
419  // If we are creating the profile synchronously, then we should load the
420  // policy data immediately.
421  bool force_immediate_policy_load = (create_mode == CREATE_MODE_SYNCHRONOUS);
422#if defined(ENABLE_CONFIGURATION_POLICY)
423  policy::BrowserPolicyConnector* connector =
424      g_browser_process->browser_policy_connector();
425  schema_registry_service_ =
426      policy::SchemaRegistryServiceFactory::CreateForContext(
427          this, connector->GetChromeSchema(), connector->GetSchemaRegistry());
428#if defined(OS_CHROMEOS)
429  cloud_policy_manager_ =
430      policy::UserCloudPolicyManagerFactoryChromeOS::CreateForProfile(
431          this, force_immediate_policy_load, sequenced_task_runner);
432#else
433  cloud_policy_manager_ =
434      policy::UserCloudPolicyManagerFactory::CreateForOriginalBrowserContext(
435          this,
436          force_immediate_policy_load,
437          sequenced_task_runner,
438          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
439          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
440#endif
441#endif
442  profile_policy_connector_ =
443      policy::ProfilePolicyConnectorFactory::CreateForProfile(
444          this, force_immediate_policy_load);
445
446  DCHECK(create_mode == CREATE_MODE_ASYNCHRONOUS ||
447         create_mode == CREATE_MODE_SYNCHRONOUS);
448  bool async_prefs = create_mode == CREATE_MODE_ASYNCHRONOUS;
449
450#if defined(OS_CHROMEOS)
451  if (chromeos::ProfileHelper::IsSigninProfile(this))
452    chrome::RegisterLoginProfilePrefs(pref_registry_.get());
453  else
454#endif
455  chrome::RegisterUserProfilePrefs(pref_registry_.get());
456
457  BrowserContextDependencyManager::GetInstance()->
458      RegisterProfilePrefsForServices(this, pref_registry_.get());
459
460  SupervisedUserSettingsService* supervised_user_settings = NULL;
461#if defined(ENABLE_MANAGED_USERS)
462  supervised_user_settings =
463      SupervisedUserSettingsServiceFactory::GetForProfile(this);
464  supervised_user_settings->Init(
465      path_, sequenced_task_runner, create_mode == CREATE_MODE_SYNCHRONOUS);
466#endif
467
468  scoped_refptr<SafeBrowsingService> safe_browsing_service(
469      g_browser_process->safe_browsing_service());
470  if (safe_browsing_service.get()) {
471    pref_validation_delegate_ =
472        safe_browsing_service->CreatePreferenceValidationDelegate(this).Pass();
473  }
474
475  {
476    // On startup, preference loading is always synchronous so a scoped timer
477    // will work here.
478    startup_metric_utils::ScopedSlowStartupUMA
479        scoped_timer("Startup.SlowStartupPreferenceLoading");
480    prefs_ = chrome_prefs::CreateProfilePrefs(
481        path_,
482        sequenced_task_runner,
483        pref_validation_delegate_.get(),
484        profile_policy_connector_->policy_service(),
485        supervised_user_settings,
486        CreateExtensionPrefStore(this, false),
487        pref_registry_,
488        async_prefs).Pass();
489    // Register on BrowserContext.
490    user_prefs::UserPrefs::Set(this, prefs_.get());
491  }
492
493  startup_metric_utils::ScopedSlowStartupUMA
494      scoped_timer("Startup.SlowStartupFinalProfileInit");
495  if (async_prefs) {
496    // Wait for the notification that prefs has been loaded
497    // (successfully or not).  Note that we can use base::Unretained
498    // because the PrefService is owned by this class and lives on
499    // the same thread.
500    prefs_->AddPrefInitObserver(base::Bind(&ProfileImpl::OnPrefsLoaded,
501                                           base::Unretained(this)));
502  } else {
503    // Prefs were loaded synchronously so we can continue directly.
504    OnPrefsLoaded(true);
505  }
506}
507
508void ProfileImpl::DoFinalInit() {
509  TRACE_EVENT0("browser", "ProfileImpl::DoFinalInit")
510  PrefService* prefs = GetPrefs();
511  pref_change_registrar_.Init(prefs);
512  pref_change_registrar_.Add(
513      prefs::kGoogleServicesUsername,
514      base::Bind(&ProfileImpl::UpdateProfileUserNameCache,
515                 base::Unretained(this)));
516  pref_change_registrar_.Add(
517      prefs::kSupervisedUserId,
518      base::Bind(&ProfileImpl::UpdateProfileSupervisedUserIdCache,
519                 base::Unretained(this)));
520  pref_change_registrar_.Add(
521      prefs::kDefaultZoomLevel,
522      base::Bind(&ProfileImpl::OnDefaultZoomLevelChanged,
523                 base::Unretained(this)));
524
525  // Changes in the profile avatar.
526  pref_change_registrar_.Add(
527      prefs::kProfileAvatarIndex,
528      base::Bind(&ProfileImpl::UpdateProfileAvatarCache,
529                 base::Unretained(this)));
530  pref_change_registrar_.Add(
531      prefs::kProfileUsingDefaultAvatar,
532      base::Bind(&ProfileImpl::UpdateProfileAvatarCache,
533                 base::Unretained(this)));
534  pref_change_registrar_.Add(
535      prefs::kProfileUsingGAIAAvatar,
536      base::Bind(&ProfileImpl::UpdateProfileAvatarCache,
537                 base::Unretained(this)));
538
539  // Changes in the profile name.
540  pref_change_registrar_.Add(
541      prefs::kProfileUsingDefaultName,
542      base::Bind(&ProfileImpl::UpdateProfileNameCache,
543                 base::Unretained(this)));
544  pref_change_registrar_.Add(
545      prefs::kProfileName,
546      base::Bind(&ProfileImpl::UpdateProfileNameCache,
547                 base::Unretained(this)));
548
549  pref_change_registrar_.Add(
550      prefs::kForceEphemeralProfiles,
551      base::Bind(&ProfileImpl::UpdateProfileIsEphemeralCache,
552                 base::Unretained(this)));
553
554  // It would be nice to use PathService for fetching this directory, but
555  // the cache directory depends on the profile directory, which isn't available
556  // to PathService.
557  chrome::GetUserCacheDirectory(path_, &base_cache_path_);
558  // Always create the cache directory asynchronously.
559  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
560      JsonPrefStore::GetTaskRunnerForFile(base_cache_path_,
561                                          BrowserThread::GetBlockingPool());
562  CreateProfileDirectory(sequenced_task_runner.get(), base_cache_path_);
563
564  // Now that the profile is hooked up to receive pref change notifications to
565  // kGoogleServicesUsername, initialize components that depend on it to reflect
566  // the current value.
567  UpdateProfileUserNameCache();
568  UpdateProfileSupervisedUserIdCache();
569  UpdateProfileIsEphemeralCache();
570  GAIAInfoUpdateServiceFactory::GetForProfile(this);
571
572  PrefService* local_state = g_browser_process->local_state();
573  ssl_config_service_manager_.reset(
574      SSLConfigServiceManager::CreateDefaultManager(local_state));
575
576  // Initialize the BackgroundModeManager - this has to be done here before
577  // InitExtensions() is called because it relies on receiving notifications
578  // when extensions are loaded. BackgroundModeManager is not needed under
579  // ChromeOS because Chrome is always running, no need for special keep-alive
580  // or launch-on-startup support unless kKeepAliveForTest is set.
581  bool init_background_mode_manager = true;
582#if defined(OS_CHROMEOS)
583  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest))
584    init_background_mode_manager = false;
585#endif
586  if (init_background_mode_manager) {
587    if (g_browser_process->background_mode_manager())
588      g_browser_process->background_mode_manager()->RegisterProfile(this);
589  }
590
591  base::FilePath cookie_path = GetPath();
592  cookie_path = cookie_path.Append(chrome::kCookieFilename);
593  base::FilePath channel_id_path = GetPath();
594  channel_id_path = channel_id_path.Append(chrome::kChannelIDFilename);
595  base::FilePath cache_path = base_cache_path_;
596  int cache_max_size;
597  GetCacheParameters(false, &cache_path, &cache_max_size);
598  cache_path = GetCachePath(cache_path);
599
600  base::FilePath media_cache_path = base_cache_path_;
601  int media_cache_max_size;
602  GetCacheParameters(true, &media_cache_path, &media_cache_max_size);
603  media_cache_path = GetMediaCachePath(media_cache_path);
604
605  base::FilePath extensions_cookie_path = GetPath();
606  extensions_cookie_path =
607      extensions_cookie_path.Append(chrome::kExtensionsCookieFilename);
608
609  base::FilePath infinite_cache_path = GetPath();
610  infinite_cache_path =
611      infinite_cache_path.Append(FILE_PATH_LITERAL("Infinite Cache"));
612
613#if defined(OS_ANDROID)
614  SessionStartupPref::Type startup_pref_type =
615      SessionStartupPref::GetDefaultStartupType();
616#else
617  SessionStartupPref::Type startup_pref_type =
618      StartupBrowserCreator::GetSessionStartupPref(
619          *CommandLine::ForCurrentProcess(), this).type;
620#endif
621  content::CookieStoreConfig::SessionCookieMode session_cookie_mode =
622      content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES;
623  if (GetLastSessionExitType() == Profile::EXIT_CRASHED ||
624      startup_pref_type == SessionStartupPref::LAST) {
625    session_cookie_mode = content::CookieStoreConfig::RESTORED_SESSION_COOKIES;
626  }
627
628  InitHostZoomMap();
629
630  base::Callback<void(bool)> data_reduction_proxy_unavailable;
631  scoped_ptr<data_reduction_proxy::DataReductionProxyParams>
632      data_reduction_proxy_params;
633  scoped_ptr<DataReductionProxyChromeConfigurator> chrome_configurator;
634  scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs>
635      data_reduction_proxy_statistics_prefs;
636  DataReductionProxyChromeSettings* data_reduction_proxy_chrome_settings =
637      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(this);
638  data_reduction_proxy_params =
639      data_reduction_proxy_chrome_settings->params()->Clone();
640  data_reduction_proxy_unavailable =
641      base::Bind(
642          &data_reduction_proxy::DataReductionProxySettings::SetUnreachable,
643          base::Unretained(data_reduction_proxy_chrome_settings));
644  // The configurator is used by DataReductionProxyChromeSettings and
645  // ProfileIOData. Ownership is passed to the latter via ProfileIOData::Handle,
646  // which is only destroyed after BrowserContextKeyedServices,
647  // including DataReductionProxyChromeSettings.
648  chrome_configurator.reset(
649      new DataReductionProxyChromeConfigurator(
650          prefs_.get(),
651          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
652  // Retain a raw pointer to use for initialization of data reduction proxy
653  // settings after ownership is passed.
654  DataReductionProxyChromeConfigurator*
655      data_reduction_proxy_chrome_configurator = chrome_configurator.get();
656#if defined(OS_ANDROID) || defined(OS_IOS)
657  // On mobile we write data reduction proxy prefs directly to the pref service.
658  // On desktop we store data reduction proxy prefs in memory, writing to disk
659  // every 60 minutes and on termination. Shutdown hooks must be added for
660  // Android and iOS in order for non-zero delays to be supported.
661  // (http://crbug.com/408264)
662  base::TimeDelta commit_delay = base::TimeDelta();
663#else
664  base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60);
665#endif
666  data_reduction_proxy_statistics_prefs =
667      scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs>(
668          new data_reduction_proxy::DataReductionProxyStatisticsPrefs(
669              g_browser_process->local_state(),
670              base::MessageLoopProxy::current(),
671              commit_delay));
672  data_reduction_proxy_chrome_settings->SetDataReductionProxyStatisticsPrefs(
673      data_reduction_proxy_statistics_prefs.get());
674
675  // Make sure we initialize the ProfileIOData after everything else has been
676  // initialized that we might be reading from the IO thread.
677
678  io_data_.Init(cookie_path, channel_id_path, cache_path,
679                cache_max_size, media_cache_path, media_cache_max_size,
680                extensions_cookie_path, GetPath(), infinite_cache_path,
681                predictor_, session_cookie_mode, GetSpecialStoragePolicy(),
682                CreateDomainReliabilityMonitor(local_state),
683                data_reduction_proxy_unavailable,
684                chrome_configurator.Pass(),
685                data_reduction_proxy_params.Pass(),
686                data_reduction_proxy_statistics_prefs.Pass());
687  data_reduction_proxy_chrome_settings->InitDataReductionProxySettings(
688      data_reduction_proxy_chrome_configurator,
689      prefs_.get(),
690      g_browser_process->local_state(),
691      GetRequestContext());
692
693#if defined(ENABLE_PLUGINS)
694  ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
695      PluginPrefs::GetForProfile(this).get(),
696      io_data_.GetResourceContextNoInit());
697#endif
698
699  // Delay README creation to not impact startup performance.
700  BrowserThread::PostDelayedTask(
701        BrowserThread::FILE, FROM_HERE,
702        base::Bind(&EnsureReadmeFile, GetPath()),
703        base::TimeDelta::FromMilliseconds(create_readme_delay_ms));
704
705  TRACE_EVENT0("browser", "ProfileImpl::SetSaveSessionStorageOnDisk");
706  content::BrowserContext::GetDefaultStoragePartition(this)->
707      GetDOMStorageContext()->SetSaveSessionStorageOnDisk();
708
709  // The DomDistillerViewerSource is not a normal WebUI so it must be registered
710  // as a URLDataSource early.
711  RegisterDomDistillerViewerSource(this);
712
713  // Creation has been finished.
714  TRACE_EVENT_END1("browser",
715                   "Profile::CreateProfile",
716                   "profile_path",
717                   path_.value().c_str());
718
719#if defined(OS_CHROMEOS)
720  if (chromeos::LoginUtils::Get()->RestartToApplyPerSessionFlagsIfNeed(this,
721                                                                       true)) {
722    return;
723  }
724#endif
725
726  if (delegate_) {
727    TRACE_EVENT0("browser", "ProfileImpl::DoFileInit:DelegateOnProfileCreated")
728    delegate_->OnProfileCreated(this, true, IsNewProfile());
729  }
730
731  content::NotificationService::current()->Notify(
732      chrome::NOTIFICATION_PROFILE_CREATED,
733      content::Source<Profile>(this),
734      content::NotificationService::NoDetails());
735
736#if !defined(OS_CHROMEOS)
737  // Listen for bookmark model load, to bootstrap the sync service.
738  // On CrOS sync service will be initialized after sign in.
739  BookmarkModel* model = BookmarkModelFactory::GetForProfile(this);
740  model->AddObserver(new BookmarkModelLoadedObserver(this));
741#endif
742
743  gcm::PushMessagingServiceImpl::InitializeForProfile(this);
744
745#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_IOS)
746  signin_ui_util::InitializePrefsForProfile(this);
747#endif
748}
749
750void ProfileImpl::InitHostZoomMap() {
751  HostZoomMap* host_zoom_map = HostZoomMap::GetDefaultForBrowserContext(this);
752  host_zoom_map->SetDefaultZoomLevel(
753      prefs_->GetDouble(prefs::kDefaultZoomLevel));
754
755  const base::DictionaryValue* host_zoom_dictionary =
756      prefs_->GetDictionary(prefs::kPerHostZoomLevels);
757  // Careful: The returned value could be NULL if the pref has never been set.
758  if (host_zoom_dictionary != NULL) {
759    std::vector<std::string> keys_to_remove;
760    for (base::DictionaryValue::Iterator i(*host_zoom_dictionary); !i.IsAtEnd();
761         i.Advance()) {
762      const std::string& host(i.key());
763      double zoom_level = 0;
764
765      bool success = i.value().GetAsDouble(&zoom_level);
766      DCHECK(success);
767
768      // Filter out A) the empty host, B) zoom levels equal to the default; and
769      // remember them, so that we can later erase them from Prefs.
770      // Values of type A and B could have been stored due to crbug.com/364399.
771      // Values of type B could further have been stored before the default zoom
772      // level was set to its current value. In either case, SetZoomLevelForHost
773      // will ignore type B values, thus, to have consistency with HostZoomMap's
774      // internal state, these values must also be removed from Prefs.
775      if (host.empty() ||
776          content::ZoomValuesEqual(zoom_level,
777                                   host_zoom_map->GetDefaultZoomLevel())) {
778        keys_to_remove.push_back(host);
779        continue;
780      }
781
782      host_zoom_map->SetZoomLevelForHost(host, zoom_level);
783    }
784
785    DictionaryPrefUpdate update(prefs_.get(), prefs::kPerHostZoomLevels);
786    base::DictionaryValue* host_zoom_dictionary = update.Get();
787    for (std::vector<std::string>::const_iterator it = keys_to_remove.begin();
788         it != keys_to_remove.end(); ++it) {
789      host_zoom_dictionary->RemoveWithoutPathExpansion(*it, NULL);
790    }
791  }
792
793  zoom_subscription_ = host_zoom_map->AddZoomLevelChangedCallback(
794      base::Bind(&ProfileImpl::OnZoomLevelChanged, base::Unretained(this)));
795}
796
797base::FilePath ProfileImpl::last_selected_directory() {
798  return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory);
799}
800
801void ProfileImpl::set_last_selected_directory(const base::FilePath& path) {
802  GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, path);
803}
804
805ProfileImpl::~ProfileImpl() {
806  MaybeSendDestroyedNotification();
807
808  bool prefs_loaded = prefs_->GetInitializationStatus() !=
809      PrefService::INITIALIZATION_STATUS_WAITING;
810
811#if defined(ENABLE_SESSION_SERVICE)
812  StopCreateSessionServiceTimer();
813#endif
814
815  // Remove pref observers
816  pref_change_registrar_.RemoveAll();
817
818#if defined(ENABLE_PLUGINS)
819  ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext(
820      io_data_.GetResourceContextNoInit());
821#endif
822
823  // Destroy OTR profile and its profile services first.
824  if (off_the_record_profile_) {
825    ProfileDestroyer::DestroyOffTheRecordProfileNow(
826        off_the_record_profile_.get());
827  } else {
828#if defined(ENABLE_EXTENSIONS)
829    ExtensionPrefValueMapFactory::GetForBrowserContext(this)->
830        ClearAllIncognitoSessionOnlyPreferences();
831#endif
832  }
833
834  BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
835      this);
836
837  if (top_sites_.get())
838    top_sites_->Shutdown();
839
840  if (pref_proxy_config_tracker_)
841    pref_proxy_config_tracker_->DetachFromPrefService();
842
843  if (host_content_settings_map_.get())
844    host_content_settings_map_->ShutdownOnUIThread();
845
846  // This causes the Preferences file to be written to disk.
847  if (prefs_loaded)
848    SetExitType(EXIT_NORMAL);
849}
850
851std::string ProfileImpl::GetProfileName() {
852  return GetPrefs()->GetString(prefs::kGoogleServicesUsername);
853}
854
855Profile::ProfileType ProfileImpl::GetProfileType() const {
856  return REGULAR_PROFILE;
857}
858
859base::FilePath ProfileImpl::GetPath() const {
860  return path_;
861}
862
863scoped_refptr<base::SequencedTaskRunner> ProfileImpl::GetIOTaskRunner() {
864  return JsonPrefStore::GetTaskRunnerForFile(
865      GetPath(), BrowserThread::GetBlockingPool());
866}
867
868bool ProfileImpl::IsOffTheRecord() const {
869  return false;
870}
871
872Profile* ProfileImpl::GetOffTheRecordProfile() {
873  if (!off_the_record_profile_) {
874    scoped_ptr<Profile> p(CreateOffTheRecordProfile());
875    off_the_record_profile_.swap(p);
876
877    content::NotificationService::current()->Notify(
878        chrome::NOTIFICATION_PROFILE_CREATED,
879        content::Source<Profile>(off_the_record_profile_.get()),
880        content::NotificationService::NoDetails());
881  }
882  return off_the_record_profile_.get();
883}
884
885void ProfileImpl::DestroyOffTheRecordProfile() {
886  off_the_record_profile_.reset();
887#if defined(ENABLE_EXTENSIONS)
888  ExtensionPrefValueMapFactory::GetForBrowserContext(this)->
889      ClearAllIncognitoSessionOnlyPreferences();
890#endif
891}
892
893bool ProfileImpl::HasOffTheRecordProfile() {
894  return off_the_record_profile_.get() != NULL;
895}
896
897Profile* ProfileImpl::GetOriginalProfile() {
898  return this;
899}
900
901bool ProfileImpl::IsSupervised() {
902  return !GetPrefs()->GetString(prefs::kSupervisedUserId).empty();
903}
904
905ExtensionSpecialStoragePolicy*
906    ProfileImpl::GetExtensionSpecialStoragePolicy() {
907#if defined(ENABLE_EXTENSIONS)
908  if (!extension_special_storage_policy_.get()) {
909    TRACE_EVENT0("browser", "ProfileImpl::GetExtensionSpecialStoragePolicy")
910    extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy(
911        CookieSettings::Factory::GetForProfile(this).get());
912  }
913  return extension_special_storage_policy_.get();
914#else
915  return NULL;
916#endif
917}
918
919void ProfileImpl::OnPrefsLoaded(bool success) {
920  TRACE_EVENT0("browser", "ProfileImpl::OnPrefsLoaded")
921  if (!success) {
922    if (delegate_)
923      delegate_->OnProfileCreated(this, false, false);
924    return;
925  }
926
927  // TODO(mirandac): remove migration code after 6 months (crbug.com/69995).
928  if (g_browser_process->local_state())
929    chrome::MigrateBrowserPrefs(this, g_browser_process->local_state());
930  // TODO(ivankr): remove cleanup code eventually (crbug.com/165672).
931  chrome::MigrateUserPrefs(this);
932
933  // |kSessionExitType| was added after |kSessionExitedCleanly|. If the pref
934  // value is empty fallback to checking for |kSessionExitedCleanly|.
935  const std::string exit_type_pref_value(
936      prefs_->GetString(prefs::kSessionExitType));
937  if (exit_type_pref_value.empty()) {
938    last_session_exit_type_ =
939        prefs_->GetBoolean(prefs::kSessionExitedCleanly) ?
940          EXIT_NORMAL : EXIT_CRASHED;
941  } else {
942    last_session_exit_type_ =
943        SessionTypePrefValueToExitType(exit_type_pref_value);
944  }
945  // Mark the session as open.
946  prefs_->SetString(prefs::kSessionExitType, kPrefExitTypeCrashed);
947  // Force this to true in case we fallback and use it.
948  // TODO(sky): remove this in a couple of releases (m28ish).
949  prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
950
951#if defined(OS_ANDROID) && defined(FULL_SAFE_BROWSING)
952  // Clear safe browsing setting in the case we need to roll back
953  // for users enrolled in Finch trial before.
954  if (!SafeBrowsingService::IsEnabledByFieldTrial())
955    prefs_->ClearPref(prefs::kSafeBrowsingEnabled);
956#endif
957
958  g_browser_process->profile_manager()->InitProfileUserPrefs(this);
959
960  BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
961      this);
962
963  DCHECK(!net_pref_observer_);
964  {
965    TRACE_EVENT0("browser", "ProfileImpl::OnPrefsLoaded:NetPrefObserver")
966    net_pref_observer_.reset(new NetPrefObserver(prefs_.get()));
967  }
968
969  chrome_prefs::SchedulePrefsFilePathVerification(path_);
970
971  ChromeVersionService::OnProfileLoaded(prefs_.get(), IsNewProfile());
972  DoFinalInit();
973}
974
975bool ProfileImpl::WasCreatedByVersionOrLater(const std::string& version) {
976  Version profile_version(ChromeVersionService::GetVersion(prefs_.get()));
977  Version arg_version(version);
978  return (profile_version.CompareTo(arg_version) >= 0);
979}
980
981void ProfileImpl::SetExitType(ExitType exit_type) {
982#if defined(OS_CHROMEOS)
983  if (chromeos::ProfileHelper::IsSigninProfile(this))
984    return;
985#endif
986  if (!prefs_)
987    return;
988  ExitType current_exit_type = SessionTypePrefValueToExitType(
989      prefs_->GetString(prefs::kSessionExitType));
990  // This may be invoked multiple times during shutdown. Only persist the value
991  // first passed in (unless it's a reset to the crash state, which happens when
992  // foregrounding the app on mobile).
993  if (exit_type == EXIT_CRASHED || current_exit_type == EXIT_CRASHED) {
994    prefs_->SetString(prefs::kSessionExitType,
995                      ExitTypeToSessionTypePrefValue(exit_type));
996
997    // NOTE: If you change what thread this writes on, be sure and update
998    // chrome::SessionEnding().
999    prefs_->CommitPendingWrite();
1000  }
1001}
1002
1003Profile::ExitType ProfileImpl::GetLastSessionExitType() {
1004  // last_session_exited_cleanly_ is set when the preferences are loaded. Force
1005  // it to be set by asking for the prefs.
1006  GetPrefs();
1007  return last_session_exit_type_;
1008}
1009
1010PrefService* ProfileImpl::GetPrefs() {
1011  DCHECK(prefs_);  // Should explicitly be initialized.
1012  return prefs_.get();
1013}
1014
1015PrefService* ProfileImpl::GetOffTheRecordPrefs() {
1016  DCHECK(prefs_);
1017  if (!otr_prefs_) {
1018    // The new ExtensionPrefStore is ref_counted and the new PrefService
1019    // stores a reference so that we do not leak memory here.
1020    otr_prefs_.reset(prefs_->CreateIncognitoPrefService(
1021        CreateExtensionPrefStore(this, true)));
1022  }
1023  return otr_prefs_.get();
1024}
1025
1026net::URLRequestContextGetter* ProfileImpl::CreateRequestContext(
1027    content::ProtocolHandlerMap* protocol_handlers,
1028    content::URLRequestInterceptorScopedVector request_interceptors) {
1029  return io_data_.CreateMainRequestContextGetter(
1030      protocol_handlers,
1031      request_interceptors.Pass(),
1032      g_browser_process->local_state(),
1033      g_browser_process->io_thread()).get();
1034}
1035
1036net::URLRequestContextGetter* ProfileImpl::GetRequestContext() {
1037  return GetDefaultStoragePartition(this)->GetURLRequestContext();
1038}
1039
1040net::URLRequestContextGetter* ProfileImpl::GetRequestContextForRenderProcess(
1041    int renderer_child_id) {
1042  content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
1043      renderer_child_id);
1044
1045  return rph->GetStoragePartition()->GetURLRequestContext();
1046}
1047
1048net::URLRequestContextGetter* ProfileImpl::GetMediaRequestContext() {
1049  // Return the default media context.
1050  return io_data_.GetMediaRequestContextGetter().get();
1051}
1052
1053net::URLRequestContextGetter*
1054ProfileImpl::GetMediaRequestContextForRenderProcess(
1055    int renderer_child_id) {
1056  content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
1057      renderer_child_id);
1058  content::StoragePartition* storage_partition = rph->GetStoragePartition();
1059
1060  return storage_partition->GetMediaURLRequestContext();
1061}
1062
1063net::URLRequestContextGetter*
1064ProfileImpl::GetMediaRequestContextForStoragePartition(
1065    const base::FilePath& partition_path,
1066    bool in_memory) {
1067  return io_data_
1068      .GetIsolatedMediaRequestContextGetter(partition_path, in_memory).get();
1069}
1070
1071content::ResourceContext* ProfileImpl::GetResourceContext() {
1072  return io_data_.GetResourceContext();
1073}
1074
1075net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
1076  return io_data_.GetExtensionsRequestContextGetter().get();
1077}
1078
1079net::URLRequestContextGetter*
1080ProfileImpl::CreateRequestContextForStoragePartition(
1081    const base::FilePath& partition_path,
1082    bool in_memory,
1083    content::ProtocolHandlerMap* protocol_handlers,
1084    content::URLRequestInterceptorScopedVector request_interceptors) {
1085  return io_data_.CreateIsolatedAppRequestContextGetter(
1086      partition_path,
1087      in_memory,
1088      protocol_handlers,
1089      request_interceptors.Pass()).get();
1090}
1091
1092net::SSLConfigService* ProfileImpl::GetSSLConfigService() {
1093  // If ssl_config_service_manager_ is null, this typically means that some
1094  // KeyedService is trying to create a RequestContext at startup,
1095  // but SSLConfigServiceManager is not initialized until DoFinalInit() which is
1096  // invoked after all KeyedServices have been initialized (see
1097  // http://crbug.com/171406).
1098  DCHECK(ssl_config_service_manager_) <<
1099      "SSLConfigServiceManager is not initialized yet";
1100  return ssl_config_service_manager_->Get();
1101}
1102
1103HostContentSettingsMap* ProfileImpl::GetHostContentSettingsMap() {
1104  if (!host_content_settings_map_.get()) {
1105    host_content_settings_map_ = new HostContentSettingsMap(GetPrefs(), false);
1106  }
1107  return host_content_settings_map_.get();
1108}
1109
1110content::BrowserPluginGuestManager* ProfileImpl::GetGuestManager() {
1111#if defined(ENABLE_EXTENSIONS)
1112  return extensions::GuestViewManager::FromBrowserContext(this);
1113#else
1114  return NULL;
1115#endif
1116}
1117
1118DownloadManagerDelegate* ProfileImpl::GetDownloadManagerDelegate() {
1119  return DownloadServiceFactory::GetForBrowserContext(this)->
1120      GetDownloadManagerDelegate();
1121}
1122
1123storage::SpecialStoragePolicy* ProfileImpl::GetSpecialStoragePolicy() {
1124#if defined(ENABLE_EXTENSIONS)
1125  return GetExtensionSpecialStoragePolicy();
1126#else
1127  return NULL;
1128#endif
1129}
1130
1131content::PushMessagingService* ProfileImpl::GetPushMessagingService() {
1132  return gcm::GCMProfileServiceFactory::GetForProfile(
1133      this)->push_messaging_service();
1134}
1135
1136content::SSLHostStateDelegate* ProfileImpl::GetSSLHostStateDelegate() {
1137  return ChromeSSLHostStateDelegateFactory::GetForProfile(this);
1138}
1139
1140bool ProfileImpl::IsSameProfile(Profile* profile) {
1141  if (profile == static_cast<Profile*>(this))
1142    return true;
1143  Profile* otr_profile = off_the_record_profile_.get();
1144  return otr_profile && profile == otr_profile;
1145}
1146
1147Time ProfileImpl::GetStartTime() const {
1148  return start_time_;
1149}
1150
1151history::TopSites* ProfileImpl::GetTopSites() {
1152  if (!top_sites_.get()) {
1153    top_sites_ = history::TopSites::Create(
1154        this, GetPath().Append(chrome::kTopSitesFilename));
1155  }
1156  return top_sites_.get();
1157}
1158
1159history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() {
1160  return top_sites_.get();
1161}
1162
1163void ProfileImpl::OnDefaultZoomLevelChanged() {
1164  HostZoomMap::GetDefaultForBrowserContext(this)->SetDefaultZoomLevel(
1165      pref_change_registrar_.prefs()->GetDouble(prefs::kDefaultZoomLevel));
1166}
1167
1168void ProfileImpl::OnZoomLevelChanged(
1169    const HostZoomMap::ZoomLevelChange& change) {
1170
1171  if (change.mode != HostZoomMap::ZOOM_CHANGED_FOR_HOST)
1172    return;
1173  HostZoomMap* host_zoom_map = HostZoomMap::GetDefaultForBrowserContext(this);
1174  double level = change.zoom_level;
1175  DictionaryPrefUpdate update(prefs_.get(), prefs::kPerHostZoomLevels);
1176  base::DictionaryValue* host_zoom_dictionary = update.Get();
1177  if (content::ZoomValuesEqual(level, host_zoom_map->GetDefaultZoomLevel()))
1178    host_zoom_dictionary->RemoveWithoutPathExpansion(change.host, NULL);
1179  else
1180    host_zoom_dictionary->SetDoubleWithoutPathExpansion(change.host, level);
1181}
1182
1183#if defined(ENABLE_SESSION_SERVICE)
1184void ProfileImpl::StopCreateSessionServiceTimer() {
1185  create_session_service_timer_.Stop();
1186}
1187
1188void ProfileImpl::EnsureSessionServiceCreated() {
1189  SessionServiceFactory::GetForProfile(this);
1190}
1191#endif
1192
1193#if defined(OS_CHROMEOS)
1194void ProfileImpl::ChangeAppLocale(
1195    const std::string& new_locale, AppLocaleChangedVia via) {
1196  if (new_locale.empty()) {
1197    NOTREACHED();
1198    return;
1199  }
1200  PrefService* local_state = g_browser_process->local_state();
1201  DCHECK(local_state);
1202  if (local_state->IsManagedPreference(prefs::kApplicationLocale))
1203    return;
1204  std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale);
1205  bool do_update_pref = true;
1206  switch (via) {
1207    case APP_LOCALE_CHANGED_VIA_SETTINGS:
1208    case APP_LOCALE_CHANGED_VIA_REVERT: {
1209      // We keep kApplicationLocaleBackup value as a reference.  In case value
1210      // of kApplicationLocale preference would change due to sync from other
1211      // device then kApplicationLocaleBackup value will trigger and allow us to
1212      // show notification about automatic locale change in LocaleChangeGuard.
1213      GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
1214      GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted);
1215      // We maintain kApplicationLocale property in both a global storage
1216      // and user's profile.  Global property determines locale of login screen,
1217      // while user's profile determines his personal locale preference.
1218      break;
1219    }
1220    case APP_LOCALE_CHANGED_VIA_LOGIN:
1221    case APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN: {
1222      if (!pref_locale.empty()) {
1223        DCHECK(pref_locale == new_locale);
1224        std::string accepted_locale =
1225            GetPrefs()->GetString(prefs::kApplicationLocaleAccepted);
1226        if (accepted_locale == new_locale) {
1227          // If locale is accepted then we do not want to show LocaleChange
1228          // notification.  This notification is triggered by different values
1229          // of kApplicationLocaleBackup and kApplicationLocale preferences,
1230          // so make them identical.
1231          GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
1232        } else {
1233          // Back up locale of login screen.
1234          std::string cur_locale = g_browser_process->GetApplicationLocale();
1235          GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1236          if (locale_change_guard_ == NULL)
1237            locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1238          locale_change_guard_->PrepareChangingLocale(cur_locale, new_locale);
1239        }
1240      } else {
1241        std::string cur_locale = g_browser_process->GetApplicationLocale();
1242        std::string backup_locale =
1243            GetPrefs()->GetString(prefs::kApplicationLocaleBackup);
1244        // Profile synchronization takes time and is not completed at that
1245        // moment at first login.  So we initialize locale preference in steps:
1246        // (1) first save it to temporary backup;
1247        // (2) on next login we assume that synchronization is already completed
1248        //     and we may finalize initialization.
1249        GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1250        if (!new_locale.empty())
1251          GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
1252        else if (!backup_locale.empty())
1253          GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale);
1254        do_update_pref = false;
1255      }
1256      break;
1257    }
1258    case APP_LOCALE_CHANGED_VIA_UNKNOWN:
1259    default: {
1260      NOTREACHED();
1261      break;
1262    }
1263  }
1264  if (do_update_pref)
1265    GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
1266  if (via != APP_LOCALE_CHANGED_VIA_PUBLIC_SESSION_LOGIN)
1267    local_state->SetString(prefs::kApplicationLocale, new_locale);
1268
1269  if (user_manager::UserManager::Get()->GetOwnerEmail() ==
1270      chromeos::ProfileHelper::Get()->GetUserByProfile(this)->email())
1271    local_state->SetString(prefs::kOwnerLocale, new_locale);
1272}
1273
1274void ProfileImpl::OnLogin() {
1275  if (locale_change_guard_ == NULL)
1276    locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1277  locale_change_guard_->OnLogin();
1278}
1279
1280void ProfileImpl::InitChromeOSPreferences() {
1281  chromeos_preferences_.reset(new chromeos::Preferences());
1282  chromeos_preferences_->Init(
1283      this, chromeos::ProfileHelper::Get()->GetUserByProfile(this));
1284}
1285
1286#endif  // defined(OS_CHROMEOS)
1287
1288PrefProxyConfigTracker* ProfileImpl::GetProxyConfigTracker() {
1289  if (!pref_proxy_config_tracker_)
1290    pref_proxy_config_tracker_.reset(CreateProxyConfigTracker());
1291  return pref_proxy_config_tracker_.get();
1292}
1293
1294chrome_browser_net::Predictor* ProfileImpl::GetNetworkPredictor() {
1295  return predictor_;
1296}
1297
1298DevToolsNetworkController* ProfileImpl::GetDevToolsNetworkController() {
1299  return io_data_.GetDevToolsNetworkController();
1300}
1301
1302void ProfileImpl::ClearNetworkingHistorySince(
1303    base::Time time,
1304    const base::Closure& completion) {
1305  io_data_.ClearNetworkingHistorySince(time, completion);
1306}
1307
1308GURL ProfileImpl::GetHomePage() {
1309  // --homepage overrides any preferences.
1310  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1311  if (command_line.HasSwitch(switches::kHomePage)) {
1312    // TODO(evanm): clean up usage of DIR_CURRENT.
1313    //   http://code.google.com/p/chromium/issues/detail?id=60630
1314    // For now, allow this code to call getcwd().
1315    base::ThreadRestrictions::ScopedAllowIO allow_io;
1316
1317    base::FilePath browser_directory;
1318    PathService::Get(base::DIR_CURRENT, &browser_directory);
1319    GURL home_page(url_fixer::FixupRelativeFile(
1320        browser_directory,
1321        command_line.GetSwitchValuePath(switches::kHomePage)));
1322    if (home_page.is_valid())
1323      return home_page;
1324  }
1325
1326  if (GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
1327    return GURL(chrome::kChromeUINewTabURL);
1328  GURL home_page(url_fixer::FixupURL(GetPrefs()->GetString(prefs::kHomePage),
1329                                     std::string()));
1330  if (!home_page.is_valid())
1331    return GURL(chrome::kChromeUINewTabURL);
1332  return home_page;
1333}
1334
1335void ProfileImpl::UpdateProfileUserNameCache() {
1336  ProfileManager* profile_manager = g_browser_process->profile_manager();
1337  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1338  size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1339  if (index != std::string::npos) {
1340    std::string user_name =
1341        GetPrefs()->GetString(prefs::kGoogleServicesUsername);
1342    cache.SetUserNameOfProfileAtIndex(index, base::UTF8ToUTF16(user_name));
1343    ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
1344  }
1345}
1346
1347void ProfileImpl::UpdateProfileSupervisedUserIdCache() {
1348  ProfileManager* profile_manager = g_browser_process->profile_manager();
1349  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1350  size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1351  if (index != std::string::npos) {
1352    std::string supervised_user_id =
1353        GetPrefs()->GetString(prefs::kSupervisedUserId);
1354    cache.SetSupervisedUserIdOfProfileAtIndex(index, supervised_user_id);
1355    ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager);
1356  }
1357}
1358
1359void ProfileImpl::UpdateProfileNameCache() {
1360  ProfileManager* profile_manager = g_browser_process->profile_manager();
1361  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1362  size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1363  if (index != std::string::npos) {
1364    std::string profile_name =
1365        GetPrefs()->GetString(prefs::kProfileName);
1366    cache.SetNameOfProfileAtIndex(index, base::UTF8ToUTF16(profile_name));
1367    bool default_name =
1368        GetPrefs()->GetBoolean(prefs::kProfileUsingDefaultName);
1369    cache.SetProfileIsUsingDefaultNameAtIndex(index, default_name);
1370  }
1371}
1372
1373void ProfileImpl::UpdateProfileAvatarCache() {
1374  ProfileManager* profile_manager = g_browser_process->profile_manager();
1375  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1376  size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1377  if (index != std::string::npos) {
1378    size_t avatar_index =
1379        GetPrefs()->GetInteger(prefs::kProfileAvatarIndex);
1380    cache.SetAvatarIconOfProfileAtIndex(index, avatar_index);
1381    bool default_avatar =
1382        GetPrefs()->GetBoolean(prefs::kProfileUsingDefaultAvatar);
1383    cache.SetProfileIsUsingDefaultAvatarAtIndex(index, default_avatar);
1384    bool gaia_avatar =
1385        GetPrefs()->GetBoolean(prefs::kProfileUsingGAIAAvatar);
1386    cache.SetIsUsingGAIAPictureOfProfileAtIndex(index, gaia_avatar);
1387  }
1388}
1389
1390void ProfileImpl::UpdateProfileIsEphemeralCache() {
1391  ProfileManager* profile_manager = g_browser_process->profile_manager();
1392  ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1393  size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1394  if (index != std::string::npos) {
1395    bool is_ephemeral = GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
1396    cache.SetProfileIsEphemeralAtIndex(index, is_ephemeral);
1397  }
1398}
1399
1400// Gets the cache parameters from the command line. If |is_media_context| is
1401// set to true then settings for the media context type is what we need,
1402// |cache_path| will be set to the user provided path, or will not be touched if
1403// there is not an argument. |max_size| will be the user provided value or zero
1404// by default.
1405void ProfileImpl::GetCacheParameters(bool is_media_context,
1406                                     base::FilePath* cache_path,
1407                                     int* max_size) {
1408  DCHECK(cache_path);
1409  DCHECK(max_size);
1410  base::FilePath path(prefs_->GetFilePath(prefs::kDiskCacheDir));
1411  if (!path.empty())
1412    *cache_path = path;
1413  *max_size = is_media_context ? prefs_->GetInteger(prefs::kMediaCacheSize) :
1414                                 prefs_->GetInteger(prefs::kDiskCacheSize);
1415}
1416
1417PrefProxyConfigTracker* ProfileImpl::CreateProxyConfigTracker() {
1418#if defined(OS_CHROMEOS)
1419  if (chromeos::ProfileHelper::IsSigninProfile(this)) {
1420    return ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
1421        g_browser_process->local_state());
1422  }
1423#endif  // defined(OS_CHROMEOS)
1424  return ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
1425      GetPrefs(), g_browser_process->local_state());
1426}
1427
1428scoped_ptr<domain_reliability::DomainReliabilityMonitor>
1429ProfileImpl::CreateDomainReliabilityMonitor(PrefService* local_state) {
1430  domain_reliability::DomainReliabilityService* service =
1431      domain_reliability::DomainReliabilityServiceFactory::GetInstance()->
1432          GetForBrowserContext(this);
1433  if (!service)
1434    return scoped_ptr<domain_reliability::DomainReliabilityMonitor>();
1435
1436  return service->CreateMonitor(
1437      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
1438}
1439