diff options
Diffstat (limited to 'chrome/browser/profiles/profile.cc')
-rw-r--r-- | chrome/browser/profiles/profile.cc | 667 |
1 files changed, 667 insertions, 0 deletions
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc new file mode 100644 index 0000000..38aadf0 --- /dev/null +++ b/chrome/browser/profiles/profile.cc @@ -0,0 +1,667 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/profiles/profile.h" + +#include "app/resource_bundle.h" +#include "base/command_line.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "chrome/browser/background_contents_service.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/chrome_blob_storage_context.h" +#include "chrome/browser/download/download_manager.h" +#include "chrome/browser/extensions/extension_message_service.h" +#include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/file_system/browser_file_system_context.h" +#include "chrome/browser/in_process_webkit/webkit_context.h" +#include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/browser/notifications/desktop_notification_service.h" +#include "chrome/browser/ssl/ssl_host_state.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/ui/find_bar/find_bar_state.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/json_pref_store.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/render_messages.h" +#include "grit/browser_resources.h" +#include "grit/locale_settings.h" +#include "net/base/transport_security_state.h" +#include "webkit/database/database_tracker.h" +#if defined(TOOLKIT_USES_GTK) +#include "chrome/browser/gtk/gtk_theme_provider.h" +#endif + +#if defined(OS_WIN) +#include "chrome/browser/password_manager/password_store_win.h" +#elif defined(OS_MACOSX) +#include "chrome/browser/keychain_mac.h" +#include "chrome/browser/password_manager/password_store_mac.h" +#elif defined(OS_POSIX) && !defined(OS_CHROMEOS) +#include "chrome/browser/password_manager/native_backend_gnome_x.h" +#include "chrome/browser/password_manager/native_backend_kwallet_x.h" +#include "chrome/browser/password_manager/password_store_x.h" +#endif + +using base::Time; +using base::TimeDelta; + +// A pointer to the request context for the default profile. See comments on +// Profile::GetDefaultRequestContext. +URLRequestContextGetter* Profile::default_request_context_; + +namespace { + +// TODO(pathorn): Duplicated in profile_impl.cc +void CleanupRequestContext(ChromeURLRequestContextGetter* context) { + if (context) + context->CleanupOnUIThread(); +} + +} // namespace + +// static +const ProfileId Profile::InvalidProfileId = static_cast<ProfileId>(0); + +// static +void Profile::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kSearchSuggestEnabled, true); + prefs->RegisterBooleanPref(prefs::kSessionExitedCleanly, true); + prefs->RegisterBooleanPref(prefs::kSafeBrowsingEnabled, true); + prefs->RegisterBooleanPref(prefs::kSafeBrowsingReportingEnabled, false); + // TODO(estade): IDS_SPELLCHECK_DICTIONARY should be an ASCII string. + prefs->RegisterLocalizedStringPref(prefs::kSpellCheckDictionary, + IDS_SPELLCHECK_DICTIONARY); + prefs->RegisterBooleanPref(prefs::kEnableSpellCheck, true); + prefs->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, true); +#if defined(TOOLKIT_USES_GTK) + prefs->RegisterBooleanPref(prefs::kUsesSystemTheme, + GtkThemeProvider::DefaultUsesSystemTheme()); +#endif + prefs->RegisterFilePathPref(prefs::kCurrentThemePackFilename, FilePath()); + prefs->RegisterStringPref(prefs::kCurrentThemeID, + BrowserThemeProvider::kDefaultThemeID); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeImages); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeColors); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeTints); + prefs->RegisterDictionaryPref(prefs::kCurrentThemeDisplayProperties); + prefs->RegisterBooleanPref(prefs::kDisableExtensions, false); + prefs->RegisterStringPref(prefs::kSelectFileLastDirectory, ""); +#if defined(OS_CHROMEOS) + // TODO(dilmah): For OS_CHROMEOS we maintain kApplicationLocale in both + // local state and user's profile. For other platforms we maintain + // kApplicationLocale only in local state. + // In the future we may want to maintain kApplicationLocale + // in user's profile for other platforms as well. + prefs->RegisterStringPref(prefs::kApplicationLocale, ""); +#endif +} + +// static +URLRequestContextGetter* Profile::GetDefaultRequestContext() { + return default_request_context_; +} + +bool Profile::IsSyncAccessible() { + ProfileSyncService* syncService = GetProfileSyncService(); + return syncService && !syncService->IsManaged(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// OffTheRecordProfileImpl is a profile subclass that wraps an existing profile +// to make it suitable for the off the record mode. +// +//////////////////////////////////////////////////////////////////////////////// +class OffTheRecordProfileImpl : public Profile, + public BrowserList::Observer { + public: + explicit OffTheRecordProfileImpl(Profile* real_profile) + : profile_(real_profile), + start_time_(Time::Now()) { + request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this); + extension_process_manager_.reset(ExtensionProcessManager::Create(this)); + + BrowserList::AddObserver(this); + + background_contents_service_.reset( + new BackgroundContentsService(this, CommandLine::ForCurrentProcess())); + } + + virtual ~OffTheRecordProfileImpl() { + NotificationService::current()->Notify(NotificationType::PROFILE_DESTROYED, + Source<Profile>(this), + NotificationService::NoDetails()); + CleanupRequestContext(request_context_); + CleanupRequestContext(extensions_request_context_); + + // Clean up all DB files/directories + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + NewRunnableMethod( + db_tracker_.get(), + &webkit_database::DatabaseTracker::DeleteIncognitoDBDirectory)); + + BrowserList::RemoveObserver(this); + } + + virtual ProfileId GetRuntimeId() { + return reinterpret_cast<ProfileId>(this); + } + + virtual FilePath GetPath() { return profile_->GetPath(); } + + virtual bool IsOffTheRecord() { + return true; + } + + virtual Profile* GetOffTheRecordProfile() { + return this; + } + + virtual void DestroyOffTheRecordProfile() { + // Suicide is bad! + NOTREACHED(); + } + + virtual bool HasOffTheRecordProfile() { + return true; + } + + virtual Profile* GetOriginalProfile() { + return profile_; + } + + virtual ChromeAppCacheService* GetAppCacheService() { + if (!appcache_service_) { + appcache_service_ = new ChromeAppCacheService; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(appcache_service_.get(), + &ChromeAppCacheService::InitializeOnIOThread, + GetPath(), IsOffTheRecord(), + make_scoped_refptr(GetHostContentSettingsMap()))); + } + return appcache_service_; + } + + virtual webkit_database::DatabaseTracker* GetDatabaseTracker() { + if (!db_tracker_) { + db_tracker_ = new webkit_database::DatabaseTracker( + GetPath(), IsOffTheRecord()); + } + return db_tracker_; + } + + virtual VisitedLinkMaster* GetVisitedLinkMaster() { + // We don't provide access to the VisitedLinkMaster when we're OffTheRecord + // because we don't want to leak the sites that the user has visited before. + return NULL; + } + + virtual ExtensionsService* GetExtensionsService() { + return GetOriginalProfile()->GetExtensionsService(); + } + + virtual BackgroundContentsService* GetBackgroundContentsService() const { + return background_contents_service_.get(); + } + + virtual StatusTray* GetStatusTray() { + return GetOriginalProfile()->GetStatusTray(); + } + + virtual UserScriptMaster* GetUserScriptMaster() { + return GetOriginalProfile()->GetUserScriptMaster(); + } + + virtual ExtensionDevToolsManager* GetExtensionDevToolsManager() { + // TODO(mpcomplete): figure out whether we should return the original + // profile's version. + return NULL; + } + + virtual ExtensionProcessManager* GetExtensionProcessManager() { + return extension_process_manager_.get(); + } + + virtual ExtensionMessageService* GetExtensionMessageService() { + return GetOriginalProfile()->GetExtensionMessageService(); + } + + virtual ExtensionEventRouter* GetExtensionEventRouter() { + return GetOriginalProfile()->GetExtensionEventRouter(); + } + + virtual SSLHostState* GetSSLHostState() { + if (!ssl_host_state_.get()) + ssl_host_state_.reset(new SSLHostState()); + + DCHECK(ssl_host_state_->CalledOnValidThread()); + return ssl_host_state_.get(); + } + + virtual net::TransportSecurityState* GetTransportSecurityState() { + if (!transport_security_state_.get()) + transport_security_state_ = new net::TransportSecurityState(); + + return transport_security_state_.get(); + } + + virtual HistoryService* GetHistoryService(ServiceAccessType sat) { + if (sat == EXPLICIT_ACCESS) + return profile_->GetHistoryService(sat); + + NOTREACHED() << "This profile is OffTheRecord"; + return NULL; + } + + virtual HistoryService* GetHistoryServiceWithoutCreating() { + return profile_->GetHistoryServiceWithoutCreating(); + } + + virtual FaviconService* GetFaviconService(ServiceAccessType sat) { + if (sat == EXPLICIT_ACCESS) + return profile_->GetFaviconService(sat); + + NOTREACHED() << "This profile is OffTheRecord"; + return NULL; + } + + virtual AutocompleteClassifier* GetAutocompleteClassifier() { + return profile_->GetAutocompleteClassifier(); + } + + virtual WebDataService* GetWebDataService(ServiceAccessType sat) { + if (sat == EXPLICIT_ACCESS) + return profile_->GetWebDataService(sat); + + NOTREACHED() << "This profile is OffTheRecord"; + return NULL; + } + + virtual WebDataService* GetWebDataServiceWithoutCreating() { + return profile_->GetWebDataServiceWithoutCreating(); + } + + virtual PasswordStore* GetPasswordStore(ServiceAccessType sat) { + if (sat == EXPLICIT_ACCESS) + return profile_->GetPasswordStore(sat); + + NOTREACHED() << "This profile is OffTheRecord"; + return NULL; + } + + virtual PrefService* GetPrefs() { + return profile_->GetPrefs(); + } + + virtual TemplateURLModel* GetTemplateURLModel() { + return profile_->GetTemplateURLModel(); + } + + virtual TemplateURLFetcher* GetTemplateURLFetcher() { + return profile_->GetTemplateURLFetcher(); + } + + virtual DownloadManager* GetDownloadManager() { + if (!download_manager_.get()) { + scoped_refptr<DownloadManager> dlm( + new DownloadManager(g_browser_process->download_status_updater())); + dlm->Init(this); + download_manager_.swap(dlm); + } + return download_manager_.get(); + } + + virtual bool HasCreatedDownloadManager() const { + return (download_manager_.get() != NULL); + } + + virtual PersonalDataManager* GetPersonalDataManager() { + return NULL; + } + + virtual BrowserFileSystemContext* GetFileSystemContext() { + if (!browser_file_system_context_) + browser_file_system_context_ = new BrowserFileSystemContext( + GetPath(), IsOffTheRecord()); + DCHECK(browser_file_system_context_.get()); + return browser_file_system_context_.get(); + } + + virtual void InitThemes() { + profile_->InitThemes(); + } + + virtual void SetTheme(const Extension* extension) { + profile_->SetTheme(extension); + } + + virtual void SetNativeTheme() { + profile_->SetNativeTheme(); + } + + virtual void ClearTheme() { + profile_->ClearTheme(); + } + + virtual const Extension* GetTheme() { + return profile_->GetTheme(); + } + + virtual BrowserThemeProvider* GetThemeProvider() { + return profile_->GetThemeProvider(); + } + + virtual URLRequestContextGetter* GetRequestContext() { + return request_context_; + } + + virtual URLRequestContextGetter* GetRequestContextForMedia() { + // In OTR mode, media request context is the same as the original one. + return request_context_; + } + + URLRequestContextGetter* GetRequestContextForExtensions() { + if (!extensions_request_context_) { + extensions_request_context_ = + ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(this); + } + + return extensions_request_context_; + } + + virtual net::SSLConfigService* GetSSLConfigService() { + return profile_->GetSSLConfigService(); + } + + virtual HostContentSettingsMap* GetHostContentSettingsMap() { + // Retrieve the host content settings map of the parent profile in order to + // ensure the preferences have been migrated. + profile_->GetHostContentSettingsMap(); + if (!host_content_settings_map_.get()) + host_content_settings_map_ = new HostContentSettingsMap(this); + return host_content_settings_map_.get(); + } + + virtual HostZoomMap* GetHostZoomMap() { + if (!host_zoom_map_) + host_zoom_map_ = new HostZoomMap(this); + return host_zoom_map_.get(); + } + + virtual GeolocationContentSettingsMap* GetGeolocationContentSettingsMap() { + return profile_->GetGeolocationContentSettingsMap(); + } + + virtual GeolocationPermissionContext* GetGeolocationPermissionContext() { + return profile_->GetGeolocationPermissionContext(); + } + + virtual UserStyleSheetWatcher* GetUserStyleSheetWatcher() { + return profile_->GetUserStyleSheetWatcher(); + } + + virtual FindBarState* GetFindBarState() { + if (!find_bar_state_.get()) + find_bar_state_.reset(new FindBarState()); + return find_bar_state_.get(); + } + + virtual SessionService* GetSessionService() { + // Don't save any sessions when off the record. + return NULL; + } + + virtual void ShutdownSessionService() { + // We don't allow a session service, nothing to do. + } + + virtual bool HasSessionService() const { + // We never have a session service. + return false; + } + + virtual bool HasProfileSyncService() const { + // We never have a profile sync service. + return false; + } + + virtual bool DidLastSessionExitCleanly() { + return profile_->DidLastSessionExitCleanly(); + } + + virtual BookmarkModel* GetBookmarkModel() { + return profile_->GetBookmarkModel(); + } + + virtual DesktopNotificationService* GetDesktopNotificationService() { + if (!desktop_notification_service_.get()) { + desktop_notification_service_.reset(new DesktopNotificationService( + this, g_browser_process->notification_ui_manager())); + } + return desktop_notification_service_.get(); + } + + virtual TokenService* GetTokenService() { + return NULL; + } + + virtual ProfileSyncService* GetProfileSyncService() { + return NULL; + } + + virtual ProfileSyncService* GetProfileSyncService( + const std::string& cros_user) { + return NULL; + } + + virtual BrowserSignin* GetBrowserSignin() { + return profile_->GetBrowserSignin(); + } + + virtual CloudPrintProxyService* GetCloudPrintProxyService() { + return NULL; + } + + virtual bool IsSameProfile(Profile* profile) { + return (profile == this) || (profile == profile_); + } + + virtual Time GetStartTime() const { + return start_time_; + } + + virtual TabRestoreService* GetTabRestoreService() { + return NULL; + } + + virtual void ResetTabRestoreService() { + } + + virtual SpellCheckHost* GetSpellCheckHost() { + return profile_->GetSpellCheckHost(); + } + + virtual void ReinitializeSpellCheckHost(bool force) { + profile_->ReinitializeSpellCheckHost(force); + } + + virtual WebKitContext* GetWebKitContext() { + if (!webkit_context_.get()) + webkit_context_ = new WebKitContext(this, false); + DCHECK(webkit_context_.get()); + return webkit_context_.get(); + } + + virtual history::TopSites* GetTopSitesWithoutCreating() { + return NULL; + } + + virtual history::TopSites* GetTopSites() { + return NULL; + } + + virtual void MarkAsCleanShutdown() { + } + + virtual void InitExtensions() { + NOTREACHED(); + } + + virtual void InitWebResources() { + NOTREACHED(); + } + + virtual NTPResourceCache* GetNTPResourceCache() { + // Just return the real profile resource cache. + return profile_->GetNTPResourceCache(); + } + + virtual FilePath last_selected_directory() { + const FilePath& directory = last_selected_directory_; + if (directory.empty()) { + return profile_->last_selected_directory(); + } + return directory; + } + + virtual void set_last_selected_directory(const FilePath& path) { + last_selected_directory_ = path; + } + +#if defined(OS_CHROMEOS) + virtual chromeos::ProxyConfigServiceImpl* + GetChromeOSProxyConfigServiceImpl() { + return profile_->GetChromeOSProxyConfigServiceImpl(); + } + + virtual void SetupChromeOSEnterpriseExtensionObserver() { + profile_->SetupChromeOSEnterpriseExtensionObserver(); + } +#endif // defined(OS_CHROMEOS) + + virtual void ExitedOffTheRecordMode() { + // DownloadManager is lazily created, so check before accessing it. + if (download_manager_.get()) { + // Drop our download manager so we forget about all the downloads made + // in off-the-record mode. + download_manager_->Shutdown(); + download_manager_ = NULL; + } + } + + virtual void OnBrowserAdded(const Browser* browser) { + } + + virtual void OnBrowserRemoved(const Browser* browser) { + if (BrowserList::GetBrowserCount(this) == 0) + ExitedOffTheRecordMode(); + } + + virtual ChromeBlobStorageContext* GetBlobStorageContext() { + if (!blob_storage_context_) { + blob_storage_context_ = new ChromeBlobStorageContext(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod( + blob_storage_context_.get(), + &ChromeBlobStorageContext::InitializeOnIOThread)); + } + return blob_storage_context_; + } + + virtual ExtensionInfoMap* GetExtensionInfoMap() { + return profile_->GetExtensionInfoMap(); + } + + virtual policy::ProfilePolicyContext* GetPolicyContext() { + return NULL; + } + + virtual PromoCounter* GetInstantPromoCounter() { + return NULL; + } + + virtual PrefProxyConfigTracker* GetProxyConfigTracker() { + return profile_->GetProxyConfigTracker(); + } + + private: + NotificationRegistrar registrar_; + + // The real underlying profile. + Profile* profile_; + + scoped_ptr<ExtensionProcessManager> extension_process_manager_; + + // The context to use for requests made from this OTR session. + scoped_refptr<ChromeURLRequestContextGetter> request_context_; + + // The context to use for requests made by an extension while in OTR mode. + scoped_refptr<ChromeURLRequestContextGetter> extensions_request_context_; + + // The download manager that only stores downloaded items in memory. + scoped_refptr<DownloadManager> download_manager_; + + // Use a separate desktop notification service for OTR. + scoped_ptr<DesktopNotificationService> desktop_notification_service_; + + // We use a non-writable content settings map for OTR. + scoped_refptr<HostContentSettingsMap> host_content_settings_map_; + + // Use a separate zoom map for OTR. + scoped_refptr<HostZoomMap> host_zoom_map_; + + // Use a special WebKit context for OTR browsing. + scoped_refptr<WebKitContext> webkit_context_; + + // We don't want SSLHostState from the OTR profile to leak back to the main + // profile because then the main profile would learn some of the host names + // the user visited while OTR. + scoped_ptr<SSLHostState> ssl_host_state_; + + // Use a separate FindBarState so search terms do not leak back to the main + // profile. + scoped_ptr<FindBarState> find_bar_state_; + + // The TransportSecurityState that only stores enabled sites in memory. + scoped_refptr<net::TransportSecurityState> + transport_security_state_; + + // Time we were started. + Time start_time_; + + scoped_refptr<ChromeAppCacheService> appcache_service_; + + // The main database tracker for this profile. + // Should be used only on the file thread. + scoped_refptr<webkit_database::DatabaseTracker> db_tracker_; + + FilePath last_selected_directory_; + + // Tracks all BackgroundContents running under this profile. + scoped_ptr<BackgroundContentsService> background_contents_service_; + + scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; + + // The file_system context for this profile. + scoped_refptr<BrowserFileSystemContext> browser_file_system_context_; + + DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl); +}; + +Profile* Profile::CreateOffTheRecordProfile() { + return new OffTheRecordProfileImpl(this); +} |