| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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_impl.h" | 5 #include "chrome/browser/chromeos/login/user_manager_impl.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "ash/desktop_background/desktop_background_controller.h" |
| 9 #include "ash/shell.h" | 10 #include "ash/shell.h" |
| 10 #include "ash/desktop_background/desktop_background_controller.h" | |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/chromeos/chromeos_version.h" | 12 #include "base/chromeos/chromeos_version.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
| 15 #include "base/file_path.h" | 15 #include "base/file_path.h" |
| 16 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
| 19 #include "base/path_service.h" | 19 #include "base/path_service.h" |
| 20 #include "base/rand_util.h" | 20 #include "base/rand_util.h" |
| 21 #include "base/stl_util.h" | 21 #include "base/stl_util.h" |
| 22 #include "base/string_number_conversions.h" | 22 #include "base/string_number_conversions.h" |
| 23 #include "base/string_util.h" | 23 #include "base/string_util.h" |
| 24 #include "base/stringprintf.h" | 24 #include "base/stringprintf.h" |
| 25 #include "base/time.h" | 25 #include "base/time.h" |
| 26 #include "base/utf_string_conversions.h" | 26 #include "base/utf_string_conversions.h" |
| 27 #include "base/values.h" | 27 #include "base/values.h" |
| 28 #include "chrome/browser/browser_process.h" | 28 #include "chrome/browser/browser_process.h" |
| 29 #include "chrome/browser/chromeos/cros/cert_library.h" | 29 #include "chrome/browser/chromeos/cros/cert_library.h" |
| 30 #include "chrome/browser/chromeos/cros/cros_library.h" | 30 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 31 #include "chrome/browser/chromeos/cros_settings.h" | 31 #include "chrome/browser/chromeos/cros_settings.h" |
| 32 #include "chrome/browser/chromeos/cryptohome/async_method_caller.h" | 32 #include "chrome/browser/chromeos/cryptohome/async_method_caller.h" |
| 33 #include "chrome/browser/chromeos/input_method/input_method_manager.h" | 33 #include "chrome/browser/chromeos/input_method/input_method_manager.h" |
| 34 #include "chrome/browser/chromeos/login/default_user_images.h" | 34 #include "chrome/browser/chromeos/login/default_user_images.h" |
| 35 #include "chrome/browser/chromeos/login/helper.h" | 35 #include "chrome/browser/chromeos/login/helper.h" |
| 36 #include "chrome/browser/chromeos/login/login_display.h" | 36 #include "chrome/browser/chromeos/login/login_display.h" |
| 37 #include "chrome/browser/chromeos/login/ownership_service.h" | |
| 38 #include "chrome/browser/chromeos/login/remove_user_delegate.h" | 37 #include "chrome/browser/chromeos/login/remove_user_delegate.h" |
| 39 #include "chrome/browser/chromeos/login/user_image.h" | 38 #include "chrome/browser/chromeos/login/user_image.h" |
| 40 #include "chrome/browser/chromeos/login/wizard_controller.h" | 39 #include "chrome/browser/chromeos/login/wizard_controller.h" |
| 41 #include "chrome/browser/policy/browser_policy_connector.h" | 40 #include "chrome/browser/policy/browser_policy_connector.h" |
| 42 #include "chrome/browser/prefs/pref_service.h" | 41 #include "chrome/browser/prefs/pref_service.h" |
| 43 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 42 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 44 #include "chrome/browser/profiles/profile_downloader.h" | 43 #include "chrome/browser/profiles/profile_downloader.h" |
| 45 #include "chrome/browser/profiles/profile_manager.h" | 44 #include "chrome/browser/profiles/profile_manager.h" |
| 46 #include "chrome/browser/sync/profile_sync_service.h" | 45 #include "chrome/browser/sync/profile_sync_service.h" |
| 47 #include "chrome/browser/sync/profile_sync_service_factory.h" | 46 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 ash::GetInvalidWallpaperIndex())), | 216 ash::GetInvalidWallpaperIndex())), |
| 218 ephemeral_users_enabled_(false), | 217 ephemeral_users_enabled_(false), |
| 219 observed_sync_service_(NULL), | 218 observed_sync_service_(NULL), |
| 220 last_image_set_async_(false), | 219 last_image_set_async_(false), |
| 221 downloaded_profile_image_data_url_(chrome::kAboutBlankURL), | 220 downloaded_profile_image_data_url_(chrome::kAboutBlankURL), |
| 222 downloading_profile_image_(false) { | 221 downloading_profile_image_(false) { |
| 223 // UserManager instance should be used only on UI thread. | 222 // UserManager instance should be used only on UI thread. |
| 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 225 | 224 |
| 226 MigrateWallpaperData(); | 225 MigrateWallpaperData(); |
| 227 registrar_.Add(this, chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED, | 226 registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, |
| 228 content::NotificationService::AllSources()); | 227 content::NotificationService::AllSources()); |
| 229 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, | 228 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, |
| 230 content::NotificationService::AllSources()); | 229 content::NotificationService::AllSources()); |
| 231 RetrieveTrustedDevicePolicies(); | 230 RetrieveTrustedDevicePolicies(); |
| 232 } | 231 } |
| 233 | 232 |
| 234 UserManagerImpl::~UserManagerImpl() { | 233 UserManagerImpl::~UserManagerImpl() { |
| 235 // Can't use STLDeleteElements because of the private destructor of User. | 234 // Can't use STLDeleteElements because of the private destructor of User. |
| 236 for (size_t i = 0; i < users_.size();++i) | 235 for (size_t i = 0; i < users_.size(); ++i) |
| 237 delete users_[i]; | 236 delete users_[i]; |
| 238 users_.clear(); | 237 users_.clear(); |
| 239 if (is_current_user_ephemeral_) | 238 if (is_current_user_ephemeral_) |
| 240 delete logged_in_user_; | 239 delete logged_in_user_; |
| 241 } | 240 } |
| 242 | 241 |
| 243 const UserList& UserManagerImpl::GetUsers() const { | 242 const UserList& UserManagerImpl::GetUsers() const { |
| 244 const_cast<UserManagerImpl*>(this)->EnsureUsersLoaded(); | 243 const_cast<UserManagerImpl*>(this)->EnsureUsersLoaded(); |
| 245 return users_; | 244 return users_; |
| 246 } | 245 } |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 } | 668 } |
| 670 | 669 |
| 671 void UserManagerImpl::DownloadProfileImage(const std::string& reason) { | 670 void UserManagerImpl::DownloadProfileImage(const std::string& reason) { |
| 672 DownloadProfileData(reason, true); | 671 DownloadProfileData(reason, true); |
| 673 } | 672 } |
| 674 | 673 |
| 675 void UserManagerImpl::Observe(int type, | 674 void UserManagerImpl::Observe(int type, |
| 676 const content::NotificationSource& source, | 675 const content::NotificationSource& source, |
| 677 const content::NotificationDetails& details) { | 676 const content::NotificationDetails& details) { |
| 678 switch (type) { | 677 switch (type) { |
| 679 case chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED: | 678 case chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED: |
| 680 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 679 CheckOwnership(); |
| 681 base::Bind(&UserManagerImpl::CheckOwnership, | 680 RetrieveTrustedDevicePolicies(); |
| 682 base::Unretained(this))); | |
| 683 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 684 base::Bind(&UserManagerImpl::RetrieveTrustedDevicePolicies, | |
| 685 base::Unretained(this))); | |
| 686 break; | 681 break; |
| 687 case chrome::NOTIFICATION_PROFILE_ADDED: | 682 case chrome::NOTIFICATION_PROFILE_ADDED: |
| 688 if (IsUserLoggedIn() && !IsLoggedInAsGuest()) { | 683 if (IsUserLoggedIn() && !IsLoggedInAsGuest()) { |
| 689 Profile* profile = content::Source<Profile>(source).ptr(); | 684 Profile* profile = content::Source<Profile>(source).ptr(); |
| 690 if (!profile->IsOffTheRecord() && | 685 if (!profile->IsOffTheRecord() && |
| 691 profile == ProfileManager::GetDefaultProfile()) { | 686 profile == ProfileManager::GetDefaultProfile()) { |
| 692 DCHECK(NULL == observed_sync_service_); | 687 DCHECK(NULL == observed_sync_service_); |
| 693 observed_sync_service_ = | 688 observed_sync_service_ = |
| 694 ProfileSyncServiceFactory::GetForProfile(profile); | 689 ProfileSyncServiceFactory::GetForProfile(profile); |
| 695 if (observed_sync_service_) | 690 if (observed_sync_service_) |
| 696 observed_sync_service_->AddObserver(this); | 691 observed_sync_service_->AddObserver(this); |
| 697 } | 692 } |
| 698 } | 693 } |
| 699 break; | 694 break; |
| 700 default: | 695 default: |
| 701 NOTREACHED(); | 696 NOTREACHED(); |
| 702 } | 697 } |
| 703 } | 698 } |
| 704 | 699 |
| 705 void UserManagerImpl::OnStateChanged() { | 700 void UserManagerImpl::OnStateChanged() { |
| 706 DCHECK(IsUserLoggedIn() && !IsLoggedInAsGuest()); | 701 DCHECK(IsUserLoggedIn() && !IsLoggedInAsGuest()); |
| 707 AuthError::State state = observed_sync_service_->GetAuthError().state(); | 702 AuthError::State state = observed_sync_service_->GetAuthError().state(); |
| 708 if (state != AuthError::NONE && | 703 if (state != AuthError::NONE && |
| 709 state != AuthError::CONNECTION_FAILED && | 704 state != AuthError::CONNECTION_FAILED && |
| 710 state != AuthError::SERVICE_UNAVAILABLE && | 705 state != AuthError::SERVICE_UNAVAILABLE && |
| 711 state != AuthError::REQUEST_CANCELED) { | 706 state != AuthError::REQUEST_CANCELED) { |
| 712 // Invalidate OAuth token to force Gaia sign-in flow. This is needed | 707 // Invalidate OAuth token to force Gaia sign-in flow. This is needed |
| 713 // because sign-out/sign-in solution is suggested to the user. | 708 // because sign-out/sign-in solution is suggested to the user. |
| 714 // TODO(altimofeev): this code isn't needed after crosbug.com/25978 is | 709 // TODO(altimofeev): this code isn't needed after crosbug.com/25978 is |
| 715 // implemented. | 710 // implemented. |
| 716 DVLOG(1) << "Invalidate OAuth token because of a sync error."; | 711 DVLOG(1) << "Invalidate OAuth token because of a sync error."; |
| 717 SaveUserOAuthStatus(GetLoggedInUser().email(), | 712 SaveUserOAuthStatus(GetLoggedInUser().email(), |
| 718 User::OAUTH_TOKEN_STATUS_INVALID); | 713 User::OAUTH_TOKEN_STATUS_INVALID); |
| 719 } | 714 } |
| 720 } | 715 } |
| 721 | 716 |
| 722 bool UserManagerImpl::IsCurrentUserOwner() const { | 717 bool UserManagerImpl::IsCurrentUserOwner() const { |
| 723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 718 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 724 base::AutoLock lk(is_current_user_owner_lock_); | 719 base::AutoLock lk(is_current_user_owner_lock_); |
| 725 return is_current_user_owner_; | 720 return is_current_user_owner_; |
| 726 } | 721 } |
| 727 | 722 |
| 728 void UserManagerImpl::SetCurrentUserIsOwner(bool is_current_user_owner) { | 723 void UserManagerImpl::SetCurrentUserIsOwner(bool is_current_user_owner) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 759 bool UserManagerImpl::IsLoggedInAsStub() const { | 754 bool UserManagerImpl::IsLoggedInAsStub() const { |
| 760 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 755 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 761 return IsUserLoggedIn() && logged_in_user_->email() == kStubUser; | 756 return IsUserLoggedIn() && logged_in_user_->email() == kStubUser; |
| 762 } | 757 } |
| 763 | 758 |
| 764 bool UserManagerImpl::IsSessionStarted() const { | 759 bool UserManagerImpl::IsSessionStarted() const { |
| 765 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 760 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 766 return session_started_; | 761 return session_started_; |
| 767 } | 762 } |
| 768 | 763 |
| 769 void UserManagerImpl::AddObserver(Observer* obs) { | 764 void UserManagerImpl::AddObserver(UserManager::Observer* obs) { |
| 770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 765 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 771 observer_list_.AddObserver(obs); | 766 observer_list_.AddObserver(obs); |
| 772 } | 767 } |
| 773 | 768 |
| 774 void UserManagerImpl::RemoveObserver(Observer* obs) { | 769 void UserManagerImpl::RemoveObserver(UserManager::Observer* obs) { |
| 775 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 776 observer_list_.RemoveObserver(obs); | 771 observer_list_.RemoveObserver(obs); |
| 777 } | 772 } |
| 778 | 773 |
| 779 const SkBitmap& UserManagerImpl::DownloadedProfileImage() const { | 774 const SkBitmap& UserManagerImpl::DownloadedProfileImage() const { |
| 780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 775 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 781 return downloaded_profile_image_; | 776 return downloaded_profile_image_; |
| 782 } | 777 } |
| 783 | 778 |
| 784 void UserManagerImpl::NotifyLocalStateChanged() { | 779 void UserManagerImpl::NotifyLocalStateChanged() { |
| 785 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 786 FOR_EACH_OBSERVER( | 781 FOR_EACH_OBSERVER(UserManager::Observer, observer_list_, |
| 787 Observer, | 782 LocalStateChanged(this)); |
| 788 observer_list_, | |
| 789 LocalStateChanged(this)); | |
| 790 } | 783 } |
| 791 | 784 |
| 792 FilePath UserManagerImpl::GetImagePathForUser(const std::string& username) { | 785 FilePath UserManagerImpl::GetImagePathForUser(const std::string& username) { |
| 793 std::string filename = username + ".png"; | 786 std::string filename = username + ".png"; |
| 794 FilePath user_data_dir; | 787 FilePath user_data_dir; |
| 795 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | 788 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); |
| 796 return user_data_dir.AppendASCII(filename); | 789 return user_data_dir.AppendASCII(filename); |
| 797 } | 790 } |
| 798 | 791 |
| 799 FilePath UserManagerImpl::GetWallpaperPathForUser(const std::string& username, | 792 FilePath UserManagerImpl::GetWallpaperPathForUser(const std::string& username, |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 | 994 |
| 1002 void UserManagerImpl::NotifyOnLogin() { | 995 void UserManagerImpl::NotifyOnLogin() { |
| 1003 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 996 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1004 content::NotificationService::current()->Notify( | 997 content::NotificationService::current()->Notify( |
| 1005 chrome::NOTIFICATION_LOGIN_USER_CHANGED, | 998 chrome::NOTIFICATION_LOGIN_USER_CHANGED, |
| 1006 content::Source<UserManagerImpl>(this), | 999 content::Source<UserManagerImpl>(this), |
| 1007 content::Details<const User>(logged_in_user_)); | 1000 content::Details<const User>(logged_in_user_)); |
| 1008 | 1001 |
| 1009 CrosLibrary::Get()->GetCertLibrary()->LoadKeyStore(); | 1002 CrosLibrary::Get()->GetCertLibrary()->LoadKeyStore(); |
| 1010 | 1003 |
| 1011 // Schedules current user ownership check on file thread. | 1004 // Indicate to DeviceSettingsService that the owner key may have become |
| 1012 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 1005 // available. |
| 1013 base::Bind(&UserManagerImpl::CheckOwnership, | 1006 DeviceSettingsService::Get()->SetUsername(logged_in_user_->email()); |
| 1014 base::Unretained(this))); | |
| 1015 } | 1007 } |
| 1016 | 1008 |
| 1017 void UserManagerImpl::SetInitialUserImage(const std::string& username) { | 1009 void UserManagerImpl::SetInitialUserImage(const std::string& username) { |
| 1018 // Choose a random default image. | 1010 // Choose a random default image. |
| 1019 int image_id = base::RandInt(0, kDefaultImagesCount - 1); | 1011 int image_id = base::RandInt(0, kDefaultImagesCount - 1); |
| 1020 SaveUserDefaultImageIndex(username, image_id); | 1012 SaveUserDefaultImageIndex(username, image_id); |
| 1021 } | 1013 } |
| 1022 | 1014 |
| 1023 void UserManagerImpl::SetInitialUserWallpaper(const std::string& username) { | 1015 void UserManagerImpl::SetInitialUserWallpaper(const std::string& username) { |
| 1024 current_user_wallpaper_type_ = User::DEFAULT; | 1016 current_user_wallpaper_type_ = User::DEFAULT; |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 } | 1456 } |
| 1465 | 1457 |
| 1466 void UserManagerImpl::DeleteUserImage(const FilePath& image_path) { | 1458 void UserManagerImpl::DeleteUserImage(const FilePath& image_path) { |
| 1467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 1468 if (!file_util::Delete(image_path, false)) { | 1460 if (!file_util::Delete(image_path, false)) { |
| 1469 LOG(ERROR) << "Failed to remove user image."; | 1461 LOG(ERROR) << "Failed to remove user image."; |
| 1470 return; | 1462 return; |
| 1471 } | 1463 } |
| 1472 } | 1464 } |
| 1473 | 1465 |
| 1474 void UserManagerImpl::UpdateOwnership(bool is_owner) { | 1466 void UserManagerImpl::UpdateOwnership( |
| 1475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1467 DeviceSettingsService::OwnershipStatus status, |
| 1468 bool is_owner) { |
| 1469 VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner"); |
| 1476 | 1470 |
| 1477 SetCurrentUserIsOwner(is_owner); | 1471 SetCurrentUserIsOwner(is_owner); |
| 1478 content::NotificationService::current()->Notify( | |
| 1479 chrome::NOTIFICATION_OWNERSHIP_CHECKED, | |
| 1480 content::NotificationService::AllSources(), | |
| 1481 content::NotificationService::NoDetails()); | |
| 1482 if (is_owner) { | |
| 1483 // Also update cached value. | |
| 1484 CrosSettings::Get()->SetString(kDeviceOwner, GetLoggedInUser().email()); | |
| 1485 } | |
| 1486 } | 1472 } |
| 1487 | 1473 |
| 1488 void UserManagerImpl::CheckOwnership() { | 1474 void UserManagerImpl::CheckOwnership() { |
| 1489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1475 DeviceSettingsService::Get()->GetOwnershipStatusAsync( |
| 1490 bool is_owner = OwnershipService::GetSharedInstance()->IsCurrentUserOwner(); | |
| 1491 VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner"); | |
| 1492 | |
| 1493 // UserManagerImpl should be accessed only on UI thread. | |
| 1494 BrowserThread::PostTask( | |
| 1495 BrowserThread::UI, | |
| 1496 FROM_HERE, | |
| 1497 base::Bind(&UserManagerImpl::UpdateOwnership, | 1476 base::Bind(&UserManagerImpl::UpdateOwnership, |
| 1498 base::Unretained(this), | 1477 base::Unretained(this))); |
| 1499 is_owner)); | |
| 1500 } | 1478 } |
| 1501 | 1479 |
| 1502 // ProfileDownloaderDelegate override. | 1480 // ProfileDownloaderDelegate override. |
| 1503 bool UserManagerImpl::NeedsProfilePicture() const { | 1481 bool UserManagerImpl::NeedsProfilePicture() const { |
| 1504 return downloading_profile_image_; | 1482 return downloading_profile_image_; |
| 1505 } | 1483 } |
| 1506 | 1484 |
| 1507 // ProfileDownloaderDelegate override. | 1485 // ProfileDownloaderDelegate override. |
| 1508 int UserManagerImpl::GetDesiredImageSideLength() const { | 1486 int UserManagerImpl::GetDesiredImageSideLength() const { |
| 1509 return GetCurrentUserImageSize(); | 1487 return GetCurrentUserImageSize(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 BrowserThread::PostTask( | 1667 BrowserThread::PostTask( |
| 1690 BrowserThread::FILE, | 1668 BrowserThread::FILE, |
| 1691 FROM_HERE, | 1669 FROM_HERE, |
| 1692 base::Bind(&UserManagerImpl::DeleteUserImage, | 1670 base::Bind(&UserManagerImpl::DeleteUserImage, |
| 1693 base::Unretained(this), | 1671 base::Unretained(this), |
| 1694 image_path)); | 1672 image_path)); |
| 1695 } | 1673 } |
| 1696 } | 1674 } |
| 1697 | 1675 |
| 1698 } // namespace chromeos | 1676 } // namespace chromeos |
| OLD | NEW |