This source file includes following definitions.
- ProfilesToDelete
- ComputeFilesSize
- ProfileSizeTask
- QueueProfileDirectoryForDeletion
- IsProfileMarkedForDeletion
- NukeProfileFromDisk
- CheckCryptohomeIsMounted
- GetEnabledAppCount
- closing_all_browsers_
- ShutdownSessionServices
- NukeDeletedProfilesFromDisk
- GetLastUsedProfile
- GetLastUsedProfileAllowedByPolicy
- GetLastOpenedProfiles
- GetPrimaryUserProfile
- GetActiveUserProfile
- GetProfile
- GetNumberOfProfiles
- CreateProfileAsync
- IsValidProfile
- GetInitialProfileDir
- GetLastUsedProfile
- GetLastUsedProfileDir
- GetLastOpenedProfiles
- GetLoadedProfiles
- GetProfileByPath
- CreateMultiProfileAsync
- GetGuestProfilePath
- GenerateNextProfileDirectoryPath
- GetProfileInfoCache
- profile_shortcut_manager
- ScheduleProfileForDeletion
- CleanUpStaleProfiles
- AutoloadProfiles
- InitProfileUserPrefs
- RegisterTestingProfile
- Observe
- OnProfileCreated
- DoFinalInit
- DoFinalInitForServices
- DoFinalInitLogging
- CreateProfileHelper
- CreateProfileAsyncHelper
- GetActiveUserOrOffTheRecordProfileFromPath
- AddProfile
- FinishDeletingProfile
- RegisterProfile
- GetProfileInfoByPath
- AddProfileToCache
- SetGuestProfilePrefs
- ShouldGoOffTheRecord
- RunCallbacks
- created
- OnBrowserAdded
- OnBrowserRemoved
- OnBrowserSetLastActive
- OnNewActiveProfileLoaded
#include "chrome/browser/profiles/profile_manager.h"
#include <set>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/deferred_sequenced_task_runner.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
#include "chrome/browser/profiles/profile_destroyer.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/profiles/startup_task_runner_service.h"
#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/sync/sync_promo_ui.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/profile_management_switches.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest.h"
#include "grit/generated_resources.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(ENABLE_MANAGED_USERS)
#include "chrome/browser/managed_mode/managed_user_service.h"
#include "chrome/browser/managed_mode/managed_user_service_factory.h"
#endif
#if !defined(OS_IOS)
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/ui/browser_list.h"
#include "extensions/browser/extension_system.h"
#endif
#if defined(OS_WIN)
#include "base/win/metro.h"
#include "chrome/installer/util/browser_distribution.h"
#endif
#if defined(OS_CHROMEOS)
#include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#endif
using base::UserMetricsAction;
using content::BrowserThread;
namespace {
std::vector<base::FilePath>& ProfilesToDelete() {
CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
return profiles_to_delete;
}
int64 ComputeFilesSize(const base::FilePath& directory,
const base::FilePath::StringType& pattern) {
int64 running_size = 0;
base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
pattern);
while (!iter.Next().empty())
running_size += iter.GetInfo().GetSize();
return running_size;
}
void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
const int64 kBytesInOneMB = 1024 * 1024;
int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*"));
int size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("History"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("History*"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Cookies"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Bookmarks"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Favicons"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Top Sites"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Visited Links"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Web Data"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Extension*"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
size_MB = static_cast<int>(size / kBytesInOneMB);
UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
if (enabled_app_count != -1)
UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count);
}
void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
ProfilesToDelete().push_back(path);
}
bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
profile_path) != ProfilesToDelete().end();
}
void NukeProfileFromDisk(const base::FilePath& profile_path) {
base::FilePath cache_path;
chrome::GetUserCacheDirectory(profile_path, &cache_path);
base::DeleteFile(profile_path, true);
base::DeleteFile(cache_path, true);
}
#if defined(OS_CHROMEOS)
void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
bool is_mounted) {
if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
LOG(ERROR) << "IsMounted call failed.";
return;
}
if (!is_mounted)
LOG(ERROR) << "Cryptohome is not mounted.";
}
#endif
#if defined(ENABLE_EXTENSIONS)
size_t GetEnabledAppCount(Profile* profile) {
size_t installed_apps = 0u;
const extensions::ExtensionSet& extensions =
extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
iter != extensions.end();
++iter) {
if ((*iter)->is_app() &&
(*iter)->location() != extensions::Manifest::COMPONENT) {
++installed_apps;
}
}
return installed_apps;
}
#endif
}
ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
: user_data_dir_(user_data_dir),
logged_in_(false),
#if !defined(OS_ANDROID) && !defined(OS_IOS)
browser_list_observer_(this),
#endif
closing_all_browsers_(false) {
#if defined(OS_CHROMEOS)
registrar_.Add(
this,
chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources());
#endif
registrar_.Add(
this,
chrome::NOTIFICATION_BROWSER_OPENED,
content::NotificationService::AllSources());
registrar_.Add(
this,
chrome::NOTIFICATION_BROWSER_CLOSED,
content::NotificationService::AllSources());
registrar_.Add(
this,
chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
content::NotificationService::AllSources());
registrar_.Add(
this,
chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
content::NotificationService::AllSources());
registrar_.Add(
this,
chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
content::NotificationService::AllSources());
if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
profile_shortcut_manager_.reset(ProfileShortcutManager::Create(
this));
}
ProfileManager::~ProfileManager() {
}
#if defined(ENABLE_SESSION_SERVICE)
void ProfileManager::ShutdownSessionServices() {
ProfileManager* pm = g_browser_process->profile_manager();
if (!pm)
return;
std::vector<Profile*> profiles(pm->GetLoadedProfiles());
for (size_t i = 0; i < profiles.size(); ++i)
SessionServiceFactory::ShutdownForProfile(profiles[i]);
}
#endif
void ProfileManager::NukeDeletedProfilesFromDisk() {
for (std::vector<base::FilePath>::iterator it =
ProfilesToDelete().begin();
it != ProfilesToDelete().end();
++it) {
NukeProfileFromDisk(*it);
}
ProfilesToDelete().clear();
}
Profile* ProfileManager::GetLastUsedProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
}
Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
Profile* profile = GetLastUsedProfile();
if (profile->IsGuestSession() ||
IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
IncognitoModePrefs::FORCED) {
return profile->GetOffTheRecordProfile();
}
return profile;
}
std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
return profile_manager->GetLastOpenedProfiles(
profile_manager->user_data_dir_);
}
Profile* ProfileManager::GetPrimaryUserProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
#if defined(OS_CHROMEOS)
if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
profile_manager->user_data_dir());
chromeos::UserManager* manager = chromeos::UserManager::Get();
return manager->GetProfileByUser(manager->GetPrimaryUser());
#else
return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
profile_manager->user_data_dir());
#endif
}
Profile* ProfileManager::GetActiveUserProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
#if defined(OS_CHROMEOS)
if (!chromeos::UserManager::IsMultipleProfilesAllowed() ||
!profile_manager->IsLoggedIn() ||
!chromeos::UserManager::IsInitialized())
return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
profile_manager->user_data_dir());
chromeos::UserManager* manager = chromeos::UserManager::Get();
const chromeos::User* user = manager->GetActiveUser();
if (user && user->is_profile_created())
return manager->GetProfileByUser(user);
#endif
return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(
profile_manager->user_data_dir());
}
Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
TRACE_EVENT0("browser", "ProfileManager::GetProfile")
Profile* profile = GetProfileByPath(profile_dir);
if (NULL != profile)
return profile;
profile = CreateProfileHelper(profile_dir);
DCHECK(profile);
if (profile) {
bool result = AddProfile(profile);
DCHECK(result);
}
return profile;
}
size_t ProfileManager::GetNumberOfProfiles() {
return GetProfileInfoCache().GetNumberOfProfiles();
}
void ProfileManager::CreateProfileAsync(
const base::FilePath& profile_path,
const CreateCallback& callback,
const base::string16& name,
const base::string16& icon_url,
const std::string& managed_user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsProfileMarkedForDeletion(profile_path)) {
if (!callback.is_null())
callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
return;
}
ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
ProfileInfo* info = NULL;
if (iter != profiles_info_.end()) {
info = iter->second.get();
} else {
info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
ProfileInfoCache& cache = GetProfileInfoCache();
size_t icon_index;
std::string icon_url_std = base::UTF16ToASCII(icon_url);
if (cache.IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) {
cache.AddProfileToCache(profile_path, name, base::string16(), icon_index,
managed_user_id);
}
if (!managed_user_id.empty()) {
content::RecordAction(
UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
}
ProfileMetrics::UpdateReportedProfilesStatistics(this);
}
if (!callback.is_null()) {
if (iter != profiles_info_.end() && info->created) {
Profile* profile = info->profile.get();
if (profile->GetPath() == ProfileManager::GetGuestProfilePath()) {
SetGuestProfilePrefs(profile);
profile = profile->GetOffTheRecordProfile();
}
callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
} else {
info->callbacks.push_back(callback);
}
}
}
bool ProfileManager::IsValidProfile(Profile* profile) {
for (ProfilesInfoMap::iterator iter = profiles_info_.begin();
iter != profiles_info_.end(); ++iter) {
if (iter->second->created) {
Profile* candidate = iter->second->profile.get();
if (candidate == profile ||
(candidate->HasOffTheRecordProfile() &&
candidate->GetOffTheRecordProfile() == profile)) {
return true;
}
}
}
return false;
}
base::FilePath ProfileManager::GetInitialProfileDir() {
base::FilePath relative_profile_dir;
#if defined(OS_CHROMEOS)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (logged_in_) {
base::FilePath profile_dir;
if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
profile_dir = chromeos::ProfileHelper::
GetProfileDirByLegacyLoginProfileSwitch();
} else if (!command_line.HasSwitch(switches::kMultiProfiles)) {
NOTREACHED();
return base::FilePath("");
}
std::string user_id_hash = g_browser_process->platform_part()->
profile_helper()->active_user_id_hash();
if (command_line.HasSwitch(switches::kMultiProfiles) &&
!user_id_hash.empty()) {
profile_dir = g_browser_process->platform_part()->
profile_helper()->GetActiveUserProfileDir();
}
relative_profile_dir = relative_profile_dir.Append(profile_dir);
return relative_profile_dir;
}
#endif
relative_profile_dir =
relative_profile_dir.AppendASCII(chrome::kInitialProfile);
return relative_profile_dir;
}
Profile* ProfileManager::GetLastUsedProfile(
const base::FilePath& user_data_dir) {
#if defined(OS_CHROMEOS)
if (!logged_in_) {
return GetActiveUserOrOffTheRecordProfileFromPath(user_data_dir);
} else {
base::FilePath profile_dir;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kMultiProfiles)) {
profile_dir = g_browser_process->platform_part()->
profile_helper()->GetActiveUserProfileDir();
} else {
profile_dir =
chromeos::ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
}
base::FilePath profile_path(user_data_dir);
Profile* profile = GetProfile(profile_path.Append(profile_dir));
return profile->IsGuestSession() ? profile->GetOffTheRecordProfile() :
profile;
}
#endif
return GetProfile(GetLastUsedProfileDir(user_data_dir));
}
base::FilePath ProfileManager::GetLastUsedProfileDir(
const base::FilePath& user_data_dir) {
base::FilePath last_used_profile_dir(user_data_dir);
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
if (local_state->HasPrefPath(prefs::kProfileLastUsed)) {
return last_used_profile_dir.AppendASCII(
local_state->GetString(prefs::kProfileLastUsed));
}
return last_used_profile_dir.AppendASCII(chrome::kInitialProfile);
}
std::vector<Profile*> ProfileManager::GetLastOpenedProfiles(
const base::FilePath& user_data_dir) {
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
std::vector<Profile*> to_return;
if (local_state->HasPrefPath(prefs::kProfilesLastActive) &&
local_state->GetList(prefs::kProfilesLastActive)) {
scoped_ptr<base::ListValue> profile_list(
local_state->GetList(prefs::kProfilesLastActive)->DeepCopy());
base::ListValue::const_iterator it;
std::string profile;
for (it = profile_list->begin(); it != profile_list->end(); ++it) {
if (!(*it)->GetAsString(&profile) || profile.empty()) {
LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive;
continue;
}
to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
}
}
return to_return;
}
std::vector<Profile*> ProfileManager::GetLoadedProfiles() const {
std::vector<Profile*> profiles;
for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin();
iter != profiles_info_.end(); ++iter) {
if (iter->second->created)
profiles.push_back(iter->second->profile.get());
}
return profiles;
}
Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
ProfileInfo* profile_info = GetProfileInfoByPath(path);
return profile_info ? profile_info->profile.get() : NULL;
}
base::FilePath ProfileManager::CreateMultiProfileAsync(
const base::string16& name,
const base::string16& icon_url,
const CreateCallback& callback,
const std::string& managed_user_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ProfileManager* profile_manager = g_browser_process->profile_manager();
base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
profile_manager->CreateProfileAsync(new_path,
callback,
name,
icon_url,
managed_user_id);
return new_path;
}
base::FilePath ProfileManager::GetGuestProfilePath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ProfileManager* profile_manager = g_browser_process->profile_manager();
base::FilePath guest_path = profile_manager->user_data_dir();
return guest_path.Append(chrome::kGuestProfileDir);
}
base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() {
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
DCHECK(profiles::IsMultipleProfilesEnabled());
int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated);
std::string profile_name = chrome::kMultiProfileDirPrefix;
profile_name.append(base::IntToString(next_directory));
base::FilePath new_path = user_data_dir_;
#if defined(OS_WIN)
new_path = new_path.Append(base::ASCIIToUTF16(profile_name));
#else
new_path = new_path.Append(profile_name);
#endif
local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
return new_path;
}
ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
if (!profile_info_cache_) {
profile_info_cache_.reset(new ProfileInfoCache(
g_browser_process->local_state(), user_data_dir_));
}
return *profile_info_cache_.get();
}
ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
return profile_shortcut_manager_.get();
}
void ProfileManager::ScheduleProfileForDeletion(
const base::FilePath& profile_dir,
const CreateCallback& callback) {
DCHECK(profiles::IsMultipleProfilesEnabled());
PrefService* local_state = g_browser_process->local_state();
ProfileInfoCache& cache = GetProfileInfoCache();
if (profile_dir.BaseName().MaybeAsASCII() ==
local_state->GetString(prefs::kProfileLastUsed)) {
base::FilePath last_non_managed_profile_path;
for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
!IsProfileMarkedForDeletion(cur_path)) {
last_non_managed_profile_path = cur_path;
break;
}
}
const std::string last_non_managed_profile =
last_non_managed_profile_path.BaseName().MaybeAsASCII();
if (last_non_managed_profile.empty()) {
base::FilePath new_path = GenerateNextProfileDirectoryPath();
local_state->SetString(prefs::kProfileLastUsed,
new_path.BaseName().MaybeAsASCII());
CreateProfileAsync(new_path,
callback,
base::string16(),
base::string16(),
std::string());
} else {
#if defined(OS_MACOSX)
CreateProfileAsync(last_non_managed_profile_path,
base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
base::Unretained(this),
profile_dir,
last_non_managed_profile_path,
callback),
base::string16(),
base::string16(),
std::string());
return;
#else
local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
#endif
}
}
FinishDeletingProfile(profile_dir);
}
void ProfileManager::CleanUpStaleProfiles(
const std::vector<base::FilePath>& profile_paths) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
it != profile_paths.end(); ++it) {
NukeProfileFromDisk(*it);
}
}
void ProfileManager::AutoloadProfiles() {
PrefService* local_state = g_browser_process->local_state();
if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
!local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
return;
}
ProfileInfoCache& cache = GetProfileInfoCache();
size_t number_of_profiles = cache.GetNumberOfProfiles();
for (size_t p = 0; p < number_of_profiles; ++p) {
if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
GetProfile(cache.GetPathOfProfileAtIndex(p));
}
}
}
void ProfileManager::InitProfileUserPrefs(Profile* profile) {
ProfileInfoCache& cache = GetProfileInfoCache();
if (profile->GetPath().DirName() != cache.GetUserDataDir())
return;
size_t avatar_index;
std::string profile_name;
std::string managed_user_id;
if (profile->IsGuestSession()) {
profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME);
avatar_index = 0;
} else {
size_t profile_cache_index =
cache.GetIndexOfProfileWithPath(profile->GetPath());
if (profile_cache_index != std::string::npos) {
avatar_index =
cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
profile_name =
base::UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
managed_user_id =
cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index);
} else if (profile->GetPath() ==
profiles::GetDefaultProfileDir(cache.GetUserDataDir())) {
avatar_index = 0;
profile_name = switches::IsNewProfileManagement() ?
base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index)) :
l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
} else {
avatar_index = cache.ChooseAvatarIconIndexForNewProfile();
profile_name =
base::UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index));
}
}
if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex))
profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index);
if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName))
profile->GetPrefs()->SetString(prefs::kProfileName, profile_name);
CommandLine* command_line = CommandLine::ForCurrentProcess();
bool force_managed_user_id =
command_line->HasSwitch(switches::kManagedUserId);
if (force_managed_user_id) {
managed_user_id =
command_line->GetSwitchValueASCII(switches::kManagedUserId);
}
if (force_managed_user_id ||
!profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) {
profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id);
}
}
void ProfileManager::RegisterTestingProfile(Profile* profile,
bool add_to_cache,
bool start_deferred_task_runners) {
RegisterProfile(profile, true);
if (add_to_cache) {
InitProfileUserPrefs(profile);
AddProfileToCache(profile);
}
if (start_deferred_task_runners) {
StartupTaskRunnerServiceFactory::GetForProfile(profile)->
StartDeferredTaskRunners();
}
}
void ProfileManager::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
#if defined(OS_CHROMEOS)
if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
logged_in_ = true;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kTestType)) {
chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
base::Bind(&CheckCryptohomeIsMounted));
base::FilePath default_profile_dir = user_data_dir_.Append(
GetInitialProfileDir());
CHECK(!GetProfileByPath(default_profile_dir))
<< "The default profile was loaded before we mounted the cryptohome.";
}
return;
}
#endif
bool save_active_profiles = false;
switch (type) {
case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
closing_all_browsers_ = true;
save_active_profiles = true;
break;
}
case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
closing_all_browsers_ = false;
save_active_profiles = true;
break;
}
case chrome::NOTIFICATION_BROWSER_OPENED: {
Browser* browser = content::Source<Browser>(source).ptr();
DCHECK(browser);
Profile* profile = browser->profile();
DCHECK(profile);
bool is_ephemeral =
profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
if (!profile->IsOffTheRecord() && !is_ephemeral &&
++browser_counts_[profile] == 1) {
active_profiles_.push_back(profile);
save_active_profiles = true;
}
closing_all_browsers_ = false;
break;
}
case chrome::NOTIFICATION_BROWSER_CLOSED: {
Browser* browser = content::Source<Browser>(source).ptr();
DCHECK(browser);
Profile* profile = browser->profile();
DCHECK(profile);
if (!profile->IsOffTheRecord() && --browser_counts_[profile] == 0) {
active_profiles_.erase(std::find(active_profiles_.begin(),
active_profiles_.end(), profile));
save_active_profiles = !closing_all_browsers_;
}
break;
}
case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: {
save_active_profiles = !closing_all_browsers_;
break;
}
default: {
NOTREACHED();
break;
}
}
if (save_active_profiles) {
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
ListPrefUpdate update(local_state, prefs::kProfilesLastActive);
base::ListValue* profile_list = update.Get();
profile_list->Clear();
std::set<std::string> profile_paths;
std::vector<Profile*>::const_iterator it;
for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) {
std::string profile_path = (*it)->GetPath().BaseName().MaybeAsASCII();
if (!(*it)->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
profile_paths.find(profile_path) == profile_paths.end()) {
profile_paths.insert(profile_path);
profile_list->Append(new base::StringValue(profile_path));
}
}
}
}
void ProfileManager::OnProfileCreated(Profile* profile,
bool success,
bool is_new_profile) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath());
DCHECK(iter != profiles_info_.end());
ProfileInfo* info = iter->second.get();
std::vector<CreateCallback> callbacks;
info->callbacks.swap(callbacks);
bool go_off_the_record = ShouldGoOffTheRecord(profile);
if (success && !go_off_the_record)
RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
if (success) {
DoFinalInit(profile, go_off_the_record);
if (go_off_the_record)
profile = profile->GetOffTheRecordProfile();
info->created = true;
} else {
profile = NULL;
profiles_info_.erase(iter);
}
if (profile) {
if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
SetGuestProfilePrefs(profile);
if (go_off_the_record)
RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
}
RunCallbacks(callbacks, profile,
profile ? Profile::CREATE_STATUS_INITIALIZED :
Profile::CREATE_STATUS_LOCAL_FAIL);
}
void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
DoFinalInitForServices(profile, go_off_the_record);
AddProfileToCache(profile);
DoFinalInitLogging(profile);
ProfileMetrics::LogNumberOfProfiles(this);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_ADDED,
content::Source<Profile>(profile),
content::NotificationService::NoDetails());
}
void ProfileManager::DoFinalInitForServices(Profile* profile,
bool go_off_the_record) {
#if defined(ENABLE_EXTENSIONS)
extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
!go_off_the_record);
if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
profile->GetHostContentSettingsMap()->RegisterExtensionService(
extensions::ExtensionSystem::Get(profile)->extension_service());
}
#endif
#if defined(ENABLE_MANAGED_USERS)
ManagedUserServiceFactory::GetForProfile(profile)->Init();
#endif
StartupTaskRunnerServiceFactory::GetForProfile(profile)->
StartDeferredTaskRunners();
if (switches::IsNewProfileManagement())
AccountReconcilorFactory::GetForProfile(profile);
}
void ProfileManager::DoFinalInitLogging(Profile* profile) {
int enabled_app_count = -1;
#if defined(ENABLE_EXTENSIONS)
enabled_app_count = GetEnabledAppCount(profile);
#endif
BrowserThread::PostDelayedTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&ProfileSizeTask, profile->GetPath(), enabled_app_count),
base::TimeDelta::FromSeconds(112));
}
Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) {
return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
}
Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path,
Delegate* delegate) {
return Profile::CreateProfile(path,
delegate,
Profile::CREATE_MODE_ASYNCHRONOUS);
}
Profile* ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath(
const base::FilePath& user_data_dir) {
#if defined(OS_CHROMEOS)
base::FilePath default_profile_dir(user_data_dir);
if (!logged_in_) {
default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
Profile* profile = GetProfile(default_profile_dir);
if (ShouldGoOffTheRecord(profile))
return profile->GetOffTheRecordProfile();
DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest());
return profile;
}
default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
if (profile_info && !profile_info->created)
default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
Profile* profile = GetProfile(default_profile_dir);
if (chromeos::UserManager::IsInitialized() &&
chromeos::UserManager::Get()->IsLoggedInAsGuest())
return profile->GetOffTheRecordProfile();
return profile;
#else
base::FilePath default_profile_dir(user_data_dir);
default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
return GetProfile(default_profile_dir);
#endif
}
bool ProfileManager::AddProfile(Profile* profile) {
DCHECK(profile);
if (GetProfileByPath(profile->GetPath())) {
NOTREACHED() << "Attempted to add profile with the same path (" <<
profile->GetPath().value() <<
") as an already-loaded profile.";
return false;
}
RegisterProfile(profile, true);
InitProfileUserPrefs(profile);
DoFinalInit(profile, ShouldGoOffTheRecord(profile));
return true;
}
void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
ProfileInfoCache& cache = GetProfileInfoCache();
Profile* profile = GetProfileByPath(profile_dir);
if (profile) {
BrowserList::CloseAllBrowsersWithProfile(profile);
if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
profile)) {
ProfileSyncServiceFactory::GetInstance()->GetForProfile(
profile)->DisableForUser();
}
}
QueueProfileDirectoryForDeletion(profile_dir);
cache.DeleteProfileFromCache(profile_dir);
ProfileMetrics::UpdateReportedProfilesStatistics(this);
}
ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
Profile* profile,
bool created) {
ProfileInfo* info = new ProfileInfo(profile, created);
profiles_info_.insert(
std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
return info;
}
ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath(
const base::FilePath& path) const {
ProfilesInfoMap::const_iterator iter = profiles_info_.find(path);
return (iter == profiles_info_.end()) ? NULL : iter->second.get();
}
void ProfileManager::AddProfileToCache(Profile* profile) {
if (profile->IsGuestSession())
return;
ProfileInfoCache& cache = GetProfileInfoCache();
if (profile->GetPath().DirName() != cache.GetUserDataDir())
return;
if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
return;
base::string16 username = base::UTF8ToUTF16(profile->GetPrefs()->GetString(
prefs::kGoogleServicesUsername));
base::string16 profile_name =
base::UTF8ToUTF16(profile->GetPrefs()->GetString(prefs::kProfileName));
size_t icon_index = profile->GetPrefs()->GetInteger(
prefs::kProfileAvatarIndex);
std::string managed_user_id =
profile->GetPrefs()->GetString(prefs::kManagedUserId);
cache.AddProfileToCache(profile->GetPath(),
profile_name,
username,
icon_index,
managed_user_id);
if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
cache.SetProfileIsEphemeralAtIndex(
cache.GetIndexOfProfileWithPath(profile->GetPath()), true);
}
}
void ProfileManager::SetGuestProfilePrefs(Profile* profile) {
PrefService* prefs = profile->GetPrefs();
prefs->SetBoolean(prefs::kSigninAllowed, false);
prefs->SetBoolean(prefs::kEditBookmarksEnabled, false);
prefs->SetBoolean(prefs::kShowBookmarkBar, false);
IncognitoModePrefs::SetAvailability(prefs, IncognitoModePrefs::ENABLED);
}
bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) {
#if defined(OS_CHROMEOS)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (profile->GetPath().BaseName().value() == chrome::kInitialProfile &&
(!command_line.HasSwitch(switches::kTestType) ||
command_line.HasSwitch(chromeos::switches::kLoginProfile))) {
return true;
}
#endif
return profile->IsGuestSession();
}
void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
Profile* profile,
Profile::CreateStatus status) {
for (size_t i = 0; i < callbacks.size(); ++i)
callbacks[i].Run(profile, status);
}
ProfileManager::ProfileInfo::ProfileInfo(
Profile* profile,
bool created)
: profile(profile),
created(created) {
}
ProfileManager::ProfileInfo::~ProfileInfo() {
ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());
}
#if !defined(OS_ANDROID) && !defined(OS_IOS)
ProfileManager::BrowserListObserver::BrowserListObserver(
ProfileManager* manager)
: profile_manager_(manager) {
BrowserList::AddObserver(this);
}
ProfileManager::BrowserListObserver::~BrowserListObserver() {
BrowserList::RemoveObserver(this);
}
void ProfileManager::BrowserListObserver::OnBrowserAdded(
Browser* browser) {}
void ProfileManager::BrowserListObserver::OnBrowserRemoved(
Browser* browser) {
Profile* profile = browser->profile();
for (chrome::BrowserIterator it; !it.done(); it.Next()) {
if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
return;
}
base::FilePath path = profile->GetPath();
if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
!IsProfileMarkedForDeletion(path)) {
g_browser_process->profile_manager()->ScheduleProfileForDeletion(
path, ProfileManager::CreateCallback());
}
}
void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
Browser* browser) {
if (profile_manager_->closing_all_browsers_)
return;
Profile* last_active = browser->profile();
if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
return;
PrefService* local_state = g_browser_process->local_state();
DCHECK(local_state);
if (profile_manager_->profiles_info_.find(
last_active->GetPath()) != profile_manager_->profiles_info_.end()) {
local_state->SetString(prefs::kProfileLastUsed,
last_active->GetPath().BaseName().MaybeAsASCII());
ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
size_t profile_index =
cache.GetIndexOfProfileWithPath(last_active->GetPath());
if (profile_index != std::string::npos)
cache.SetProfileActiveTimeAtIndex(profile_index);
}
}
#endif
#if defined(OS_MACOSX)
void ProfileManager::OnNewActiveProfileLoaded(
const base::FilePath& profile_to_delete_path,
const base::FilePath& last_non_managed_profile_path,
const CreateCallback& original_callback,
Profile* loaded_profile,
Profile::CreateStatus status) {
DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
status != Profile::CREATE_STATUS_REMOTE_FAIL);
if (status == Profile::CREATE_STATUS_INITIALIZED) {
if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
} else {
g_browser_process->local_state()->SetString(
prefs::kProfileLastUsed,
last_non_managed_profile_path.BaseName().MaybeAsASCII());
FinishDeletingProfile(profile_to_delete_path);
}
}
}
#endif
ProfileManagerWithoutInit::ProfileManagerWithoutInit(
const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {
}