Commit 364aaef8 authored by bartfab@chromium.org's avatar bartfab@chromium.org

Add public accounts to UserManager

This is a re-land of CL 11419184:

This CL extends the UserManager to handle public accounts defined through
policy. User pods are dynamically added and removed when the list of
public accounts in policy changes. Any data belonging to obsolete accounts
is also removed, taking care not to remove it prematurely if a user is
currently logged into the account.

The CL also makes the user list handling more robust by checking for
duplicate entries in the user list prefs and logging these as errors.

The pods added for public accounts are not functional yet. The login flow
for public accounts will be the topic of another CL.

BUG=158509,163690

Review URL: https://chromiumcodereview.appspot.com/11411314

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170943 0039d316-1c4b-4281-b951-d872f2087c98
parent cec80c3d
......@@ -655,6 +655,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// Delete ContactManager while |g_browser_process| is still alive.
contact_manager_.reset();
// Let the UserManager unregister itself as an observer of the CrosSettings
// singleton before it is destroyed.
UserManager::Get()->Shutdown();
ChromeBrowserMainPartsLinux::PostMainMessageLoopRun();
}
......
......@@ -190,8 +190,10 @@ void ExistingUserController::UpdateLoginDisplay(const UserList& users) {
if (show_users_on_signin) {
for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
// TODO(xiyuan): Clean user profile whose email is not in whitelist.
if (LoginUtils::IsWhitelisted((*it)->email()))
if (LoginUtils::IsWhitelisted((*it)->email()) ||
(*it)->GetType() != User::USER_TYPE_REGULAR) {
filtered_users.push_back(*it);
}
}
}
......
......@@ -21,6 +21,7 @@ class MockUserManager : public UserManager {
MockUserManager();
virtual ~MockUserManager();
MOCK_METHOD0(Shutdown, void(void));
MOCK_CONST_METHOD0(GetUsers, const UserList&(void));
MOCK_METHOD2(UserLoggedIn, void(const std::string&, bool));
MOCK_METHOD0(RetailModeUserLoggedIn, void(void));
......@@ -44,6 +45,7 @@ class MockUserManager : public UserManager {
MOCK_CONST_METHOD0(IsCurrentUserEphemeral, bool(void));
MOCK_CONST_METHOD0(CanCurrentUserLock, bool(void));
MOCK_CONST_METHOD0(IsUserLoggedIn, bool(void));
MOCK_CONST_METHOD0(IsLoggedInAsRegularUser, bool(void));
MOCK_CONST_METHOD0(IsLoggedInAsDemoUser, bool(void));
MOCK_CONST_METHOD0(IsLoggedInAsPublicAccount, bool(void));
MOCK_CONST_METHOD0(IsLoggedInAsGuest, bool(void));
......
......@@ -62,6 +62,10 @@ class UserManager {
// Registers user manager preferences.
static void RegisterPrefs(PrefService* local_state);
// Indicates imminent shutdown, allowing the UserManager to remove any
// observers it has registered.
virtual void Shutdown() = 0;
virtual ~UserManager();
virtual UserImageManager* GetUserImageManager() = 0;
......@@ -157,6 +161,9 @@ class UserManager {
// Returns true if user is signed in.
virtual bool IsUserLoggedIn() const = 0;
// Returns true if we're logged in as a regular user.
virtual bool IsLoggedInAsRegularUser() const = 0;
// Returns true if we're logged in as a demo user.
virtual bool IsLoggedInAsDemoUser() const = 0;
......
......@@ -12,11 +12,13 @@
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "chrome/browser/api/sync/profile_sync_service_observer.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wallpaper_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
......@@ -37,6 +39,7 @@ class UserManagerImpl : public UserManager,
virtual ~UserManagerImpl();
// UserManager implementation:
virtual void Shutdown() OVERRIDE;
virtual UserImageManager* GetUserImageManager() OVERRIDE;
virtual const UserList& GetUsers() const OVERRIDE;
virtual void UserLoggedIn(const std::string& email,
......@@ -68,6 +71,7 @@ class UserManagerImpl : public UserManager,
virtual bool IsCurrentUserEphemeral() const OVERRIDE;
virtual bool CanCurrentUserLock() const OVERRIDE;
virtual bool IsUserLoggedIn() const OVERRIDE;
virtual bool IsLoggedInAsRegularUser() const OVERRIDE;
virtual bool IsLoggedInAsDemoUser() const OVERRIDE;
virtual bool IsLoggedInAsPublicAccount() const OVERRIDE;
virtual bool IsLoggedInAsGuest() const OVERRIDE;
......@@ -125,13 +129,32 @@ class UserManagerImpl : public UserManager,
// Triggers an asynchronous ownership check.
void CheckOwnership();
// Removes the user from the persistent list only. Also removes the user's
// picture.
void RemoveUserFromListInternal(const std::string& email);
// Removes data stored or cached outside the user's cryptohome (wallpaper,
// avatar, OAuth token status, display name, display email).
void RemoveNonCryptohomeData(const std::string& email);
// List of all known users. User instances are owned by |this| and deleted
// when users are removed by |RemoveUserFromListInternal|.
mutable UserList users_;
// Removes a regular user from the user list. Returns the user if found or
// NULL otherwise. Also removes the user from the persistent regular user
// list.
User *RemoveRegularUserFromList(const std::string& email);
// Replaces the list of public accounts with |public_accounts|. Ensures that
// data belonging to accounts no longer on the list is removed. Returns |true|
// if the list has changed.
// Public accounts are defined by policy. This method is called whenever an
// updated list of public accounts is received from policy.
bool UpdateAndCleanUpPublicAccounts(const base::ListValue& public_accounts);
// Interface to the signed settings store.
CrosSettings* cros_settings_;
// True if users have been loaded from prefs already.
bool users_loaded_;
// List of all known users. User instances are owned by |this|. Regular users
// are removed by |RemoveUserFromList|, public accounts by
// |UpdateAndCleanUpPublicAccounts|.
UserList users_;
// The logged-in user. NULL until a user has logged in, then points to one
// of the User instances in |users_|, the |guest_user_| instance or an
......@@ -176,6 +199,7 @@ class UserManagerImpl : public UserManager,
ObserverList<UserManager::Observer> observer_list_;
// User avatar manager.
scoped_ptr<UserImageManagerImpl> user_image_manager_;
DISALLOW_COPY_AND_ASSIGN(UserManagerImpl);
......
......@@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/cros_settings_names.h"
#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/test/base/testing_browser_process.h"
......@@ -80,6 +81,14 @@ class UserManagerTest : public testing::Test {
cros_settings_->AddSettingsProvider(device_settings_provider_);
UserManager::Set(old_user_manager_);
// Shut down the DeviceSettingsService.
DeviceSettingsService::Get()->Shutdown();
// Shut down the remaining UserManager instances.
if (user_manager_impl)
user_manager_impl->Shutdown();
UserManager::Get()->Shutdown();
}
bool GetUserManagerEphemeralUsersEnabled() const {
......@@ -103,6 +112,8 @@ class UserManagerTest : public testing::Test {
}
void ResetUserManager() {
if (user_manager_impl)
user_manager_impl->Shutdown();
user_manager_impl.reset(new UserManagerImpl());
UserManager::Set(user_manager_impl.get());
}
......
......@@ -16,6 +16,7 @@
#include "base/values.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/test/base/testing_browser_process.h"
#include "ui/aura/env.h"
......@@ -27,8 +28,6 @@ namespace chromeos {
namespace {
const char kTestUser1[] = "test-user@example.com";
#if defined(GOOGLE_CHROME_BUILD)
int kExpectedSmallWallpaperWidth = ash::kSmallWallpaperMaxWidth;
int kExpectedSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
......@@ -83,13 +82,6 @@ class WallpaperManagerBrowserTest : public CrosInProcessBrowserTest,
MessageLoop::current()->Quit();
}
// Sets |username| wallpaper.
void SetUserWallpaper(const std::string& username) {
ListPrefUpdate users_pref(local_state_, "LoggedInUsers");
users_pref->AppendIfNotPresent(new base::StringValue(username));
WallpaperManager::Get()->SetUserWallpaper(username);
}
protected:
// Saves bitmap |resource_id| to disk.
void SaveUserWallpaperData(const std::string& username,
......@@ -129,9 +121,9 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
User::DEFAULT,
base::Time::Now().LocalMidnight()
};
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
wallpaper_manager->SetUserWallpaperInfo(UserManager::kStubUser, info, true);
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
WaitAsyncWallpaperLoad();
gfx::ImageSkia wallpaper = controller_->GetWallpaper();
......@@ -165,31 +157,30 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
LoadCustomLargeWallpaperForLargeExternalScreen) {
WallpaperManager* wallpaper_manager = WallpaperManager::Get();
FilePath small_wallpaper_path =
wallpaper_manager->GetWallpaperPathForUser(kTestUser1, true);
wallpaper_manager->GetWallpaperPathForUser(UserManager::kStubUser, true);
FilePath large_wallpaper_path =
wallpaper_manager->GetWallpaperPathForUser(kTestUser1, false);
wallpaper_manager->GetWallpaperPathForUser(UserManager::kStubUser, false);
// Saves the small/large resolution wallpapers to small/large custom
// wallpaper paths.
SaveUserWallpaperData(kTestUser1,
SaveUserWallpaperData(UserManager::kStubUser,
small_wallpaper_path,
ash::kDefaultSmallWallpaper.idr);
SaveUserWallpaperData(kTestUser1,
SaveUserWallpaperData(UserManager::kStubUser,
large_wallpaper_path,
ash::kDefaultLargeWallpaper.idr);
// Saves wallpaper info to local state for user |kTestUser1|.
// Saves wallpaper info to local state for user |UserManager::kStubUser|.
WallpaperInfo info = {
"DUMMY",
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::CUSTOMIZED,
base::Time::Now().LocalMidnight()
};
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
// Add user |kTestUser1|.
wallpaper_manager->SetUserWallpaperInfo(UserManager::kStubUser, info, true);
SetUserWallpaper(kTestUser1);
// Set the wallpaper for |UserManager::kStubUser|.
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
WaitAsyncWallpaperLoad();
gfx::ImageSkia wallpaper = controller_->GetWallpaper();
......@@ -224,46 +215,46 @@ IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
PreventReloadingSameWallpaper) {
WallpaperManager* wallpaper_manager = WallpaperManager::Get();
FilePath small_wallpaper_path =
wallpaper_manager->GetWallpaperPathForUser(kTestUser1, true);
wallpaper_manager->GetWallpaperPathForUser(UserManager::kStubUser, true);
SaveUserWallpaperData(kTestUser1,
SaveUserWallpaperData(UserManager::kStubUser,
small_wallpaper_path,
ash::kDefaultSmallWallpaper.idr);
// Saves wallpaper info to local state for user |kTestUser1|.
// Saves wallpaper info to local state for user |UserManager::kStubUser|.
WallpaperInfo info = {
"DUMMY",
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::CUSTOMIZED,
base::Time::Now().LocalMidnight()
};
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
wallpaper_manager->SetUserWallpaperInfo(UserManager::kStubUser, info, true);
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(1, LoadedWallpapers());
// Loads the same wallpaper before the initial one finished. It should be
// prevented.
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(1, LoadedWallpapers());
WaitAsyncWallpaperLoad();
// Loads the same wallpaper after the initial one finished. It should be
// prevented.
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(1, LoadedWallpapers());
wallpaper_manager->ClearWallpaperCache();
// Tests default wallpaper for user |kTestUser1|.
// Tests default wallpaper for user |UserManager::kStubUser|.
info.file = "";
info.type = User::DEFAULT;
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaperInfo(UserManager::kStubUser, info, true);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(2, LoadedWallpapers());
// Loads the same wallpaper before the initial one finished. It should be
// prevented.
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(2, LoadedWallpapers());
WaitAsyncWallpaperLoad();
SetUserWallpaper(kTestUser1);
wallpaper_manager->SetUserWallpaper(UserManager::kStubUser);
EXPECT_EQ(2, LoadedWallpapers());
}
......
......@@ -85,7 +85,8 @@ void DeviceSettingsService::Shutdown() {
pending_operations_.end());
pending_operations_.clear();
session_manager_client_->RemoveObserver(this);
if (session_manager_client_)
session_manager_client_->RemoveObserver(this);
session_manager_client_ = NULL;
owner_key_util_ = NULL;
}
......
......@@ -20,6 +20,7 @@ const char* kHandledSettings[] = {
kAccountsPrefShowUserNamesOnSignIn,
kAccountsPrefUsers,
kAccountsPrefEphemeralUsersEnabled,
kAccountsPrefDeviceLocalAccounts,
kDeviceOwner,
kPolicyMissingMitigationMode,
kReleaseChannel,
......@@ -84,6 +85,7 @@ void StubCrosSettingsProvider::SetDefaults() {
values_.SetBoolean(kAccountsPrefAllowGuest, true);
values_.SetBoolean(kAccountsPrefAllowNewUser, true);
values_.SetBoolean(kAccountsPrefShowUserNamesOnSignIn, true);
values_.SetValue(kAccountsPrefDeviceLocalAccounts, new ListValue);
// |kDeviceOwner| will be set to the logged-in user by |UserManager|.
}
......
......@@ -68,6 +68,7 @@ const char kKeyUsername[] = "username";
const char kKeyDisplayName[] = "displayName";
const char kKeyEmailAddress[] = "emailAddress";
const char kKeyNameTooltip[] = "nameTooltip";
const char kKeyPublicAccount[] = "publicAccount";
const char kKeySignedIn[] = "signedIn";
const char kKeyCanRemove[] = "canRemove";
const char kKeyOauthTokenStatus[] = "oauthTokenStatus";
......@@ -735,6 +736,7 @@ void SigninScreenHandler::SendUserList(bool animated) {
std::string owner;
chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
bool is_owner = (email == owner);
bool public_account = ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
bool signed_in = *it == UserManager::Get()->GetLoggedInUser();
if (non_owner_count < max_non_owner_users || is_owner) {
......@@ -743,6 +745,7 @@ void SigninScreenHandler::SendUserList(bool animated) {
user_dict->SetString(kKeyEmailAddress, (*it)->display_email());
user_dict->SetString(kKeyDisplayName, (*it)->GetDisplayName());
user_dict->SetString(kKeyNameTooltip, (*it)->display_email());
user_dict->SetBoolean(kKeyPublicAccount, public_account);
user_dict->SetInteger(kKeyOauthTokenStatus, (*it)->oauth_token_status());
user_dict->SetBoolean(kKeySignedIn, signed_in);
......@@ -753,6 +756,7 @@ void SigninScreenHandler::SendUserList(bool animated) {
!single_user &&
!email.empty() &&
!is_owner &&
!public_account &&
!signed_in);
users_list.Append(user_dict);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment