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.
5 #include "chrome/browser/profiles/profile_impl.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/compiler_specific.h"
11 #include "base/environment.h"
12 #include "base/file_path.h"
13 #include "base/file_util.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/path_service.h"
16 #include "base/prefs/json_pref_store.h"
17 #include "base/string_number_conversions.h"
18 #include "base/string_tokenizer.h"
19 #include "base/string_util.h"
20 #include "base/stringprintf.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/threading/sequenced_worker_pool.h"
23 #include "base/utf_string_conversions.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/browser_process.h"
29 #include "chrome/browser/chrome_plugin_service_filter.h"
30 #include "chrome/browser/content_settings/cookie_settings.h"
31 #include "chrome/browser/content_settings/host_content_settings_map.h"
32 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
33 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.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/metrics/metrics_service.h"
48 #include "chrome/browser/net/chrome_url_request_context.h"
49 #include "chrome/browser/net/net_pref_observer.h"
50 #include "chrome/browser/net/predictor.h"
51 #include "chrome/browser/net/proxy_service_factory.h"
52 #include "chrome/browser/net/ssl_config_service_manager.h"
53 #include "chrome/browser/net/url_fixer_upper.h"
54 #include "chrome/browser/plugins/plugin_prefs.h"
55 #include "chrome/browser/prefs/browser_prefs.h"
56 #include "chrome/browser/prefs/scoped_user_pref_update.h"
57 #include "chrome/browser/prerender/prerender_manager_factory.h"
58 #include "chrome/browser/profiles/chrome_version_service.h"
59 #include "chrome/browser/profiles/gaia_info_update_service.h"
60 #include "chrome/browser/profiles/profile_dependency_manager.h"
61 #include "chrome/browser/profiles/profile_destroyer.h"
62 #include "chrome/browser/profiles/profile_info_cache.h"
63 #include "chrome/browser/profiles/profile_manager.h"
64 #include "chrome/browser/search_engines/template_url_fetcher.h"
65 #include "chrome/browser/sessions/session_service_factory.h"
66 #include "chrome/browser/speech/chrome_speech_recognition_preferences.h"
67 #include "chrome/browser/sync/profile_sync_service_factory.h"
68 #include "chrome/browser/ui/startup/startup_browser_creator.h"
69 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
70 #include "chrome/browser/user_style_sheet_watcher.h"
71 #include "chrome/browser/web_resource/promo_resource_service.h"
72 #include "chrome/browser/webdata/web_data_service.h"
73 #include "chrome/common/chrome_constants.h"
74 #include "chrome/common/chrome_notification_types.h"
75 #include "chrome/common/chrome_paths_internal.h"
76 #include "chrome/common/chrome_switches.h"
77 #include "chrome/common/chrome_version_info.h"
78 #include "chrome/common/pref_names.h"
79 #include "chrome/common/url_constants.h"
80 #include "content/public/browser/browser_thread.h"
81 #include "content/public/browser/dom_storage_context.h"
82 #include "content/public/browser/host_zoom_map.h"
83 #include "content/public/browser/notification_service.h"
84 #include "content/public/browser/render_process_host.h"
85 #include "content/public/browser/storage_partition.h"
86 #include "content/public/browser/user_metrics.h"
87 #include "content/public/common/content_constants.h"
88 #include "grit/chromium_strings.h"
89 #include "grit/generated_resources.h"
90 #include "ui/base/l10n/l10n_util.h"
92 #if defined(ENABLE_CONFIGURATION_POLICY)
93 #include "chrome/browser/policy/browser_policy_connector.h"
94 #include "chrome/browser/policy/managed_mode_policy_provider.h"
95 #include "chrome/browser/policy/user_cloud_policy_manager.h"
97 #include "chrome/browser/policy/policy_service_stub.h"
98 #endif // defined(ENABLE_CONFIGURATION_POLICY)
101 #include "chrome/installer/util/install_util.h"
104 #if defined(OS_CHROMEOS)
105 #include "chrome/browser/chromeos/enterprise_extension_observer.h"
106 #include "chrome/browser/chromeos/locale_change_guard.h"
107 #include "chrome/browser/chromeos/login/user_manager.h"
108 #include "chrome/browser/chromeos/preferences.h"
109 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
113 using base::TimeDelta
;
114 using content::BrowserThread
;
115 using content::DownloadManagerDelegate
;
116 using content::HostZoomMap
;
117 using content::UserMetricsAction
;
121 // Constrict us to a very specific platform and architecture to make sure
122 // ifdefs don't cause problems with the check.
123 #if defined(OS_LINUX) && defined(TOOLKIT_GTK) && defined(ARCH_CPU_X86_64) && \
124 !defined(_GLIBCXX_DEBUG)
125 // Make sure that the ProfileImpl doesn't grow. We're currently trying to drive
126 // the number of services that are included in ProfileImpl (instead of using
127 // ProfileKeyedServiceFactory) to zero.
129 // If you don't know about this effort, please read:
130 // https://sites.google.com/a/chromium.org/dev/developers/design-documents/profile-architecture
132 // REVIEWERS: Do not let anyone increment this. We need to drive the number of
133 // raw accessed services down to zero. DO NOT LET PEOPLE REGRESS THIS UNLESS
134 // THE PATCH ITSELF IS MAKING PROGRESS ON PKSF REFACTORING.
135 COMPILE_ASSERT(sizeof(ProfileImpl
) <= 744u, profile_impl_size_unexpected
);
138 #if defined(ENABLE_SESSION_SERVICE)
139 // Delay, in milliseconds, before we explicitly create the SessionService.
140 static const int kCreateSessionServiceDelayMS
= 500;
143 // Text content of README file created in each profile directory. Both %s
144 // placeholders must contain the product name. This is not localizable and hence
146 static const char kReadmeText
[] =
147 "%s settings and storage represent user-selected preferences and "
148 "information and MUST not be extracted, overwritten or modified except "
149 "through %s defined APIs.";
151 // Value written to prefs for EXIT_CRASHED and EXIT_SESSION_ENDED.
152 const char* const kPrefExitTypeCrashed
= "Crashed";
153 const char* const kPrefExitTypeSessionEnded
= "SessionEnded";
155 // Helper method needed because PostTask cannot currently take a Callback
156 // function with non-void return type.
157 void CreateDirectoryAndSignal(const FilePath
& path
,
158 base::WaitableEvent
* done_creating
) {
159 DVLOG(1) << "Creating directory " << path
.value();
160 file_util::CreateDirectory(path
);
161 done_creating
->Signal();
164 // Task that blocks the FILE thread until CreateDirectoryAndSignal() finishes on
165 // blocking I/O pool.
166 void BlockFileThreadOnDirectoryCreate(base::WaitableEvent
* done_creating
) {
167 done_creating
->Wait();
170 // Initiates creation of profile directory on |sequenced_task_runner| and
171 // ensures that FILE thread is blocked until that operation finishes.
172 void CreateProfileDirectory(base::SequencedTaskRunner
* sequenced_task_runner
,
173 const FilePath
& path
) {
174 base::WaitableEvent
* done_creating
= new base::WaitableEvent(false, false);
175 sequenced_task_runner
->PostTask(FROM_HERE
,
176 base::Bind(&CreateDirectoryAndSignal
,
179 // Block the FILE thread until directory is created on I/O pool to make sure
180 // that we don't attempt any operation until that part completes.
181 BrowserThread::PostTask(
182 BrowserThread::FILE, FROM_HERE
,
183 base::Bind(&BlockFileThreadOnDirectoryCreate
,
184 base::Owned(done_creating
)));
187 FilePath
GetCachePath(const FilePath
& base
) {
188 return base
.Append(chrome::kCacheDirname
);
191 FilePath
GetMediaCachePath(const FilePath
& base
) {
192 return base
.Append(chrome::kMediaCacheDirname
);
195 void EnsureReadmeFile(const FilePath
& base
) {
196 FilePath readme_path
= base
.Append(chrome::kReadmeFilename
);
197 if (file_util::PathExists(readme_path
))
199 std::string product_name
= l10n_util::GetStringUTF8(IDS_PRODUCT_NAME
);
200 std::string readme_text
= base::StringPrintf(
201 kReadmeText
, product_name
.c_str(), product_name
.c_str());
202 if (file_util::WriteFile(
203 readme_path
, readme_text
.data(), readme_text
.size()) == -1) {
204 LOG(ERROR
) << "Could not create README file.";
208 // Converts the kSessionExitedCleanly pref to the corresponding EXIT_TYPE.
209 Profile::ExitType
SessionTypePrefValueToExitType(const std::string
& value
) {
210 if (value
== kPrefExitTypeSessionEnded
)
211 return Profile::EXIT_SESSION_ENDED
;
212 if (value
== kPrefExitTypeCrashed
)
213 return Profile::EXIT_CRASHED
;
214 return Profile::EXIT_NORMAL
;
217 // Converts an ExitType into a string that is written to prefs.
218 std::string
ExitTypeToSessionTypePrefValue(Profile::ExitType type
) {
220 case Profile::EXIT_NORMAL
:
221 return ProfileImpl::kPrefExitTypeNormal
;
222 case Profile::EXIT_SESSION_ENDED
:
223 return kPrefExitTypeSessionEnded
;
224 case Profile::EXIT_CRASHED
:
225 return kPrefExitTypeCrashed
;
228 return std::string();
234 Profile
* Profile::CreateProfile(const FilePath
& path
,
236 CreateMode create_mode
) {
237 // Get sequenced task runner for making sure that file operations of
238 // this profile (defined by |path|) are executed in expected order
239 // (what was previously assured by the FILE thread).
240 scoped_refptr
<base::SequencedTaskRunner
> sequenced_task_runner
=
241 JsonPrefStore::GetTaskRunnerForFile(path
,
242 BrowserThread::GetBlockingPool());
243 if (create_mode
== CREATE_MODE_ASYNCHRONOUS
) {
245 CreateProfileDirectory(sequenced_task_runner
, path
);
246 } else if (create_mode
== CREATE_MODE_SYNCHRONOUS
) {
247 if (!file_util::PathExists(path
)) {
248 // TODO(tc): http://b/1094718 Bad things happen if we can't write to the
249 // profile directory. We should eventually be able to run in this
251 if (!file_util::CreateDirectory(path
))
258 return new ProfileImpl(path
, delegate
, create_mode
, sequenced_task_runner
);
262 int ProfileImpl::create_readme_delay_ms
= 60000;
265 const char* const ProfileImpl::kPrefExitTypeNormal
= "Normal";
268 void ProfileImpl::RegisterUserPrefs(PrefService
* prefs
) {
269 prefs
->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled
,
271 PrefService::UNSYNCABLE_PREF
);
272 prefs
->RegisterBooleanPref(prefs::kForceSafeSearch
,
274 PrefService::UNSYNCABLE_PREF
);
275 prefs
->RegisterIntegerPref(prefs::kProfileAvatarIndex
,
277 PrefService::SYNCABLE_PREF
);
278 prefs
->RegisterStringPref(prefs::kProfileName
,
280 PrefService::SYNCABLE_PREF
);
281 prefs
->RegisterStringPref(prefs::kHomePage
,
283 PrefService::SYNCABLE_PREF
);
284 #if defined(ENABLE_PRINTING)
285 prefs
->RegisterBooleanPref(prefs::kPrintingEnabled
,
287 PrefService::UNSYNCABLE_PREF
);
289 prefs
->RegisterBooleanPref(prefs::kPrintPreviewDisabled
,
290 #if defined(GOOGLE_CHROME_BUILD)
295 PrefService::UNSYNCABLE_PREF
);
297 // Initialize the cache prefs.
298 prefs
->RegisterFilePathPref(prefs::kDiskCacheDir
,
300 PrefService::UNSYNCABLE_PREF
);
301 prefs
->RegisterIntegerPref(prefs::kDiskCacheSize
,
303 PrefService::UNSYNCABLE_PREF
);
304 prefs
->RegisterIntegerPref(prefs::kMediaCacheSize
,
306 PrefService::UNSYNCABLE_PREF
);
308 // Deprecated. Kept around for migration.
309 prefs
->RegisterBooleanPref(prefs::kClearSiteDataOnExit
,
311 PrefService::SYNCABLE_PREF
);
314 ProfileImpl::ProfileImpl(
315 const FilePath
& path
,
317 CreateMode create_mode
,
318 base::SequencedTaskRunner
* sequenced_task_runner
)
320 ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),
321 host_content_settings_map_(NULL
),
322 last_session_exit_type_(EXIT_NORMAL
),
323 start_time_(Time::Now()),
326 DCHECK(!path
.empty()) << "Using an empty path will attempt to write " <<
327 "profile files to the root directory!";
329 #if defined(ENABLE_SESSION_SERVICE)
330 create_session_service_timer_
.Start(FROM_HERE
,
331 TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS
), this,
332 &ProfileImpl::EnsureSessionServiceCreated
);
335 // Determine if prefetch is enabled for this profile.
336 // If not profile_manager is present, it means we are in a unittest.
337 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
338 predictor_
= chrome_browser_net::Predictor::CreatePredictor(
339 !command_line
->HasSwitch(switches::kDisablePreconnect
),
340 g_browser_process
->profile_manager() == NULL
);
342 #if defined(ENABLE_CONFIGURATION_POLICY)
343 // TODO(atwilson): Change these to ProfileKeyedServices once PrefService is
344 // a ProfileKeyedService (policy must be initialized before PrefService
345 // because PrefService depends on policy loading to get overridden pref
347 policy::BrowserPolicyConnector
* connector
=
348 g_browser_process
->browser_policy_connector();
349 cloud_policy_manager_
= connector
->CreateCloudPolicyManager(this);
350 if (cloud_policy_manager_
)
351 cloud_policy_manager_
->Init();
352 managed_mode_policy_provider_
.reset(
353 policy::ManagedModePolicyProvider::Create(this, sequenced_task_runner
));
354 managed_mode_policy_provider_
->Init();
355 policy_service_
= connector
->CreatePolicyService(this);
357 policy_service_
.reset(new policy::PolicyServiceStub());
360 if (create_mode
== CREATE_MODE_ASYNCHRONOUS
) {
361 prefs_
.reset(PrefService::CreatePrefService(
363 sequenced_task_runner
,
364 policy_service_
.get(),
365 new ExtensionPrefStore(
366 ExtensionPrefValueMapFactory::GetForProfile(this), false),
368 // Wait for the notification that prefs has been loaded
369 // (successfully or not). Note that we can use base::Unretained
370 // because the PrefService is owned by this class and lives on
372 prefs_
->AddPrefInitObserver(base::Bind(&ProfileImpl::OnPrefsLoaded
,
373 base::Unretained(this)));
374 } else if (create_mode
== CREATE_MODE_SYNCHRONOUS
) {
375 // Load prefs synchronously.
376 prefs_
.reset(PrefService::CreatePrefService(
378 sequenced_task_runner
,
379 policy_service_
.get(),
380 new ExtensionPrefStore(
381 ExtensionPrefValueMapFactory::GetForProfile(this), false),
389 void ProfileImpl::DoFinalInit(bool is_new_profile
) {
390 PrefService
* prefs
= GetPrefs();
391 pref_change_registrar_
.Init(prefs
);
392 pref_change_registrar_
.Add(prefs::kGoogleServicesUsername
, this);
393 pref_change_registrar_
.Add(prefs::kDefaultZoomLevel
, this);
394 pref_change_registrar_
.Add(prefs::kProfileAvatarIndex
, this);
395 pref_change_registrar_
.Add(prefs::kProfileName
, this);
397 // It would be nice to use PathService for fetching this directory, but
398 // the cache directory depends on the profile directory, which isn't available
400 chrome::GetUserCacheDirectory(path_
, &base_cache_path_
);
401 // Always create the cache directory asynchronously.
402 scoped_refptr
<base::SequencedTaskRunner
> sequenced_task_runner
=
403 JsonPrefStore::GetTaskRunnerForFile(base_cache_path_
,
404 BrowserThread::GetBlockingPool());
405 CreateProfileDirectory(sequenced_task_runner
, base_cache_path_
);
407 // Now that the profile is hooked up to receive pref change notifications to
408 // kGoogleServicesUsername, initialize components that depend on it to reflect
409 // the current value.
410 UpdateProfileUserNameCache();
411 GetGAIAInfoUpdateService();
413 #if !defined(OS_CHROMEOS)
414 // Listen for bookmark model load, to bootstrap the sync service.
415 // On CrOS sync service will be initialized after sign in.
416 registrar_
.Add(this, chrome::NOTIFICATION_BOOKMARK_MODEL_LOADED
,
417 content::Source
<Profile
>(this));
420 PrefService
* local_state
= g_browser_process
->local_state();
421 ssl_config_service_manager_
.reset(
422 SSLConfigServiceManager::CreateDefaultManager(local_state
, prefs
));
424 // Initialize the BackgroundModeManager - this has to be done here before
425 // InitExtensions() is called because it relies on receiving notifications
426 // when extensions are loaded. BackgroundModeManager is not needed under
427 // ChromeOS because Chrome is always running, no need for special keep-alive
428 // or launch-on-startup support unless kKeepAliveForTest is set.
429 bool init_background_mode_manager
= true;
430 #if defined(OS_CHROMEOS)
431 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest
))
432 init_background_mode_manager
= false;
434 if (init_background_mode_manager
) {
435 if (g_browser_process
->background_mode_manager())
436 g_browser_process
->background_mode_manager()->RegisterProfile(this);
439 FilePath cookie_path
= GetPath();
440 cookie_path
= cookie_path
.Append(chrome::kCookieFilename
);
441 FilePath server_bound_cert_path
= GetPath();
442 server_bound_cert_path
=
443 server_bound_cert_path
.Append(chrome::kOBCertFilename
);
444 FilePath cache_path
= base_cache_path_
;
446 GetCacheParameters(false, &cache_path
, &cache_max_size
);
447 cache_path
= GetCachePath(cache_path
);
449 FilePath media_cache_path
= base_cache_path_
;
450 int media_cache_max_size
;
451 GetCacheParameters(true, &media_cache_path
, &media_cache_max_size
);
452 media_cache_path
= GetMediaCachePath(media_cache_path
);
454 FilePath extensions_cookie_path
= GetPath();
455 extensions_cookie_path
=
456 extensions_cookie_path
.Append(chrome::kExtensionsCookieFilename
);
458 FilePath infinite_cache_path
= GetPath();
459 infinite_cache_path
=
460 infinite_cache_path
.Append(FILE_PATH_LITERAL("Infinite Cache"));
462 #if defined(OS_ANDROID)
463 SessionStartupPref::Type startup_pref_type
=
464 SessionStartupPref::GetDefaultStartupType();
466 SessionStartupPref::Type startup_pref_type
=
467 StartupBrowserCreator::GetSessionStartupPref(
468 *CommandLine::ForCurrentProcess(), this).type
;
470 bool restore_old_session_cookies
=
471 (GetLastSessionExitType() == Profile::EXIT_CRASHED
||
472 startup_pref_type
== SessionStartupPref::LAST
);
476 // Make sure we initialize the ProfileIOData after everything else has been
477 // initialized that we might be reading from the IO thread.
479 io_data_
.Init(cookie_path
, server_bound_cert_path
, cache_path
,
480 cache_max_size
, media_cache_path
, media_cache_max_size
,
481 extensions_cookie_path
, GetPath(), infinite_cache_path
,
483 g_browser_process
->local_state(),
484 g_browser_process
->io_thread(),
485 restore_old_session_cookies
,
486 GetSpecialStoragePolicy());
488 ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
489 PluginPrefs::GetForProfile(this),
490 io_data_
.GetResourceContextNoInit());
492 // Delay README creation to not impact startup performance.
493 BrowserThread::PostDelayedTask(
494 BrowserThread::FILE, FROM_HERE
,
495 base::Bind(&EnsureReadmeFile
, GetPath()),
496 base::TimeDelta::FromMilliseconds(create_readme_delay_ms
));
498 if (!CommandLine::ForCurrentProcess()->HasSwitch(
499 switches::kDisableRestoreSessionState
)) {
500 content::BrowserContext::GetDefaultStoragePartition(this)->
501 GetDOMStorageContext()->SetSaveSessionStorageOnDisk();
504 // Creation has been finished.
506 delegate_
->OnProfileCreated(this, true, is_new_profile
);
508 content::NotificationService::current()->Notify(
509 chrome::NOTIFICATION_PROFILE_CREATED
,
510 content::Source
<Profile
>(this),
511 content::NotificationService::NoDetails());
514 void ProfileImpl::InitHostZoomMap() {
515 HostZoomMap
* host_zoom_map
= HostZoomMap::GetForBrowserContext(this);
516 host_zoom_map
->SetDefaultZoomLevel(
517 prefs_
->GetDouble(prefs::kDefaultZoomLevel
));
519 const DictionaryValue
* host_zoom_dictionary
=
520 prefs_
->GetDictionary(prefs::kPerHostZoomLevels
);
521 // Careful: The returned value could be NULL if the pref has never been set.
522 if (host_zoom_dictionary
!= NULL
) {
523 for (DictionaryValue::key_iterator
i(host_zoom_dictionary
->begin_keys());
524 i
!= host_zoom_dictionary
->end_keys(); ++i
) {
525 const std::string
& host(*i
);
526 double zoom_level
= 0;
528 bool success
= host_zoom_dictionary
->GetDoubleWithoutPathExpansion(
531 host_zoom_map
->SetZoomLevel(host
, zoom_level
);
535 registrar_
.Add(this, content::NOTIFICATION_ZOOM_LEVEL_CHANGED
,
536 content::Source
<HostZoomMap
>(host_zoom_map
));
539 void ProfileImpl::InitPromoResources() {
540 if (promo_resource_service_
)
542 promo_resource_service_
= new PromoResourceService(this);
543 promo_resource_service_
->StartAfterDelay();
546 FilePath
ProfileImpl::last_selected_directory() {
547 return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory
);
550 void ProfileImpl::set_last_selected_directory(const FilePath
& path
) {
551 GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory
, path
);
554 ProfileImpl::~ProfileImpl() {
555 MaybeSendDestroyedNotification();
557 bool prefs_loaded
= prefs_
->GetInitializationStatus() !=
558 PrefService::INITIALIZATION_STATUS_WAITING
;
560 #if defined(ENABLE_SESSION_SERVICE)
561 StopCreateSessionServiceTimer();
564 // Remove pref observers
565 pref_change_registrar_
.RemoveAll();
567 ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext(
568 io_data_
.GetResourceContextNoInit());
570 // Destroy OTR profile and its profile services first.
571 if (off_the_record_profile_
.get()) {
572 ProfileDestroyer::DestroyOffTheRecordProfileNow(
573 off_the_record_profile_
.get());
575 ExtensionPrefValueMapFactory::GetForProfile(this)->
576 ClearAllIncognitoSessionOnlyPreferences();
579 ProfileDependencyManager::GetInstance()->DestroyProfileServices(this);
581 if (top_sites_
.get())
582 top_sites_
->Shutdown();
584 if (pref_proxy_config_tracker_
.get())
585 pref_proxy_config_tracker_
->DetachFromPrefService();
587 if (host_content_settings_map_
)
588 host_content_settings_map_
->ShutdownOnUIThread();
590 #if defined(ENABLE_CONFIGURATION_POLICY)
591 if (cloud_policy_manager_
)
592 cloud_policy_manager_
->Shutdown();
593 if (managed_mode_policy_provider_
)
594 managed_mode_policy_provider_
->Shutdown();
597 // This causes the Preferences file to be written to disk.
599 SetExitType(EXIT_NORMAL
);
602 std::string
ProfileImpl::GetProfileName() {
603 return GetPrefs()->GetString(prefs::kGoogleServicesUsername
);
606 FilePath
ProfileImpl::GetPath() {
610 scoped_refptr
<base::SequencedTaskRunner
> ProfileImpl::GetIOTaskRunner() {
611 return JsonPrefStore::GetTaskRunnerForFile(
612 GetPath(), BrowserThread::GetBlockingPool());
615 bool ProfileImpl::IsOffTheRecord() const {
619 Profile
* ProfileImpl::GetOffTheRecordProfile() {
620 if (!off_the_record_profile_
.get()) {
621 scoped_ptr
<Profile
> p(CreateOffTheRecordProfile());
622 off_the_record_profile_
.swap(p
);
624 content::NotificationService::current()->Notify(
625 chrome::NOTIFICATION_PROFILE_CREATED
,
626 content::Source
<Profile
>(off_the_record_profile_
.get()),
627 content::NotificationService::NoDetails());
629 return off_the_record_profile_
.get();
632 void ProfileImpl::DestroyOffTheRecordProfile() {
633 off_the_record_profile_
.reset();
634 ExtensionPrefValueMapFactory::GetForProfile(this)->
635 ClearAllIncognitoSessionOnlyPreferences();
638 bool ProfileImpl::HasOffTheRecordProfile() {
639 return off_the_record_profile_
.get() != NULL
;
642 Profile
* ProfileImpl::GetOriginalProfile() {
646 ExtensionService
* ProfileImpl::GetExtensionService() {
647 return extensions::ExtensionSystem::Get(this)->extension_service();
650 ExtensionSpecialStoragePolicy
*
651 ProfileImpl::GetExtensionSpecialStoragePolicy() {
652 if (!extension_special_storage_policy_
.get()) {
653 extension_special_storage_policy_
= new ExtensionSpecialStoragePolicy(
654 CookieSettings::Factory::GetForProfile(this));
656 return extension_special_storage_policy_
.get();
659 void ProfileImpl::OnPrefsLoaded(bool success
) {
662 delegate_
->OnProfileCreated(this, false, false);
666 // The Profile class and ProfileManager class may read some prefs so
667 // register known prefs as soon as possible.
668 Profile::RegisterUserPrefs(prefs_
.get());
669 chrome::RegisterUserPrefs(prefs_
.get());
670 // TODO(mirandac): remove migration code after 6 months (crbug.com/69995).
671 if (g_browser_process
->local_state())
672 chrome::MigrateBrowserPrefs(this, g_browser_process
->local_state());
674 // |kSessionExitType| was added after |kSessionExitedCleanly|. If the pref
675 // value is empty fallback to checking for |kSessionExitedCleanly|.
676 const std::string
exit_type_pref_value(
677 prefs_
->GetString(prefs::kSessionExitType
));
678 if (exit_type_pref_value
.empty()) {
679 last_session_exit_type_
=
680 prefs_
->GetBoolean(prefs::kSessionExitedCleanly
) ?
681 EXIT_NORMAL
: EXIT_CRASHED
;
683 last_session_exit_type_
=
684 SessionTypePrefValueToExitType(exit_type_pref_value
);
686 // Mark the session as open.
687 prefs_
->SetString(prefs::kSessionExitType
, kPrefExitTypeCrashed
);
688 // Force this to true in case we fallback and use it.
689 // TODO(sky): remove this in a couple of releases (m28ish).
690 prefs_
->SetBoolean(prefs::kSessionExitedCleanly
, true);
692 ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false);
694 DCHECK(!net_pref_observer_
.get());
695 net_pref_observer_
.reset(new NetPrefObserver(
697 prerender::PrerenderManagerFactory::GetForProfile(this),
700 bool is_new_profile
= prefs_
->GetInitializationStatus() ==
701 PrefService::INITIALIZATION_STATUS_CREATED_NEW_PROFILE
;
702 ChromeVersionService::OnProfileLoaded(prefs_
.get(), is_new_profile
);
703 DoFinalInit(is_new_profile
);
706 bool ProfileImpl::WasCreatedByVersionOrLater(const std::string
& version
) {
707 Version
profile_version(ChromeVersionService::GetVersion(prefs_
.get()));
708 Version
arg_version(version
);
709 return (profile_version
.CompareTo(arg_version
) >= 0);
712 void ProfileImpl::SetExitType(ExitType exit_type
) {
715 ExitType current_exit_type
= SessionTypePrefValueToExitType(
716 prefs_
->GetString(prefs::kSessionExitType
));
717 // This may be invoked multiple times during shutdown. Only persist the value
718 // first passed in (unless it's a reset to the crash state, which happens when
719 // foregrounding the app on mobile).
720 if (exit_type
== EXIT_CRASHED
|| current_exit_type
== EXIT_CRASHED
) {
721 prefs_
->SetString(prefs::kSessionExitType
,
722 ExitTypeToSessionTypePrefValue(exit_type
));
724 // NOTE: If you change what thread this writes on, be sure and update
725 // ChromeFrame::EndSession().
726 prefs_
->CommitPendingWrite();
730 Profile::ExitType
ProfileImpl::GetLastSessionExitType() {
731 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
732 // it to be set by asking for the prefs.
734 return last_session_exit_type_
;
737 policy::UserCloudPolicyManager
* ProfileImpl::GetUserCloudPolicyManager() {
738 #if defined(ENABLE_CONFIGURATION_POLICY)
739 return cloud_policy_manager_
.get();
745 policy::ManagedModePolicyProvider
* ProfileImpl::GetManagedModePolicyProvider() {
746 #if defined(ENABLE_CONFIGURATION_POLICY)
747 return managed_mode_policy_provider_
.get();
753 policy::PolicyService
* ProfileImpl::GetPolicyService() {
754 DCHECK(policy_service_
.get()); // Should explicitly be initialized.
755 return policy_service_
.get();
758 PrefService
* ProfileImpl::GetPrefs() {
759 DCHECK(prefs_
.get()); // Should explicitly be initialized.
763 PrefService
* ProfileImpl::GetOffTheRecordPrefs() {
764 if (!otr_prefs_
.get()) {
765 // The new ExtensionPrefStore is ref_counted and the new PrefService
766 // stores a reference so that we do not leak memory here.
767 otr_prefs_
.reset(GetPrefs()->CreateIncognitoPrefService(
768 new ExtensionPrefStore(
769 ExtensionPrefValueMapFactory::GetForProfile(this), true)));
771 return otr_prefs_
.get();
774 FilePath
ProfileImpl::GetPrefFilePath() {
775 FilePath pref_file_path
= path_
;
776 pref_file_path
= pref_file_path
.Append(chrome::kPreferencesFilename
);
777 return pref_file_path
;
780 net::URLRequestContextGetter
* ProfileImpl::GetRequestContext() {
781 return io_data_
.GetMainRequestContextGetter();
784 net::URLRequestContextGetter
* ProfileImpl::GetRequestContextForRenderProcess(
785 int renderer_child_id
) {
786 content::RenderProcessHost
* rph
= content::RenderProcessHost::FromID(
789 return rph
->GetStoragePartition()->GetURLRequestContext();
792 net::URLRequestContextGetter
* ProfileImpl::GetMediaRequestContext() {
793 // Return the default media context.
794 return io_data_
.GetMediaRequestContextGetter();
797 net::URLRequestContextGetter
*
798 ProfileImpl::GetMediaRequestContextForRenderProcess(
799 int renderer_child_id
) {
800 content::RenderProcessHost
* rph
= content::RenderProcessHost::FromID(
802 content::StoragePartition
* storage_partition
= rph
->GetStoragePartition();
804 return storage_partition
->GetMediaURLRequestContext();
807 net::URLRequestContextGetter
*
808 ProfileImpl::GetMediaRequestContextForStoragePartition(
809 const FilePath
& partition_path
,
811 return io_data_
.GetIsolatedMediaRequestContextGetter(partition_path
,
815 content::ResourceContext
* ProfileImpl::GetResourceContext() {
816 return io_data_
.GetResourceContext();
819 net::URLRequestContextGetter
* ProfileImpl::GetRequestContextForExtensions() {
820 return io_data_
.GetExtensionsRequestContextGetter();
823 net::URLRequestContextGetter
* ProfileImpl::GetRequestContextForStoragePartition(
824 const FilePath
& partition_path
,
826 return io_data_
.GetIsolatedAppRequestContextGetter(partition_path
, in_memory
);
829 net::SSLConfigService
* ProfileImpl::GetSSLConfigService() {
830 return ssl_config_service_manager_
->Get();
833 HostContentSettingsMap
* ProfileImpl::GetHostContentSettingsMap() {
834 if (!host_content_settings_map_
.get()) {
835 host_content_settings_map_
= new HostContentSettingsMap(GetPrefs(), false);
837 return host_content_settings_map_
.get();
840 content::GeolocationPermissionContext
*
841 ProfileImpl::GetGeolocationPermissionContext() {
842 if (!geolocation_permission_context_
.get()) {
843 geolocation_permission_context_
=
844 ChromeGeolocationPermissionContextFactory::Create(this);
846 return geolocation_permission_context_
.get();
849 content::SpeechRecognitionPreferences
*
850 ProfileImpl::GetSpeechRecognitionPreferences() {
851 #if defined(ENABLE_INPUT_SPEECH)
852 return ChromeSpeechRecognitionPreferences::GetForProfile(this);
858 GAIAInfoUpdateService
* ProfileImpl::GetGAIAInfoUpdateService() {
859 if (!gaia_info_update_service_
.get() &&
860 GAIAInfoUpdateService::ShouldUseGAIAProfileInfo(this)) {
861 gaia_info_update_service_
.reset(new GAIAInfoUpdateService(this));
863 return gaia_info_update_service_
.get();
866 DownloadManagerDelegate
* ProfileImpl::GetDownloadManagerDelegate() {
867 return DownloadServiceFactory::GetForProfile(this)->
868 GetDownloadManagerDelegate();
871 quota::SpecialStoragePolicy
* ProfileImpl::GetSpecialStoragePolicy() {
872 return GetExtensionSpecialStoragePolicy();
875 ProtocolHandlerRegistry
* ProfileImpl::GetProtocolHandlerRegistry() {
876 // TODO(smckay): Update all existing callers to use
877 // ProtocolHandlerRegistryFactory. Once that's done, this method
878 // can be nuked from Profile and ProfileImpl.
879 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
880 return ProtocolHandlerRegistryFactory::GetForProfile(this);
883 bool ProfileImpl::IsSameProfile(Profile
* profile
) {
884 if (profile
== static_cast<Profile
*>(this))
886 Profile
* otr_profile
= off_the_record_profile_
.get();
887 return otr_profile
&& profile
== otr_profile
;
890 Time
ProfileImpl::GetStartTime() const {
894 history::TopSites
* ProfileImpl::GetTopSites() {
895 if (!top_sites_
.get()) {
896 top_sites_
= new history::TopSites(this);
897 top_sites_
->Init(GetPath().Append(chrome::kTopSitesFilename
));
902 history::TopSites
* ProfileImpl::GetTopSitesWithoutCreating() {
906 void ProfileImpl::Observe(int type
,
907 const content::NotificationSource
& source
,
908 const content::NotificationDetails
& details
) {
910 case chrome::NOTIFICATION_BOOKMARK_MODEL_LOADED
:
911 // Causes lazy-load if sync is enabled.
912 ProfileSyncServiceFactory::GetInstance()->GetForProfile(this);
913 registrar_
.Remove(this, chrome::NOTIFICATION_BOOKMARK_MODEL_LOADED
,
914 content::Source
<Profile
>(this));
916 case content::NOTIFICATION_ZOOM_LEVEL_CHANGED
: {
917 const std::string
& host
=
918 *(content::Details
<const std::string
>(details
).ptr());
920 HostZoomMap
* host_zoom_map
= HostZoomMap::GetForBrowserContext(this);
921 double level
= host_zoom_map
->GetZoomLevel(host
);
922 DictionaryPrefUpdate
update(prefs_
.get(), prefs::kPerHostZoomLevels
);
923 DictionaryValue
* host_zoom_dictionary
= update
.Get();
924 if (level
== host_zoom_map
->GetDefaultZoomLevel()) {
925 host_zoom_dictionary
->RemoveWithoutPathExpansion(host
, NULL
);
927 host_zoom_dictionary
->SetWithoutPathExpansion(
928 host
, Value::CreateDoubleValue(level
));
938 void ProfileImpl::OnPreferenceChanged(PrefServiceBase
* prefs
,
939 const std::string
& pref_name_in
) {
941 if (pref_name_in
== prefs::kGoogleServicesUsername
) {
942 UpdateProfileUserNameCache();
943 } else if (pref_name_in
== prefs::kProfileAvatarIndex
) {
944 UpdateProfileAvatarCache();
945 } else if (pref_name_in
== prefs::kProfileName
) {
946 UpdateProfileNameCache();
947 } else if (pref_name_in
== prefs::kDefaultZoomLevel
) {
948 HostZoomMap::GetForBrowserContext(this)->SetDefaultZoomLevel(
949 prefs
->GetDouble(prefs::kDefaultZoomLevel
));
953 #if defined(ENABLE_SESSION_SERVICE)
954 void ProfileImpl::StopCreateSessionServiceTimer() {
955 create_session_service_timer_
.Stop();
958 void ProfileImpl::EnsureSessionServiceCreated() {
959 SessionServiceFactory::GetForProfile(this);
963 #if defined(OS_CHROMEOS)
964 void ProfileImpl::ChangeAppLocale(
965 const std::string
& new_locale
, AppLocaleChangedVia via
) {
966 if (new_locale
.empty()) {
970 PrefService
* local_state
= g_browser_process
->local_state();
972 if (local_state
->IsManagedPreference(prefs::kApplicationLocale
))
974 std::string pref_locale
= GetPrefs()->GetString(prefs::kApplicationLocale
);
975 bool do_update_pref
= true;
977 case APP_LOCALE_CHANGED_VIA_SETTINGS
:
978 case APP_LOCALE_CHANGED_VIA_REVERT
: {
979 // We keep kApplicationLocaleBackup value as a reference. In case value
980 // of kApplicationLocale preference would change due to sync from other
981 // device then kApplicationLocaleBackup value will trigger and allow us to
982 // show notification about automatic locale change in LocaleChangeGuard.
983 GetPrefs()->SetString(prefs::kApplicationLocaleBackup
, new_locale
);
984 GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted
);
985 // We maintain kApplicationLocale property in both a global storage
986 // and user's profile. Global property determines locale of login screen,
987 // while user's profile determines his personal locale preference.
990 case APP_LOCALE_CHANGED_VIA_LOGIN
: {
991 if (!pref_locale
.empty()) {
992 DCHECK(pref_locale
== new_locale
);
993 std::string accepted_locale
=
994 GetPrefs()->GetString(prefs::kApplicationLocaleAccepted
);
995 if (accepted_locale
== new_locale
) {
996 // If locale is accepted then we do not want to show LocaleChange
997 // notification. This notification is triggered by different values
998 // of kApplicationLocaleBackup and kApplicationLocale preferences,
999 // so make them identical.
1000 GetPrefs()->SetString(prefs::kApplicationLocaleBackup
, new_locale
);
1002 // Back up locale of login screen.
1003 std::string cur_locale
= g_browser_process
->GetApplicationLocale();
1004 GetPrefs()->SetString(prefs::kApplicationLocaleBackup
, cur_locale
);
1005 if (locale_change_guard_
== NULL
)
1006 locale_change_guard_
.reset(new chromeos::LocaleChangeGuard(this));
1007 locale_change_guard_
->PrepareChangingLocale(cur_locale
, new_locale
);
1010 std::string cur_locale
= g_browser_process
->GetApplicationLocale();
1011 std::string backup_locale
=
1012 GetPrefs()->GetString(prefs::kApplicationLocaleBackup
);
1013 // Profile synchronization takes time and is not completed at that
1014 // moment at first login. So we initialize locale preference in steps:
1015 // (1) first save it to temporary backup;
1016 // (2) on next login we assume that synchronization is already completed
1017 // and we may finalize initialization.
1018 GetPrefs()->SetString(prefs::kApplicationLocaleBackup
, cur_locale
);
1019 if (!backup_locale
.empty())
1020 GetPrefs()->SetString(prefs::kApplicationLocale
, backup_locale
);
1021 do_update_pref
= false;
1025 case APP_LOCALE_CHANGED_VIA_UNKNOWN
:
1032 GetPrefs()->SetString(prefs::kApplicationLocale
, new_locale
);
1033 local_state
->SetString(prefs::kApplicationLocale
, new_locale
);
1035 if (chromeos::UserManager::Get()->IsCurrentUserOwner())
1036 local_state
->SetString(prefs::kOwnerLocale
, new_locale
);
1039 void ProfileImpl::OnLogin() {
1040 if (locale_change_guard_
== NULL
)
1041 locale_change_guard_
.reset(new chromeos::LocaleChangeGuard(this));
1042 locale_change_guard_
->OnLogin();
1045 void ProfileImpl::SetupChromeOSEnterpriseExtensionObserver() {
1046 DCHECK(!chromeos_enterprise_extension_observer_
.get());
1047 chromeos_enterprise_extension_observer_
.reset(
1048 new chromeos::EnterpriseExtensionObserver(this));
1051 void ProfileImpl::InitChromeOSPreferences() {
1052 chromeos_preferences_
.reset(new chromeos::Preferences());
1053 chromeos_preferences_
->Init(GetPrefs());
1055 #endif // defined(OS_CHROMEOS)
1057 PrefProxyConfigTracker
* ProfileImpl::GetProxyConfigTracker() {
1058 if (!pref_proxy_config_tracker_
.get()) {
1059 pref_proxy_config_tracker_
.reset(
1060 ProxyServiceFactory::CreatePrefProxyConfigTracker(GetPrefs()));
1062 return pref_proxy_config_tracker_
.get();
1065 chrome_browser_net::Predictor
* ProfileImpl::GetNetworkPredictor() {
1069 void ProfileImpl::ClearNetworkingHistorySince(base::Time time
,
1070 const base::Closure
& completion
) {
1071 io_data_
.ClearNetworkingHistorySince(time
, completion
);
1074 GURL
ProfileImpl::GetHomePage() {
1075 // --homepage overrides any preferences.
1076 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
1077 if (command_line
.HasSwitch(switches::kHomePage
)) {
1078 // TODO(evanm): clean up usage of DIR_CURRENT.
1079 // http://code.google.com/p/chromium/issues/detail?id=60630
1080 // For now, allow this code to call getcwd().
1081 base::ThreadRestrictions::ScopedAllowIO allow_io
;
1083 FilePath browser_directory
;
1084 PathService::Get(base::DIR_CURRENT
, &browser_directory
);
1085 GURL
home_page(URLFixerUpper::FixupRelativeFile(browser_directory
,
1086 command_line
.GetSwitchValuePath(switches::kHomePage
)));
1087 if (home_page
.is_valid())
1091 if (GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage
))
1092 return GURL(chrome::kChromeUINewTabURL
);
1093 GURL
home_page(URLFixerUpper::FixupURL(
1094 GetPrefs()->GetString(prefs::kHomePage
),
1096 if (!home_page
.is_valid())
1097 return GURL(chrome::kChromeUINewTabURL
);
1101 void ProfileImpl::UpdateProfileUserNameCache() {
1102 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1103 ProfileInfoCache
& cache
= profile_manager
->GetProfileInfoCache();
1104 size_t index
= cache
.GetIndexOfProfileWithPath(GetPath());
1105 if (index
!= std::string::npos
) {
1106 std::string user_name
=
1107 GetPrefs()->GetString(prefs::kGoogleServicesUsername
);
1108 cache
.SetUserNameOfProfileAtIndex(index
, UTF8ToUTF16(user_name
));
1112 void ProfileImpl::UpdateProfileNameCache() {
1113 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1114 ProfileInfoCache
& cache
= profile_manager
->GetProfileInfoCache();
1115 size_t index
= cache
.GetIndexOfProfileWithPath(GetPath());
1116 if (index
!= std::string::npos
) {
1117 std::string profile_name
=
1118 GetPrefs()->GetString(prefs::kProfileName
);
1119 cache
.SetNameOfProfileAtIndex(index
, UTF8ToUTF16(profile_name
));
1123 void ProfileImpl::UpdateProfileAvatarCache() {
1124 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1125 ProfileInfoCache
& cache
= profile_manager
->GetProfileInfoCache();
1126 size_t index
= cache
.GetIndexOfProfileWithPath(GetPath());
1127 if (index
!= std::string::npos
) {
1128 size_t avatar_index
=
1129 GetPrefs()->GetInteger(prefs::kProfileAvatarIndex
);
1130 cache
.SetAvatarIconOfProfileAtIndex(index
, avatar_index
);
1134 // Gets the cache parameters from the command line. If |is_media_context| is
1135 // set to true then settings for the media context type is what we need,
1136 // |cache_path| will be set to the user provided path, or will not be touched if
1137 // there is not an argument. |max_size| will be the user provided value or zero
1139 void ProfileImpl::GetCacheParameters(bool is_media_context
,
1140 FilePath
* cache_path
,
1144 FilePath
path(prefs_
->GetFilePath(prefs::kDiskCacheDir
));
1147 *max_size
= is_media_context
? prefs_
->GetInteger(prefs::kMediaCacheSize
) :
1148 prefs_
->GetInteger(prefs::kDiskCacheSize
);
1151 base::Callback
<ChromeURLDataManagerBackend
*(void)>
1152 ProfileImpl::GetChromeURLDataManagerBackendGetter() const {
1153 return io_data_
.GetChromeURLDataManagerBackendGetter();