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