Chromium Code Reviews| 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 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. Call observer 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(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, |
| 372 observer); | 357 callback); |
|
Robert Sesek
2011/12/07 16:36:13
nit: Does this fit on one line now?
sail
2011/12/07 17:18:13
Done.
| |
| 373 } | 358 } |
| 374 | 359 |
| 375 bool ProfileManager::AddProfile(Profile* profile) { | 360 bool ProfileManager::AddProfile(Profile* profile) { |
| 376 DCHECK(profile); | 361 DCHECK(profile); |
| 377 | 362 |
| 378 // Make sure that we're not loading a profile with the same ID as a profile | 363 // Make sure that we're not loading a profile with the same ID as a profile |
| 379 // that's already loaded. | 364 // that's already loaded. |
| 380 if (GetProfileByPath(profile->GetPath())) { | 365 if (GetProfileByPath(profile->GetPath())) { |
| 381 NOTREACHED() << "Attempted to add profile with the same path (" << | 366 NOTREACHED() << "Attempted to add profile with the same path (" << |
| 382 profile->GetPath().value() << | 367 profile->GetPath().value() << |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 return Profile::CreateProfileAsync(path, delegate); | 481 return Profile::CreateProfileAsync(path, delegate); |
| 497 } | 482 } |
| 498 | 483 |
| 499 void ProfileManager::OnProfileCreated(Profile* profile, bool success) { | 484 void ProfileManager::OnProfileCreated(Profile* profile, bool success) { |
| 500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 501 | 486 |
| 502 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); | 487 ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); |
| 503 DCHECK(iter != profiles_info_.end()); | 488 DCHECK(iter != profiles_info_.end()); |
| 504 ProfileInfo* info = iter->second.get(); | 489 ProfileInfo* info = iter->second.get(); |
| 505 | 490 |
| 506 std::vector<ProfileManagerObserver*> observers; | 491 std::vector<CreateCallback> callbacks; |
| 507 info->observers.swap(observers); | 492 info->callbacks.swap(callbacks); |
| 508 | 493 |
| 494 // Invoke CREATED callback for normal profiles. | |
| 509 bool go_off_the_record = ShouldGoOffTheRecord(); | 495 bool go_off_the_record = ShouldGoOffTheRecord(); |
| 496 if (success & !go_off_the_record) { | |
|
Robert Sesek
2011/12/07 16:36:13
&&
sail
2011/12/07 17:18:13
Done.
| |
| 497 for (size_t i = 0; i < callbacks.size(); ++i) | |
| 498 callbacks[i].Run(profile, Profile::CREATE_STATUS_CREATED); | |
| 499 } | |
| 500 | |
| 510 if (success) { | 501 if (success) { |
|
Robert Sesek
2011/12/07 16:36:13
I think this if-block structure is less clear than
sail
2011/12/07 17:18:13
I found the original code very confusing which is
| |
| 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); | 502 DoFinalInit(profile, go_off_the_record); |
| 503 if (go_off_the_record) | |
| 504 profile = profile->GetOffTheRecordProfile(); | |
| 518 info->created = true; | 505 info->created = true; |
| 519 } else { | 506 } else { |
| 520 profile = NULL; | 507 profile = NULL; |
| 521 profiles_info_.erase(iter); | 508 profiles_info_.erase(iter); |
| 522 } | 509 } |
| 523 | 510 |
| 524 std::vector<ProfileManagerObserver*> observers_to_delete; | 511 // Invoke CREATED callback for incognito profiles. |
| 525 | 512 if (profile && go_off_the_record) { |
| 526 for (size_t i = 0; i < observers.size(); ++i) { | 513 for (size_t i = 0; i < callbacks.size(); ++i) |
| 527 if (profile && go_off_the_record) { | 514 callbacks[i].Run(profile, Profile::CREATE_STATUS_CREATED); |
|
Robert Sesek
2011/12/07 16:36:13
What's the point of the CREATED status? It seems l
sail
2011/12/07 17:18:13
It looks like CREATED was added for the ChromeOS c
| |
| 528 profile = profile->GetOffTheRecordProfile(); | |
| 529 DCHECK(profile); | |
| 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 } | 515 } |
| 539 | 516 |
| 540 STLDeleteElements(&observers_to_delete); | 517 // Invoke INITIALIZED or FAIL for all profiles. |
| 518 for (size_t i = 0; i < callbacks.size(); ++i) { | |
| 519 callbacks[i].Run(profile, profile ? Profile::CREATE_STATUS_INITIALIZED : | |
| 520 Profile::CREATE_STATUS_FAIL); | |
| 521 } | |
| 541 } | 522 } |
| 542 | 523 |
| 543 FilePath ProfileManager::GenerateNextProfileDirectoryPath() { | 524 FilePath ProfileManager::GenerateNextProfileDirectoryPath() { |
| 544 PrefService* local_state = g_browser_process->local_state(); | 525 PrefService* local_state = g_browser_process->local_state(); |
| 545 DCHECK(local_state); | 526 DCHECK(local_state); |
| 546 | 527 |
| 547 // Create the next profile in the next available directory slot. | 528 // Create the next profile in the next available directory slot. |
| 548 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); | 529 int next_directory = local_state->GetInteger(prefs::kProfilesNumCreated); |
| 549 std::string profile_name = chrome::kMultiProfileDirPrefix; | 530 std::string profile_name = chrome::kMultiProfileDirPrefix; |
| 550 profile_name.append(base::IntToString(next_directory)); | 531 profile_name.append(base::IntToString(next_directory)); |
| 551 FilePath new_path = user_data_dir_; | 532 FilePath new_path = user_data_dir_; |
| 552 #if defined(OS_WIN) | 533 #if defined(OS_WIN) |
| 553 new_path = new_path.Append(ASCIIToUTF16(profile_name)); | 534 new_path = new_path.Append(ASCIIToUTF16(profile_name)); |
| 554 #else | 535 #else |
| 555 new_path = new_path.Append(profile_name); | 536 new_path = new_path.Append(profile_name); |
| 556 #endif | 537 #endif |
| 557 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); | 538 local_state->SetInteger(prefs::kProfilesNumCreated, ++next_directory); |
| 558 return new_path; | 539 return new_path; |
| 559 } | 540 } |
| 560 | 541 |
| 561 // static | 542 // static |
| 562 void ProfileManager::CreateMultiProfileAsync() { | 543 void ProfileManager::CreateMultiProfileAsync() { |
| 563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 544 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 564 | 545 |
| 565 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 546 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| 566 | 547 |
| 567 FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); | 548 FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
| 568 | 549 |
| 569 // The launcher is deleted by the manager when profile creation is finished. | 550 profile_manager->CreateProfileAsync(new_path, |
| 570 NewProfileLauncher* launcher = new NewProfileLauncher(); | 551 base::Bind(&OnOpenWindowForNewProfile)); |
| 571 profile_manager->CreateProfileAsync(new_path, launcher); | |
| 572 } | 552 } |
| 573 | 553 |
| 574 // static | 554 // static |
| 575 void ProfileManager::RegisterPrefs(PrefService* prefs) { | 555 void ProfileManager::RegisterPrefs(PrefService* prefs) { |
| 576 prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); | 556 prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); |
| 577 prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); | 557 prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); |
| 578 } | 558 } |
| 579 | 559 |
| 580 size_t ProfileManager::GetNumberOfProfiles() { | 560 size_t ProfileManager::GetNumberOfProfiles() { |
| 581 return GetProfileInfoCache().GetNumberOfProfiles(); | 561 return GetProfileInfoCache().GetNumberOfProfiles(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 646 return go_off_the_record; | 626 return go_off_the_record; |
| 647 } | 627 } |
| 648 | 628 |
| 649 void ProfileManager::ScheduleProfileForDeletion(const FilePath& profile_dir) { | 629 void ProfileManager::ScheduleProfileForDeletion(const FilePath& profile_dir) { |
| 650 // If we're deleting the last profile, then create a new profile in its | 630 // If we're deleting the last profile, then create a new profile in its |
| 651 // place. | 631 // place. |
| 652 ProfileInfoCache& cache = GetProfileInfoCache(); | 632 ProfileInfoCache& cache = GetProfileInfoCache(); |
| 653 if (cache.GetNumberOfProfiles() == 1) { | 633 if (cache.GetNumberOfProfiles() == 1) { |
| 654 FilePath new_path = GenerateNextProfileDirectoryPath(); | 634 FilePath new_path = GenerateNextProfileDirectoryPath(); |
| 655 | 635 |
| 656 // The launcher is deleted by the manager when profile creation is finished. | 636 CreateProfileAsync(new_path, base::Bind(&OnOpenWindowForNewProfile)); |
| 657 NewProfileLauncher* launcher = new NewProfileLauncher(); | |
| 658 CreateProfileAsync(new_path, launcher); | |
| 659 } | 637 } |
| 660 | 638 |
| 661 // Update the last used profile pref before closing browser windows. This way | 639 // Update the last used profile pref before closing browser windows. This way |
| 662 // the correct last used profile is set for any notification observers. | 640 // the correct last used profile is set for any notification observers. |
| 663 PrefService* local_state = g_browser_process->local_state(); | 641 PrefService* local_state = g_browser_process->local_state(); |
| 664 std::string last_profile = local_state->GetString(prefs::kProfileLastUsed); | 642 std::string last_profile = local_state->GetString(prefs::kProfileLastUsed); |
| 665 if (profile_dir.BaseName().MaybeAsASCII() == last_profile) { | 643 if (profile_dir.BaseName().MaybeAsASCII() == last_profile) { |
| 666 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { | 644 for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { |
| 667 FilePath cur_path = cache.GetPathOfProfileAtIndex(i); | 645 FilePath cur_path = cache.GetPathOfProfileAtIndex(i); |
| 668 if (cur_path != profile_dir) { | 646 if (cur_path != profile_dir) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 719 RegisterProfile(profile, true); | 697 RegisterProfile(profile, true); |
| 720 if (add_to_cache) | 698 if (add_to_cache) |
| 721 AddProfileToCache(profile); | 699 AddProfileToCache(profile); |
| 722 } | 700 } |
| 723 | 701 |
| 724 #if defined(OS_WIN) | 702 #if defined(OS_WIN) |
| 725 void ProfileManager::RemoveProfileShortcutManagerForTesting() { | 703 void ProfileManager::RemoveProfileShortcutManagerForTesting() { |
| 726 profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get()); | 704 profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get()); |
| 727 } | 705 } |
| 728 #endif | 706 #endif |
| OLD | NEW |