1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "ash/ash_switches.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/chromeos/login/fake_user_manager.h"
14 #include "chrome/browser/prefs/pref_service_syncable.h"
15 #include "chrome/browser/profiles/avatar_menu.h"
16 #include "chrome/browser/profiles/avatar_menu_observer.h"
17 #include "chrome/browser/profiles/profile_info_cache.h"
18 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/testing_browser_process.h"
22 #include "chrome/test/base/testing_profile_manager.h"
23 #include "components/variations/entropy_provider.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/base/l10n/l10n_util.h"
29 // As defined in /chromeos/dbus/cryptohome_client.cc.
30 static const char kUserIdHashSuffix[] = "-hash";
32 class MockObserver : public AvatarMenuObserver {
34 MockObserver() : count_(0) {}
35 virtual ~MockObserver() {}
37 virtual void OnAvatarMenuChanged(
38 AvatarMenu* avatar_menu) OVERRIDE {
42 int change_count() const { return count_; }
47 DISALLOW_COPY_AND_ASSIGN(MockObserver);
54 class ProfileListChromeOSTest : public testing::Test {
56 ProfileListChromeOSTest()
57 : manager_(TestingBrowserProcess::GetGlobal()) {
60 virtual void SetUp() {
61 ASSERT_TRUE(manager_.SetUp());
63 // AvatarMenu and multiple profiles works after user logged in.
64 manager_.SetLoggedIn(true);
66 // We only instantiate UserMenuModel if multi-profile mode is enabled.
67 CommandLine* cl = CommandLine::ForCurrentProcess();
68 cl->AppendSwitch(switches::kMultiProfiles);
70 field_trial_list_.reset(new base::FieldTrialList(
71 new metrics::SHA1EntropyProvider("42")));
72 base::FieldTrialList::CreateTrialsFromString(
73 "ChromeOSUseMultiProfiles/Enable/",
74 base::FieldTrialList::ACTIVATE_TRIALS);
76 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
77 user_manager_enabler_.reset(
78 new ScopedUserManagerEnabler(new FakeUserManager));
81 FakeUserManager* GetFakeUserManager() {
82 return static_cast<FakeUserManager*>(UserManager::Get());
85 void AddProfile(string16 name, bool log_in) {
86 std::string email_string = UTF16ToASCII(name) + "@example.com";
88 // Add a user to the fake user manager.
89 GetFakeUserManager()->AddUser(email_string);
91 GetFakeUserManager()->UserLoggedIn(
93 email_string + kUserIdHashSuffix,
97 // Create a profile for the user.
98 manager()->CreateTestingProfile(
99 chrome::kProfileDirPrefix + email_string + kUserIdHashSuffix,
100 scoped_ptr<PrefServiceSyncable>(),
101 ASCIIToUTF16(email_string), 0, std::string());
104 AvatarMenu* GetAvatarMenu() {
105 // Reset the MockObserver.
106 mock_observer_.reset(new MockObserver());
107 EXPECT_EQ(0, change_count());
110 avatar_menu_.reset(new AvatarMenu(
111 manager()->profile_info_cache(),
112 mock_observer_.get(),
114 avatar_menu_->RebuildMenu();
115 EXPECT_EQ(0, change_count());
116 return avatar_menu_.get();
119 TestingProfileManager* manager() { return &manager_; }
121 int change_count() const { return mock_observer_->change_count(); }
124 TestingProfileManager manager_;
125 scoped_ptr<MockObserver> mock_observer_;
126 scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
127 scoped_ptr<AvatarMenu> avatar_menu_;
128 ChromeShellDelegate chrome_shell_delegate_;
129 scoped_ptr<base::FieldTrialList> field_trial_list_;
131 DISALLOW_COPY_AND_ASSIGN(ProfileListChromeOSTest);
134 TEST_F(ProfileListChromeOSTest, InitialCreation) {
135 string16 name1(ASCIIToUTF16("p1"));
137 AddProfile(name1, true);
139 AvatarMenu* menu = GetAvatarMenu();
141 ASSERT_EQ(1U, menu->GetNumberOfItems());
143 const AvatarMenu::Item& item1 = menu->GetItemAt(0);
144 EXPECT_EQ(0U, item1.menu_index);
145 EXPECT_EQ(name1, item1.name);
148 TEST_F(ProfileListChromeOSTest, ShowLoggedInUsers) {
149 string16 name1(ASCIIToUTF16("p1"));
150 string16 name2(ASCIIToUTF16("p2"));
151 string16 name3(ASCIIToUTF16("p3"));
152 string16 name4(ASCIIToUTF16("p4"));
154 AddProfile(name1, true);
155 AddProfile(name2, false);
156 AddProfile(name3, true);
157 AddProfile(name4, false);
159 AvatarMenu* menu = GetAvatarMenu();
161 ASSERT_EQ(2U, menu->GetNumberOfItems());
163 const AvatarMenu::Item& item1 = menu->GetItemAt(0);
164 EXPECT_EQ(0U, item1.menu_index);
165 EXPECT_EQ(name1, item1.name);
167 const AvatarMenu::Item& item3 = menu->GetItemAt(1);
168 EXPECT_EQ(1U, item3.menu_index);
169 EXPECT_EQ(name3, item3.name);
172 TEST_F(ProfileListChromeOSTest, DontShowManagedUsers) {
173 string16 name1(ASCIIToUTF16("p1"));
174 string16 managed_name(ASCIIToUTF16("p2@example.com"));
176 AddProfile(name1, true);
178 // Add a managed user profile.
179 ProfileInfoCache* cache = manager()->profile_info_cache();
180 manager()->profile_info_cache()->AddProfileToCache(
181 cache->GetUserDataDir().AppendASCII("p2"), managed_name,
182 string16(), 0, "TEST_ID");
184 GetFakeUserManager()->AddUser(UTF16ToASCII(managed_name));
186 AvatarMenu* menu = GetAvatarMenu();
187 ASSERT_EQ(1U, menu->GetNumberOfItems());
189 const AvatarMenu::Item& item1 = menu->GetItemAt(0);
190 EXPECT_EQ(0U, item1.menu_index);
191 EXPECT_EQ(name1, item1.name);
194 TEST_F(ProfileListChromeOSTest, ShowAddProfileLink) {
195 string16 name1(ASCIIToUTF16("p1.com"));
196 string16 name2(ASCIIToUTF16("p2.com"));
198 AddProfile(name1, true);
199 AddProfile(name2, false);
201 AvatarMenu* menu = GetAvatarMenu();
203 ASSERT_EQ(1U, menu->GetNumberOfItems());
204 EXPECT_TRUE(menu->ShouldShowAddNewProfileLink());
207 TEST_F(ProfileListChromeOSTest, DontShowAddProfileLink) {
208 string16 name1(ASCIIToUTF16("p1.com"));
209 string16 name2(ASCIIToUTF16("p2.com"));
211 AddProfile(name1, true);
212 AddProfile(name2, true);
214 AvatarMenu* menu = GetAvatarMenu();
216 ASSERT_EQ(2U, menu->GetNumberOfItems());
217 EXPECT_FALSE(menu->ShouldShowAddNewProfileLink());
220 TEST_F(ProfileListChromeOSTest, ActiveItem) {
221 string16 name1(ASCIIToUTF16("p1.com"));
222 string16 name2(ASCIIToUTF16("p2.com"));
224 AddProfile(name1, true);
225 AddProfile(name2, true);
227 AvatarMenu* menu = GetAvatarMenu();
229 ASSERT_EQ(2U, menu->GetNumberOfItems());
230 // TODO(jeremy): Expand test to verify active profile index other than 0
232 ASSERT_EQ(0U, menu->GetActiveProfileIndex());
235 TEST_F(ProfileListChromeOSTest, ModifyingNameResortsCorrectly) {
236 string16 name1(ASCIIToUTF16("Alpha"));
237 string16 name2(ASCIIToUTF16("Beta"));
238 string16 newname1(ASCIIToUTF16("Gamma"));
240 AddProfile(name1, true);
241 AddProfile(name2, true);
243 AvatarMenu* menu = GetAvatarMenu();
245 ASSERT_EQ(2U, menu->GetNumberOfItems());
247 const AvatarMenu::Item& item1 = menu->GetItemAt(0);
248 EXPECT_EQ(0U, item1.menu_index);
249 EXPECT_EQ(name1, item1.name);
251 const AvatarMenu::Item& item2 = menu->GetItemAt(1);
252 EXPECT_EQ(1U, item2.menu_index);
253 EXPECT_EQ(name2, item2.name);
255 // Change name of the first profile, to trigger resorting of the profiles:
256 // now the first menu item should be named "beta", and the second be "gamma".
257 GetFakeUserManager()->SaveUserDisplayName(
258 UTF16ToASCII(name1) + "@example.com", newname1);
259 manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, newname1);
261 const AvatarMenu::Item& item1next = menu->GetItemAt(0);
262 EXPECT_GT(change_count(), 1);
263 EXPECT_EQ(0U, item1next.menu_index);
264 EXPECT_EQ(name2, item1next.name);
266 const AvatarMenu::Item& item2next = menu->GetItemAt(1);
267 EXPECT_EQ(1U, item2next.menu_index);
268 EXPECT_EQ(newname1, item2next.name);
271 TEST_F(ProfileListChromeOSTest, ChangeOnNotify) {
272 string16 name1(ASCIIToUTF16("p1.com"));
273 string16 name2(ASCIIToUTF16("p2.com"));
275 AddProfile(name1, true);
276 AddProfile(name2, true);
278 AvatarMenu* menu = GetAvatarMenu();
279 EXPECT_EQ(2U, menu->GetNumberOfItems());
281 string16 name3(ASCIIToUTF16("p3.com"));
282 AddProfile(name3, true);
284 // Four changes happened via the call to CreateTestingProfile: adding the
285 // profile to the cache, setting the user name, rebuilding the list of
286 // profiles after the name change, and changing the avatar.
287 // TODO(michaelpg): Determine why actual change number does not match comment.
288 EXPECT_GE(change_count(), 4);
289 ASSERT_EQ(3U, menu->GetNumberOfItems());
291 const AvatarMenu::Item& item1 = menu->GetItemAt(0);
292 EXPECT_EQ(0U, item1.menu_index);
293 EXPECT_EQ(name1, item1.name);
295 const AvatarMenu::Item& item2 = menu->GetItemAt(1);
296 EXPECT_EQ(1U, item2.menu_index);
297 EXPECT_EQ(name2, item2.name);
299 const AvatarMenu::Item& item3 = menu->GetItemAt(2);
300 EXPECT_EQ(2U, item3.menu_index);
301 EXPECT_EQ(name3, item3.name);
304 TEST_F(ProfileListChromeOSTest, DontShowAvatarMenu) {
305 // If in the new M-32 UX mode the icon gets shown, the menu will not.
306 string16 name1(ASCIIToUTF16("p1"));
307 string16 name2(ASCIIToUTF16("p2"));
309 AddProfile(name1, true);
311 // Should only show avatar menu with multiple users.
312 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
314 AddProfile(name2, false);
316 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
319 TEST_F(ProfileListChromeOSTest, ShowAvatarMenuInM31) {
320 // In M-31 mode, the menu will get shown.
321 CommandLine* cl = CommandLine::ForCurrentProcess();
322 cl->AppendSwitch(ash::switches::kAshEnableFullMultiProfileMode);
324 string16 name1(ASCIIToUTF16("p1"));
325 string16 name2(ASCIIToUTF16("p2"));
327 AddProfile(name1, true);
329 // Should only show avatar menu with multiple users.
330 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu());
332 AddProfile(name2, false);
334 EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu());
337 } // namespace chromeos