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. 4 5 #include <string> 6 7 #include "ash/ash_switches.h" 8 #include "base/command_line.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/string16.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "chrome/browser/chromeos/login/users/fake_user_manager.h" 13 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" 14 #include "chrome/browser/chromeos/profiles/profile_helper.h" 15 #include "chrome/browser/prefs/pref_service_syncable.h" 16 #include "chrome/browser/profiles/avatar_menu.h" 17 #include "chrome/browser/profiles/avatar_menu_observer.h" 18 #include "chrome/browser/profiles/profile_info_cache.h" 19 #include "chrome/browser/ui/ash/chrome_shell_delegate.h" 20 #include "chrome/common/chrome_constants.h" 21 #include "chrome/common/chrome_switches.h" 22 #include "chrome/test/base/testing_browser_process.h" 23 #include "chrome/test/base/testing_profile_manager.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 using base::ASCIIToUTF16; 27 28 namespace { 29 30 class MockObserver : public AvatarMenuObserver { 31 public: 32 MockObserver() : count_(0) {} 33 virtual ~MockObserver() {} 34 35 virtual void OnAvatarMenuChanged( 36 AvatarMenu* avatar_menu) OVERRIDE { 37 ++count_; 38 } 39 40 int change_count() const { return count_; } 41 42 private: 43 int count_; 44 45 DISALLOW_COPY_AND_ASSIGN(MockObserver); 46 }; 47 48 } // namespace 49 50 namespace chromeos { 51 52 class ProfileListChromeOSTest : public testing::Test { 53 public: 54 ProfileListChromeOSTest() 55 : manager_(TestingBrowserProcess::GetGlobal()) { 56 } 57 58 virtual void SetUp() { 59 ASSERT_TRUE(manager_.SetUp()); 60 61 // AvatarMenu and multiple profiles works after user logged in. 62 manager_.SetLoggedIn(true); 63 64 // Initialize the UserManager singleton to a fresh FakeUserManager instance. 65 user_manager_enabler_.reset( 66 new ScopedUserManagerEnabler(new FakeUserManager)); 67 } 68 69 FakeUserManager* GetFakeUserManager() { 70 return static_cast<FakeUserManager*>(user_manager::UserManager::Get()); 71 } 72 73 void AddProfile(base::string16 name, bool log_in) { 74 std::string email_string = base::UTF16ToASCII(name) + "@example.com"; 75 76 // Add a user to the fake user manager. 77 GetFakeUserManager()->AddUser(email_string); 78 if (log_in) 79 GetFakeUserManager()->LoginUser(email_string); 80 81 // Create a profile for the user. 82 manager()->CreateTestingProfile(email_string); 83 } 84 85 AvatarMenu* GetAvatarMenu() { 86 // Reset the MockObserver. 87 mock_observer_.reset(new MockObserver()); 88 EXPECT_EQ(0, change_count()); 89 90 // Reset the menu. 91 avatar_menu_.reset(new AvatarMenu( 92 manager()->profile_info_cache(), 93 mock_observer_.get(), 94 NULL)); 95 avatar_menu_->RebuildMenu(); 96 EXPECT_EQ(0, change_count()); 97 return avatar_menu_.get(); 98 } 99 100 void ActiveUserChanged(const base::string16& name) { 101 std::string email_string = base::UTF16ToASCII(name) + "@example.com"; 102 GetFakeUserManager()->SwitchActiveUser(email_string); 103 } 104 105 TestingProfileManager* manager() { return &manager_; } 106 107 int change_count() const { return mock_observer_->change_count(); } 108 109 private: 110 TestingProfileManager manager_; 111 scoped_ptr<MockObserver> mock_observer_; 112 scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_; 113 scoped_ptr<AvatarMenu> avatar_menu_; 114 ChromeShellDelegate chrome_shell_delegate_; 115 116 DISALLOW_COPY_AND_ASSIGN(ProfileListChromeOSTest); 117 }; 118 119 TEST_F(ProfileListChromeOSTest, InitialCreation) { 120 base::string16 name1(ASCIIToUTF16("p1")); 121 122 AddProfile(name1, true); 123 124 AvatarMenu* menu = GetAvatarMenu(); 125 126 ASSERT_EQ(1U, menu->GetNumberOfItems()); 127 128 const AvatarMenu::Item& item1 = menu->GetItemAt(0); 129 EXPECT_EQ(0U, item1.menu_index); 130 EXPECT_EQ(name1, item1.name); 131 } 132 133 TEST_F(ProfileListChromeOSTest, ShowLoggedInUsers) { 134 base::string16 name1(ASCIIToUTF16("p1")); 135 base::string16 name2(ASCIIToUTF16("p2")); 136 base::string16 name3(ASCIIToUTF16("p3")); 137 base::string16 name4(ASCIIToUTF16("p4")); 138 139 AddProfile(name1, true); 140 AddProfile(name2, false); 141 AddProfile(name3, true); 142 AddProfile(name4, false); 143 144 AvatarMenu* menu = GetAvatarMenu(); 145 146 ASSERT_EQ(2U, menu->GetNumberOfItems()); 147 148 const AvatarMenu::Item& item1 = menu->GetItemAt(0); 149 EXPECT_EQ(0U, item1.menu_index); 150 EXPECT_EQ(name1, item1.name); 151 152 const AvatarMenu::Item& item3 = menu->GetItemAt(1); 153 EXPECT_EQ(1U, item3.menu_index); 154 EXPECT_EQ(name3, item3.name); 155 } 156 157 TEST_F(ProfileListChromeOSTest, DontShowSupervisedUsers) { 158 base::string16 name1(ASCIIToUTF16("p1")); 159 base::string16 supervised_name(ASCIIToUTF16("p2 (at) example.com")); 160 161 AddProfile(name1, true); 162 163 // Add a managed user profile. 164 ProfileInfoCache* cache = manager()->profile_info_cache(); 165 manager()->profile_info_cache()->AddProfileToCache( 166 cache->GetUserDataDir().AppendASCII("p2"), supervised_name, 167 base::string16(), 0, "TEST_ID"); 168 169 GetFakeUserManager()->AddUser(base::UTF16ToASCII(supervised_name)); 170 171 AvatarMenu* menu = GetAvatarMenu(); 172 ASSERT_EQ(1U, menu->GetNumberOfItems()); 173 174 const AvatarMenu::Item& item1 = menu->GetItemAt(0); 175 EXPECT_EQ(0U, item1.menu_index); 176 EXPECT_EQ(name1, item1.name); 177 } 178 179 TEST_F(ProfileListChromeOSTest, ShowAddProfileLink) { 180 base::string16 name1(ASCIIToUTF16("p1.com")); 181 base::string16 name2(ASCIIToUTF16("p2.com")); 182 183 AddProfile(name1, true); 184 AddProfile(name2, false); 185 186 AvatarMenu* menu = GetAvatarMenu(); 187 188 ASSERT_EQ(1U, menu->GetNumberOfItems()); 189 EXPECT_TRUE(menu->ShouldShowAddNewProfileLink()); 190 } 191 192 TEST_F(ProfileListChromeOSTest, DontShowAddProfileLink) { 193 base::string16 name1(ASCIIToUTF16("p1.com")); 194 base::string16 name2(ASCIIToUTF16("p2.com")); 195 196 AddProfile(name1, true); 197 AddProfile(name2, true); 198 199 AvatarMenu* menu = GetAvatarMenu(); 200 201 ASSERT_EQ(2U, menu->GetNumberOfItems()); 202 EXPECT_FALSE(menu->ShouldShowAddNewProfileLink()); 203 } 204 205 TEST_F(ProfileListChromeOSTest, ActiveItem) { 206 base::string16 name1(ASCIIToUTF16("p1.com")); 207 base::string16 name2(ASCIIToUTF16("p2.com")); 208 209 AddProfile(name1, true); 210 AddProfile(name2, true); 211 212 ActiveUserChanged(name1); 213 214 AvatarMenu* menu = GetAvatarMenu(); 215 216 ASSERT_EQ(2U, menu->GetNumberOfItems()); 217 // TODO(jeremy): Expand test to verify active profile index other than 0 218 // crbug.com/100871 219 ASSERT_EQ(0U, menu->GetActiveProfileIndex()); 220 } 221 222 TEST_F(ProfileListChromeOSTest, ModifyingNameResortsCorrectly) { 223 base::string16 name1(ASCIIToUTF16("Alpha")); 224 base::string16 name2(ASCIIToUTF16("Beta")); 225 base::string16 newname1(ASCIIToUTF16("Gamma")); 226 227 AddProfile(name1, true); 228 AddProfile(name2, true); 229 230 AvatarMenu* menu = GetAvatarMenu(); 231 232 ASSERT_EQ(2U, menu->GetNumberOfItems()); 233 234 const AvatarMenu::Item& item1 = menu->GetItemAt(0); 235 EXPECT_EQ(0U, item1.menu_index); 236 EXPECT_EQ(name1, item1.name); 237 238 const AvatarMenu::Item& item2 = menu->GetItemAt(1); 239 EXPECT_EQ(1U, item2.menu_index); 240 EXPECT_EQ(name2, item2.name); 241 242 // Change name of the first profile, to trigger resorting of the profiles: 243 // now the first menu item should be named "beta", and the second be "gamma". 244 GetFakeUserManager()->SaveUserDisplayName( 245 base::UTF16ToASCII(name1) + "@example.com", newname1); 246 manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, newname1); 247 248 const AvatarMenu::Item& item1next = menu->GetItemAt(0); 249 EXPECT_GT(change_count(), 1); 250 EXPECT_EQ(0U, item1next.menu_index); 251 EXPECT_EQ(name2, item1next.name); 252 253 const AvatarMenu::Item& item2next = menu->GetItemAt(1); 254 EXPECT_EQ(1U, item2next.menu_index); 255 EXPECT_EQ(newname1, item2next.name); 256 } 257 258 TEST_F(ProfileListChromeOSTest, ChangeOnNotify) { 259 base::string16 name1(ASCIIToUTF16("p1.com")); 260 base::string16 name2(ASCIIToUTF16("p2.com")); 261 262 AddProfile(name1, true); 263 AddProfile(name2, true); 264 265 AvatarMenu* menu = GetAvatarMenu(); 266 EXPECT_EQ(2U, menu->GetNumberOfItems()); 267 268 base::string16 name3(ASCIIToUTF16("p3.com")); 269 AddProfile(name3, true); 270 271 // Four changes happened via the call to CreateTestingProfile: adding the 272 // profile to the cache, setting the user name, rebuilding the list of 273 // profiles after the name change, and changing the avatar. 274 // TODO(michaelpg): Determine why actual change number does not match comment. 275 EXPECT_GE(change_count(), 4); 276 ASSERT_EQ(3U, menu->GetNumberOfItems()); 277 278 const AvatarMenu::Item& item1 = menu->GetItemAt(0); 279 EXPECT_EQ(0U, item1.menu_index); 280 EXPECT_EQ(name1, item1.name); 281 282 const AvatarMenu::Item& item2 = menu->GetItemAt(1); 283 EXPECT_EQ(1U, item2.menu_index); 284 EXPECT_EQ(name2, item2.name); 285 286 const AvatarMenu::Item& item3 = menu->GetItemAt(2); 287 EXPECT_EQ(2U, item3.menu_index); 288 EXPECT_EQ(name3, item3.name); 289 } 290 291 TEST_F(ProfileListChromeOSTest, DontShowAvatarMenu) { 292 // If in the new M-32 UX mode the icon gets shown, the menu will not. 293 base::string16 name1(ASCIIToUTF16("p1")); 294 base::string16 name2(ASCIIToUTF16("p2")); 295 296 AddProfile(name1, true); 297 298 // Should only show avatar menu with multiple users. 299 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 300 301 AddProfile(name2, false); 302 303 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 304 } 305 306 } // namespace chromeos 307