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 "chrome/browser/chromeos/login/user_manager.h" | 5 #include "chrome/browser/chromeos/login/user_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 // depends on that and it's hard to figure out what). | 69 // depends on that and it's hard to figure out what). |
70 const char kGuestUser[] = ""; | 70 const char kGuestUser[] = ""; |
71 | 71 |
72 // Stub user email (for test paths). | 72 // Stub user email (for test paths). |
73 const char kStubUser[] = "stub-user@example.com"; | 73 const char kStubUser[] = "stub-user@example.com"; |
74 | 74 |
75 // Names of nodes with info about user image. | 75 // Names of nodes with info about user image. |
76 const char kImagePathNodeName[] = "path"; | 76 const char kImagePathNodeName[] = "path"; |
77 const char kImageIndexNodeName[] = "index"; | 77 const char kImageIndexNodeName[] = "index"; |
78 | 78 |
| 79 // Index of the default image used as stub while the real user image is loading |
| 80 // from file and for the |kStubUser| user. |
| 81 const int kStubDefaultImageIndex = 0; |
| 82 |
79 // Delay betweeen user login and attempt to update user's profile image. | 83 // Delay betweeen user login and attempt to update user's profile image. |
80 const long kProfileImageDownloadDelayMs = 10000; | 84 const long kProfileImageDownloadDelayMs = 10000; |
81 | 85 |
82 base::LazyInstance<UserManager> g_user_manager(base::LINKER_INITIALIZED); | 86 base::LazyInstance<UserManager> g_user_manager(base::LINKER_INITIALIZED); |
83 | 87 |
84 // Used to handle the asynchronous response of deleting a cryptohome directory. | 88 // Used to handle the asynchronous response of deleting a cryptohome directory. |
85 class RemoveAttempt : public CryptohomeLibrary::Delegate { | 89 class RemoveAttempt : public CryptohomeLibrary::Delegate { |
86 public: | 90 public: |
87 // Creates new remove attempt for the given user. Note, |delegate| can | 91 // Creates new remove attempt for the given user. Note, |delegate| can |
88 // be NULL. | 92 // be NULL. |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 return static_cast<User::OAuthTokenStatus>(oauth_token_status); | 414 return static_cast<User::OAuthTokenStatus>(oauth_token_status); |
411 } | 415 } |
412 } | 416 } |
413 | 417 |
414 return User::OAUTH_TOKEN_STATUS_UNKNOWN; | 418 return User::OAUTH_TOKEN_STATUS_UNKNOWN; |
415 } | 419 } |
416 | 420 |
417 void UserManager::SaveUserDefaultImageIndex(const std::string& username, | 421 void UserManager::SaveUserDefaultImageIndex(const std::string& username, |
418 int image_index) { | 422 int image_index) { |
419 DCHECK(image_index >= 0 && image_index < kDefaultImagesCount); | 423 DCHECK(image_index >= 0 && image_index < kDefaultImagesCount); |
420 SetUserImage(username, image_index, | 424 SetUserImage(username, image_index, GetDefaultImage(image_index)); |
421 *ResourceBundle::GetSharedInstance(). | |
422 GetBitmapNamed(kDefaultImageResources[image_index])); | |
423 SaveImageToLocalState(username, "", image_index, false); | 425 SaveImageToLocalState(username, "", image_index, false); |
424 } | 426 } |
425 | 427 |
426 void UserManager::SaveUserImage(const std::string& username, | 428 void UserManager::SaveUserImage(const std::string& username, |
427 const SkBitmap& image) { | 429 const SkBitmap& image) { |
428 SaveUserImageInternal(username, User::kExternalImageIndex, image); | 430 SaveUserImageInternal(username, User::kExternalImageIndex, image); |
429 } | 431 } |
430 | 432 |
431 void UserManager::SaveUserImageFromFile(const std::string& username, | 433 void UserManager::SaveUserImageFromFile(const std::string& username, |
432 const FilePath& path) { | 434 const FilePath& path) { |
(...skipping 11 matching lines...) Expand all Loading... |
444 } else { | 446 } else { |
445 // No profile image - use the default gray avatar. | 447 // No profile image - use the default gray avatar. |
446 SetUserImage(username, User::kProfileImageIndex, | 448 SetUserImage(username, User::kProfileImageIndex, |
447 *ResourceBundle::GetSharedInstance(). | 449 *ResourceBundle::GetSharedInstance(). |
448 GetBitmapNamed(IDR_PROFILE_PICTURE_LOADING)); | 450 GetBitmapNamed(IDR_PROFILE_PICTURE_LOADING)); |
449 SaveImageToLocalState(username, "", User::kProfileImageIndex, false); | 451 SaveImageToLocalState(username, "", User::kProfileImageIndex, false); |
450 } | 452 } |
451 } | 453 } |
452 | 454 |
453 void UserManager::DownloadProfileImage() { | 455 void UserManager::DownloadProfileImage() { |
454 if (!profile_image_downloader_.get()) | 456 if (profile_image_downloader_.get()) { |
455 profile_image_downloader_.reset(new ProfileImageDownloader(this)); | 457 // Another download is already in progress |
| 458 return; |
| 459 } |
| 460 profile_image_downloader_.reset(new ProfileImageDownloader(this)); |
456 profile_image_downloader_->Start(); | 461 profile_image_downloader_->Start(); |
457 profile_image_load_start_time_ = base::Time::Now(); | 462 profile_image_load_start_time_ = base::Time::Now(); |
458 } | 463 } |
459 | 464 |
460 void UserManager::Observe(int type, | 465 void UserManager::Observe(int type, |
461 const content::NotificationSource& source, | 466 const content::NotificationSource& source, |
462 const content::NotificationDetails& details) { | 467 const content::NotificationDetails& details) { |
463 if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) { | 468 if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) { |
464 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 469 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
465 base::Bind(&UserManager::CheckOwnership, | 470 base::Bind(&UserManager::CheckOwnership, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 | 551 |
547 if (prefs_images) { | 552 if (prefs_images) { |
548 // Get account image path. | 553 // Get account image path. |
549 // TODO(avayvod): Reading image path as a string is here for | 554 // TODO(avayvod): Reading image path as a string is here for |
550 // backward compatibility. | 555 // backward compatibility. |
551 std::string image_path; | 556 std::string image_path; |
552 base::DictionaryValue* image_properties; | 557 base::DictionaryValue* image_properties; |
553 if (prefs_images->GetStringWithoutPathExpansion(email, &image_path)) { | 558 if (prefs_images->GetStringWithoutPathExpansion(email, &image_path)) { |
554 int image_id = User::kInvalidImageIndex; | 559 int image_id = User::kInvalidImageIndex; |
555 if (IsDefaultImagePath(image_path, &image_id)) { | 560 if (IsDefaultImagePath(image_path, &image_id)) { |
556 DCHECK(image_id >= 0 && image_id < kDefaultImagesCount); | 561 user->SetImage(GetDefaultImage(image_id), image_id); |
557 int resource_id = kDefaultImageResources[image_id]; | |
558 user->SetImage(*ResourceBundle::GetSharedInstance(). | |
559 GetBitmapNamed(resource_id), | |
560 image_id); | |
561 } else { | 562 } else { |
562 int image_index = User::kExternalImageIndex; | 563 int image_index = User::kExternalImageIndex; |
| 564 // Until image has been loaded, use a stub. |
| 565 user->SetImage(GetDefaultImage(kStubDefaultImageIndex), |
| 566 image_index); |
| 567 DCHECK(!image_path.empty()); |
563 // Load user image asynchronously. | 568 // Load user image asynchronously. |
564 image_loader_->Start( | 569 image_loader_->Start( |
565 image_path, 0, | 570 image_path, 0, |
566 base::Bind(&UserManager::SetUserImage, | 571 base::Bind(&UserManager::SetUserImage, |
567 base::Unretained(this), email, image_index)); | 572 base::Unretained(this), email, image_index)); |
568 } | 573 } |
569 } else if (prefs_images->GetDictionaryWithoutPathExpansion( | 574 } else if (prefs_images->GetDictionaryWithoutPathExpansion( |
570 email, &image_properties)) { | 575 email, &image_properties)) { |
571 int image_index = User::kInvalidImageIndex; | 576 int image_index = User::kInvalidImageIndex; |
572 image_properties->GetString(kImagePathNodeName, &image_path); | 577 image_properties->GetString(kImagePathNodeName, &image_path); |
573 image_properties->GetInteger(kImageIndexNodeName, &image_index); | 578 image_properties->GetInteger(kImageIndexNodeName, &image_index); |
574 if (image_index >= 0 && image_index < kDefaultImagesCount) { | 579 if (image_index >= 0 && image_index < kDefaultImagesCount) { |
575 int resource_id = kDefaultImageResources[image_index]; | 580 user->SetImage(GetDefaultImage(image_index), image_index); |
576 user->SetImage(*ResourceBundle::GetSharedInstance(). | |
577 GetBitmapNamed(resource_id), | |
578 image_index); | |
579 } else if (image_index == User::kProfileImageIndex && | |
580 image_path.empty()) { | |
581 // User has profile image as his picture but no profile image | |
582 // has been downloaded yet, so use a grey avatar for now. | |
583 user->SetImage(*ResourceBundle::GetSharedInstance(). | |
584 GetBitmapNamed(IDR_PROFILE_PICTURE_LOADING), | |
585 User::kProfileImageIndex); | |
586 } else if (image_index == User::kExternalImageIndex || | 581 } else if (image_index == User::kExternalImageIndex || |
587 image_index == User::kProfileImageIndex) { | 582 image_index == User::kProfileImageIndex) { |
588 // Load user image asynchronously. | 583 // Path may be empty for profile images (meaning that the image |
589 image_loader_->Start( | 584 // hasn't been downloaded for the first time yet, in which case a |
590 image_path, 0, | 585 // download will be scheduled for |kProfileImageDownloadDelayMs| |
591 base::Bind(&UserManager::SetUserImage, | 586 // after user logs in). |
592 base::Unretained(this), email, image_index)); | 587 DCHECK(!image_path.empty() || |
| 588 image_index == User::kProfileImageIndex); |
| 589 // Until image has been loaded, use a stub. |
| 590 user->SetImage(GetDefaultImage(kStubDefaultImageIndex), |
| 591 image_index); |
| 592 if (!image_path.empty()) { |
| 593 // Load user image asynchronously. |
| 594 image_loader_->Start( |
| 595 image_path, 0, |
| 596 base::Bind(&UserManager::SetUserImage, |
| 597 base::Unretained(this), email, image_index)); |
| 598 } |
593 } else { | 599 } else { |
594 NOTREACHED(); | 600 NOTREACHED(); |
595 } | 601 } |
596 } | 602 } |
597 } | 603 } |
598 } | 604 } |
599 } | 605 } |
600 } | 606 } |
601 } | 607 } |
602 | 608 |
603 void UserManager::StubUserLoggedIn() { | 609 void UserManager::StubUserLoggedIn() { |
604 logged_in_user_ = &stub_user_; | 610 logged_in_user_ = &stub_user_; |
605 SetUserImage(stub_user_.email(), 0, | 611 stub_user_.SetImage(GetDefaultImage(kStubDefaultImageIndex), |
606 *ResourceBundle::GetSharedInstance(). | 612 kStubDefaultImageIndex); |
607 GetBitmapNamed(kDefaultImageResources[0])); | |
608 } | 613 } |
609 | 614 |
610 void UserManager::NotifyOnLogin() { | 615 void UserManager::NotifyOnLogin() { |
611 content::NotificationService::current()->Notify( | 616 content::NotificationService::current()->Notify( |
612 chrome::NOTIFICATION_LOGIN_USER_CHANGED, | 617 chrome::NOTIFICATION_LOGIN_USER_CHANGED, |
613 content::Source<UserManager>(this), | 618 content::Source<UserManager>(this), |
614 content::Details<const User>(logged_in_user_)); | 619 content::Details<const User>(logged_in_user_)); |
615 | 620 |
616 chromeos::input_method::InputMethodManager::GetInstance()-> | 621 chromeos::input_method::InputMethodManager::GetInstance()-> |
617 SetDeferImeStartup(false); | 622 SetDeferImeStartup(false); |
(...skipping 30 matching lines...) Expand all Loading... |
648 // Choose a random default image. | 653 // Choose a random default image. |
649 int image_id = base::RandInt(0, kDefaultImagesCount - 1); | 654 int image_id = base::RandInt(0, kDefaultImagesCount - 1); |
650 SaveUserDefaultImageIndex(username, image_id); | 655 SaveUserDefaultImageIndex(username, image_id); |
651 } | 656 } |
652 | 657 |
653 void UserManager::SetUserImage(const std::string& username, | 658 void UserManager::SetUserImage(const std::string& username, |
654 int image_index, | 659 int image_index, |
655 const SkBitmap& image) { | 660 const SkBitmap& image) { |
656 User* user = const_cast<User*>(FindUser(username)); | 661 User* user = const_cast<User*>(FindUser(username)); |
657 // User may have been removed by now. | 662 // User may have been removed by now. |
658 if (user) | 663 if (user) { |
| 664 // For existing users, a valid image index should have been set upon loading |
| 665 // them from Local State. |
| 666 DCHECK(user->image_index() != User::kInvalidImageIndex || |
| 667 current_user_is_new_); |
| 668 bool image_changed = user->image_index() != User::kInvalidImageIndex; |
659 user->SetImage(image, image_index); | 669 user->SetImage(image, image_index); |
| 670 if (image_changed) { |
| 671 // Unless this is first-time setting with |SetInitialUserImage|, |
| 672 // send a notification about image change. |
| 673 content::NotificationService::current()->Notify( |
| 674 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, |
| 675 content::Source<UserManager>(this), |
| 676 content::Details<const User>(user)); |
| 677 } |
| 678 } |
660 } | 679 } |
661 | 680 |
662 void UserManager::SaveUserImageInternal(const std::string& username, | 681 void UserManager::SaveUserImageInternal(const std::string& username, |
663 int image_index, | 682 int image_index, |
664 const SkBitmap& image) { | 683 const SkBitmap& image) { |
665 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 684 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
666 | 685 |
667 SetUserImage(username, image_index, image); | 686 SetUserImage(username, image_index, image); |
668 | 687 |
669 FilePath image_path = GetImagePathForUser(username); | 688 FilePath image_path = GetImagePathForUser(username); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 DictionaryPrefUpdate images_update(local_state, kUserImages); | 746 DictionaryPrefUpdate images_update(local_state, kUserImages); |
728 base::DictionaryValue* image_properties = new base::DictionaryValue(); | 747 base::DictionaryValue* image_properties = new base::DictionaryValue(); |
729 image_properties->Set(kImagePathNodeName, new StringValue(image_path)); | 748 image_properties->Set(kImagePathNodeName, new StringValue(image_path)); |
730 image_properties->Set(kImageIndexNodeName, | 749 image_properties->Set(kImageIndexNodeName, |
731 new base::FundamentalValue(image_index)); | 750 new base::FundamentalValue(image_index)); |
732 images_update->SetWithoutPathExpansion(username, image_properties); | 751 images_update->SetWithoutPathExpansion(username, image_properties); |
733 DVLOG(1) << "Saving path to user image in Local State."; | 752 DVLOG(1) << "Saving path to user image in Local State."; |
734 local_state->ScheduleSavePersistentPrefs(); | 753 local_state->ScheduleSavePersistentPrefs(); |
735 | 754 |
736 NotifyLocalStateChanged(); | 755 NotifyLocalStateChanged(); |
737 content::NotificationService::current()->Notify( | |
738 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, | |
739 content::Source<UserManager>(this), | |
740 content::Details<const User>(logged_in_user_)); | |
741 } | 756 } |
742 | 757 |
743 void UserManager::DeleteUserImage(const FilePath& image_path) { | 758 void UserManager::DeleteUserImage(const FilePath& image_path) { |
744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
745 if (!file_util::Delete(image_path, false)) { | 760 if (!file_util::Delete(image_path, false)) { |
746 LOG(ERROR) << "Failed to remove user image."; | 761 LOG(ERROR) << "Failed to remove user image."; |
747 return; | 762 return; |
748 } | 763 } |
749 } | 764 } |
750 | 765 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 ProfileImageDownloader::kDownloadResultsCount); | 820 ProfileImageDownloader::kDownloadResultsCount); |
806 | 821 |
807 // This will persist |downloaded_profile_image_| to file. | 822 // This will persist |downloaded_profile_image_| to file. |
808 SaveUserImageFromProfileImage(logged_in_user().email()); | 823 SaveUserImageFromProfileImage(logged_in_user().email()); |
809 } | 824 } |
810 | 825 |
811 content::NotificationService::current()->Notify( | 826 content::NotificationService::current()->Notify( |
812 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED, | 827 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED, |
813 content::Source<UserManager>(this), | 828 content::Source<UserManager>(this), |
814 content::Details<const SkBitmap>(&image)); | 829 content::Details<const SkBitmap>(&image)); |
| 830 |
| 831 profile_image_downloader_.reset(); |
815 } | 832 } |
816 | 833 |
817 void UserManager::OnDownloadFailure() { | 834 void UserManager::OnDownloadFailure() { |
818 VLOG(1) << "Download of profile image for logged-in user failed."; | 835 VLOG(1) << "Download of profile image for logged-in user failed."; |
819 UMA_HISTOGRAM_ENUMERATION("UserImageDownloadResult.LoggedIn", | 836 UMA_HISTOGRAM_ENUMERATION("UserImageDownloadResult.LoggedIn", |
820 ProfileImageDownloader::kDownloadFailure, | 837 ProfileImageDownloader::kDownloadFailure, |
821 ProfileImageDownloader::kDownloadResultsCount); | 838 ProfileImageDownloader::kDownloadResultsCount); |
822 content::NotificationService::current()->Notify( | 839 content::NotificationService::current()->Notify( |
823 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED, | 840 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED, |
824 content::Source<UserManager>(this), | 841 content::Source<UserManager>(this), |
825 content::NotificationService::NoDetails()); | 842 content::NotificationService::NoDetails()); |
| 843 profile_image_downloader_.reset(); |
826 } | 844 } |
827 | 845 |
828 void UserManager::OnDownloadDefaultImage() { | 846 void UserManager::OnDownloadDefaultImage() { |
829 VLOG(1) << "Logged-in user still has the default profile image."; | 847 VLOG(1) << "Logged-in user still has the default profile image."; |
830 UMA_HISTOGRAM_ENUMERATION("UserImageDownloadResult.LoggedIn", | 848 UMA_HISTOGRAM_ENUMERATION("UserImageDownloadResult.LoggedIn", |
831 ProfileImageDownloader::kDownloadDefault, | 849 ProfileImageDownloader::kDownloadDefault, |
832 ProfileImageDownloader::kDownloadResultsCount); | 850 ProfileImageDownloader::kDownloadResultsCount); |
833 content::NotificationService::current()->Notify( | 851 content::NotificationService::current()->Notify( |
834 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED, | 852 chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED, |
835 content::Source<UserManager>(this), | 853 content::Source<UserManager>(this), |
836 content::NotificationService::NoDetails()); | 854 content::NotificationService::NoDetails()); |
| 855 profile_image_downloader_.reset(); |
837 } | 856 } |
838 | 857 |
839 User* UserManager::CreateUser(const std::string& email) const { | 858 User* UserManager::CreateUser(const std::string& email) const { |
840 User* user = new User(email); | 859 User* user = new User(email); |
841 user->set_oauth_token_status(GetUserOAuthStatus(email)); | 860 user->set_oauth_token_status(GetUserOAuthStatus(email)); |
842 // Used to determine whether user's display name is unique. | 861 // Used to determine whether user's display name is unique. |
843 ++display_name_count_[user->GetDisplayName()]; | 862 ++display_name_count_[user->GetDisplayName()]; |
844 return user; | 863 return user; |
845 } | 864 } |
846 | 865 |
847 } // namespace chromeos | 866 } // namespace chromeos |
OLD | NEW |