| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <set> | 5 #include <set> |
| 6 | 6 |
| 7 #include "chrome/browser/profiles/profile_manager.h" | 7 #include "chrome/browser/profiles/profile_manager.h" |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/stl_util.h" | |
| 15 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
| 16 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 17 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 18 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/extensions/default_apps_trial.h" | 18 #include "chrome/browser/extensions/default_apps_trial.h" |
| 20 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
| 21 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
| 22 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 21 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 23 #include "chrome/browser/profiles/profile_info_cache.h" | 22 #include "chrome/browser/profiles/profile_info_cache.h" |
| 24 #include "chrome/browser/sessions/session_service_factory.h" | 23 #include "chrome/browser/sessions/session_service_factory.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 kDefaultAppsTrialName), | 134 kDefaultAppsTrialName), |
| 136 extension_count_); | 135 extension_count_); |
| 137 } | 136 } |
| 138 } | 137 } |
| 139 } | 138 } |
| 140 | 139 |
| 141 void QueueProfileDirectoryForDeletion(const FilePath& path) { | 140 void QueueProfileDirectoryForDeletion(const FilePath& path) { |
| 142 ProfilesToDelete().push_back(path); | 141 ProfilesToDelete().push_back(path); |
| 143 } | 142 } |
| 144 | 143 |
| 144 // Called upon completion of profile creation. This function takes care of |
| 145 // launching a new browser window and signing the user in to their Google |
| 146 // account. |
| 147 void OnOpenWindowForNewProfile(Profile* profile, |
| 148 Profile::CreateStatus status) { |
| 149 if (status == Profile::CREATE_STATUS_INITIALIZED) { |
| 150 ProfileManager::NewWindowWithProfile(profile, |
| 151 BrowserInit::IS_PROCESS_STARTUP, |
| 152 BrowserInit::IS_FIRST_RUN); |
| 153 } |
| 154 } |
| 155 |
| 145 } // namespace | 156 } // namespace |
| 146 | 157 |
| 147 bool ProfileManagerObserver::DeleteAfter() { | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 151 // The NewProfileLauncher class is created when to wait for a multi-profile | |
| 152 // to be created asynchronously. Upon completion of profile creation, the | |
| 153 // NPL takes care of launching a new browser window and signing the user | |
| 154 // in to their Google account. | |
| 155 class NewProfileLauncher : public ProfileManagerObserver { | |
| 156 public: | |
| 157 virtual void OnProfileCreated(Profile* profile, Status status) { | |
| 158 if (status == STATUS_INITIALIZED) { | |
| 159 ProfileManager::NewWindowWithProfile(profile, | |
| 160 BrowserInit::IS_PROCESS_STARTUP, | |
| 161 BrowserInit::IS_FIRST_RUN); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 virtual bool DeleteAfter() OVERRIDE { return true; } | |
| 166 }; | |
| 167 | |
| 168 // static | 158 // static |
| 169 void ProfileManager::ShutdownSessionServices() { | 159 void ProfileManager::ShutdownSessionServices() { |
| 170 ProfileManager* pm = g_browser_process->profile_manager(); | 160 ProfileManager* pm = g_browser_process->profile_manager(); |
| 171 if (!pm) // Is NULL when running unit tests. | 161 if (!pm) // Is NULL when running unit tests. |
| 172 return; | 162 return; |
| 173 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); | 163 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); |
| 174 for (size_t i = 0; i < profiles.size(); ++i) | 164 for (size_t i = 0; i < profiles.size(); ++i) |
| 175 SessionServiceFactory::ShutdownForProfile(profiles[i]); | 165 SessionServiceFactory::ShutdownForProfile(profiles[i]); |
| 176 } | 166 } |
| 177 | 167 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 | 315 |
| 326 profile = CreateProfileHelper(profile_dir); | 316 profile = CreateProfileHelper(profile_dir); |
| 327 DCHECK(profile); | 317 DCHECK(profile); |
| 328 if (profile) { | 318 if (profile) { |
| 329 bool result = AddProfile(profile); | 319 bool result = AddProfile(profile); |
| 330 DCHECK(result); | 320 DCHECK(result); |
| 331 } | 321 } |
| 332 return profile; | 322 return profile; |
| 333 } | 323 } |
| 334 | 324 |
| 335 void ProfileManager::CreateProfileAsync(const FilePath& user_data_dir, | 325 void ProfileManager::CreateProfileAsync(const FilePath& profile_path, |
| 336 ProfileManagerObserver* observer) { | 326 const CreateCallback& callback) { |
| 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 338 ProfilesInfoMap::iterator iter = profiles_info_.find(user_data_dir); | 328 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); |
| 339 if (iter != profiles_info_.end()) { | 329 if (iter != profiles_info_.end()) { |
| 340 ProfileInfo* info = iter->second.get(); | 330 ProfileInfo* info = iter->second.get(); |
| 341 if (info->created) { | 331 if (info->created) { |
| 342 // Profile has already been created. Call observer immediately. | 332 // Profile has already been created. Run callback immediately. |
| 343 observer->OnProfileCreated( | 333 callback.Run(info->profile.get(), Profile::CREATE_STATUS_INITIALIZED); |
| 344 info->profile.get(), ProfileManagerObserver::STATUS_INITIALIZED); | |
| 345 if (observer->DeleteAfter()) | |
| 346 delete observer; | |
| 347 } else { | 334 } else { |
| 348 // Profile is being created. Add observer to list. | 335 // Profile is being created. Add callback to list. |
| 349 info->observers.push_back(observer); | 336 info->callbacks.push_back(callback); |
| 350 } | 337 } |
| 351 } else { | 338 } else { |
| 352 // Initiate asynchronous creation process. | 339 // Initiate asynchronous creation process. |
| 353 ProfileInfo* info = | 340 ProfileInfo* info = |
| 354 RegisterProfile(CreateProfileAsyncHelper(user_data_dir, this), | 341 RegisterProfile(CreateProfileAsyncHelper(profile_path, this), false); |
| 355 false); | 342 info->callbacks.push_back(callback); |
| 356 info->observers.push_back(observer); | |
| 357 } | 343 } |
| 358 } | 344 } |
| 359 | 345 |
| 360 // static | 346 // static |
| 361 void ProfileManager::CreateDefaultProfileAsync( | 347 void ProfileManager::CreateDefaultProfileAsync(const CreateCallback& callback) { |
| 362 ProfileManagerObserver* observer) { | |
| 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 364 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 349 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| 365 | 350 |
| 366 FilePath default_profile_dir = profile_manager->user_data_dir_; | 351 FilePath default_profile_dir = profile_manager->user_data_dir_; |
| 367 // TODO(mirandac): current directory will not always be default in the future | 352 // TODO(mirandac): current directory will not always be default in the future |
| 368 default_profile_dir = default_profile_dir.Append( | 353 default_profile_dir = default_profile_dir.Append( |
| 369 profile_manager->GetInitialProfileDir()); | 354 profile_manager->GetInitialProfileDir()); |
| 370 | 355 |
| 371 profile_manager->CreateProfileAsync(default_profile_dir, | 356 profile_manager->CreateProfileAsync(default_profile_dir, callback); |
| 372 observer); | |
| 373 } | 357 } |
| 374 | 358 |
| 375 bool ProfileManager::AddProfile(Profile* profile) { | 359 bool ProfileManager::AddProfile(Profile* profile) { |
| 376 DCHECK(profile); | 360 DCHECK(profile); |
| 377 | 361 |
| 378 // Make sure that we're not loading a profile with the same ID as a profile | 362 // Make sure that we're not loading a profile with the same ID as a profile |
| 379 // that's already loaded. | 363 // that's already loaded. |
| 380 if (GetProfileByPath(profile->GetPath())) { | 364 if (GetProfileByPath(profile->GetPath())) { |
| 381 NOTREACHED() << "Attempted to add profile with the same path (" << | 365 NOTREACHED() << "Attempted to add profile with the same path (" << |
| 382 profile->GetPath().value() << | 366 profile->GetPath().value() << |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 return Profile::CreateProfileAsync(path, delegate); | 480 return Profile::CreateProfileAsync(path, delegate); |
| 497 } | 481 } |
| 498 | 482 |
| 499 void ProfileManager::OnProfileCreated(Profile* profile, bool success) { | 483 void ProfileManager::OnProfileCreated(Profile* profile, bool success) { |
| 500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 501 | 485 |
| 502 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); | 486 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); |
| 503 DCHECK(iter != profiles_info_.end()); | 487 DCHECK(iter != profiles_info_.end()); |
| 504 ProfileInfo* info = iter->second.get(); | 488 ProfileInfo* info = iter->second.get(); |
| 505 | 489 |
| 506 std::vector<ProfileManagerObserver*> observers; | 490 std::vector<CreateCallback> callbacks; |
| 507 info->observers.swap(observers); | 491 info->callbacks.swap(callbacks); |
| 508 | 492 |
| 493 // Invoke CREATED callback for normal profiles. |
| 509 bool go_off_the_record = ShouldGoOffTheRecord(); | 494 bool go_off_the_record = ShouldGoOffTheRecord(); |
| 495 if (success && !go_off_the_record) |
| 496 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
| 497 |
| 498 // Perform initialization. |
| 510 if (success) { | 499 if (success) { |
| 511 if (!go_off_the_record) { | |
| 512 for (size_t i = 0; i < observers.size(); ++i) { | |
| 513 observers[i]->OnProfileCreated( | |
| 514 profile, ProfileManagerObserver::STATUS_CREATED); | |
| 515 } | |
| 516 } | |
| 517 DoFinalInit(profile, go_off_the_record); | 500 DoFinalInit(profile, go_off_the_record); |
| 501 if (go_off_the_record) |
| 502 profile = profile->GetOffTheRecordProfile(); |
| 518 info->created = true; | 503 info->created = true; |
| 519 } else { | 504 } else { |
| 520 profile = NULL; | 505 profile = NULL; |
| 521 profiles_info_.erase(iter); | 506 profiles_info_.erase(iter); |
| 522 } | 507 } |
| 523 | 508 |
| 524 std::vector<ProfileManagerObserver*> observers_to_delete; | 509 // Invoke CREATED callback for incognito profiles. |
| 510 if (profile && go_off_the_record) |
| 511 RunCallbacks(callbacks, profile, Profile::CREATE_STATUS_CREATED); |
| 525 | 512 |
| 526 for (size_t i = 0; i < observers.size(); ++i) { | 513 // Invoke INITIALIZED or FAIL for all profiles. |
| 527 if (profile && go_off_the_record) { | 514 RunCallbacks(callbacks, profile, |
| 528 profile = profile->GetOffTheRecordProfile(); | 515 profile ? Profile::CREATE_STATUS_INITIALIZED : |
| 529 DCHECK(profile); | 516 Profile::CREATE_STATUS_FAIL); |
| 530 observers[i]->OnProfileCreated( | |
| 531 profile, ProfileManagerObserver::STATUS_CREATED); | |
| 532 } | |
| 533 observers[i]->OnProfileCreated( | |
| 534 profile, profile ? ProfileManagerObserver::STATUS_INITIALIZED : | |
| 535 ProfileManagerObserver::STATUS_FAIL); | |
| 536 if (observers[i]->DeleteAfter()) | |
| 537 observers_to_delete.push_back(observers[i]); | |
| 538 } | |
| 539 | |
| 540 STLDeleteElements(&observers_to_delete); | |
| 541 } | 517 } |
| 542 | 518 |
| 543 FilePath ProfileManager::GenerateNextProfileDirectoryPath() { | 519 FilePath ProfileManager::GenerateNextProfileDirectoryPath() { |
| 544 PrefService* local_state = g_browser_process->local_state(); | 520 PrefService* local_state = g_browser_process->local_state(); |
| 545 DCHECK(local_state); | 521 DCHECK(local_state); |
| 546 | 522 |
| 547 // Create the next profile in the next available directory slot. | 523 // Create the next profile in the next available directory slot. |
| 548 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); | 524 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); |
| 549 std::string profile_name = chrome::kMultiProfileDirPrefix; | 525 std::string profile_name = chrome::kMultiProfileDirPrefix; |
| 550 profile_name.append(base::IntToString(next_directory)); | 526 profile_name.append(base::IntToString(next_directory)); |
| 551 FilePath new_path = user_data_dir_; | 527 FilePath new_path = user_data_dir_; |
| 552 #if defined(OS_WIN) | 528 #if defined(OS_WIN) |
| 553 new_path = new_path.Append(ASCIIToUTF16(profile_name)); | 529 new_path = new_path.Append(ASCIIToUTF16(profile_name)); |
| 554 #else | 530 #else |
| 555 new_path = new_path.Append(profile_name); | 531 new_path = new_path.Append(profile_name); |
| 556 #endif | 532 #endif |
| 557 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); | 533 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); |
| 558 return new_path; | 534 return new_path; |
| 559 } | 535 } |
| 560 | 536 |
| 561 // static | 537 // static |
| 562 void ProfileManager::CreateMultiProfileAsync() { | 538 void ProfileManager::CreateMultiProfileAsync() { |
| 563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 564 | 540 |
| 565 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 541 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| 566 | 542 |
| 567 FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); | 543 FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
| 568 | 544 |
| 569 // The launcher is deleted by the manager when profile creation is finished. | 545 profile_manager->CreateProfileAsync(new_path, |
| 570 NewProfileLauncher* launcher = new NewProfileLauncher(); | 546 base::Bind(&OnOpenWindowForNewProfile)); |
| 571 profile_manager->CreateProfileAsync(new_path, launcher); | |
| 572 } | 547 } |
| 573 | 548 |
| 574 // static | 549 // static |
| 575 void ProfileManager::RegisterPrefs(PrefService* prefs) { | 550 void ProfileManager::RegisterPrefs(PrefService* prefs) { |
| 576 prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); | 551 prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); |
| 577 prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); | 552 prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); |
| 578 } | 553 } |
| 579 | 554 |
| 580 size_t ProfileManager::GetNumberOfProfiles() { | 555 size_t ProfileManager::GetNumberOfProfiles() { |
| 581 return GetProfileInfoCache().GetNumberOfProfiles(); | 556 return GetProfileInfoCache().GetNumberOfProfiles(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 return go_off_the_record; | 621 return go_off_the_record; |
| 647 } | 622 } |
| 648 | 623 |
| 649 void ProfileManager::ScheduleProfileForDeletion(const FilePath& profile_dir) { | 624 void ProfileManager::ScheduleProfileForDeletion(const FilePath& profile_dir) { |
| 650 // If we're deleting the last profile, then create a new profile in its | 625 // If we're deleting the last profile, then create a new profile in its |
| 651 // place. | 626 // place. |
| 652 ProfileInfoCache& cache = GetProfileInfoCache(); | 627 ProfileInfoCache& cache = GetProfileInfoCache(); |
| 653 if (cache.GetNumberOfProfiles() == 1) { | 628 if (cache.GetNumberOfProfiles() == 1) { |
| 654 FilePath new_path = GenerateNextProfileDirectoryPath(); | 629 FilePath new_path = GenerateNextProfileDirectoryPath(); |
| 655 | 630 |
| 656 // The launcher is deleted by the manager when profile creation is finished. | 631 CreateProfileAsync(new_path, base::Bind(&OnOpenWindowForNewProfile)); |
| 657 NewProfileLauncher* launcher = new NewProfileLauncher(); | |
| 658 CreateProfileAsync(new_path, launcher); | |
| 659 } | 632 } |
| 660 | 633 |
| 661 // Update the last used profile pref before closing browser windows. This way | 634 // Update the last used profile pref before closing browser windows. This way |
| 662 // the correct last used profile is set for any notification observers. | 635 // the correct last used profile is set for any notification observers. |
| 663 PrefService* local_state = g_browser_process->local_state(); | 636 PrefService* local_state = g_browser_process->local_state(); |
| 664 std::string last_profile = local_state->GetString(prefs::kProfileLastUsed); | 637 std::string last_profile = local_state->GetString(prefs::kProfileLastUsed); |
| 665 if (profile_dir.BaseName().MaybeAsASCII() == last_profile) { | 638 if (profile_dir.BaseName().MaybeAsASCII() == last_profile) { |
| 666 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | 639 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
| 667 FilePath cur_path = cache.GetPathOfProfileAtIndex(i); | 640 FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
| 668 if (cur_path != profile_dir) { | 641 if (cur_path != profile_dir) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 RegisterProfile(profile, true); | 692 RegisterProfile(profile, true); |
| 720 if (add_to_cache) | 693 if (add_to_cache) |
| 721 AddProfileToCache(profile); | 694 AddProfileToCache(profile); |
| 722 } | 695 } |
| 723 | 696 |
| 724 #if defined(OS_WIN) | 697 #if defined(OS_WIN) |
| 725 void ProfileManager::RemoveProfileShortcutManagerForTesting() { | 698 void ProfileManager::RemoveProfileShortcutManagerForTesting() { |
| 726 profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get()); | 699 profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get()); |
| 727 } | 700 } |
| 728 #endif | 701 #endif |
| 702 |
| 703 void ProfileManager::RunCallbacks(const std::vector<CreateCallback>& callbacks, |
| 704 Profile* profile, |
| 705 Profile::CreateStatus status) { |
| 706 for (size_t i = 0; i < callbacks.size(); ++i) |
| 707 callbacks[i].Run(profile, status); |
| 708 } |
| OLD | NEW |