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