1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/profiles/profile_manager.h"
6
7#include <set>
8
9#include "base/bind.h"
10#include "base/command_line.h"
11#include "base/debug/trace_event.h"
12#include "base/deferred_sequenced_task_runner.h"
13#include "base/file_util.h"
14#include "base/files/file_enumerator.h"
15#include "base/files/file_path.h"
16#include "base/metrics/histogram.h"
17#include "base/prefs/pref_service.h"
18#include "base/prefs/scoped_user_pref_update.h"
19#include "base/strings/string_number_conversions.h"
20#include "base/strings/string_util.h"
21#include "base/strings/utf_string_conversions.h"
22#include "chrome/browser/bookmarks/bookmark_model.h"
23#include "chrome/browser/bookmarks/bookmark_model_factory.h"
24#include "chrome/browser/browser_process.h"
25#include "chrome/browser/chrome_notification_types.h"
26#include "chrome/browser/content_settings/host_content_settings_map.h"
27#include "chrome/browser/prefs/incognito_mode_prefs.h"
28#include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
29#include "chrome/browser/profiles/profile_destroyer.h"
30#include "chrome/browser/profiles/profile_info_cache.h"
31#include "chrome/browser/profiles/profile_metrics.h"
32#include "chrome/browser/profiles/profiles_state.h"
33#include "chrome/browser/profiles/startup_task_runner_service.h"
34#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
35#include "chrome/browser/signin/account_reconcilor_factory.h"
36#include "chrome/browser/sync/profile_sync_service.h"
37#include "chrome/browser/sync/profile_sync_service_factory.h"
38#include "chrome/browser/ui/browser.h"
39#include "chrome/browser/ui/browser_iterator.h"
40#include "chrome/browser/ui/sync/sync_promo_ui.h"
41#include "chrome/common/chrome_constants.h"
42#include "chrome/common/chrome_paths_internal.h"
43#include "chrome/common/chrome_switches.h"
44#include "chrome/common/logging_chrome.h"
45#include "chrome/common/pref_names.h"
46#include "chrome/common/url_constants.h"
47#include "content/public/browser/browser_thread.h"
48#include "content/public/browser/notification_service.h"
49#include "content/public/browser/user_metrics.h"
50#include "grit/generated_resources.h"
51#include "net/http/http_transaction_factory.h"
52#include "net/url_request/url_request_context.h"
53#include "net/url_request/url_request_context_getter.h"
54#include "net/url_request/url_request_job.h"
55#include "ui/base/l10n/l10n_util.h"
56
57#if defined(ENABLE_MANAGED_USERS)
58#include "chrome/browser/managed_mode/managed_user_service.h"
59#include "chrome/browser/managed_mode/managed_user_service_factory.h"
60#endif
61
62#if !defined(OS_IOS)
63#include "chrome/browser/extensions/extension_service.h"
64#include "chrome/browser/extensions/extension_system.h"
65#include "chrome/browser/sessions/session_service_factory.h"
66#include "chrome/browser/ui/browser_list.h"
67#endif  // !defined (OS_IOS)
68
69#if defined(OS_WIN)
70#include "base/win/metro.h"
71#include "chrome/installer/util/browser_distribution.h"
72#endif
73
74#if defined(OS_CHROMEOS)
75#include "chrome/browser/browser_process_platform_part_chromeos.h"
76#include "chrome/browser/chromeos/login/user.h"
77#include "chrome/browser/chromeos/login/user_manager.h"
78#include "chrome/browser/chromeos/profiles/profile_helper.h"
79#include "chromeos/chromeos_switches.h"
80#include "chromeos/dbus/cryptohome_client.h"
81#include "chromeos/dbus/dbus_thread_manager.h"
82#endif
83
84using content::BrowserThread;
85using content::UserMetricsAction;
86
87namespace {
88
89// Profiles that should be deleted on shutdown.
90std::vector<base::FilePath>& ProfilesToDelete() {
91  CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ());
92  return profiles_to_delete;
93}
94
95int64 ComputeFilesSize(const base::FilePath& directory,
96                       const base::FilePath::StringType& pattern) {
97  int64 running_size = 0;
98  base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES,
99                            pattern);
100  while (!iter.Next().empty())
101    running_size += iter.GetInfo().GetSize();
102  return running_size;
103}
104
105// Simple task to log the size of the current profile.
106void ProfileSizeTask(const base::FilePath& path, int extension_count) {
107  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
108  const int64 kBytesInOneMB = 1024 * 1024;
109
110  int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*"));
111  int size_MB = static_cast<int>(size / kBytesInOneMB);
112  UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
113
114  size = ComputeFilesSize(path, FILE_PATH_LITERAL("History"));
115  size_MB = static_cast<int>(size / kBytesInOneMB);
116  UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
117
118  size = ComputeFilesSize(path, FILE_PATH_LITERAL("History*"));
119  size_MB = static_cast<int>(size / kBytesInOneMB);
120  UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
121
122  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Cookies"));
123  size_MB = static_cast<int>(size / kBytesInOneMB);
124  UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
125
126  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Bookmarks"));
127  size_MB = static_cast<int>(size / kBytesInOneMB);
128  UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
129
130  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Favicons"));
131  size_MB = static_cast<int>(size / kBytesInOneMB);
132  UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
133
134  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Top Sites"));
135  size_MB = static_cast<int>(size / kBytesInOneMB);
136  UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
137
138  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Visited Links"));
139  size_MB = static_cast<int>(size / kBytesInOneMB);
140  UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
141
142  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Web Data"));
143  size_MB = static_cast<int>(size / kBytesInOneMB);
144  UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
145
146  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Extension*"));
147  size_MB = static_cast<int>(size / kBytesInOneMB);
148  UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
149
150  size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy"));
151  size_MB = static_cast<int>(size / kBytesInOneMB);
152  UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
153
154  // Count number of extensions in this profile, if we know.
155  if (extension_count != -1)
156    UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count);
157}
158
159void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
160  ProfilesToDelete().push_back(path);
161}
162
163bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) {
164  return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(),
165      profile_path) != ProfilesToDelete().end();
166}
167
168// Physically remove deleted profile directories from disk.
169void NukeProfileFromDisk(const base::FilePath& profile_path) {
170  // Delete both the profile directory and its corresponding cache.
171  base::FilePath cache_path;
172  chrome::GetUserCacheDirectory(profile_path, &cache_path);
173  base::DeleteFile(profile_path, true);
174  base::DeleteFile(cache_path, true);
175}
176
177#if defined(OS_CHROMEOS)
178void CheckCryptohomeIsMounted(chromeos::DBusMethodCallStatus call_status,
179                              bool is_mounted) {
180  if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
181    LOG(ERROR) << "IsMounted call failed.";
182    return;
183  }
184  if (!is_mounted)
185    LOG(ERROR) << "Cryptohome is not mounted.";
186}
187
188#endif
189
190} // namespace
191
192#if defined(ENABLE_SESSION_SERVICE)
193// static
194void ProfileManager::ShutdownSessionServices() {
195  ProfileManager* pm = g_browser_process->profile_manager();
196  if (!pm)  // Is NULL when running unit tests.
197    return;
198  std::vector<Profile*> profiles(pm->GetLoadedProfiles());
199  for (size_t i = 0; i < profiles.size(); ++i)
200    SessionServiceFactory::ShutdownForProfile(profiles[i]);
201}
202#endif
203
204// static
205void ProfileManager::NukeDeletedProfilesFromDisk() {
206  for (std::vector<base::FilePath>::iterator it =
207          ProfilesToDelete().begin();
208       it != ProfilesToDelete().end();
209       ++it) {
210    NukeProfileFromDisk(*it);
211  }
212  ProfilesToDelete().clear();
213}
214
215namespace {
216
217bool s_allow_get_default_profile = false;
218
219}  // namespace
220
221// static
222void ProfileManager::AllowGetDefaultProfile() {
223  s_allow_get_default_profile = true;
224}
225
226// static
227bool ProfileManager::IsGetDefaultProfileAllowed() {
228  return s_allow_get_default_profile;
229}
230
231// static
232// TODO(skuhne): Remove this method once all clients are migrated.
233Profile* ProfileManager::GetDefaultProfile() {
234  CHECK(s_allow_get_default_profile)
235      << "GetDefaultProfile() called before allowed.";
236  ProfileManager* profile_manager = g_browser_process->profile_manager();
237  return profile_manager->GetDefaultProfile(profile_manager->user_data_dir_);
238}
239
240// static
241// TODO(skuhne): Remove this method once all clients are migrated.
242Profile* ProfileManager::GetDefaultProfileOrOffTheRecord() {
243  return GetDefaultProfile();
244}
245
246// static
247Profile* ProfileManager::GetLastUsedProfile() {
248  ProfileManager* profile_manager = g_browser_process->profile_manager();
249  return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_);
250}
251
252// static
253Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
254  Profile* profile = GetLastUsedProfile();
255  if (IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
256      IncognitoModePrefs::FORCED) {
257    return profile->GetOffTheRecordProfile();
258  }
259  return profile;
260}
261
262// static
263std::vector<Profile*> ProfileManager::GetLastOpenedProfiles() {
264  ProfileManager* profile_manager = g_browser_process->profile_manager();
265  return profile_manager->GetLastOpenedProfiles(
266      profile_manager->user_data_dir_);
267}
268
269ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
270    : user_data_dir_(user_data_dir),
271      logged_in_(false),
272
273#if !defined(OS_ANDROID) && !defined(OS_IOS)
274      browser_list_observer_(this),
275#endif
276      closing_all_browsers_(false) {
277#if defined(OS_CHROMEOS)
278  registrar_.Add(
279      this,
280      chrome::NOTIFICATION_LOGIN_USER_CHANGED,
281      content::NotificationService::AllSources());
282#endif
283  registrar_.Add(
284      this,
285      chrome::NOTIFICATION_BROWSER_OPENED,
286      content::NotificationService::AllSources());
287  registrar_.Add(
288      this,
289      chrome::NOTIFICATION_BROWSER_CLOSED,
290      content::NotificationService::AllSources());
291  registrar_.Add(
292      this,
293      chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
294      content::NotificationService::AllSources());
295  registrar_.Add(
296      this,
297      chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
298      content::NotificationService::AllSources());
299  registrar_.Add(
300      this,
301      chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
302      content::NotificationService::AllSources());
303
304  if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
305    profile_shortcut_manager_.reset(ProfileShortcutManager::Create(
306                                    this));
307}
308
309ProfileManager::~ProfileManager() {
310}
311
312base::FilePath ProfileManager::GetInitialProfileDir() {
313  base::FilePath relative_profile_dir;
314#if defined(OS_CHROMEOS)
315  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
316  if (logged_in_) {
317    base::FilePath profile_dir;
318    // If the user has logged in, pick up the new profile.
319    if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
320      // TODO(nkostylev): Remove this code completely once we eliminate
321      // legacy --login-profile=user switch and enable multi-profiles on CrOS
322      // by default. http://crbug.com/294628
323      profile_dir = chromeos::ProfileHelper::
324          GetProfileDirByLegacyLoginProfileSwitch();
325    } else if (!command_line.HasSwitch(switches::kMultiProfiles)) {
326      // We should never be logged in with no profile dir unless
327      // multi-profiles are enabled.
328      // In that case profile dir will be defined by user_id hash.
329      NOTREACHED();
330      return base::FilePath("");
331    }
332    // In case of multi-profiles ignore --login-profile switch.
333    // TODO(nkostylev): Some cases like Guest mode will have empty username_hash
334    // so default kLoginProfile dir will be used.
335    std::string user_id_hash = g_browser_process->platform_part()->
336        profile_helper()->active_user_id_hash();
337    if (command_line.HasSwitch(switches::kMultiProfiles) &&
338        !user_id_hash.empty()) {
339      profile_dir = g_browser_process->platform_part()->
340          profile_helper()->GetActiveUserProfileDir();
341    }
342    relative_profile_dir = relative_profile_dir.Append(profile_dir);
343    return relative_profile_dir;
344  }
345#endif
346  // TODO(mirandac): should not automatically be default profile.
347  relative_profile_dir =
348      relative_profile_dir.AppendASCII(chrome::kInitialProfile);
349  return relative_profile_dir;
350}
351
352Profile* ProfileManager::GetLastUsedProfile(
353    const base::FilePath& user_data_dir) {
354#if defined(OS_CHROMEOS)
355  // Use default login profile if user has not logged in yet.
356  if (!logged_in_) {
357    return GetDefaultProfile(user_data_dir);
358  } else {
359    // CrOS multi-profiles implementation is different so GetLastUsedProfile
360    // has custom implementation too.
361    base::FilePath profile_dir;
362    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
363    if (command_line.HasSwitch(switches::kMultiProfiles)) {
364      // In case of multi-profiles we ignore "last used profile" preference
365      // since it may refer to profile that has been in use in previous session.
366      // That profile dir may not be mounted in this session so instead return
367      // active profile from current session.
368      profile_dir = g_browser_process->platform_part()->
369          profile_helper()->GetActiveUserProfileDir();
370    } else {
371      // For legacy (not multi-profiles) implementation always default to
372      // --login-profile value.
373      profile_dir =
374          chromeos::ProfileHelper::GetProfileDirByLegacyLoginProfileSwitch();
375    }
376
377    base::FilePath profile_path(user_data_dir);
378    Profile* profile = GetProfile(profile_path.Append(profile_dir));
379    return (profile && profile->IsGuestSession()) ?
380        profile->GetOffTheRecordProfile() : profile;
381  }
382#endif
383
384  return GetProfile(GetLastUsedProfileDir(user_data_dir));
385}
386
387base::FilePath ProfileManager::GetLastUsedProfileDir(
388    const base::FilePath& user_data_dir) {
389  base::FilePath last_used_profile_dir(user_data_dir);
390  PrefService* local_state = g_browser_process->local_state();
391  DCHECK(local_state);
392
393  if (local_state->HasPrefPath(prefs::kProfileLastUsed)) {
394    return last_used_profile_dir.AppendASCII(
395        local_state->GetString(prefs::kProfileLastUsed));
396  }
397
398  return last_used_profile_dir.AppendASCII(chrome::kInitialProfile);
399}
400
401std::vector<Profile*> ProfileManager::GetLastOpenedProfiles(
402    const base::FilePath& user_data_dir) {
403  PrefService* local_state = g_browser_process->local_state();
404  DCHECK(local_state);
405
406  std::vector<Profile*> to_return;
407  if (local_state->HasPrefPath(prefs::kProfilesLastActive) &&
408      local_state->GetList(prefs::kProfilesLastActive)) {
409    // Make a copy because the list might change in the calls to GetProfile.
410    scoped_ptr<base::ListValue> profile_list(
411        local_state->GetList(prefs::kProfilesLastActive)->DeepCopy());
412    base::ListValue::const_iterator it;
413    std::string profile;
414    for (it = profile_list->begin(); it != profile_list->end(); ++it) {
415      if (!(*it)->GetAsString(&profile) || profile.empty()) {
416        LOG(WARNING) << "Invalid entry in " << prefs::kProfilesLastActive;
417        continue;
418      }
419      to_return.push_back(GetProfile(user_data_dir.AppendASCII(profile)));
420    }
421  }
422  return to_return;
423}
424
425Profile* ProfileManager::GetPrimaryUserProfile() {
426#if defined(OS_CHROMEOS)
427  // TODO(skuhne): Remove once GetDefaultProfile is removed.
428  CHECK(s_allow_get_default_profile)
429      << "GetPrimaryUserProfile() called before allowed.";
430  ProfileManager* profile_manager = g_browser_process->profile_manager();
431  if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
432    return GetDefaultProfile();
433  chromeos::UserManager* manager = chromeos::UserManager::Get();
434  // Note: The user manager will take care of guest profiles.
435  return manager->GetProfileByUser(manager->GetPrimaryUser());
436#else
437  return GetDefaultProfile();
438#endif
439}
440
441Profile* ProfileManager::GetActiveUserProfile() {
442#if defined(OS_CHROMEOS)
443  // TODO(skuhne): Remove once GetDefaultProfile is removed.
444  CHECK(s_allow_get_default_profile)
445      << "GetActiveUserProfile() called before allowed.";
446  ProfileManager* profile_manager = g_browser_process->profile_manager();
447  if (!profile_manager->IsLoggedIn() || !chromeos::UserManager::IsInitialized())
448    return GetDefaultProfile();
449  chromeos::UserManager* manager = chromeos::UserManager::Get();
450  // Note: The user manager will take care of guest profiles.
451  return manager->GetProfileByUser(manager->GetActiveUser());
452#else
453  return GetDefaultProfile();
454#endif
455}
456
457// TODO(skuhne): Remove this method once all clients are migrated.
458Profile* ProfileManager::GetPrimaryUserProfileOrOffTheRecord() {
459  return GetPrimaryUserProfile();
460}
461
462// TODO(skuhne): Remove this method once all clients are migrated.
463Profile* ProfileManager::GetActiveUserProfileOrOffTheRecord() {
464  return GetActiveUserProfile();
465}
466
467Profile* ProfileManager::GetDefaultProfile(
468    const base::FilePath& user_data_dir) {
469#if defined(OS_CHROMEOS)
470  base::FilePath default_profile_dir(user_data_dir);
471  if (logged_in_) {
472    default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
473  } else {
474    default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
475  }
476#else
477  base::FilePath default_profile_dir(user_data_dir);
478  default_profile_dir = default_profile_dir.Append(GetInitialProfileDir());
479#endif
480#if defined(OS_CHROMEOS)
481  if (!logged_in_) {
482    Profile* profile = GetProfile(default_profile_dir);
483    // For cros, return the OTR profile so we never accidentally keep
484    // user data in an unencrypted profile. But doing this makes
485    // many of the browser and ui tests fail. We do return the OTR profile
486    // if the login-profile switch is passed so that we can test this.
487    if (ShouldGoOffTheRecord(profile))
488      return profile->GetOffTheRecordProfile();
489    DCHECK(!chromeos::UserManager::Get()->IsLoggedInAsGuest());
490    return profile;
491  }
492
493  ProfileInfo* profile_info = GetProfileInfoByPath(default_profile_dir);
494  // Fallback to default off-the-record profile, if user profile has not fully
495  // loaded yet.
496  if (profile_info && !profile_info->created)
497    default_profile_dir = profiles::GetDefaultProfileDir(user_data_dir);
498
499  Profile* profile = GetProfile(default_profile_dir);
500  // Some unit tests didn't initialize the UserManager.
501  if (chromeos::UserManager::IsInitialized() &&
502      chromeos::UserManager::Get()->IsLoggedInAsGuest())
503    return profile->GetOffTheRecordProfile();
504  return profile;
505#else
506  return GetProfile(default_profile_dir);
507#endif
508}
509
510bool ProfileManager::IsValidProfile(Profile* profile) {
511  for (ProfilesInfoMap::iterator iter = profiles_info_.begin();
512       iter != profiles_info_.end(); ++iter) {
513    if (iter->second->created) {
514      Profile* candidate = iter->second->profile.get();
515      if (candidate == profile ||
516          (candidate->HasOffTheRecordProfile() &&
517           candidate->GetOffTheRecordProfile() == profile)) {
518        return true;
519      }
520    }
521  }
522  return false;
523}
524
525std::vector<Profile*> ProfileManager::GetLoadedProfiles() const {
526  std::vector<Profile*> profiles;
527  for (ProfilesInfoMap::const_iterator iter = profiles_info_.begin();
528       iter != profiles_info_.end(); ++iter) {
529    if (iter->second->created)
530      profiles.push_back(iter->second->profile.get());
531  }
532  return profiles;
533}
534
535Profile* ProfileManager::GetProfile(const base::FilePath& profile_dir) {
536  TRACE_EVENT0("browser", "ProfileManager::GetProfile")
537  // If the profile is already loaded (e.g., chrome.exe launched twice), just
538  // return it.
539  Profile* profile = GetProfileByPath(profile_dir);
540  if (NULL != profile)
541    return profile;
542
543  profile = CreateProfileHelper(profile_dir);
544  DCHECK(profile);
545  if (profile) {
546    bool result = AddProfile(profile);
547    DCHECK(result);
548  }
549  return profile;
550}
551
552void ProfileManager::CreateProfileAsync(
553    const base::FilePath& profile_path,
554    const CreateCallback& callback,
555    const base::string16& name,
556    const base::string16& icon_url,
557    const std::string& managed_user_id) {
558  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
559
560  // Make sure that this profile is not pending deletion.
561  if (IsProfileMarkedForDeletion(profile_path)) {
562    if (!callback.is_null())
563      callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL);
564    return;
565  }
566
567  // Create the profile if needed and collect its ProfileInfo.
568  ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path);
569  ProfileInfo* info = NULL;
570
571  if (iter != profiles_info_.end()) {
572    info = iter->second.get();
573  } else {
574    // Initiate asynchronous creation process.
575    info = RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false);
576    ProfileInfoCache& cache = GetProfileInfoCache();
577    // Get the icon index from the user's icon url
578    size_t icon_index;
579    std::string icon_url_std = UTF16ToASCII(icon_url);
580    if (cache.IsDefaultAvatarIconUrl(icon_url_std, &icon_index)) {
581      // add profile to cache with user selected name and avatar
582      cache.AddProfileToCache(profile_path, name, base::string16(), icon_index,
583                              managed_user_id);
584    }
585
586    if (!managed_user_id.empty()) {
587      content::RecordAction(
588          UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
589    }
590
591    ProfileMetrics::UpdateReportedProfilesStatistics(this);
592  }
593
594  // Call or enqueue the callback.
595  if (!callback.is_null()) {
596    if (iter != profiles_info_.end() && info->created) {
597      Profile* profile = info->profile.get();
598      // If this was the guest profile, apply settings.
599      if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
600        SetGuestProfilePrefs(profile);
601      // Profile has already been created. Run callback immediately.
602      callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
603    } else {
604      // Profile is either already in the process of being created, or new.
605      // Add callback to the list.
606      info->callbacks.push_back(callback);
607    }
608  }
609}
610
611bool ProfileManager::AddProfile(Profile* profile) {
612  DCHECK(profile);
613
614  // Make sure that we're not loading a profile with the same ID as a profile
615  // that's already loaded.
616  if (GetProfileByPath(profile->GetPath())) {
617    NOTREACHED() << "Attempted to add profile with the same path (" <<
618                    profile->GetPath().value() <<
619                    ") as an already-loaded profile.";
620    return false;
621  }
622
623  RegisterProfile(profile, true);
624  InitProfileUserPrefs(profile);
625  DoFinalInit(profile, ShouldGoOffTheRecord(profile));
626  return true;
627}
628
629ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(
630    Profile* profile,
631    bool created) {
632  ProfileInfo* info = new ProfileInfo(profile, created);
633  profiles_info_.insert(
634      std::make_pair(profile->GetPath(), linked_ptr<ProfileInfo>(info)));
635  return info;
636}
637
638ProfileManager::ProfileInfo* ProfileManager::GetProfileInfoByPath(
639    const base::FilePath& path) const {
640  ProfilesInfoMap::const_iterator iter = profiles_info_.find(path);
641  return (iter == profiles_info_.end()) ? NULL : iter->second.get();
642}
643
644Profile* ProfileManager::GetProfileByPath(const base::FilePath& path) const {
645  ProfileInfo* profile_info = GetProfileInfoByPath(path);
646  return profile_info ? profile_info->profile.get() : NULL;
647}
648
649void ProfileManager::Observe(
650    int type,
651    const content::NotificationSource& source,
652    const content::NotificationDetails& details) {
653#if defined(OS_CHROMEOS)
654  if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
655    logged_in_ = true;
656
657    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
658    if (!command_line.HasSwitch(switches::kTestType)) {
659      // If we don't have a mounted profile directory we're in trouble.
660      // TODO(davemoore) Once we have better api this check should ensure that
661      // our profile directory is the one that's mounted, and that it's mounted
662      // as the current user.
663      chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->IsMounted(
664          base::Bind(&CheckCryptohomeIsMounted));
665
666      // Confirm that we hadn't loaded the new profile previously.
667      base::FilePath default_profile_dir = user_data_dir_.Append(
668          GetInitialProfileDir());
669      CHECK(!GetProfileByPath(default_profile_dir))
670          << "The default profile was loaded before we mounted the cryptohome.";
671    }
672    return;
673  }
674#endif
675  bool save_active_profiles = false;
676  switch (type) {
677    case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
678      // Ignore any browsers closing from now on.
679      closing_all_browsers_ = true;
680      save_active_profiles = true;
681      break;
682    }
683    case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
684      // This will cancel the shutdown process, so the active profiles are
685      // tracked again. Also, as the active profiles may have changed (i.e. if
686      // some windows were closed) we save the current list of active profiles
687      // again.
688      closing_all_browsers_ = false;
689      save_active_profiles = true;
690      break;
691    }
692    case chrome::NOTIFICATION_BROWSER_OPENED: {
693      Browser* browser = content::Source<Browser>(source).ptr();
694      DCHECK(browser);
695      Profile* profile = browser->profile();
696      DCHECK(profile);
697      bool is_ephemeral =
698          profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles);
699      if (!profile->IsOffTheRecord() && !is_ephemeral &&
700          ++browser_counts_[profile] == 1) {
701        active_profiles_.push_back(profile);
702        save_active_profiles = true;
703      }
704      // If browsers are opening, we can't be closing all the browsers. This
705      // can happen if the application was exited, but background mode or
706      // packaged apps prevented the process from shutting down, and then
707      // a new browser window was opened.
708      closing_all_browsers_ = false;
709      break;
710    }
711    case chrome::NOTIFICATION_BROWSER_CLOSED: {
712      Browser* browser = content::Source<Browser>(source).ptr();
713      DCHECK(browser);
714      Profile* profile = browser->profile();
715      DCHECK(profile);
716      if (!profile->IsOffTheRecord() && --browser_counts_[profile] == 0) {
717        active_profiles_.erase(std::find(active_profiles_.begin(),
718                                         active_profiles_.end(), profile));
719        save_active_profiles = !closing_all_browsers_;
720      }
721      break;
722    }
723    case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED: {
724      save_active_profiles = !closing_all_browsers_;
725      break;
726    }
727    default: {
728      NOTREACHED();
729      break;
730    }
731  }
732
733  if (save_active_profiles) {
734    PrefService* local_state = g_browser_process->local_state();
735    DCHECK(local_state);
736    ListPrefUpdate update(local_state, prefs::kProfilesLastActive);
737    ListValue* profile_list = update.Get();
738
739    profile_list->Clear();
740
741    // crbug.com/120112 -> several non-incognito profiles might have the same
742    // GetPath().BaseName(). In that case, we cannot restore both
743    // profiles. Include each base name only once in the last active profile
744    // list.
745    std::set<std::string> profile_paths;
746    std::vector<Profile*>::const_iterator it;
747    for (it = active_profiles_.begin(); it != active_profiles_.end(); ++it) {
748      std::string profile_path = (*it)->GetPath().BaseName().MaybeAsASCII();
749      // Some profiles might become ephemeral after they are created.
750      if (!(*it)->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
751          profile_paths.find(profile_path) == profile_paths.end()) {
752        profile_paths.insert(profile_path);
753        profile_list->Append(new StringValue(profile_path));
754      }
755    }
756  }
757}
758
759#if !defined(OS_ANDROID) && !defined(OS_IOS)
760ProfileManager::BrowserListObserver::BrowserListObserver(
761    ProfileManager* manager)
762    : profile_manager_(manager) {
763  BrowserList::AddObserver(this);
764}
765
766ProfileManager::BrowserListObserver::~BrowserListObserver() {
767  BrowserList::RemoveObserver(this);
768}
769
770void ProfileManager::BrowserListObserver::OnBrowserAdded(
771    Browser* browser) {}
772
773void ProfileManager::BrowserListObserver::OnBrowserRemoved(
774    Browser* browser) {
775  Profile* profile = browser->profile();
776  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
777    if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
778      // Not the last window for this profile.
779      return;
780  }
781
782  // If the last browser of a profile that is scheduled for deletion is closed
783  // do that now.
784  base::FilePath path = profile->GetPath();
785  if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles) &&
786      !IsProfileMarkedForDeletion(path)) {
787    g_browser_process->profile_manager()->ScheduleProfileForDeletion(
788        path, ProfileManager::CreateCallback());
789  }
790}
791
792void ProfileManager::BrowserListObserver::OnBrowserSetLastActive(
793    Browser* browser) {
794  // If all browsers are being closed (e.g. the user is in the process of
795  // shutting down), this event will be fired after each browser is
796  // closed. This does not represent a user intention to change the active
797  // browser so is not handled here.
798  if (profile_manager_->closing_all_browsers_)
799    return;
800
801  Profile* last_active = browser->profile();
802
803  // Don't remember ephemeral profiles as last because they are not going to
804  // persist after restart.
805  if (last_active->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles))
806    return;
807
808  PrefService* local_state = g_browser_process->local_state();
809  DCHECK(local_state);
810  // Only keep track of profiles that we are managing; tests may create others.
811  if (profile_manager_->profiles_info_.find(
812      last_active->GetPath()) != profile_manager_->profiles_info_.end()) {
813    local_state->SetString(prefs::kProfileLastUsed,
814                           last_active->GetPath().BaseName().MaybeAsASCII());
815  }
816}
817#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
818
819void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
820  DoFinalInitForServices(profile, go_off_the_record);
821  AddProfileToCache(profile);
822  DoFinalInitLogging(profile);
823
824  ProfileMetrics::LogNumberOfProfiles(this);
825  content::NotificationService::current()->Notify(
826      chrome::NOTIFICATION_PROFILE_ADDED,
827      content::Source<Profile>(profile),
828      content::NotificationService::NoDetails());
829}
830
831void ProfileManager::DoFinalInitForServices(Profile* profile,
832                                            bool go_off_the_record) {
833#if defined(ENABLE_EXTENSIONS)
834  extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
835      !go_off_the_record);
836  // During tests, when |profile| is an instance of TestingProfile,
837  // ExtensionSystem might not create an ExtensionService.
838  if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
839    profile->GetHostContentSettingsMap()->RegisterExtensionService(
840        extensions::ExtensionSystem::Get(profile)->extension_service());
841  }
842#endif
843#if defined(ENABLE_MANAGED_USERS)
844  // Initialization needs to happen after extension system initialization (for
845  // extension::ManagementPolicy) and InitProfileUserPrefs (for setting the
846  // initializing the managed flag if necessary).
847  ManagedUserServiceFactory::GetForProfile(profile)->Init();
848#endif
849  // Start the deferred task runners once the profile is loaded.
850  StartupTaskRunnerServiceFactory::GetForProfile(profile)->
851      StartDeferredTaskRunners();
852
853  if (profiles::IsNewProfileManagementEnabled())
854    AccountReconcilorFactory::GetForProfile(profile);
855}
856
857void ProfileManager::DoFinalInitLogging(Profile* profile) {
858  // Count number of extensions in this profile.
859  int extension_count = -1;
860#if defined(ENABLE_EXTENSIONS)
861  ExtensionService* extension_service = profile->GetExtensionService();
862  if (extension_service)
863    extension_count = extension_service->GetAppIds().size();
864#endif
865
866  // Log the profile size after a reasonable startup delay.
867  BrowserThread::PostDelayedTask(
868      BrowserThread::FILE, FROM_HERE,
869      base::Bind(&ProfileSizeTask, profile->GetPath(), extension_count),
870      base::TimeDelta::FromSeconds(112));
871}
872
873Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) {
874  return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
875}
876
877Profile* ProfileManager::CreateProfileAsyncHelper(const base::FilePath& path,
878                                                  Delegate* delegate) {
879  return Profile::CreateProfile(path,
880                                delegate,
881                                Profile::CREATE_MODE_ASYNCHRONOUS);
882}
883
884void ProfileManager::OnProfileCreated(Profile* profile,
885                                      bool success,
886                                      bool is_new_profile) {
887  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
888
889  ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath());
890  DCHECK(iter != profiles_info_.end());
891  ProfileInfo* info = iter->second.get();
892
893  std::vector<CreateCallback> callbacks;
894  info->callbacks.swap(callbacks);
895
896  // Invoke CREATED callback for normal profiles.
897  bool go_off_the_record = ShouldGoOffTheRecord(profile);
898  if (success && !go_off_the_record)
899    RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
900
901  // Perform initialization.
902  if (success) {
903    DoFinalInit(profile, go_off_the_record);
904    if (go_off_the_record)
905      profile = profile->GetOffTheRecordProfile();
906    info->created = true;
907  } else {
908    profile = NULL;
909    profiles_info_.erase(iter);
910  }
911
912  if (profile) {
913    // If this was the guest profile, finish setting its incognito status.
914    if (profile->GetPath() == ProfileManager::GetGuestProfilePath())
915      SetGuestProfilePrefs(profile);
916
917    // Invoke CREATED callback for incognito profiles.
918    if (go_off_the_record)
919      RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED);
920  }
921
922  // Invoke INITIALIZED or FAIL for all profiles.
923  RunCallbacks(callbacks, profile,
924               profile ? Profile::CREATE_STATUS_INITIALIZED :
925                         Profile::CREATE_STATUS_LOCAL_FAIL);
926}
927
928base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() {
929  PrefService* local_state = g_browser_process->local_state();
930  DCHECK(local_state);
931
932  DCHECK(profiles::IsMultipleProfilesEnabled());
933
934  // Create the next profile in the next available directory slot.
935  int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated);
936  std::string profile_name = chrome::kMultiProfileDirPrefix;
937  profile_name.append(base::IntToString(next_directory));
938  base::FilePath new_path = user_data_dir_;
939#if defined(OS_WIN)
940  new_path = new_path.Append(ASCIIToUTF16(profile_name));
941#else
942  new_path = new_path.Append(profile_name);
943#endif
944  local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory);
945  return new_path;
946}
947
948// static
949base::FilePath ProfileManager::CreateMultiProfileAsync(
950    const base::string16& name,
951    const base::string16& icon_url,
952    const CreateCallback& callback,
953    const std::string& managed_user_id) {
954  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
955
956  ProfileManager* profile_manager = g_browser_process->profile_manager();
957
958  base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
959
960  profile_manager->CreateProfileAsync(new_path,
961                                      callback,
962                                      name,
963                                      icon_url,
964                                      managed_user_id);
965  return new_path;
966}
967
968// static
969base::FilePath ProfileManager::GetGuestProfilePath() {
970  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
971
972  ProfileManager* profile_manager = g_browser_process->profile_manager();
973
974  base::FilePath guest_path = profile_manager->user_data_dir();
975  return guest_path.Append(chrome::kGuestProfileDir);
976}
977
978size_t ProfileManager::GetNumberOfProfiles() {
979  return GetProfileInfoCache().GetNumberOfProfiles();
980}
981
982bool ProfileManager::CompareProfilePathAndName(
983    const ProfileManager::ProfilePathAndName& pair1,
984    const ProfileManager::ProfilePathAndName& pair2) {
985  int name_compare = pair1.second.compare(pair2.second);
986  if (name_compare < 0) {
987    return true;
988  } else if (name_compare > 0) {
989    return false;
990  } else {
991    return pair1.first < pair2.first;
992  }
993}
994
995ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
996  if (!profile_info_cache_) {
997    profile_info_cache_.reset(new ProfileInfoCache(
998        g_browser_process->local_state(), user_data_dir_));
999  }
1000  return *profile_info_cache_.get();
1001}
1002
1003ProfileShortcutManager* ProfileManager::profile_shortcut_manager() {
1004  return profile_shortcut_manager_.get();
1005}
1006
1007void ProfileManager::AddProfileToCache(Profile* profile) {
1008  if (profile->IsGuestSession())
1009    return;
1010  ProfileInfoCache& cache = GetProfileInfoCache();
1011  if (profile->GetPath().DirName() != cache.GetUserDataDir())
1012    return;
1013
1014  if (cache.GetIndexOfProfileWithPath(profile->GetPath()) != std::string::npos)
1015    return;
1016
1017  base::string16 username = UTF8ToUTF16(profile->GetPrefs()->GetString(
1018      prefs::kGoogleServicesUsername));
1019
1020  // Profile name and avatar are set by InitProfileUserPrefs and stored in the
1021  // profile. Use those values to setup the cache entry.
1022  base::string16 profile_name = UTF8ToUTF16(profile->GetPrefs()->GetString(
1023      prefs::kProfileName));
1024
1025  size_t icon_index = profile->GetPrefs()->GetInteger(
1026      prefs::kProfileAvatarIndex);
1027
1028  std::string managed_user_id =
1029      profile->GetPrefs()->GetString(prefs::kManagedUserId);
1030
1031  cache.AddProfileToCache(profile->GetPath(),
1032                          profile_name,
1033                          username,
1034                          icon_index,
1035                          managed_user_id);
1036
1037  if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
1038    cache.SetProfileIsEphemeralAtIndex(
1039        cache.GetIndexOfProfileWithPath(profile->GetPath()), true);
1040  }
1041}
1042
1043void ProfileManager::InitProfileUserPrefs(Profile* profile) {
1044  ProfileInfoCache& cache = GetProfileInfoCache();
1045
1046  if (profile->GetPath().DirName() != cache.GetUserDataDir())
1047    return;
1048
1049  size_t avatar_index;
1050  std::string profile_name;
1051  std::string managed_user_id;
1052  if (profile->IsGuestSession()) {
1053    profile_name = l10n_util::GetStringUTF8(IDS_PROFILES_GUEST_PROFILE_NAME);
1054    avatar_index = 0;
1055  } else {
1056    size_t profile_cache_index =
1057        cache.GetIndexOfProfileWithPath(profile->GetPath());
1058    // If the cache has an entry for this profile, use the cache data.
1059    if (profile_cache_index != std::string::npos) {
1060      avatar_index =
1061          cache.GetAvatarIconIndexOfProfileAtIndex(profile_cache_index);
1062      profile_name =
1063          UTF16ToUTF8(cache.GetNameOfProfileAtIndex(profile_cache_index));
1064      managed_user_id =
1065          cache.GetManagedUserIdOfProfileAtIndex(profile_cache_index);
1066    } else if (profile->GetPath() ==
1067               profiles::GetDefaultProfileDir(cache.GetUserDataDir())) {
1068      avatar_index = 0;
1069      profile_name = l10n_util::GetStringUTF8(IDS_DEFAULT_PROFILE_NAME);
1070    } else {
1071      avatar_index = cache.ChooseAvatarIconIndexForNewProfile();
1072      profile_name = UTF16ToUTF8(cache.ChooseNameForNewProfile(avatar_index));
1073    }
1074  }
1075
1076  if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileAvatarIndex))
1077    profile->GetPrefs()->SetInteger(prefs::kProfileAvatarIndex, avatar_index);
1078
1079  if (!profile->GetPrefs()->HasPrefPath(prefs::kProfileName))
1080    profile->GetPrefs()->SetString(prefs::kProfileName, profile_name);
1081
1082  CommandLine* command_line = CommandLine::ForCurrentProcess();
1083  bool force_managed_user_id =
1084      command_line->HasSwitch(switches::kManagedUserId);
1085  if (force_managed_user_id) {
1086    managed_user_id =
1087        command_line->GetSwitchValueASCII(switches::kManagedUserId);
1088  }
1089  if (force_managed_user_id ||
1090      !profile->GetPrefs()->HasPrefPath(prefs::kManagedUserId)) {
1091    profile->GetPrefs()->SetString(prefs::kManagedUserId, managed_user_id);
1092  }
1093}
1094
1095void ProfileManager::SetGuestProfilePrefs(Profile* profile) {
1096  IncognitoModePrefs::SetAvailability(profile->GetPrefs(),
1097                                      IncognitoModePrefs::FORCED);
1098  profile->GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false);
1099}
1100
1101bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) {
1102  bool go_off_the_record = false;
1103#if defined(OS_CHROMEOS)
1104  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1105  if (command_line.HasSwitch(chromeos::switches::kGuestSession) ||
1106      (profile->GetPath().BaseName().value() == chrome::kInitialProfile &&
1107       (!command_line.HasSwitch(switches::kTestType) ||
1108       command_line.HasSwitch(chromeos::switches::kLoginProfile)))) {
1109    go_off_the_record = true;
1110  }
1111#endif
1112  return go_off_the_record;
1113}
1114
1115void ProfileManager::ScheduleProfileForDeletion(
1116    const base::FilePath& profile_dir,
1117    const CreateCallback& callback) {
1118  DCHECK(profiles::IsMultipleProfilesEnabled());
1119  PrefService* local_state = g_browser_process->local_state();
1120  ProfileInfoCache& cache = GetProfileInfoCache();
1121
1122  if (profile_dir.BaseName().MaybeAsASCII() ==
1123      local_state->GetString(prefs::kProfileLastUsed)) {
1124    // Update the last used profile pref before closing browser windows. This
1125    // way the correct last used profile is set for any notification observers.
1126    base::FilePath last_non_managed_profile_path;
1127    for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
1128      base::FilePath cur_path = cache.GetPathOfProfileAtIndex(i);
1129      // Make sure that this profile is not pending deletion.
1130      if (cur_path != profile_dir && !cache.ProfileIsManagedAtIndex(i) &&
1131          !IsProfileMarkedForDeletion(cur_path)) {
1132        last_non_managed_profile_path = cur_path;
1133        break;
1134      }
1135    }
1136
1137    // If we're deleting the last (non-managed) profile, then create a new
1138    // profile in its place.
1139    const std::string last_non_managed_profile =
1140        last_non_managed_profile_path.BaseName().MaybeAsASCII();
1141    if (last_non_managed_profile.empty()) {
1142      base::FilePath new_path = GenerateNextProfileDirectoryPath();
1143      // Make sure the last used profile path is pointing at it. This way the
1144      // correct last used profile is set for any notification observers.
1145      local_state->SetString(prefs::kProfileLastUsed,
1146                             new_path.BaseName().MaybeAsASCII());
1147      CreateProfileAsync(new_path,
1148                         callback,
1149                         base::string16(),
1150                         base::string16(),
1151                         std::string());
1152    } else {
1153      // On the Mac, the browser process is not killed when all browser windows
1154      // are closed, so just in case we are deleting the active profile, and no
1155      // other profile has been loaded, we must pre-load a next one.
1156#if defined(OS_MACOSX)
1157      CreateProfileAsync(last_non_managed_profile_path,
1158                         base::Bind(&ProfileManager::OnNewActiveProfileLoaded,
1159                                    base::Unretained(this),
1160                                    profile_dir,
1161                                    last_non_managed_profile_path,
1162                                    callback),
1163                         base::string16(),
1164                         base::string16(),
1165                         std::string());
1166      return;
1167#else
1168      // For OS_MACOSX the pref is updated in the callback to make sure that
1169      // it isn't used before the profile is actually loaded.
1170      local_state->SetString(prefs::kProfileLastUsed, last_non_managed_profile);
1171#endif
1172    }
1173  }
1174  FinishDeletingProfile(profile_dir);
1175}
1176
1177// static
1178void ProfileManager::CleanUpStaleProfiles(
1179    const std::vector<base::FilePath>& profile_paths) {
1180  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1181
1182  for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin();
1183       it != profile_paths.end(); ++it) {
1184    NukeProfileFromDisk(*it);
1185  }
1186}
1187
1188void ProfileManager::OnNewActiveProfileLoaded(
1189    const base::FilePath& profile_to_delete_path,
1190    const base::FilePath& last_non_managed_profile_path,
1191    const CreateCallback& original_callback,
1192    Profile* loaded_profile,
1193    Profile::CreateStatus status) {
1194  DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL &&
1195         status != Profile::CREATE_STATUS_REMOTE_FAIL);
1196
1197  // Only run the code if the profile initialization has finished completely.
1198  if (status == Profile::CREATE_STATUS_INITIALIZED) {
1199    if (IsProfileMarkedForDeletion(last_non_managed_profile_path)) {
1200      // If the profile we tried to load as the next active profile has been
1201      // deleted, then retry deleting this profile to redo the logic to load
1202      // the next available profile.
1203      ScheduleProfileForDeletion(profile_to_delete_path, original_callback);
1204    } else {
1205      // Update the local state as promised in the ScheduleProfileForDeletion.
1206      g_browser_process->local_state()->SetString(
1207          prefs::kProfileLastUsed,
1208          last_non_managed_profile_path.BaseName().MaybeAsASCII());
1209      FinishDeletingProfile(profile_to_delete_path);
1210    }
1211  }
1212}
1213
1214void ProfileManager::FinishDeletingProfile(const base::FilePath& profile_dir) {
1215  ProfileInfoCache& cache = GetProfileInfoCache();
1216  // TODO(sail): Due to bug 88586 we don't delete the profile instance. Once we
1217  // start deleting the profile instance we need to close background apps too.
1218  Profile* profile = GetProfileByPath(profile_dir);
1219
1220  if (profile) {
1221    BrowserList::CloseAllBrowsersWithProfile(profile);
1222
1223    // Disable sync for doomed profile.
1224    if (ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1225        profile)) {
1226      ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1227          profile)->DisableForUser();
1228    }
1229  }
1230
1231  QueueProfileDirectoryForDeletion(profile_dir);
1232  cache.DeleteProfileFromCache(profile_dir);
1233  ProfileMetrics::UpdateReportedProfilesStatistics(this);
1234}
1235
1236void ProfileManager::AutoloadProfiles() {
1237  // If running in the background is disabled for the browser, do not autoload
1238  // any profiles.
1239  PrefService* local_state = g_browser_process->local_state();
1240  if (!local_state->HasPrefPath(prefs::kBackgroundModeEnabled) ||
1241      !local_state->GetBoolean(prefs::kBackgroundModeEnabled)) {
1242    return;
1243  }
1244
1245  ProfileInfoCache& cache = GetProfileInfoCache();
1246  size_t number_of_profiles = cache.GetNumberOfProfiles();
1247  for (size_t p = 0; p < number_of_profiles; ++p) {
1248    if (cache.GetBackgroundStatusOfProfileAtIndex(p)) {
1249      // If status is true, that profile is running background apps. By calling
1250      // GetProfile, we automatically cause the profile to be loaded which will
1251      // register it with the BackgroundModeManager.
1252      GetProfile(cache.GetPathOfProfileAtIndex(p));
1253    }
1254  }
1255}
1256
1257ProfileManagerWithoutInit::ProfileManagerWithoutInit(
1258    const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) {
1259}
1260
1261void ProfileManager::RegisterTestingProfile(Profile* profile,
1262                                            bool add_to_cache,
1263                                            bool start_deferred_task_runners) {
1264  RegisterProfile(profile, true);
1265  if (add_to_cache) {
1266    InitProfileUserPrefs(profile);
1267    AddProfileToCache(profile);
1268  }
1269  if (start_deferred_task_runners) {
1270    StartupTaskRunnerServiceFactory::GetForProfile(profile)->
1271        StartDeferredTaskRunners();
1272  }
1273}
1274
1275void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks,
1276                                  Profile* profile,
1277                                  Profile::CreateStatus status) {
1278  for (size_t i = 0; i < callbacks.size(); ++i)
1279    callbacks[i].Run(profile, status);
1280}
1281
1282ProfileManager::ProfileInfo::ProfileInfo(
1283    Profile* profile,
1284    bool created)
1285    : profile(profile),
1286      created(created) {
1287}
1288
1289ProfileManager::ProfileInfo::~ProfileInfo() {
1290  ProfileDestroyer::DestroyProfileWhenAppropriate(profile.release());
1291}
1292