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