Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / profiles / profile_impl.cc
blob728a900b7f5b3fd7e12aaf768d90c60bdae61b2f
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"
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/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"
96 #else
97 #include "chrome/browser/policy/policy_service_stub.h"
98 #endif // defined(ENABLE_CONFIGURATION_POLICY)
100 #if defined(OS_WIN)
101 #include "chrome/installer/util/install_util.h"
102 #endif
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"
110 #endif
112 using base::Time;
113 using base::TimeDelta;
114 using content::BrowserThread;
115 using content::DownloadManagerDelegate;
116 using content::HostZoomMap;
117 using content::UserMetricsAction;
119 namespace {
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);
136 #endif
138 #if defined(ENABLE_SESSION_SERVICE)
139 // Delay, in milliseconds, before we explicitly create the SessionService.
140 static const int kCreateSessionServiceDelayMS = 500;
141 #endif
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
145 // not in resources.
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,
177 path,
178 done_creating));
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))
198 return;
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) {
219 switch (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;
227 NOTREACHED();
228 return std::string();
231 } // namespace
233 // static
234 Profile* Profile::CreateProfile(const FilePath& path,
235 Delegate* delegate,
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) {
244 DCHECK(delegate);
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
250 // situation.
251 if (!file_util::CreateDirectory(path))
252 return NULL;
254 } else {
255 NOTREACHED();
258 return new ProfileImpl(path, delegate, create_mode, sequenced_task_runner);
261 // static
262 int ProfileImpl::create_readme_delay_ms = 60000;
264 // static
265 const char* const ProfileImpl::kPrefExitTypeNormal = "Normal";
267 // static
268 void ProfileImpl::RegisterUserPrefs(PrefService* prefs) {
269 prefs->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled,
270 false,
271 PrefService::UNSYNCABLE_PREF);
272 prefs->RegisterBooleanPref(prefs::kForceSafeSearch,
273 false,
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,
282 std::string(),
283 PrefService::SYNCABLE_PREF);
284 #if defined(ENABLE_PRINTING)
285 prefs->RegisterBooleanPref(prefs::kPrintingEnabled,
286 true,
287 PrefService::UNSYNCABLE_PREF);
288 #endif
289 prefs->RegisterBooleanPref(prefs::kPrintPreviewDisabled,
290 #if defined(GOOGLE_CHROME_BUILD)
291 false,
292 #else
293 true,
294 #endif
295 PrefService::UNSYNCABLE_PREF);
297 // Initialize the cache prefs.
298 prefs->RegisterFilePathPref(prefs::kDiskCacheDir,
299 FilePath(),
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,
310 false,
311 PrefService::SYNCABLE_PREF);
314 ProfileImpl::ProfileImpl(
315 const FilePath& path,
316 Delegate* delegate,
317 CreateMode create_mode,
318 base::SequencedTaskRunner* sequenced_task_runner)
319 : path_(path),
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()),
324 delegate_(delegate),
325 predictor_(NULL) {
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);
333 #endif
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
346 // values).
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);
356 #else
357 policy_service_.reset(new policy::PolicyServiceStub());
358 #endif
360 if (create_mode == CREATE_MODE_ASYNCHRONOUS) {
361 prefs_.reset(PrefService::CreatePrefService(
362 GetPrefFilePath(),
363 sequenced_task_runner,
364 policy_service_.get(),
365 new ExtensionPrefStore(
366 ExtensionPrefValueMapFactory::GetForProfile(this), false),
367 true));
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
371 // the same thread.
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(
377 GetPrefFilePath(),
378 sequenced_task_runner,
379 policy_service_.get(),
380 new ExtensionPrefStore(
381 ExtensionPrefValueMapFactory::GetForProfile(this), false),
382 false));
383 OnPrefsLoaded(true);
384 } else {
385 NOTREACHED();
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
399 // to PathService.
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));
418 #endif
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;
433 #endif
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_;
445 int cache_max_size;
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();
465 #else
466 SessionStartupPref::Type startup_pref_type =
467 StartupBrowserCreator::GetSessionStartupPref(
468 *CommandLine::ForCurrentProcess(), this).type;
469 #endif
470 bool restore_old_session_cookies =
471 (GetLastSessionExitType() == Profile::EXIT_CRASHED ||
472 startup_pref_type == SessionStartupPref::LAST);
474 InitHostZoomMap();
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,
482 predictor_,
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.
505 if (delegate_)
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(
529 host, &zoom_level);
530 DCHECK(success);
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_)
541 return;
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();
562 #endif
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());
574 } else {
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();
595 #endif
597 // This causes the Preferences file to be written to disk.
598 if (prefs_loaded)
599 SetExitType(EXIT_NORMAL);
602 std::string ProfileImpl::GetProfileName() {
603 return GetPrefs()->GetString(prefs::kGoogleServicesUsername);
606 FilePath ProfileImpl::GetPath() {
607 return path_;
610 scoped_refptr<base::SequencedTaskRunner> ProfileImpl::GetIOTaskRunner() {
611 return JsonPrefStore::GetTaskRunnerForFile(
612 GetPath(), BrowserThread::GetBlockingPool());
615 bool ProfileImpl::IsOffTheRecord() const {
616 return false;
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() {
643 return this;
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) {
660 if (!success) {
661 if (delegate_)
662 delegate_->OnProfileCreated(this, false, false);
663 return;
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;
682 } else {
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(
696 prefs_.get(),
697 prerender::PrerenderManagerFactory::GetForProfile(this),
698 predictor_));
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) {
713 if (!prefs_)
714 return;
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.
733 GetPrefs();
734 return last_session_exit_type_;
737 policy::UserCloudPolicyManager* ProfileImpl::GetUserCloudPolicyManager() {
738 #if defined(ENABLE_CONFIGURATION_POLICY)
739 return cloud_policy_manager_.get();
740 #else
741 return NULL;
742 #endif
745 policy::ManagedModePolicyProvider* ProfileImpl::GetManagedModePolicyProvider() {
746 #if defined(ENABLE_CONFIGURATION_POLICY)
747 return managed_mode_policy_provider_.get();
748 #else
749 return NULL;
750 #endif
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.
760 return prefs_.get();
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(
787 renderer_child_id);
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(
801 renderer_child_id);
802 content::StoragePartition* storage_partition = rph->GetStoragePartition();
804 return storage_partition->GetMediaURLRequestContext();
807 net::URLRequestContextGetter*
808 ProfileImpl::GetMediaRequestContextForStoragePartition(
809 const FilePath& partition_path,
810 bool in_memory) {
811 return io_data_.GetIsolatedMediaRequestContextGetter(partition_path,
812 in_memory);
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,
825 bool in_memory) {
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);
853 #else
854 return NULL;
855 #endif
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))
885 return true;
886 Profile* otr_profile = off_the_record_profile_.get();
887 return otr_profile && profile == otr_profile;
890 Time ProfileImpl::GetStartTime() const {
891 return start_time_;
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));
899 return top_sites_;
902 history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() {
903 return top_sites_;
906 void ProfileImpl::Observe(int type,
907 const content::NotificationSource& source,
908 const content::NotificationDetails& details) {
909 switch (type) {
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));
915 break;
916 case content::NOTIFICATION_ZOOM_LEVEL_CHANGED: {
917 const std::string& host =
918 *(content::Details<const std::string>(details).ptr());
919 if (!host.empty()) {
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);
926 } else {
927 host_zoom_dictionary->SetWithoutPathExpansion(
928 host, Value::CreateDoubleValue(level));
931 break;
933 default:
934 NOTREACHED();
938 void ProfileImpl::OnPreferenceChanged(PrefServiceBase* prefs,
939 const std::string& pref_name_in) {
940 DCHECK(prefs);
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);
961 #endif
963 #if defined(OS_CHROMEOS)
964 void ProfileImpl::ChangeAppLocale(
965 const std::string& new_locale, AppLocaleChangedVia via) {
966 if (new_locale.empty()) {
967 NOTREACHED();
968 return;
970 PrefService* local_state = g_browser_process->local_state();
971 DCHECK(local_state);
972 if (local_state->IsManagedPreference(prefs::kApplicationLocale))
973 return;
974 std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale);
975 bool do_update_pref = true;
976 switch (via) {
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.
988 break;
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);
1001 } else {
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);
1009 } else {
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;
1023 break;
1025 case APP_LOCALE_CHANGED_VIA_UNKNOWN:
1026 default: {
1027 NOTREACHED();
1028 break;
1031 if (do_update_pref)
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() {
1066 return predictor_;
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())
1088 return home_page;
1091 if (GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
1092 return GURL(chrome::kChromeUINewTabURL);
1093 GURL home_page(URLFixerUpper::FixupURL(
1094 GetPrefs()->GetString(prefs::kHomePage),
1095 std::string()));
1096 if (!home_page.is_valid())
1097 return GURL(chrome::kChromeUINewTabURL);
1098 return home_page;
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
1138 // by default.
1139 void ProfileImpl::GetCacheParameters(bool is_media_context,
1140 FilePath* cache_path,
1141 int* max_size) {
1142 DCHECK(cache_path);
1143 DCHECK(max_size);
1144 FilePath path(prefs_->GetFilePath(prefs::kDiskCacheDir));
1145 if (!path.empty())
1146 *cache_path = path;
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();