1 // Copyright (c) 2011 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/command_line.h" 8 #include "base/compiler_specific.h" 9 #include "base/environment.h" 10 #include "base/file_path.h" 11 #include "base/file_util.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/metrics/histogram.h" 14 #include "base/path_service.h" 15 #include "base/string_number_conversions.h" 16 #include "base/string_util.h" 17 #include "chrome/browser/autocomplete/autocomplete_classifier.h" 18 #include "chrome/browser/autofill/personal_data_manager.h" 19 #include "chrome/browser/background_contents_service_factory.h" 20 #include "chrome/browser/background_mode_manager_factory.h" 21 #include "chrome/browser/bookmarks/bookmark_model.h" 22 #include "chrome/browser/browser_process.h" 23 #include "chrome/browser/browser_signin.h" 24 #include "chrome/browser/content_settings/host_content_settings_map.h" 25 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 26 #include "chrome/browser/defaults.h" 27 #include "chrome/browser/download/download_manager.h" 28 #include "chrome/browser/extensions/extension_devtools_manager.h" 29 #include "chrome/browser/extensions/extension_error_reporter.h" 30 #include "chrome/browser/extensions/extension_event_router.h" 31 #include "chrome/browser/extensions/extension_info_map.h" 32 #include "chrome/browser/extensions/extension_message_service.h" 33 #include "chrome/browser/extensions/extension_pref_store.h" 34 #include "chrome/browser/extensions/extension_process_manager.h" 35 #include "chrome/browser/extensions/extension_service.h" 36 #include "chrome/browser/extensions/extension_special_storage_policy.h" 37 #include "chrome/browser/extensions/user_script_master.h" 38 #include "chrome/browser/favicon_service.h" 39 #include "chrome/browser/geolocation/geolocation_content_settings_map.h" 40 #include "chrome/browser/history/history.h" 41 #include "chrome/browser/history/top_sites.h" 42 #include "chrome/browser/instant/instant_controller.h" 43 #include "chrome/browser/metrics/user_metrics.h" 44 #include "chrome/browser/net/chrome_url_request_context.h" 45 #include "chrome/browser/net/gaia/token_service.h" 46 #include "chrome/browser/net/net_pref_observer.h" 47 #include "chrome/browser/net/pref_proxy_config_service.h" 48 #include "chrome/browser/net/ssl_config_service_manager.h" 49 #include "chrome/browser/password_manager/password_store_default.h" 50 #include "chrome/browser/policy/configuration_policy_pref_store.h" 51 #include "chrome/browser/policy/configuration_policy_provider.h" 52 #include "chrome/browser/policy/profile_policy_connector.h" 53 #include "chrome/browser/prefs/browser_prefs.h" 54 #include "chrome/browser/prefs/pref_value_store.h" 55 #include "chrome/browser/prerender/prerender_manager.h" 56 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" 57 #include "chrome/browser/profiles/profile_dependency_manager.h" 58 #include "chrome/browser/profiles/profile_manager.h" 59 #include "chrome/browser/search_engines/template_url_fetcher.h" 60 #include "chrome/browser/search_engines/template_url_model.h" 61 #include "chrome/browser/sessions/session_service.h" 62 #include "chrome/browser/sessions/tab_restore_service.h" 63 #include "chrome/browser/spellcheck_host.h" 64 #include "chrome/browser/ssl/ssl_host_state.h" 65 #include "chrome/browser/status_icons/status_tray.h" 66 #include "chrome/browser/sync/profile_sync_factory_impl.h" 67 #include "chrome/browser/sync/profile_sync_service.h" 68 #include "chrome/browser/tabs/pinned_tab_service_factory.h" 69 #include "chrome/browser/transport_security_persister.h" 70 #include "chrome/browser/ui/browser_list.h" 71 #include "chrome/browser/ui/find_bar/find_bar_state.h" 72 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" 73 #include "chrome/browser/ui/webui/extension_icon_source.h" 74 #include "chrome/browser/ui/webui/ntp_resource_cache.h" 75 #include "chrome/browser/user_style_sheet_watcher.h" 76 #include "chrome/browser/visitedlink/visitedlink_event_listener.h" 77 #include "chrome/browser/visitedlink/visitedlink_master.h" 78 #include "chrome/browser/web_resource/promo_resource_service.h" 79 #include "chrome/browser/webdata/web_data_service.h" 80 #include "chrome/common/chrome_constants.h" 81 #include "chrome/common/chrome_paths.h" 82 #include "chrome/common/chrome_paths_internal.h" 83 #include "chrome/common/chrome_switches.h" 84 #include "chrome/common/json_pref_store.h" 85 #include "chrome/common/pref_names.h" 86 #include "chrome/common/render_messages.h" 87 #include "content/browser/appcache/chrome_appcache_service.h" 88 #include "content/browser/browser_thread.h" 89 #include "content/browser/chrome_blob_storage_context.h" 90 #include "content/browser/file_system/browser_file_system_helper.h" 91 #include "content/browser/geolocation/geolocation_permission_context.h" 92 #include "content/browser/host_zoom_map.h" 93 #include "content/browser/in_process_webkit/webkit_context.h" 94 #include "content/browser/renderer_host/render_process_host.h" 95 #include "content/common/notification_service.h" 96 #include "grit/browser_resources.h" 97 #include "grit/locale_settings.h" 98 #include "net/base/transport_security_state.h" 99 #include "ui/base/resource/resource_bundle.h" 100 #include "webkit/database/database_tracker.h" 101 102 #if defined(OS_WIN) 103 #include "chrome/browser/instant/promo_counter.h" 104 #include "chrome/browser/password_manager/password_store_win.h" 105 #include "chrome/installer/util/install_util.h" 106 #elif defined(OS_MACOSX) 107 #include "chrome/browser/keychain_mac.h" 108 #include "chrome/browser/password_manager/password_store_mac.h" 109 #elif defined(OS_CHROMEOS) 110 #include "chrome/browser/chromeos/enterprise_extension_observer.h" 111 #elif defined(OS_POSIX) && !defined(OS_CHROMEOS) 112 #include "base/nix/xdg_util.h" 113 #if defined(USE_GNOME_KEYRING) 114 #include "chrome/browser/password_manager/native_backend_gnome_x.h" 115 #endif 116 #include "chrome/browser/password_manager/native_backend_kwallet_x.h" 117 #include "chrome/browser/password_manager/password_store_x.h" 118 #endif 119 120 #if defined(OS_CHROMEOS) 121 #include "chrome/browser/chromeos/locale_change_guard.h" 122 #include "chrome/browser/chromeos/login/user_manager.h" 123 #include "chrome/browser/chromeos/preferences.h" 124 #endif 125 126 using base::Time; 127 using base::TimeDelta; 128 129 namespace { 130 131 // Delay, in milliseconds, before we explicitly create the SessionService. 132 static const int kCreateSessionServiceDelayMS = 500; 133 134 enum ContextType { 135 kNormalContext, 136 kMediaContext 137 }; 138 139 // Gets the cache parameters from the command line. |type| is the type of 140 // request context that we need, |cache_path| will be set to the user provided 141 // path, or will not be touched if there is not an argument. |max_size| will 142 // be the user provided value or zero by default. 143 void GetCacheParameters(ContextType type, FilePath* cache_path, 144 int* max_size) { 145 DCHECK(cache_path); 146 DCHECK(max_size); 147 148 // Override the cache location if specified by the user. 149 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDiskCacheDir)) { 150 *cache_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( 151 switches::kDiskCacheDir); 152 } 153 154 const char* arg = kNormalContext == type ? switches::kDiskCacheSize : 155 switches::kMediaCacheSize; 156 std::string value = 157 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(arg); 158 159 // By default we let the cache determine the right size. 160 *max_size = 0; 161 if (!base::StringToInt(value, max_size)) { 162 *max_size = 0; 163 } else if (max_size < 0) { 164 *max_size = 0; 165 } 166 } 167 168 FilePath GetCachePath(const FilePath& base) { 169 return base.Append(chrome::kCacheDirname); 170 } 171 172 FilePath GetMediaCachePath(const FilePath& base) { 173 return base.Append(chrome::kMediaCacheDirname); 174 } 175 176 // Simple task to log the size of the current profile. 177 class ProfileSizeTask : public Task { 178 public: 179 explicit ProfileSizeTask(const FilePath& path) : path_(path) {} 180 virtual ~ProfileSizeTask() {} 181 182 virtual void Run(); 183 private: 184 FilePath path_; 185 }; 186 187 void ProfileSizeTask::Run() { 188 int64 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("*")); 189 int size_MB = static_cast<int>(size / (1024 * 1024)); 190 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB); 191 192 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("History")); 193 size_MB = static_cast<int>(size / (1024 * 1024)); 194 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB); 195 196 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("History*")); 197 size_MB = static_cast<int>(size / (1024 * 1024)); 198 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB); 199 200 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Cookies")); 201 size_MB = static_cast<int>(size / (1024 * 1024)); 202 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB); 203 204 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Bookmarks")); 205 size_MB = static_cast<int>(size / (1024 * 1024)); 206 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB); 207 208 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Favicons")); 209 size_MB = static_cast<int>(size / (1024 * 1024)); 210 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB); 211 212 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Top Sites")); 213 size_MB = static_cast<int>(size / (1024 * 1024)); 214 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB); 215 216 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Visited Links")); 217 size_MB = static_cast<int>(size / (1024 * 1024)); 218 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB); 219 220 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Web Data")); 221 size_MB = static_cast<int>(size / (1024 * 1024)); 222 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB); 223 224 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Extension*")); 225 size_MB = static_cast<int>(size / (1024 * 1024)); 226 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB); 227 } 228 229 } // namespace 230 231 // static 232 Profile* Profile::CreateProfile(const FilePath& path) { 233 if (!file_util::PathExists(path)) { 234 // TODO(tc): http://b/1094718 Bad things happen if we can't write to the 235 // profile directory. We should eventually be able to run in this 236 // situation. 237 if (!file_util::CreateDirectory(path)) 238 return NULL; 239 } 240 return new ProfileImpl(path, NULL); 241 } 242 243 // static 244 Profile* Profile::CreateProfileAsync(const FilePath&path, 245 Profile::Delegate* delegate) { 246 DCHECK(delegate); 247 // This is safe while all file opeartions are done on the FILE thread. 248 BrowserThread::PostTask(BrowserThread::FILE, 249 FROM_HERE, 250 NewRunnableFunction(&file_util::CreateDirectory, 251 path)); 252 // Async version. 253 return new ProfileImpl(path, delegate); 254 } 255 256 // static 257 void ProfileImpl::RegisterUserPrefs(PrefService* prefs) { 258 prefs->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false); 259 prefs->RegisterBooleanPref(prefs::kClearSiteDataOnExit, false); 260 } 261 262 ProfileImpl::ProfileImpl(const FilePath& path, 263 Profile::Delegate* delegate) 264 : path_(path), 265 visited_link_event_listener_(new VisitedLinkEventListener()), 266 extension_devtools_manager_(NULL), 267 ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)), 268 host_content_settings_map_(NULL), 269 host_zoom_map_(NULL), 270 history_service_created_(false), 271 favicon_service_created_(false), 272 created_web_data_service_(false), 273 created_password_store_(false), 274 created_download_manager_(false), 275 start_time_(Time::Now()), 276 spellcheck_host_(NULL), 277 spellcheck_host_ready_(false), 278 #if defined(OS_WIN) 279 checked_instant_promo_(false), 280 #endif 281 shutdown_session_service_(false), 282 delegate_(delegate) { 283 DCHECK(!path.empty()) << "Using an empty path will attempt to write " << 284 "profile files to the root directory!"; 285 create_session_service_timer_.Start( 286 TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this, 287 &ProfileImpl::EnsureSessionServiceCreated); 288 289 if (delegate_) { 290 prefs_.reset(PrefService::CreatePrefServiceAsync( 291 GetPrefFilePath(), 292 new ExtensionPrefStore(GetExtensionPrefValueMap(), false), 293 GetOriginalProfile(), 294 this)); // Ask to notify us in the end. 295 } else { 296 // Load prefs synchronously. 297 prefs_.reset(PrefService::CreatePrefService( 298 GetPrefFilePath(), 299 new ExtensionPrefStore(GetExtensionPrefValueMap(), false), 300 GetOriginalProfile())); 301 OnPrefsLoaded(prefs_.get(), true); 302 } 303 } 304 305 void ProfileImpl::DoFinalInit() { 306 PrefService* prefs = GetPrefs(); 307 pref_change_registrar_.Init(prefs); 308 pref_change_registrar_.Add(prefs::kSpellCheckDictionary, this); 309 pref_change_registrar_.Add(prefs::kEnableSpellCheck, this); 310 pref_change_registrar_.Add(prefs::kEnableAutoSpellCorrect, this); 311 pref_change_registrar_.Add(prefs::kClearSiteDataOnExit, this); 312 313 // It would be nice to use PathService for fetching this directory, but 314 // the cache directory depends on the profile directory, which isn't available 315 // to PathService. 316 chrome::GetUserCacheDirectory(path_, &base_cache_path_); 317 if (!delegate_) { 318 file_util::CreateDirectory(base_cache_path_); 319 } else { 320 // Async profile loading is used, so call this on the FILE thread instead. 321 // It is safe since all other file operations should also be done there. 322 BrowserThread::PostTask(BrowserThread::FILE, 323 FROM_HERE, 324 NewRunnableFunction(&file_util::CreateDirectory, 325 base_cache_path_)); 326 } 327 328 #if !defined(OS_CHROMEOS) 329 // Listen for bookmark model load, to bootstrap the sync service. 330 // On CrOS sync service will be initialized after sign in. 331 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED, 332 Source<Profile>(this)); 333 #endif 334 335 PrefService* local_state = g_browser_process->local_state(); 336 ssl_config_service_manager_.reset( 337 SSLConfigServiceManager::CreateDefaultManager(GetPrefs(), local_state)); 338 339 PinnedTabServiceFactory::GetForProfile(this); 340 341 // Initialize the BackgroundModeManager - this has to be done here before 342 // InitExtensions() is called because it relies on receiving notifications 343 // when extensions are loaded. BackgroundModeManager is not needed under 344 // ChromeOS because Chrome is always running (no need for special keep-alive 345 // or launch-on-startup support). 346 #if !defined(OS_CHROMEOS) 347 BackgroundModeManagerFactory::GetForProfile(this); 348 #endif 349 350 BackgroundContentsServiceFactory::GetForProfile(this); 351 352 extension_info_map_ = new ExtensionInfoMap(); 353 354 InitRegisteredProtocolHandlers(); 355 356 clear_local_state_on_exit_ = prefs->GetBoolean(prefs::kClearSiteDataOnExit); 357 if (clear_local_state_on_exit_) { 358 UserMetrics::RecordAction( 359 UserMetricsAction("ClearSiteDataOnExitEnabled")); 360 } else { 361 UserMetrics::RecordAction( 362 UserMetricsAction("ClearSiteDataOnExitDisabled")); 363 } 364 365 // Log the profile size after a reasonable startup delay. 366 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, 367 new ProfileSizeTask(path_), 112000); 368 369 InstantController::RecordMetrics(this); 370 371 FilePath cookie_path = GetPath(); 372 cookie_path = cookie_path.Append(chrome::kCookieFilename); 373 FilePath cache_path = base_cache_path_; 374 int cache_max_size; 375 GetCacheParameters(kNormalContext, &cache_path, &cache_max_size); 376 cache_path = GetCachePath(cache_path); 377 378 FilePath media_cache_path = base_cache_path_; 379 int media_cache_max_size; 380 GetCacheParameters(kMediaContext, &media_cache_path, &media_cache_max_size); 381 media_cache_path = GetMediaCachePath(media_cache_path); 382 383 FilePath extensions_cookie_path = GetPath(); 384 extensions_cookie_path = 385 extensions_cookie_path.Append(chrome::kExtensionsCookieFilename); 386 387 FilePath app_path = GetPath().Append(chrome::kIsolatedAppStateDirname); 388 389 // Make sure we initialize the ProfileIOData after everything else has been 390 // initialized that we might be reading from the IO thread. 391 io_data_.Init(cookie_path, cache_path, cache_max_size, 392 media_cache_path, media_cache_max_size, extensions_cookie_path, 393 app_path); 394 395 // Initialize the ProfilePolicyConnector after |io_data_| since it requires 396 // the URLRequestContextGetter to be initialized. 397 GetPolicyConnector()->Initialize(); 398 399 // Creation has been finished. 400 if (delegate_) 401 delegate_->OnProfileCreated(this, true); 402 } 403 404 void ProfileImpl::InitExtensions(bool extensions_enabled) { 405 if (user_script_master_ || extensions_service_) 406 return; // Already initialized. 407 408 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 409 if (command_line->HasSwitch( 410 switches::kEnableExtensionTimelineApi)) { 411 extension_devtools_manager_ = new ExtensionDevToolsManager(this); 412 } 413 414 extension_process_manager_.reset(ExtensionProcessManager::Create(this)); 415 extension_event_router_.reset(new ExtensionEventRouter(this)); 416 extension_message_service_ = new ExtensionMessageService(this); 417 418 ExtensionErrorReporter::Init(true); // allow noisy errors. 419 420 FilePath script_dir; // Don't look for user scripts in any directory. 421 // TODO(aa): We should just remove this functionality, 422 // since it isn't used anymore. 423 user_script_master_ = new UserScriptMaster(script_dir, this); 424 425 bool autoupdate_enabled = true; 426 #if defined(OS_CHROMEOS) 427 if (!extensions_enabled) 428 autoupdate_enabled = false; 429 else 430 autoupdate_enabled = !command_line->HasSwitch(switches::kGuestSession); 431 #endif 432 extensions_service_ = new ExtensionService( 433 this, 434 CommandLine::ForCurrentProcess(), 435 GetPath().AppendASCII(ExtensionService::kInstallDirectoryName), 436 extension_prefs_.get(), 437 autoupdate_enabled, 438 extensions_enabled); 439 440 RegisterComponentExtensions(); 441 extensions_service_->Init(); 442 443 if (extensions_enabled) { 444 // Load any extensions specified with --load-extension. 445 if (command_line->HasSwitch(switches::kLoadExtension)) { 446 FilePath path = command_line->GetSwitchValuePath( 447 switches::kLoadExtension); 448 extensions_service_->LoadExtension(path); 449 } 450 } 451 452 // Make the chrome://extension-icon/ resource available. 453 GetChromeURLDataManager()->AddDataSource(new ExtensionIconSource(this)); 454 } 455 456 void ProfileImpl::RegisterComponentExtensions() { 457 // Register the component extensions. 458 // 459 // Component extension manifest must contain a 'key' property with a unique 460 // public key, serialized in base64. You can create a suitable value with the 461 // following commands on a unixy system: 462 // 463 // ssh-keygen -t rsa -b 1024 -N '' -f /tmp/key.pem 464 // openssl rsa -pubout -outform DER < /tmp/key.pem 2>/dev/null | base64 -w 0 465 typedef std::list<std::pair<FilePath::StringType, int> > 466 ComponentExtensionList; 467 ComponentExtensionList component_extensions; 468 469 // Bookmark manager. 470 component_extensions.push_back(std::make_pair( 471 FILE_PATH_LITERAL("bookmark_manager"), 472 IDR_BOOKMARKS_MANIFEST)); 473 474 #if defined(FILE_MANAGER_EXTENSION) 475 #if defined(OS_CHROMEOS) 476 if (!CommandLine::ForCurrentProcess()->HasSwitch( 477 switches::kSkipChromeOSComponents)) { 478 #endif 479 component_extensions.push_back(std::make_pair( 480 FILE_PATH_LITERAL("file_manager"), 481 IDR_FILEMANAGER_MANIFEST)); 482 #if defined(OS_CHROMEOS) 483 } 484 #endif 485 #endif 486 487 #if defined(TOUCH_UI) 488 component_extensions.push_back(std::make_pair( 489 FILE_PATH_LITERAL("keyboard"), 490 IDR_KEYBOARD_MANIFEST)); 491 #endif 492 493 #if defined(OS_CHROMEOS) 494 if (!CommandLine::ForCurrentProcess()->HasSwitch( 495 switches::kSkipChromeOSComponents)) { 496 component_extensions.push_back(std::make_pair( 497 FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile"), 498 IDR_MOBILE_MANIFEST)); 499 500 #if defined(OFFICIAL_BUILD) 501 if (browser_defaults::enable_help_app) { 502 component_extensions.push_back(std::make_pair( 503 FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp"), 504 IDR_HELP_MANIFEST)); 505 } 506 #endif 507 } 508 #endif 509 510 // Web Store. 511 component_extensions.push_back(std::make_pair( 512 FILE_PATH_LITERAL("web_store"), 513 IDR_WEBSTORE_MANIFEST)); 514 515 for (ComponentExtensionList::iterator iter = component_extensions.begin(); 516 iter != component_extensions.end(); ++iter) { 517 FilePath path(iter->first); 518 if (!path.IsAbsolute()) { 519 if (PathService::Get(chrome::DIR_RESOURCES, &path)) { 520 path = path.Append(iter->first); 521 } else { 522 NOTREACHED(); 523 } 524 } 525 526 std::string manifest = 527 ResourceBundle::GetSharedInstance().GetRawDataResource( 528 iter->second).as_string(); 529 extensions_service_->register_component_extension( 530 ExtensionService::ComponentExtensionInfo(manifest, path)); 531 } 532 533 #if defined(OS_CHROMEOS) 534 // Register access extensions only if accessibility is enabled. 535 if (g_browser_process->local_state()-> 536 GetBoolean(prefs::kAccessibilityEnabled)) { 537 FilePath path = FilePath(extension_misc::kAccessExtensionPath) 538 .AppendASCII("access_chromevox"); 539 std::string manifest = 540 ResourceBundle::GetSharedInstance().GetRawDataResource( 541 IDR_CHROMEVOX_MANIFEST).as_string(); 542 extensions_service_->register_component_extension( 543 ExtensionService::ComponentExtensionInfo(manifest, path)); 544 } 545 #endif 546 } 547 548 void ProfileImpl::InitPromoResources() { 549 if (promo_resource_service_) 550 return; 551 552 promo_resource_service_ = new PromoResourceService(this); 553 promo_resource_service_->StartAfterDelay(); 554 } 555 556 void ProfileImpl::InitRegisteredProtocolHandlers() { 557 if (protocol_handler_registry_) 558 return; 559 protocol_handler_registry_ = new ProtocolHandlerRegistry(this); 560 protocol_handler_registry_->Load(); 561 } 562 563 NTPResourceCache* ProfileImpl::GetNTPResourceCache() { 564 if (!ntp_resource_cache_.get()) 565 ntp_resource_cache_.reset(new NTPResourceCache(this)); 566 return ntp_resource_cache_.get(); 567 } 568 569 FilePath ProfileImpl::last_selected_directory() { 570 return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory); 571 } 572 573 void ProfileImpl::set_last_selected_directory(const FilePath& path) { 574 GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, path); 575 } 576 577 ProfileImpl::~ProfileImpl() { 578 NotificationService::current()->Notify( 579 NotificationType::PROFILE_DESTROYED, 580 Source<Profile>(this), 581 NotificationService::NoDetails()); 582 583 GetPolicyConnector()->Shutdown(); 584 585 ProfileDependencyManager::GetInstance()->DestroyProfileServices(this); 586 587 tab_restore_service_ = NULL; 588 589 StopCreateSessionServiceTimer(); 590 // TemplateURLModel schedules a task on the WebDataService from its 591 // destructor. Delete it first to ensure the task gets scheduled before we 592 // shut down the database. 593 template_url_model_.reset(); 594 595 // DownloadManager is lazily created, so check before accessing it. 596 if (download_manager_.get()) { 597 // The download manager queries the history system and should be shut down 598 // before the history is shut down so it can properly cancel all requests. 599 download_manager_->Shutdown(); 600 download_manager_ = NULL; 601 } 602 603 // Remove pref observers 604 pref_change_registrar_.RemoveAll(); 605 606 // Delete the NTP resource cache so we can unregister pref observers. 607 ntp_resource_cache_.reset(); 608 609 // The sync service needs to be deleted before the services it calls. 610 sync_service_.reset(); 611 612 // Password store uses WebDB, shut it down before the WebDB has been shutdown. 613 if (password_store_.get()) 614 password_store_->Shutdown(); 615 616 // Both HistoryService and WebDataService maintain threads for background 617 // processing. Its possible each thread still has tasks on it that have 618 // increased the ref count of the service. In such a situation, when we 619 // decrement the refcount, it won't be 0, and the threads/databases aren't 620 // properly shut down. By explicitly calling Cleanup/Shutdown we ensure the 621 // databases are properly closed. 622 if (web_data_service_.get()) 623 web_data_service_->Shutdown(); 624 625 if (top_sites_.get()) 626 top_sites_->Shutdown(); 627 628 if (history_service_.get()) 629 history_service_->Cleanup(); 630 631 if (spellcheck_host_.get()) 632 spellcheck_host_->UnsetObserver(); 633 634 if (io_data_.HasMainRequestContext() && 635 default_request_context_ == GetRequestContext()) { 636 default_request_context_ = NULL; 637 } 638 639 // HistoryService may call into the BookmarkModel, as such we need to 640 // delete HistoryService before the BookmarkModel. The destructor for 641 // HistoryService will join with HistoryService's backend thread so that 642 // by the time the destructor has finished we're sure it will no longer call 643 // into the BookmarkModel. 644 history_service_ = NULL; 645 bookmark_bar_model_.reset(); 646 647 // FaviconService depends on HistoryServce so make sure we delete 648 // HistoryService first. 649 favicon_service_ = NULL; 650 651 if (extension_message_service_) 652 extension_message_service_->DestroyingProfile(); 653 654 if (extensions_service_) 655 extensions_service_->DestroyingProfile(); 656 657 if (pref_proxy_config_tracker_) 658 pref_proxy_config_tracker_->DetachFromPrefService(); 659 660 // This causes the Preferences file to be written to disk. 661 MarkAsCleanShutdown(); 662 } 663 664 ProfileId ProfileImpl::GetRuntimeId() { 665 return reinterpret_cast<ProfileId>(this); 666 } 667 668 FilePath ProfileImpl::GetPath() { 669 return path_; 670 } 671 672 bool ProfileImpl::IsOffTheRecord() { 673 return false; 674 } 675 676 Profile* ProfileImpl::GetOffTheRecordProfile() { 677 if (!off_the_record_profile_.get()) { 678 scoped_ptr<Profile> p(CreateOffTheRecordProfile()); 679 off_the_record_profile_.swap(p); 680 681 NotificationService::current()->Notify( 682 NotificationType::OTR_PROFILE_CREATED, 683 Source<Profile>(off_the_record_profile_.get()), 684 NotificationService::NoDetails()); 685 } 686 return off_the_record_profile_.get(); 687 } 688 689 void ProfileImpl::DestroyOffTheRecordProfile() { 690 off_the_record_profile_.reset(); 691 } 692 693 bool ProfileImpl::HasOffTheRecordProfile() { 694 return off_the_record_profile_.get() != NULL; 695 } 696 697 Profile* ProfileImpl::GetOriginalProfile() { 698 return this; 699 } 700 701 ChromeAppCacheService* ProfileImpl::GetAppCacheService() { 702 if (!appcache_service_) { 703 appcache_service_ = new ChromeAppCacheService; 704 BrowserThread::PostTask( 705 BrowserThread::IO, FROM_HERE, 706 NewRunnableMethod( 707 appcache_service_.get(), 708 &ChromeAppCacheService::InitializeOnIOThread, 709 IsOffTheRecord() 710 ? FilePath() : GetPath().Append(chrome::kAppCacheDirname), 711 make_scoped_refptr(GetHostContentSettingsMap()), 712 make_scoped_refptr(GetExtensionSpecialStoragePolicy()), 713 clear_local_state_on_exit_)); 714 } 715 return appcache_service_; 716 } 717 718 webkit_database::DatabaseTracker* ProfileImpl::GetDatabaseTracker() { 719 if (!db_tracker_) { 720 db_tracker_ = new webkit_database::DatabaseTracker( 721 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy()); 722 } 723 return db_tracker_; 724 } 725 726 VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() { 727 if (!visited_link_master_.get()) { 728 scoped_ptr<VisitedLinkMaster> visited_links( 729 new VisitedLinkMaster(visited_link_event_listener_.get(), this)); 730 if (!visited_links->Init()) 731 return NULL; 732 visited_link_master_.swap(visited_links); 733 } 734 735 return visited_link_master_.get(); 736 } 737 738 ExtensionService* ProfileImpl::GetExtensionService() { 739 return extensions_service_.get(); 740 } 741 742 StatusTray* ProfileImpl::GetStatusTray() { 743 if (!status_tray_.get()) 744 status_tray_.reset(StatusTray::Create()); 745 return status_tray_.get(); 746 } 747 748 UserScriptMaster* ProfileImpl::GetUserScriptMaster() { 749 return user_script_master_.get(); 750 } 751 752 ExtensionDevToolsManager* ProfileImpl::GetExtensionDevToolsManager() { 753 return extension_devtools_manager_.get(); 754 } 755 756 ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() { 757 return extension_process_manager_.get(); 758 } 759 760 ExtensionMessageService* ProfileImpl::GetExtensionMessageService() { 761 return extension_message_service_.get(); 762 } 763 764 ExtensionEventRouter* ProfileImpl::GetExtensionEventRouter() { 765 return extension_event_router_.get(); 766 } 767 768 ExtensionSpecialStoragePolicy* 769 ProfileImpl::GetExtensionSpecialStoragePolicy() { 770 if (!extension_special_storage_policy_.get()) 771 extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy(); 772 return extension_special_storage_policy_.get(); 773 } 774 775 SSLHostState* ProfileImpl::GetSSLHostState() { 776 if (!ssl_host_state_.get()) 777 ssl_host_state_.reset(new SSLHostState()); 778 779 DCHECK(ssl_host_state_->CalledOnValidThread()); 780 return ssl_host_state_.get(); 781 } 782 783 net::TransportSecurityState* 784 ProfileImpl::GetTransportSecurityState() { 785 if (!transport_security_state_.get()) { 786 transport_security_state_ = new net::TransportSecurityState(); 787 transport_security_persister_ = 788 new TransportSecurityPersister(false /* read-write */); 789 transport_security_persister_->Initialize( 790 transport_security_state_.get(), path_); 791 } 792 793 return transport_security_state_.get(); 794 } 795 796 void ProfileImpl::OnPrefsLoaded(PrefService* prefs, bool success) { 797 DCHECK(prefs == prefs_.get()); 798 799 if (!success) { 800 DCHECK(delegate_); 801 delegate_->OnProfileCreated(this, false); 802 return; 803 } 804 805 // The Profile class and ProfileManager class may read some prefs so 806 // register known prefs as soon as possible. 807 Profile::RegisterUserPrefs(prefs_.get()); 808 browser::RegisterUserPrefs(prefs_.get()); 809 // TODO(mirandac): remove migration code after 6 months (crbug.com/69995). 810 if (g_browser_process->local_state()) { 811 browser::MigrateBrowserPrefs(prefs_.get(), 812 g_browser_process->local_state()); 813 } 814 815 // The last session exited cleanly if there is no pref for 816 // kSessionExitedCleanly or the value for kSessionExitedCleanly is true. 817 last_session_exited_cleanly_ = 818 prefs_->GetBoolean(prefs::kSessionExitedCleanly); 819 // Mark the session as open. 820 prefs_->SetBoolean(prefs::kSessionExitedCleanly, false); 821 // Make sure we save to disk that the session has opened. 822 prefs_->ScheduleSavePersistentPrefs(); 823 824 // Ensure that preferences set by extensions are restored in the profile 825 // as early as possible. The constructor takes care of that. 826 extension_prefs_.reset(new ExtensionPrefs( 827 prefs_.get(), 828 GetPath().AppendASCII(ExtensionService::kInstallDirectoryName), 829 GetExtensionPrefValueMap())); 830 831 DCHECK(!net_pref_observer_.get()); 832 net_pref_observer_.reset( 833 new NetPrefObserver(prefs_.get(), GetPrerenderManager())); 834 835 DoFinalInit(); 836 } 837 838 PrefService* ProfileImpl::GetPrefs() { 839 DCHECK(prefs_.get()); // Should explicitly be initialized. 840 return prefs_.get(); 841 } 842 843 PrefService* ProfileImpl::GetOffTheRecordPrefs() { 844 if (!otr_prefs_.get()) { 845 // The new ExtensionPrefStore is ref_counted and the new PrefService 846 // stores a reference so that we do not leak memory here. 847 otr_prefs_.reset(GetPrefs()->CreateIncognitoPrefService( 848 new ExtensionPrefStore(GetExtensionPrefValueMap(), true))); 849 } 850 return otr_prefs_.get(); 851 } 852 853 FilePath ProfileImpl::GetPrefFilePath() { 854 FilePath pref_file_path = path_; 855 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename); 856 return pref_file_path; 857 } 858 859 net::URLRequestContextGetter* ProfileImpl::GetRequestContext() { 860 net::URLRequestContextGetter* request_context = 861 io_data_.GetMainRequestContextGetter(); 862 // The first request context is always a normal (non-OTR) request context. 863 // Even when Chromium is started in OTR mode, a normal profile is always 864 // created first. 865 if (!default_request_context_) { 866 default_request_context_ = request_context; 867 request_context->set_is_main(true); 868 // TODO(eroman): this isn't terribly useful anymore now that the 869 // net::URLRequestContext is constructed by the IO thread... 870 NotificationService::current()->Notify( 871 NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, 872 NotificationService::AllSources(), NotificationService::NoDetails()); 873 } 874 875 return request_context; 876 } 877 878 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForPossibleApp( 879 const Extension* installed_app) { 880 if (CommandLine::ForCurrentProcess()->HasSwitch( 881 switches::kEnableExperimentalAppManifests) && 882 installed_app != NULL && 883 installed_app->is_storage_isolated()) 884 return GetRequestContextForIsolatedApp(installed_app->id()); 885 886 return GetRequestContext(); 887 } 888 889 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForMedia() { 890 return io_data_.GetMediaRequestContextGetter(); 891 } 892 893 const content::ResourceContext& ProfileImpl::GetResourceContext() { 894 return io_data_.GetResourceContext(); 895 } 896 897 FaviconService* ProfileImpl::GetFaviconService(ServiceAccessType sat) { 898 if (!favicon_service_created_) { 899 favicon_service_created_ = true; 900 scoped_refptr<FaviconService> service(new FaviconService(this)); 901 favicon_service_.swap(service); 902 } 903 return favicon_service_.get(); 904 } 905 906 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() { 907 return io_data_.GetExtensionsRequestContextGetter(); 908 } 909 910 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForIsolatedApp( 911 const std::string& app_id) { 912 return io_data_.GetIsolatedAppRequestContextGetter(app_id); 913 } 914 915 void ProfileImpl::RegisterExtensionWithRequestContexts( 916 const Extension* extension) { 917 BrowserThread::PostTask( 918 BrowserThread::IO, FROM_HERE, 919 NewRunnableMethod(extension_info_map_.get(), 920 &ExtensionInfoMap::AddExtension, 921 make_scoped_refptr(extension))); 922 } 923 924 void ProfileImpl::UnregisterExtensionWithRequestContexts( 925 const std::string& extension_id, 926 const UnloadedExtensionInfo::Reason reason) { 927 BrowserThread::PostTask( 928 BrowserThread::IO, FROM_HERE, 929 NewRunnableMethod(extension_info_map_.get(), 930 &ExtensionInfoMap::RemoveExtension, 931 extension_id, 932 reason)); 933 } 934 935 net::SSLConfigService* ProfileImpl::GetSSLConfigService() { 936 return ssl_config_service_manager_->Get(); 937 } 938 939 HostContentSettingsMap* ProfileImpl::GetHostContentSettingsMap() { 940 if (!host_content_settings_map_.get()) 941 host_content_settings_map_ = new HostContentSettingsMap(this); 942 return host_content_settings_map_.get(); 943 } 944 945 HostZoomMap* ProfileImpl::GetHostZoomMap() { 946 if (!host_zoom_map_) 947 host_zoom_map_ = new HostZoomMap(this); 948 return host_zoom_map_.get(); 949 } 950 951 GeolocationContentSettingsMap* ProfileImpl::GetGeolocationContentSettingsMap() { 952 if (!geolocation_content_settings_map_.get()) 953 geolocation_content_settings_map_ = new GeolocationContentSettingsMap(this); 954 return geolocation_content_settings_map_.get(); 955 } 956 957 GeolocationPermissionContext* ProfileImpl::GetGeolocationPermissionContext() { 958 if (!geolocation_permission_context_.get()) 959 geolocation_permission_context_ = new GeolocationPermissionContext(this); 960 return geolocation_permission_context_.get(); 961 } 962 963 UserStyleSheetWatcher* ProfileImpl::GetUserStyleSheetWatcher() { 964 if (!user_style_sheet_watcher_.get()) { 965 user_style_sheet_watcher_ = new UserStyleSheetWatcher(GetPath()); 966 user_style_sheet_watcher_->Init(); 967 } 968 return user_style_sheet_watcher_.get(); 969 } 970 971 FindBarState* ProfileImpl::GetFindBarState() { 972 if (!find_bar_state_.get()) { 973 find_bar_state_.reset(new FindBarState()); 974 } 975 return find_bar_state_.get(); 976 } 977 978 HistoryService* ProfileImpl::GetHistoryService(ServiceAccessType sat) { 979 // If saving history is disabled, only allow explicit access. 980 if (GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled) && 981 sat != EXPLICIT_ACCESS) 982 return NULL; 983 984 if (!history_service_created_) { 985 history_service_created_ = true; 986 scoped_refptr<HistoryService> history(new HistoryService(this)); 987 if (!history->Init(GetPath(), GetBookmarkModel())) 988 return NULL; 989 history_service_.swap(history); 990 991 // Send out the notification that the history service was created. 992 NotificationService::current()-> 993 Notify(NotificationType::HISTORY_CREATED, Source<Profile>(this), 994 Details<HistoryService>(history_service_.get())); 995 } 996 return history_service_.get(); 997 } 998 999 HistoryService* ProfileImpl::GetHistoryServiceWithoutCreating() { 1000 return history_service_.get(); 1001 } 1002 1003 TemplateURLModel* ProfileImpl::GetTemplateURLModel() { 1004 if (!template_url_model_.get()) 1005 template_url_model_.reset(new TemplateURLModel(this)); 1006 return template_url_model_.get(); 1007 } 1008 1009 TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() { 1010 if (!template_url_fetcher_.get()) 1011 template_url_fetcher_.reset(new TemplateURLFetcher(this)); 1012 return template_url_fetcher_.get(); 1013 } 1014 1015 AutocompleteClassifier* ProfileImpl::GetAutocompleteClassifier() { 1016 if (!autocomplete_classifier_.get()) 1017 autocomplete_classifier_.reset(new AutocompleteClassifier(this)); 1018 return autocomplete_classifier_.get(); 1019 } 1020 1021 WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) { 1022 if (!created_web_data_service_) 1023 CreateWebDataService(); 1024 return web_data_service_.get(); 1025 } 1026 1027 WebDataService* ProfileImpl::GetWebDataServiceWithoutCreating() { 1028 return web_data_service_.get(); 1029 } 1030 1031 void ProfileImpl::CreateWebDataService() { 1032 DCHECK(!created_web_data_service_ && web_data_service_.get() == NULL); 1033 created_web_data_service_ = true; 1034 scoped_refptr<WebDataService> wds(new WebDataService()); 1035 if (!wds->Init(GetPath())) 1036 return; 1037 web_data_service_.swap(wds); 1038 } 1039 1040 PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) { 1041 if (!created_password_store_) 1042 CreatePasswordStore(); 1043 return password_store_.get(); 1044 } 1045 1046 void ProfileImpl::CreatePasswordStore() { 1047 DCHECK(!created_password_store_ && password_store_.get() == NULL); 1048 created_password_store_ = true; 1049 scoped_refptr<PasswordStore> ps; 1050 FilePath login_db_file_path = GetPath(); 1051 login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName); 1052 LoginDatabase* login_db = new LoginDatabase(); 1053 if (!login_db->Init(login_db_file_path)) { 1054 LOG(ERROR) << "Could not initialize login database."; 1055 delete login_db; 1056 return; 1057 } 1058 #if defined(OS_WIN) 1059 ps = new PasswordStoreWin(login_db, this, 1060 GetWebDataService(Profile::IMPLICIT_ACCESS)); 1061 #elif defined(OS_MACOSX) 1062 ps = new PasswordStoreMac(new MacKeychain(), login_db); 1063 #elif defined(OS_CHROMEOS) 1064 // For now, we use PasswordStoreDefault. We might want to make a native 1065 // backend for PasswordStoreX (see below) in the future though. 1066 ps = new PasswordStoreDefault(login_db, this, 1067 GetWebDataService(Profile::IMPLICIT_ACCESS)); 1068 #elif defined(OS_POSIX) 1069 // On POSIX systems, we try to use the "native" password management system of 1070 // the desktop environment currently running, allowing GNOME Keyring in XFCE. 1071 // (In all cases we fall back on the basic store in case of failure.) 1072 base::nix::DesktopEnvironment desktop_env; 1073 std::string store_type = 1074 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 1075 switches::kPasswordStore); 1076 if (store_type == "kwallet") { 1077 desktop_env = base::nix::DESKTOP_ENVIRONMENT_KDE4; 1078 } else if (store_type == "gnome") { 1079 desktop_env = base::nix::DESKTOP_ENVIRONMENT_GNOME; 1080 } else if (store_type == "basic") { 1081 desktop_env = base::nix::DESKTOP_ENVIRONMENT_OTHER; 1082 } else { 1083 // Detect the store to use automatically. 1084 scoped_ptr<base::Environment> env(base::Environment::Create()); 1085 desktop_env = base::nix::GetDesktopEnvironment(env.get()); 1086 const char* name = base::nix::GetDesktopEnvironmentName(desktop_env); 1087 VLOG(1) << "Password storage detected desktop environment: " 1088 << (name ? name : "(unknown)"); 1089 } 1090 1091 scoped_ptr<PasswordStoreX::NativeBackend> backend; 1092 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) { 1093 // KDE3 didn't use DBus, which our KWallet store uses. 1094 VLOG(1) << "Trying KWallet for password storage."; 1095 backend.reset(new NativeBackendKWallet()); 1096 if (backend->Init()) 1097 VLOG(1) << "Using KWallet for password storage."; 1098 else 1099 backend.reset(); 1100 } else if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_GNOME || 1101 desktop_env == base::nix::DESKTOP_ENVIRONMENT_XFCE) { 1102 #if defined(USE_GNOME_KEYRING) 1103 VLOG(1) << "Trying GNOME keyring for password storage."; 1104 backend.reset(new NativeBackendGnome()); 1105 if (backend->Init()) 1106 VLOG(1) << "Using GNOME keyring for password storage."; 1107 else 1108 backend.reset(); 1109 #endif // defined(USE_GNOME_KEYRING) 1110 } 1111 1112 if (!backend.get()) { 1113 LOG(INFO) << "Using basic (unencrypted) store for password storage. " 1114 "See http://code.google.com/p/chromium/wiki/LinuxPasswordStorage for " 1115 "more information about password storage options."; 1116 } 1117 1118 ps = new PasswordStoreX(login_db, this, 1119 GetWebDataService(Profile::IMPLICIT_ACCESS), 1120 backend.release()); 1121 #else 1122 NOTIMPLEMENTED(); 1123 #endif 1124 if (!ps) 1125 delete login_db; 1126 1127 if (!ps || !ps->Init()) { 1128 NOTREACHED() << "Could not initialize password manager."; 1129 return; 1130 } 1131 password_store_.swap(ps); 1132 } 1133 1134 DownloadManager* ProfileImpl::GetDownloadManager() { 1135 if (!created_download_manager_) { 1136 scoped_refptr<DownloadManager> dlm( 1137 new DownloadManager(g_browser_process->download_status_updater())); 1138 dlm->Init(this); 1139 created_download_manager_ = true; 1140 download_manager_.swap(dlm); 1141 } 1142 return download_manager_.get(); 1143 } 1144 1145 bool ProfileImpl::HasCreatedDownloadManager() const { 1146 return created_download_manager_; 1147 } 1148 1149 PersonalDataManager* ProfileImpl::GetPersonalDataManager() { 1150 if (!personal_data_manager_.get()) { 1151 personal_data_manager_ = new PersonalDataManager(); 1152 personal_data_manager_->Init(this); 1153 } 1154 return personal_data_manager_.get(); 1155 } 1156 1157 fileapi::FileSystemContext* ProfileImpl::GetFileSystemContext() { 1158 if (!file_system_context_.get()) 1159 file_system_context_ = CreateFileSystemContext( 1160 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy()); 1161 DCHECK(file_system_context_.get()); 1162 return file_system_context_.get(); 1163 } 1164 1165 SessionService* ProfileImpl::GetSessionService() { 1166 if (!session_service_.get() && !shutdown_session_service_) { 1167 session_service_ = new SessionService(this); 1168 session_service_->ResetFromCurrentBrowsers(); 1169 } 1170 return session_service_.get(); 1171 } 1172 1173 void ProfileImpl::ShutdownSessionService() { 1174 if (shutdown_session_service_) 1175 return; 1176 1177 // We're about to exit, force creation of the session service if it hasn't 1178 // been created yet. We do this to ensure session state matches the point in 1179 // time the user exited. 1180 GetSessionService(); 1181 shutdown_session_service_ = true; 1182 session_service_ = NULL; 1183 } 1184 1185 bool ProfileImpl::HasSessionService() const { 1186 return (session_service_.get() != NULL); 1187 } 1188 1189 bool ProfileImpl::HasProfileSyncService() const { 1190 return (sync_service_.get() != NULL); 1191 } 1192 1193 bool ProfileImpl::DidLastSessionExitCleanly() { 1194 // last_session_exited_cleanly_ is set when the preferences are loaded. Force 1195 // it to be set by asking for the prefs. 1196 GetPrefs(); 1197 return last_session_exited_cleanly_; 1198 } 1199 1200 BookmarkModel* ProfileImpl::GetBookmarkModel() { 1201 if (!bookmark_bar_model_.get()) { 1202 bookmark_bar_model_.reset(new BookmarkModel(this)); 1203 bookmark_bar_model_->Load(); 1204 } 1205 return bookmark_bar_model_.get(); 1206 } 1207 1208 ProtocolHandlerRegistry* ProfileImpl::GetProtocolHandlerRegistry() { 1209 return protocol_handler_registry_.get(); 1210 } 1211 1212 bool ProfileImpl::IsSameProfile(Profile* profile) { 1213 if (profile == static_cast<Profile*>(this)) 1214 return true; 1215 Profile* otr_profile = off_the_record_profile_.get(); 1216 return otr_profile && profile == otr_profile; 1217 } 1218 1219 Time ProfileImpl::GetStartTime() const { 1220 return start_time_; 1221 } 1222 1223 TabRestoreService* ProfileImpl::GetTabRestoreService() { 1224 if (!tab_restore_service_.get()) 1225 tab_restore_service_ = new TabRestoreService(this); 1226 return tab_restore_service_.get(); 1227 } 1228 1229 history::TopSites* ProfileImpl::GetTopSites() { 1230 if (!top_sites_.get()) { 1231 top_sites_ = new history::TopSites(this); 1232 top_sites_->Init(GetPath().Append(chrome::kTopSitesFilename)); 1233 } 1234 return top_sites_; 1235 } 1236 1237 history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() { 1238 return top_sites_; 1239 } 1240 1241 void ProfileImpl::ResetTabRestoreService() { 1242 tab_restore_service_ = NULL; 1243 } 1244 1245 SpellCheckHost* ProfileImpl::GetSpellCheckHost() { 1246 return spellcheck_host_ready_ ? spellcheck_host_.get() : NULL; 1247 } 1248 1249 void ProfileImpl::ReinitializeSpellCheckHost(bool force) { 1250 // If we are already loading the spellchecker, and this is just a hint to 1251 // load the spellchecker, do nothing. 1252 if (!force && spellcheck_host_.get()) 1253 return; 1254 1255 spellcheck_host_ready_ = false; 1256 1257 bool notify = false; 1258 if (spellcheck_host_.get()) { 1259 spellcheck_host_->UnsetObserver(); 1260 spellcheck_host_ = NULL; 1261 notify = true; 1262 } 1263 1264 PrefService* prefs = GetPrefs(); 1265 if (prefs->GetBoolean(prefs::kEnableSpellCheck)) { 1266 // Retrieve the (perhaps updated recently) dictionary name from preferences. 1267 spellcheck_host_ = SpellCheckHost::Create( 1268 this, 1269 prefs->GetString(prefs::kSpellCheckDictionary), 1270 GetRequestContext()); 1271 } else if (notify) { 1272 // The spellchecker has been disabled. 1273 SpellCheckHostInitialized(); 1274 } 1275 } 1276 1277 void ProfileImpl::SpellCheckHostInitialized() { 1278 spellcheck_host_ready_ = spellcheck_host_ && 1279 (spellcheck_host_->GetDictionaryFile() != 1280 base::kInvalidPlatformFileValue || 1281 spellcheck_host_->IsUsingPlatformChecker()); 1282 NotificationService::current()->Notify( 1283 NotificationType::SPELLCHECK_HOST_REINITIALIZED, 1284 Source<Profile>(this), NotificationService::NoDetails()); 1285 } 1286 1287 ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() { 1288 if (!extension_pref_value_map_.get()) 1289 extension_pref_value_map_.reset(new ExtensionPrefValueMap); 1290 return extension_pref_value_map_.get(); 1291 } 1292 1293 WebKitContext* ProfileImpl::GetWebKitContext() { 1294 if (!webkit_context_.get()) { 1295 webkit_context_ = new WebKitContext( 1296 IsOffTheRecord(), GetPath(), GetExtensionSpecialStoragePolicy(), 1297 clear_local_state_on_exit_); 1298 } 1299 return webkit_context_.get(); 1300 } 1301 1302 void ProfileImpl::MarkAsCleanShutdown() { 1303 if (prefs_.get()) { 1304 // The session cleanly exited, set kSessionExitedCleanly appropriately. 1305 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true); 1306 1307 // NOTE: If you change what thread this writes on, be sure and update 1308 // ChromeFrame::EndSession(). 1309 prefs_->SavePersistentPrefs(); 1310 } 1311 } 1312 1313 void ProfileImpl::Observe(NotificationType type, 1314 const NotificationSource& source, 1315 const NotificationDetails& details) { 1316 if (NotificationType::PREF_CHANGED == type) { 1317 std::string* pref_name_in = Details<std::string>(details).ptr(); 1318 PrefService* prefs = Source<PrefService>(source).ptr(); 1319 DCHECK(pref_name_in && prefs); 1320 if (*pref_name_in == prefs::kSpellCheckDictionary || 1321 *pref_name_in == prefs::kEnableSpellCheck) { 1322 ReinitializeSpellCheckHost(true); 1323 } else if (*pref_name_in == prefs::kEnableAutoSpellCorrect) { 1324 NotificationService::current()->Notify( 1325 NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED, 1326 Source<Profile>(this), NotificationService::NoDetails()); 1327 } else if (*pref_name_in == prefs::kClearSiteDataOnExit) { 1328 clear_local_state_on_exit_ = 1329 prefs->GetBoolean(prefs::kClearSiteDataOnExit); 1330 if (webkit_context_) { 1331 webkit_context_->set_clear_local_state_on_exit( 1332 clear_local_state_on_exit_); 1333 } 1334 if (appcache_service_) { 1335 appcache_service_->SetClearLocalStateOnExit( 1336 clear_local_state_on_exit_); 1337 } 1338 } 1339 } else if (NotificationType::BOOKMARK_MODEL_LOADED == type) { 1340 GetProfileSyncService(); // Causes lazy-load if sync is enabled. 1341 registrar_.Remove(this, NotificationType::BOOKMARK_MODEL_LOADED, 1342 Source<Profile>(this)); 1343 } 1344 } 1345 1346 void ProfileImpl::StopCreateSessionServiceTimer() { 1347 create_session_service_timer_.Stop(); 1348 } 1349 1350 TokenService* ProfileImpl::GetTokenService() { 1351 if (!token_service_.get()) { 1352 token_service_.reset(new TokenService()); 1353 } 1354 return token_service_.get(); 1355 } 1356 1357 ProfileSyncService* ProfileImpl::GetProfileSyncService() { 1358 #if defined(OS_CHROMEOS) 1359 if (!sync_service_.get()) { 1360 // In ChromeOS, sync only gets initialized properly from login, when 1361 // kLoginManager is specified. If this gets called before login, or 1362 // during a debugging session without kLoginManager, this will return 1363 // NULL, so ensure that calls either handle a NULL result, or use 1364 // HasProfileSyncService() to guard against the call. 1365 return NULL; 1366 } 1367 #endif 1368 return GetProfileSyncService(""); 1369 } 1370 1371 ProfileSyncService* ProfileImpl::GetProfileSyncService( 1372 const std::string& cros_user) { 1373 1374 if (!ProfileSyncService::IsSyncEnabled()) 1375 return NULL; 1376 if (!sync_service_.get()) 1377 InitSyncService(cros_user); 1378 return sync_service_.get(); 1379 } 1380 1381 BrowserSignin* ProfileImpl::GetBrowserSignin() { 1382 if (!browser_signin_.get()) { 1383 browser_signin_.reset(new BrowserSignin(this)); 1384 } 1385 return browser_signin_.get(); 1386 } 1387 1388 CloudPrintProxyService* ProfileImpl::GetCloudPrintProxyService() { 1389 if (!cloud_print_proxy_service_.get()) 1390 InitCloudPrintProxyService(); 1391 return cloud_print_proxy_service_.get(); 1392 } 1393 1394 void ProfileImpl::InitSyncService(const std::string& cros_user) { 1395 profile_sync_factory_.reset( 1396 new ProfileSyncFactoryImpl(this, CommandLine::ForCurrentProcess())); 1397 sync_service_.reset( 1398 profile_sync_factory_->CreateProfileSyncService(cros_user)); 1399 sync_service_->Initialize(); 1400 } 1401 1402 void ProfileImpl::InitCloudPrintProxyService() { 1403 cloud_print_proxy_service_ = new CloudPrintProxyService(this); 1404 cloud_print_proxy_service_->Initialize(); 1405 } 1406 1407 ChromeBlobStorageContext* ProfileImpl::GetBlobStorageContext() { 1408 if (!blob_storage_context_) { 1409 blob_storage_context_ = new ChromeBlobStorageContext(); 1410 BrowserThread::PostTask( 1411 BrowserThread::IO, FROM_HERE, 1412 NewRunnableMethod(blob_storage_context_.get(), 1413 &ChromeBlobStorageContext::InitializeOnIOThread)); 1414 } 1415 return blob_storage_context_; 1416 } 1417 1418 ExtensionInfoMap* ProfileImpl::GetExtensionInfoMap() { 1419 return extension_info_map_.get(); 1420 } 1421 1422 policy::ProfilePolicyConnector* ProfileImpl::GetPolicyConnector() { 1423 if (!profile_policy_connector_.get()) 1424 profile_policy_connector_.reset(new policy::ProfilePolicyConnector(this)); 1425 1426 return profile_policy_connector_.get(); 1427 } 1428 1429 ChromeURLDataManager* ProfileImpl::GetChromeURLDataManager() { 1430 if (!chrome_url_data_manager_.get()) 1431 chrome_url_data_manager_.reset(new ChromeURLDataManager(this)); 1432 return chrome_url_data_manager_.get(); 1433 } 1434 1435 PromoCounter* ProfileImpl::GetInstantPromoCounter() { 1436 #if defined(OS_WIN) 1437 // TODO: enable this when we're ready to turn on the promo. 1438 /* 1439 if (!checked_instant_promo_) { 1440 checked_instant_promo_ = true; 1441 PrefService* prefs = GetPrefs(); 1442 if (!prefs->GetBoolean(prefs::kInstantEnabledOnce) && 1443 !InstantController::IsEnabled(this) && 1444 InstallUtil::IsChromeSxSProcess()) { 1445 DCHECK(!instant_promo_counter_.get()); 1446 instant_promo_counter_.reset( 1447 new PromoCounter(this, prefs::kInstantPromo, "Instant.Promo", 3, 3)); 1448 } 1449 } 1450 */ 1451 return instant_promo_counter_.get(); 1452 #else 1453 return NULL; 1454 #endif 1455 } 1456 1457 #if defined(OS_CHROMEOS) 1458 void ProfileImpl::ChangeAppLocale( 1459 const std::string& new_locale, AppLocaleChangedVia via) { 1460 if (new_locale.empty()) { 1461 NOTREACHED(); 1462 return; 1463 } 1464 PrefService* local_state = g_browser_process->local_state(); 1465 DCHECK(local_state); 1466 if (local_state->IsManagedPreference(prefs::kApplicationLocale)) 1467 return; 1468 std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale); 1469 bool do_update_pref = true; 1470 switch (via) { 1471 case APP_LOCALE_CHANGED_VIA_SETTINGS: 1472 case APP_LOCALE_CHANGED_VIA_REVERT: { 1473 // We keep kApplicationLocaleBackup value as a reference. In case value 1474 // of kApplicationLocale preference would change due to sync from other 1475 // device then kApplicationLocaleBackup value will trigger and allow us to 1476 // show notification about automatic locale change in LocaleChangeGuard. 1477 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale); 1478 GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted); 1479 // We maintain kApplicationLocale property in both a global storage 1480 // and user's profile. Global property determines locale of login screen, 1481 // while user's profile determines his personal locale preference. 1482 break; 1483 } 1484 case APP_LOCALE_CHANGED_VIA_LOGIN: { 1485 if (!pref_locale.empty()) { 1486 DCHECK(pref_locale == new_locale); 1487 std::string accepted_locale = 1488 GetPrefs()->GetString(prefs::kApplicationLocaleAccepted); 1489 if (accepted_locale == new_locale) { 1490 // If locale is accepted then we do not want to show LocaleChange 1491 // notification. This notification is triggered by different values 1492 // of kApplicationLocaleBackup and kApplicationLocale preferences, 1493 // so make them identical. 1494 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale); 1495 } else { 1496 // Back up locale of login screen. 1497 std::string cur_locale = g_browser_process->GetApplicationLocale(); 1498 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale); 1499 if (locale_change_guard_ == NULL) 1500 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this)); 1501 locale_change_guard_->PrepareChangingLocale(cur_locale, new_locale); 1502 } 1503 } else { 1504 std::string cur_locale = g_browser_process->GetApplicationLocale(); 1505 std::string backup_locale = 1506 GetPrefs()->GetString(prefs::kApplicationLocaleBackup); 1507 // Profile synchronization takes time and is not completed at that 1508 // moment at first login. So we initialize locale preference in steps: 1509 // (1) first save it to temporary backup; 1510 // (2) on next login we assume that synchronization is already completed 1511 // and we may finalize initialization. 1512 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale); 1513 if (!backup_locale.empty()) 1514 GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale); 1515 do_update_pref = false; 1516 } 1517 break; 1518 } 1519 case APP_LOCALE_CHANGED_VIA_UNKNOWN: 1520 default: { 1521 NOTREACHED(); 1522 break; 1523 } 1524 } 1525 if (do_update_pref) 1526 GetPrefs()->SetString(prefs::kApplicationLocale, new_locale); 1527 local_state->SetString(prefs::kApplicationLocale, new_locale); 1528 1529 if (chromeos::UserManager::Get()->current_user_is_owner()) 1530 local_state->SetString(prefs::kOwnerLocale, new_locale); 1531 1532 GetPrefs()->ScheduleSavePersistentPrefs(); 1533 local_state->ScheduleSavePersistentPrefs(); 1534 } 1535 1536 void ProfileImpl::OnLogin() { 1537 if (locale_change_guard_ == NULL) 1538 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this)); 1539 locale_change_guard_->OnLogin(); 1540 } 1541 1542 void ProfileImpl::SetupChromeOSEnterpriseExtensionObserver() { 1543 DCHECK(!chromeos_enterprise_extension_observer_.get()); 1544 chromeos_enterprise_extension_observer_.reset( 1545 new chromeos::EnterpriseExtensionObserver(this)); 1546 } 1547 1548 void ProfileImpl::InitChromeOSPreferences() { 1549 chromeos_preferences_.reset(new chromeos::Preferences()); 1550 chromeos_preferences_->Init(GetPrefs()); 1551 } 1552 #endif // defined(OS_CHROMEOS) 1553 1554 PrefProxyConfigTracker* ProfileImpl::GetProxyConfigTracker() { 1555 if (!pref_proxy_config_tracker_) 1556 pref_proxy_config_tracker_ = new PrefProxyConfigTracker(GetPrefs()); 1557 1558 return pref_proxy_config_tracker_; 1559 } 1560 1561 prerender::PrerenderManager* ProfileImpl::GetPrerenderManager() { 1562 if (!prerender::PrerenderManager::IsPrerenderingPossible()) 1563 return NULL; 1564 if (!prerender_manager_) 1565 prerender_manager_ = new prerender::PrerenderManager(this); 1566 return prerender_manager_; 1567 } 1568