| 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 |