Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(524)

Unified Diff: chrome/browser/chromeos/login/user_manager.cc

Issue 9348022: [cros] Use mocked URLFetcher and other mocks in ExistingUserController tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/chromeos/login/user_manager.h ('k') | chrome/browser/chromeos/login/user_manager_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/chromeos/login/user_manager.cc
diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc
index 3b56995820865b357fa56d6669ff451387731f35..4762bd07f595d49960b7ba5819f4b394878a1aab 100644
--- a/chrome/browser/chromeos/login/user_manager.cc
+++ b/chrome/browser/chromeos/login/user_manager.cc
@@ -4,300 +4,66 @@
#include "chrome/browser/chromeos/login/user_manager.h"
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram.h"
-#include "base/path_service.h"
-#include "base/rand_util.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "base/time.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/cros/cert_library.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros_settings.h"
-#include "chrome/browser/chromeos/cryptohome/async_method_caller.h"
-#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
-#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
-#include "chrome/browser/chromeos/input_method/input_method_manager.h"
-#include "chrome/browser/chromeos/login/default_user_images.h"
-#include "chrome/browser/chromeos/login/helper.h"
-#include "chrome/browser/chromeos/login/login_display.h"
-#include "chrome/browser/chromeos/login/ownership_service.h"
-#include "chrome/browser/chromeos/login/remove_user_delegate.h"
-#include "chrome/browser/chromeos/system/runtime_environment.h"
+#include "base/synchronization/lock.h"
+#include "chrome/browser/chromeos/login/user_manager_impl.h"
#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
-#include "chrome/browser/profiles/profile_downloader.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/ui/webui/web_ui_util.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/common/url_constants.h"
-#include "crypto/nss_util.h"
-#include "ui/gfx/codec/png_codec.h"
-
-#if defined(TOOLKIT_USES_GTK)
-#include "chrome/browser/chromeos/legacy_window_manager/wm_ipc.h"
-#endif
-
-using content::BrowserThread;
-
-typedef GoogleServiceAuthError AuthError;
namespace chromeos {
-namespace {
-
-// A vector pref of the users who have logged into the device.
-const char kLoggedInUsers[] = "LoggedInUsers";
-// A dictionary that maps usernames to file paths to their images.
-const char kUserImages[] = "UserImages";
-// A dictionary that maps usernames to the displayed (non-canonical) emails.
-const char kUserDisplayEmail[] = "UserDisplayEmail";
-// A dictionary that maps usernames to OAuth token presence flag.
-const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
-
-// Incognito user is represented by an empty string (since some code already
-// depends on that and it's hard to figure out what).
-const char kGuestUser[] = "";
-
-// Stub user email (for test paths).
-const char kStubUser[] = "stub-user@example.com";
-
-// Names of nodes with info about user image.
-const char kImagePathNodeName[] = "path";
-const char kImageIndexNodeName[] = "index";
-
-// Index of the default image used for the |kStubUser| user.
-const int kStubDefaultImageIndex = 0;
-
-// Delay betweeen user login and attempt to update user's profile image.
-const long kProfileImageDownloadDelayMs = 10000;
-
-base::LazyInstance<UserManager> g_user_manager = LAZY_INSTANCE_INITIALIZER;
-
-// Enum for reporting histograms about profile picture download.
-enum ProfileDownloadResult {
- kDownloadSuccessChanged,
- kDownloadSuccess,
- kDownloadFailure,
- kDownloadDefault,
-
- // Must be the last, convenient count.
- kDownloadResultsCount
-};
-
-// Time histogram prefix for the default profile image download.
-const char kProfileDownloadDefaultTime[] =
- "UserImage.ProfileDownloadTime.Default";
-// Time histogram prefix for a failed profile image download.
-const char kProfileDownloadFailureTime[] =
- "UserImage.ProfileDownloadTime.Failure";
-// Time histogram prefix for a successful profile image download.
-const char kProfileDownloadSuccessTime[] =
- "UserImage.ProfileDownloadTime.Success";
-// Time histogram suffix for a profile image download after login.
-const char kProfileDownloadReasonLoggedIn[] = "LoggedIn";
-
-// Add a histogram showing the time it takes to download a profile image.
-// Separate histograms are reported for each download |reason| and |result|.
-void AddProfileImageTimeHistogram(ProfileDownloadResult result,
- const std::string& download_reason,
- const base::TimeDelta& time_delta) {
- std::string histogram_name;
- switch (result) {
- case kDownloadFailure:
- histogram_name = kProfileDownloadFailureTime;
- break;
- case kDownloadDefault:
- histogram_name = kProfileDownloadDefaultTime;
- break;
- case kDownloadSuccess:
- histogram_name = kProfileDownloadSuccessTime;
- break;
- default:
- NOTREACHED();
- }
- if (!download_reason.empty()) {
- histogram_name += ".";
- histogram_name += download_reason;
+// static
+const char UserManager::kLoggedInUsers[] = "LoggedInUsers";
+const char UserManager::kUserImages[] = "UserImages";
+const char UserManager::kUserDisplayEmail[] = "UserDisplayEmail";
+const char UserManager::kUserOAuthTokenStatus[] = "OAuthTokenStatus";
+
+// Class that is holds pointer to UserManager instance.
+// One could set UserManager mock instance through it (see UserManager::Set).
+class UserManagerImplWrapper {
+ public:
+ static UserManagerImplWrapper* GetInstance() {
+ return Singleton<UserManagerImplWrapper>::get();
}
- static const base::TimeDelta min_time = base::TimeDelta::FromMilliseconds(1);
- static const base::TimeDelta max_time = base::TimeDelta::FromSeconds(50);
- const size_t bucket_count(50);
-
- base::Histogram* counter = base::Histogram::FactoryTimeGet(
- histogram_name, min_time, max_time, bucket_count,
- base::Histogram::kUmaTargetedHistogramFlag);
- counter->AddTime(time_delta);
-
- DVLOG(1) << "Profile image download time: " << time_delta.InSecondsF();
-}
-
-// Callback that is called after user removal is complete.
-void OnRemoveUserComplete(const std::string& user_email,
- bool success,
- cryptohome::MountError return_code) {
- // Log the error, but there's not much we can do.
- if (!success) {
- LOG(ERROR) << "Removal of cryptohome for " << user_email
- << " failed, return code: " << return_code;
+ protected:
+ ~UserManagerImplWrapper() {
}
-}
-// This method is used to implement UserManager::RemoveUser.
-void RemoveUserInternal(const std::string& user_email,
- chromeos::RemoveUserDelegate* delegate) {
- CrosSettings* cros_settings = CrosSettings::Get();
-
- // Ensure the value of owner email has been fetched.
- if (!cros_settings->GetTrusted(
- kDeviceOwner,
- base::Bind(&RemoveUserInternal, user_email, delegate))) {
- // Value of owner email is not fetched yet. RemoveUserInternal will be
- // called again after fetch completion.
- return;
- }
- std::string owner;
- cros_settings->GetString(kDeviceOwner, &owner);
- if (user_email == owner) {
- // Owner is not allowed to be removed from the device.
- return;
+ UserManager* get() {
+ base::AutoLock create(create_lock_);
+ if (!ptr_.get())
+ reset(new UserManagerImpl);
+ return ptr_.get();
}
- if (delegate)
- delegate->OnBeforeUserRemoved(user_email);
-
- chromeos::UserManager::Get()->RemoveUserFromList(user_email);
- cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
- user_email, base::Bind(&OnRemoveUserComplete, user_email));
-
- if (delegate)
- delegate->OnUserRemoved(user_email);
-}
+ void reset(UserManager* ptr) {
+ ptr_.reset(ptr);
+ }
-class RealTPMTokenInfoDelegate : public crypto::TPMTokenInfoDelegate {
- public:
- RealTPMTokenInfoDelegate();
- virtual ~RealTPMTokenInfoDelegate();
- // TPMTokenInfoDeleagte overrides:
- virtual bool IsTokenAvailable() const OVERRIDE;
- virtual void RequestIsTokenReady(
- base::Callback<void(bool result)> callback) const OVERRIDE;
- virtual void GetTokenInfo(std::string* token_name,
- std::string* user_pin) const OVERRIDE;
private:
- // This method is used to implement RequestIsTokenReady.
- void OnPkcs11IsTpmTokenReady(base::Callback<void(bool result)> callback,
- CryptohomeClient::CallStatus call_status,
- bool is_tpm_token_ready) const;
-
- // This method is used to implement RequestIsTokenReady.
- void OnPkcs11GetTpmTokenInfo(base::Callback<void(bool result)> callback,
- CryptohomeClient::CallStatus call_status,
- const std::string& token_name,
- const std::string& user_pin) const;
-
- // These are mutable since we need to cache them in IsTokenReady().
- mutable bool token_ready_;
- mutable std::string token_name_;
- mutable std::string user_pin_;
- mutable base::WeakPtrFactory<RealTPMTokenInfoDelegate> weak_ptr_factory_;
-};
-
-RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() : token_ready_(false),
- weak_ptr_factory_(this) {
-}
+ friend struct DefaultSingletonTraits<UserManagerImplWrapper>;
-RealTPMTokenInfoDelegate::~RealTPMTokenInfoDelegate() {}
+ friend class UserManager;
-bool RealTPMTokenInfoDelegate::IsTokenAvailable() const {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- bool result = false;
- DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(&result);
- return result;
-}
-
-void RealTPMTokenInfoDelegate::RequestIsTokenReady(
- base::Callback<void(bool result)> callback) const {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (token_ready_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, true));
- return;
+ UserManagerImplWrapper() {
}
- DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady(
- base::Bind(&RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady,
- weak_ptr_factory_.GetWeakPtr(),
- callback));
-}
-void RealTPMTokenInfoDelegate::GetTokenInfo(std::string* token_name,
- std::string* user_pin) const {
- // May be called from a non UI thread, but must only be called after
- // IsTokenReady() returns true.
- CHECK(token_ready_);
- if (token_name)
- *token_name = token_name_;
- if (user_pin)
- *user_pin = user_pin_;
-}
+ base::Lock create_lock_;
+ scoped_ptr<UserManager> ptr_;
-void RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady(
- base::Callback<void(bool result)> callback,
- CryptohomeClient::CallStatus call_status,
- bool is_tpm_token_ready) const {
- if (call_status != CryptohomeClient::SUCCESS || !is_tpm_token_ready) {
- callback.Run(false);
- return;
- }
-
- // Retrieve token_name_ and user_pin_ here since they will never change
- // and CryptohomeClient calls are not thread safe.
- DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo(
- base::Bind(&RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo,
- weak_ptr_factory_.GetWeakPtr(),
- callback));
-}
+ DISALLOW_COPY_AND_ASSIGN(UserManagerImplWrapper);
+};
-void RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo(
- base::Callback<void(bool result)> callback,
- CryptohomeClient::CallStatus call_status,
- const std::string& token_name,
- const std::string& user_pin) const {
- if (call_status == CryptohomeClient::SUCCESS) {
- token_name_ = token_name;
- user_pin_ = user_pin;
- token_ready_ = true;
- }
- callback.Run(token_ready_);
+// static
+UserManager* UserManager::Get() {
+ // UserManager instance should be used only on UI thread.
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ return UserManagerImplWrapper::GetInstance()->get();
}
-} // namespace
-
// static
-UserManager* UserManager::Get() {
- // Not thread-safe.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return &g_user_manager.Get();
+void UserManager::Set(UserManager* mock) {
+ UserManagerImplWrapper::GetInstance()->reset(mock);
}
// static
@@ -311,766 +77,7 @@ void UserManager::RegisterPrefs(PrefService* local_state) {
PrefService::UNSYNCABLE_PREF);
}
-const UserList& UserManager::GetUsers() const {
- const_cast<UserManager*>(this)->EnsureUsersLoaded();
- return users_;
-}
-
-void UserManager::UserLoggedIn(const std::string& email) {
- DCHECK(!user_is_logged_in_);
-
- user_is_logged_in_ = true;
-
- if (email == kGuestUser) {
- GuestUserLoggedIn();
- return;
- }
-
- if (email == kDemoUser) {
- DemoUserLoggedIn();
- return;
- }
-
- EnsureUsersLoaded();
-
- // Clear the prefs view of the users.
- PrefService* prefs = g_browser_process->local_state();
- ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
- prefs_users_update->Clear();
-
- // Make sure this user is first.
- prefs_users_update->Append(Value::CreateStringValue(email));
- UserList::iterator logged_in_user = users_.end();
- for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
- std::string user_email = (*it)->email();
- // Skip the most recent user.
- if (email != user_email)
- prefs_users_update->Append(Value::CreateStringValue(user_email));
- else
- logged_in_user = it;
- }
-
- if (logged_in_user == users_.end()) {
- current_user_is_new_ = true;
- logged_in_user_ = CreateUser(email);
- } else {
- logged_in_user_ = *logged_in_user;
- users_.erase(logged_in_user);
- }
- // This user must be in the front of the user list.
- users_.insert(users_.begin(), logged_in_user_);
-
- NotifyOnLogin();
-
- if (current_user_is_new_) {
- SetInitialUserImage(email);
- } else {
- // Download profile image if it's user image and see if it has changed.
- int image_index = logged_in_user_->image_index();
- if (image_index == User::kProfileImageIndex) {
- InitDownloadedProfileImage();
- BrowserThread::PostDelayedTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&UserManager::DownloadProfileImage,
- base::Unretained(this),
- kProfileDownloadReasonLoggedIn),
- kProfileImageDownloadDelayMs);
- }
-
- int histogram_index = image_index;
- switch (image_index) {
- case User::kExternalImageIndex:
- // TODO(avayvod): Distinguish this from selected from file.
- histogram_index = kHistogramImageFromCamera;
- break;
-
- case User::kProfileImageIndex:
- histogram_index = kHistogramImageFromProfile;
- break;
- }
- UMA_HISTOGRAM_ENUMERATION("UserImage.LoggedIn",
- histogram_index,
- kHistogramImagesCount);
- }
-}
-
-void UserManager::DemoUserLoggedIn() {
- logged_in_user_ = &demo_user_;
- NotifyOnLogin();
-}
-
-void UserManager::GuestUserLoggedIn() {
- logged_in_user_ = &guest_user_;
- NotifyOnLogin();
-}
-
-void UserManager::RemoveUser(const std::string& email,
- RemoveUserDelegate* delegate) {
- if (!IsKnownUser(email))
- return;
-
- // Sanity check: we must not remove single user. This check may seem
- // redundant at a first sight because this single user must be an owner and
- // we perform special check later in order not to remove an owner. However
- // due to non-instant nature of ownership assignment this later check may
- // sometimes fail. See http://crosbug.com/12723
- if (users_.size() < 2)
- return;
-
- // Sanity check: do not allow the logged-in user to remove himself.
- if (logged_in_user_ && logged_in_user_->email() == email)
- return;
-
- RemoveUserInternal(email, delegate);
-}
-
-void UserManager::RemoveUserFromList(const std::string& email) {
- EnsureUsersLoaded();
-
- // Clear the prefs view of the users.
- PrefService* prefs = g_browser_process->local_state();
- ListPrefUpdate prefs_users_update(prefs, kLoggedInUsers);
- prefs_users_update->Clear();
-
- UserList::iterator user_to_remove = users_.end();
- for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
- std::string user_email = (*it)->email();
- // Skip user that we would like to delete.
- if (email != user_email)
- prefs_users_update->Append(Value::CreateStringValue(user_email));
- else
- user_to_remove = it;
- }
-
- DictionaryPrefUpdate prefs_images_update(prefs, kUserImages);
- std::string image_path_string;
- prefs_images_update->GetStringWithoutPathExpansion(email, &image_path_string);
- prefs_images_update->RemoveWithoutPathExpansion(email, NULL);
-
- DictionaryPrefUpdate prefs_oauth_update(prefs, kUserOAuthTokenStatus);
- int oauth_status;
- prefs_oauth_update->GetIntegerWithoutPathExpansion(email, &oauth_status);
- prefs_oauth_update->RemoveWithoutPathExpansion(email, NULL);
-
- DictionaryPrefUpdate prefs_display_email_update(prefs, kUserDisplayEmail);
- prefs_display_email_update->RemoveWithoutPathExpansion(email, NULL);
-
- if (user_to_remove != users_.end()) {
- --display_name_count_[(*user_to_remove)->GetDisplayName()];
- delete *user_to_remove;
- users_.erase(user_to_remove);
- }
-
- int default_image_id = User::kInvalidImageIndex;
- if (!image_path_string.empty() &&
- !IsDefaultImagePath(image_path_string, &default_image_id)) {
- FilePath image_path(image_path_string);
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&UserManager::DeleteUserImage,
- base::Unretained(this),
- image_path));
- }
-}
-
-bool UserManager::IsKnownUser(const std::string& email) const {
- return FindUser(email) != NULL;
-}
-
-const User* UserManager::FindUser(const std::string& email) const {
- // Speed up search by checking the logged-in user first.
- if (logged_in_user_ && logged_in_user_->email() == email)
- return logged_in_user_;
- const UserList& users = GetUsers();
- for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
- if ((*it)->email() == email)
- return *it;
- }
- return NULL;
-}
-
-bool UserManager::IsDisplayNameUnique(const std::string& display_name) const {
- return display_name_count_[display_name] < 2;
-}
-
-void UserManager::SaveUserOAuthStatus(
- const std::string& username,
- User::OAuthTokenStatus oauth_token_status) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- PrefService* local_state = g_browser_process->local_state();
- DictionaryPrefUpdate oauth_status_update(local_state, kUserOAuthTokenStatus);
- oauth_status_update->SetWithoutPathExpansion(username,
- new base::FundamentalValue(static_cast<int>(oauth_token_status)));
- DVLOG(1) << "Saving user OAuth token status in Local State";
- User* user = const_cast<User*>(FindUser(username));
- if (user)
- user->set_oauth_token_status(oauth_token_status);
-}
-
-User::OAuthTokenStatus UserManager::LoadUserOAuthStatus(
- const std::string& username) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSkipOAuthLogin)) {
- // Use OAUTH_TOKEN_STATUS_VALID flag if kSkipOAuthLogin is present.
- return User::OAUTH_TOKEN_STATUS_VALID;
- } else {
- PrefService* local_state = g_browser_process->local_state();
- const DictionaryValue* prefs_oauth_status =
- local_state->GetDictionary(kUserOAuthTokenStatus);
-
- int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN;
- if (prefs_oauth_status &&
- prefs_oauth_status->GetIntegerWithoutPathExpansion(username,
- &oauth_token_status)) {
- return static_cast<User::OAuthTokenStatus>(oauth_token_status);
- }
- }
-
- return User::OAUTH_TOKEN_STATUS_UNKNOWN;
-}
-
-void UserManager::SaveUserDisplayEmail(const std::string& username,
- const std::string& display_email) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- User* user = const_cast<User*>(FindUser(username));
- if (!user)
- return; // Ignore if there is no such user.
-
- user->set_display_email(display_email);
-
- PrefService* local_state = g_browser_process->local_state();
-
- DictionaryPrefUpdate display_email_update(local_state, kUserDisplayEmail);
- display_email_update->SetWithoutPathExpansion(
- username,
- base::Value::CreateStringValue(display_email));
-}
-
-std::string UserManager::GetUserDisplayEmail(
- const std::string& username) const {
- const User* user = FindUser(username);
- return user ? user->display_email() : username;
-}
-
-void UserManager::SaveUserDefaultImageIndex(const std::string& username,
- int image_index) {
- DCHECK(image_index >= 0 && image_index < kDefaultImagesCount);
- SetUserImage(username, image_index, GetDefaultImage(image_index));
- SaveImageToLocalState(username, "", image_index, false);
-}
-
-void UserManager::SaveUserImage(const std::string& username,
- const SkBitmap& image) {
- SaveUserImageInternal(username, User::kExternalImageIndex, image);
-}
-
-void UserManager::SaveUserImageFromFile(const std::string& username,
- const FilePath& path) {
- image_loader_->Start(
- path.value(), login::kUserImageSize,
- base::Bind(&UserManager::SaveUserImage,
- base::Unretained(this), username));
-}
-
-void UserManager::SaveUserImageFromProfileImage(const std::string& username) {
- if (!downloaded_profile_image_.empty()) {
- // Profile image has already been downloaded, so save it to file right now.
- SaveUserImageInternal(username, User::kProfileImageIndex,
- downloaded_profile_image_);
- } else {
- // No profile image - use the stub image (gray avatar).
- SetUserImage(username, User::kProfileImageIndex, SkBitmap());
- SaveImageToLocalState(username, "", User::kProfileImageIndex, false);
- }
-}
-
-void UserManager::DownloadProfileImage(const std::string& reason) {
- if (profile_image_downloader_.get()) {
- // Another download is already in progress
- return;
- }
-
- if (logged_in_user().email().empty()) {
- // This is a guest login so there's no profile image to download.
- return;
- }
-
- profile_image_download_reason_ = reason;
- profile_image_load_start_time_ = base::Time::Now();
- profile_image_downloader_.reset(new ProfileDownloader(this));
- profile_image_downloader_->Start();
-}
-
-void UserManager::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED:
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&UserManager::CheckOwnership,
- base::Unretained(this)));
- break;
- case chrome::NOTIFICATION_PROFILE_ADDED:
- if (user_is_logged_in() && !IsLoggedInAsGuest()) {
- Profile* profile = content::Source<Profile>(source).ptr();
- if (!profile->IsOffTheRecord() &&
- profile == ProfileManager::GetDefaultProfile()) {
- DCHECK(NULL == observed_sync_service_);
- observed_sync_service_ =
- ProfileSyncServiceFactory::GetForProfile(profile);
- if (observed_sync_service_)
- observed_sync_service_->AddObserver(this);
- }
- }
- break;
- default:
- NOTREACHED();
- }
-}
-
-void UserManager::OnStateChanged() {
- DCHECK(user_is_logged_in() && !IsLoggedInAsGuest());
- if (observed_sync_service_->GetAuthError().state() != AuthError::NONE) {
- // Invalidate OAuth token to force Gaia sign-in flow. This is needed
- // because sign-out/sign-in solution is suggested to the user.
- // TODO(altimofeev): this code isn't needed after crosbug.com/25978 is
- // implemented.
- DVLOG(1) << "Invalidate OAuth token because of a sync error.";
- SaveUserOAuthStatus(logged_in_user().email(),
- User::OAUTH_TOKEN_STATUS_INVALID);
- }
-}
-
-bool UserManager::current_user_is_owner() const {
- base::AutoLock lk(current_user_is_owner_lock_);
- return current_user_is_owner_;
-}
-
-void UserManager::set_current_user_is_owner(bool current_user_is_owner) {
- base::AutoLock lk(current_user_is_owner_lock_);
- current_user_is_owner_ = current_user_is_owner;
-}
-
-bool UserManager::IsLoggedInAsDemoUser() const {
- return logged_in_user_ == &demo_user_;
-}
-
-bool UserManager::IsLoggedInAsGuest() const {
- return logged_in_user_ == &guest_user_;
-}
-
-void UserManager::AddObserver(Observer* obs) {
- observer_list_.AddObserver(obs);
-}
-
-void UserManager::RemoveObserver(Observer* obs) {
- observer_list_.RemoveObserver(obs);
-}
-
-void UserManager::NotifyLocalStateChanged() {
- FOR_EACH_OBSERVER(
- Observer,
- observer_list_,
- LocalStateChanged(this));
-}
-
-// Protected constructor and destructor.
-UserManager::UserManager()
- : ALLOW_THIS_IN_INITIALIZER_LIST(image_loader_(new UserImageLoader)),
- demo_user_(kDemoUser, false),
- guest_user_(kGuestUser, true),
- stub_user_(kStubUser, false),
- logged_in_user_(NULL),
- current_user_is_owner_(false),
- current_user_is_new_(false),
- user_is_logged_in_(false),
- observed_sync_service_(NULL),
- last_image_set_async_(false),
- downloaded_profile_image_data_url_(chrome::kAboutBlankURL) {
- // Use stub as the logged-in user for test paths without login.
- if (!system::runtime_environment::IsRunningOnChromeOS())
- StubUserLoggedIn();
- registrar_.Add(this, chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
- content::NotificationService::AllSources());
- registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
- content::NotificationService::AllSources());
-}
-
UserManager::~UserManager() {
}
-FilePath UserManager::GetImagePathForUser(const std::string& username) {
- std::string filename = username + ".png";
- FilePath user_data_dir;
- PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
- return user_data_dir.AppendASCII(filename);
-}
-
-void UserManager::EnsureUsersLoaded() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!users_.empty())
- return;
- if (!g_browser_process)
- return;
-
- PrefService* local_state = g_browser_process->local_state();
- const ListValue* prefs_users = local_state->GetList(kLoggedInUsers);
- const DictionaryValue* prefs_images = local_state->GetDictionary(kUserImages);
- const DictionaryValue* prefs_display_emails =
- local_state->GetDictionary(kUserDisplayEmail);
-
- if (prefs_users) {
- for (ListValue::const_iterator it = prefs_users->begin();
- it != prefs_users->end(); ++it) {
- std::string email;
- if ((*it)->GetAsString(&email)) {
- User* user = CreateUser(email);
- users_.push_back(user);
-
- if (prefs_images) {
- // Get account image path.
- // TODO(avayvod): Reading image path as a string is here for
- // backward compatibility.
- std::string image_path;
- base::DictionaryValue* image_properties;
- if (prefs_images->GetStringWithoutPathExpansion(email, &image_path)) {
- int image_id = User::kInvalidImageIndex;
- if (IsDefaultImagePath(image_path, &image_id)) {
- user->SetImage(GetDefaultImage(image_id), image_id);
- } else {
- int image_index = User::kExternalImageIndex;
- // Until image has been loaded, use the stub image.
- user->SetStubImage(image_index);
- DCHECK(!image_path.empty());
- // Load user image asynchronously.
- image_loader_->Start(
- image_path, 0,
- base::Bind(&UserManager::SetUserImage,
- base::Unretained(this), email, image_index));
- }
- } else if (prefs_images->GetDictionaryWithoutPathExpansion(
- email, &image_properties)) {
- int image_index = User::kInvalidImageIndex;
- image_properties->GetString(kImagePathNodeName, &image_path);
- image_properties->GetInteger(kImageIndexNodeName, &image_index);
- if (image_index >= 0 && image_index < kDefaultImagesCount) {
- user->SetImage(GetDefaultImage(image_index), image_index);
- } else if (image_index == User::kExternalImageIndex ||
- image_index == User::kProfileImageIndex) {
- // Path may be empty for profile images (meaning that the image
- // hasn't been downloaded for the first time yet, in which case a
- // download will be scheduled for |kProfileImageDownloadDelayMs|
- // after user logs in).
- DCHECK(!image_path.empty() ||
- image_index == User::kProfileImageIndex);
- // Until image has been loaded, use the stub image (gray avatar).
- user->SetStubImage(image_index);
- if (!image_path.empty()) {
- // Load user image asynchronously.
- image_loader_->Start(
- image_path, 0,
- base::Bind(&UserManager::SetUserImage,
- base::Unretained(this), email, image_index));
- }
- } else {
- NOTREACHED();
- }
- }
- }
-
- std::string display_email;
- if (prefs_display_emails &&
- prefs_display_emails->GetStringWithoutPathExpansion(
- email, &display_email)) {
- user->set_display_email(display_email);
- }
- }
- }
- }
-}
-
-void UserManager::StubUserLoggedIn() {
- logged_in_user_ = &stub_user_;
- stub_user_.SetImage(GetDefaultImage(kStubDefaultImageIndex),
- kStubDefaultImageIndex);
-}
-
-void UserManager::NotifyOnLogin() {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_LOGIN_USER_CHANGED,
- content::Source<UserManager>(this),
- content::Details<const User>(logged_in_user_));
-
-#if defined(TOOLKIT_USES_GTK)
- // Let the window manager know that we're logged in now.
- WmIpc::instance()->SetLoggedInProperty(true);
-#endif
-
- // Ensure we've opened the real user's key/certificate database.
- crypto::OpenPersistentNSSDB();
-
- // Only load the Opencryptoki library into NSS if we have this switch.
- // TODO(gspencer): Remove this switch once cryptohomed work is finished:
- // http://crosbug.com/12295 and http://crosbug.com/12304
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kLoadOpencryptoki)) {
- crypto::EnableTPMTokenForNSS(new RealTPMTokenInfoDelegate());
- CertLibrary* cert_library;
- cert_library = chromeos::CrosLibrary::Get()->GetCertLibrary();
- // Note: this calls crypto::EnsureTPMTokenReady()
- cert_library->RequestCertificates();
- }
-
- // Schedules current user ownership check on file thread.
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&UserManager::CheckOwnership,
- base::Unretained(this)));
-}
-
-void UserManager::SetInitialUserImage(const std::string& username) {
- // Choose a random default image.
- int image_id = base::RandInt(0, kDefaultImagesCount - 1);
- SaveUserDefaultImageIndex(username, image_id);
-}
-
-void UserManager::SetUserImage(const std::string& username,
- int image_index,
- const SkBitmap& image) {
- User* user = const_cast<User*>(FindUser(username));
- // User may have been removed by now.
- if (user) {
- // For existing users, a valid image index should have been set upon loading
- // them from Local State.
- DCHECK(user->image_index() != User::kInvalidImageIndex ||
- current_user_is_new_);
- bool image_changed = user->image_index() != User::kInvalidImageIndex;
- if (!image.empty())
- user->SetImage(image, image_index);
- else
- user->SetStubImage(image_index);
- // For the logged-in user with a profile picture, initialize
- // |downloaded_profile_picture_|.
- if (user == logged_in_user_ && image_index == User::kProfileImageIndex)
- InitDownloadedProfileImage();
- if (image_changed) {
- // Unless this is first-time setting with |SetInitialUserImage|,
- // send a notification about image change.
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
- content::Source<UserManager>(this),
- content::Details<const User>(user));
- }
- }
-}
-
-void UserManager::SaveUserImageInternal(const std::string& username,
- int image_index,
- const SkBitmap& image) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- SetUserImage(username, image_index, image);
-
- FilePath image_path = GetImagePathForUser(username);
- DVLOG(1) << "Saving user image to " << image_path.value();
-
- last_image_set_async_ = true;
-
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&UserManager::SaveImageToFile,
- base::Unretained(this),
- username, image, image_path, image_index));
-}
-
-void UserManager::SaveImageToFile(const std::string& username,
- const SkBitmap& image,
- const FilePath& image_path,
- int image_index) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- std::vector<unsigned char> encoded_image;
- if (!gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &encoded_image)) {
- LOG(ERROR) << "Failed to PNG encode the image.";
- return;
- }
-
- if (file_util::WriteFile(image_path,
- reinterpret_cast<char*>(&encoded_image[0]),
- encoded_image.size()) == -1) {
- LOG(ERROR) << "Failed to save image to file.";
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&UserManager::SaveImageToLocalState,
- base::Unretained(this),
- username, image_path.value(), image_index, true));
-}
-
-void UserManager::SaveImageToLocalState(const std::string& username,
- const std::string& image_path,
- int image_index,
- bool is_async) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // TODO(ivankr): use unique filenames for user images each time
- // a new image is set so that only the last image update is saved
- // to Local State and notified.
- if (is_async && !last_image_set_async_) {
- DVLOG(1) << "Ignoring saved image because it has changed";
- return;
- } else if (!is_async) {
- // Reset the async image save flag if called directly from the UI thread.
- last_image_set_async_ = false;
- }
-
- PrefService* local_state = g_browser_process->local_state();
- DictionaryPrefUpdate images_update(local_state, kUserImages);
- base::DictionaryValue* image_properties = new base::DictionaryValue();
- image_properties->Set(kImagePathNodeName, new StringValue(image_path));
- image_properties->Set(kImageIndexNodeName,
- new base::FundamentalValue(image_index));
- images_update->SetWithoutPathExpansion(username, image_properties);
- DVLOG(1) << "Saving path to user image in Local State.";
-
- NotifyLocalStateChanged();
-}
-
-void UserManager::InitDownloadedProfileImage() {
- DCHECK(logged_in_user_);
- if (downloaded_profile_image_.empty() && !logged_in_user_->image_is_stub()) {
- VLOG(1) << "Profile image initialized";
- downloaded_profile_image_ = logged_in_user_->image();
- downloaded_profile_image_data_url_ =
- web_ui_util::GetImageDataUrl(downloaded_profile_image_);
- }
-}
-
-void UserManager::DeleteUserImage(const FilePath& image_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (!file_util::Delete(image_path, false)) {
- LOG(ERROR) << "Failed to remove user image.";
- return;
- }
-}
-
-void UserManager::UpdateOwnership(bool is_owner) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- set_current_user_is_owner(is_owner);
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_OWNERSHIP_CHECKED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
- if (is_owner) {
- // Also update cached value.
- CrosSettings::Get()->SetString(
- kDeviceOwner,
- g_user_manager.Get().logged_in_user().email());
- }
-}
-
-void UserManager::CheckOwnership() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- bool is_owner = OwnershipService::GetSharedInstance()->CurrentUserIsOwner();
- VLOG(1) << "Current user " << (is_owner ? "is owner" : "is not owner");
-
- set_current_user_is_owner(is_owner);
-
- // UserManager should be accessed only on UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&UserManager::UpdateOwnership,
- base::Unretained(this),
- is_owner));
-}
-
-int UserManager::GetDesiredImageSideLength() const {
- return login::kUserImageSize;
-}
-
-Profile* UserManager::GetBrowserProfile() {
- return ProfileManager::GetDefaultProfile();
-}
-
-std::string UserManager::GetCachedPictureURL() const {
- // Currently the profile picture URL is not cached on ChromeOS.
- return std::string();
-}
-
-void UserManager::OnDownloadComplete(ProfileDownloader* downloader,
- bool success) {
- // Make sure that |ProfileDownloader| gets deleted after return.
- scoped_ptr<ProfileDownloader> profile_image_downloader(
- profile_image_downloader_.release());
- DCHECK(profile_image_downloader.get() == downloader);
-
- ProfileDownloadResult result;
- if (!success) {
- result = kDownloadFailure;
- } else if (downloader->GetProfilePicture().isNull()) {
- result = kDownloadDefault;
- } else {
- result = kDownloadSuccess;
- }
- UMA_HISTOGRAM_ENUMERATION("UserImage.ProfileDownloadResult",
- result, kDownloadResultsCount);
-
- DCHECK(!profile_image_load_start_time_.is_null());
- base::TimeDelta delta = base::Time::Now() - profile_image_load_start_time_;
- AddProfileImageTimeHistogram(result, profile_image_download_reason_, delta);
-
- if (result == kDownloadSuccess) {
- // Check if this image is not the same as already downloaded.
- std::string new_image_data_url =
- web_ui_util::GetImageDataUrl(downloader->GetProfilePicture());
- if (!downloaded_profile_image_data_url_.empty() &&
- new_image_data_url == downloaded_profile_image_data_url_)
- return;
-
- downloaded_profile_image_data_url_ = new_image_data_url;
- downloaded_profile_image_ = downloader->GetProfilePicture();
-
- if (logged_in_user().image_index() == User::kProfileImageIndex) {
- VLOG(1) << "Updating profile image for logged-in user";
- UMA_HISTOGRAM_ENUMERATION("UserImage.ProfileDownloadResult",
- kDownloadSuccessChanged,
- kDownloadResultsCount);
-
- // This will persist |downloaded_profile_image_| to file.
- SaveUserImageFromProfileImage(logged_in_user().email());
- }
- }
-
- if (result == kDownloadSuccess) {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
- content::Source<UserManager>(this),
- content::Details<const SkBitmap>(&downloaded_profile_image_));
- } else {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
- content::Source<UserManager>(this),
- content::NotificationService::NoDetails());
- }
-}
-
-User* UserManager::CreateUser(const std::string& email) const {
- User* user = new User(email, email == kGuestUser);
- user->set_oauth_token_status(LoadUserOAuthStatus(email));
- // Used to determine whether user's display name is unique.
- ++display_name_count_[user->GetDisplayName()];
- return user;
-}
-
} // namespace chromeos
« no previous file with comments | « chrome/browser/chromeos/login/user_manager.h ('k') | chrome/browser/chromeos/login/user_manager_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698