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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/profiles/profile_list_desktop.h" 6 7 #include <string> 8 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/prefs/pref_service_syncable.h" 14 #include "chrome/browser/profiles/avatar_menu_observer.h" 15 #include "chrome/browser/profiles/profile_info_cache.h" 16 #include "chrome/browser/profiles/profiles_state.h" 17 #include "chrome/test/base/testing_browser_process.h" 18 #include "chrome/test/base/testing_profile_manager.h" 19 #include "grit/generated_resources.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "ui/base/l10n/l10n_util.h" 22 23 using base::ASCIIToUTF16; 24 25 namespace { 26 27 class MockObserver : public AvatarMenuObserver { 28 public: 29 MockObserver() : count_(0) {} 30 virtual ~MockObserver() {} 31 32 virtual void OnAvatarMenuChanged( 33 AvatarMenu* avatar_menu) OVERRIDE { 34 ++count_; 35 } 36 37 int change_count() const { return count_; } 38 39 private: 40 int count_; 41 42 DISALLOW_COPY_AND_ASSIGN(MockObserver); 43 }; 44 45 class ProfileListDesktopTest : public testing::Test { 46 public: 47 ProfileListDesktopTest() 48 : manager_(TestingBrowserProcess::GetGlobal()) { 49 } 50 51 virtual void SetUp() { 52 ASSERT_TRUE(manager_.SetUp()); 53 #if defined(OS_CHROMEOS) 54 // AvatarMenu and multiple profiles works after user logged in. 55 manager_.SetLoggedIn(true); 56 #endif 57 } 58 59 AvatarMenu* GetAvatarMenu() { 60 // Reset the MockObserver. 61 mock_observer_.reset(new MockObserver()); 62 EXPECT_EQ(0, change_count()); 63 64 // Reset the model. 65 avatar_menu_.reset(new AvatarMenu( 66 manager()->profile_info_cache(), 67 mock_observer_.get(), 68 NULL)); 69 avatar_menu_->RebuildMenu(); 70 EXPECT_EQ(0, change_count()); 71 return avatar_menu_.get(); 72 } 73 74 TestingProfileManager* manager() { return &manager_; } 75 76 void AddOmittedProfile(std::string name) { 77 ProfileInfoCache* cache = manager()->profile_info_cache(); 78 cache->AddProfileToCache( 79 cache->GetUserDataDir().AppendASCII(name), ASCIIToUTF16(name), 80 base::string16(), 0, "TEST_ID"); 81 } 82 83 int change_count() const { return mock_observer_->change_count(); } 84 85 private: 86 TestingProfileManager manager_; 87 scoped_ptr<MockObserver> mock_observer_; 88 scoped_ptr<AvatarMenu> avatar_menu_; 89 90 DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopTest); 91 }; 92 93 TEST_F(ProfileListDesktopTest, InitialCreation) { 94 manager()->CreateTestingProfile("Test 1"); 95 manager()->CreateTestingProfile("Test 2"); 96 97 AvatarMenu* model = GetAvatarMenu(); 98 EXPECT_EQ(0, change_count()); 99 100 ASSERT_EQ(2U, model->GetNumberOfItems()); 101 102 const AvatarMenu::Item& item1 = model->GetItemAt(0); 103 EXPECT_EQ(0U, item1.menu_index); 104 EXPECT_EQ(ASCIIToUTF16("Test 1"), item1.name); 105 106 const AvatarMenu::Item& item2 = model->GetItemAt(1); 107 EXPECT_EQ(1U, item2.menu_index); 108 EXPECT_EQ(ASCIIToUTF16("Test 2"), item2.name); 109 } 110 111 TEST_F(ProfileListDesktopTest, NoOmittedProfiles) { 112 ProfileListDesktop profile_list(manager()->profile_info_cache()); 113 114 // Profiles are stored and listed alphabetically. 115 manager()->CreateTestingProfile("1 included"); 116 manager()->CreateTestingProfile("2 included"); 117 manager()->CreateTestingProfile("3 included"); 118 manager()->CreateTestingProfile("4 included"); 119 120 profile_list.RebuildMenu(); 121 ASSERT_EQ(4u, profile_list.GetNumberOfItems()); 122 123 const AvatarMenu::Item& item1 = profile_list.GetItemAt(0); 124 EXPECT_EQ(0u, item1.menu_index); 125 EXPECT_EQ(0u, item1.profile_index); 126 EXPECT_EQ(ASCIIToUTF16("1 included"), item1.name); 127 128 const AvatarMenu::Item& item2 = profile_list.GetItemAt(1); 129 EXPECT_EQ(1u, item2.menu_index); 130 EXPECT_EQ(1u, item2.profile_index); 131 EXPECT_EQ(ASCIIToUTF16("2 included"), item2.name); 132 133 const AvatarMenu::Item& item3 = profile_list.GetItemAt(2); 134 EXPECT_EQ(2u, item3.menu_index); 135 EXPECT_EQ(2u, item3.profile_index); 136 EXPECT_EQ(ASCIIToUTF16("3 included"), item3.name); 137 138 const AvatarMenu::Item& item4 = profile_list.GetItemAt(3); 139 EXPECT_EQ(3u, item4.menu_index); 140 EXPECT_EQ(3u, item4.profile_index); 141 EXPECT_EQ(ASCIIToUTF16("4 included"), item4.name); 142 143 EXPECT_EQ(0u, profile_list.MenuIndexFromProfileIndex(0)); 144 EXPECT_EQ(1u, profile_list.MenuIndexFromProfileIndex(1)); 145 EXPECT_EQ(2u, profile_list.MenuIndexFromProfileIndex(2)); 146 EXPECT_EQ(3u, profile_list.MenuIndexFromProfileIndex(3)); 147 } 148 149 TEST_F(ProfileListDesktopTest, WithOmittedProfiles) { 150 ProfileListDesktop profile_list(manager()->profile_info_cache()); 151 152 // Profiles are stored and listed alphabetically. 153 AddOmittedProfile("0 omitted"); 154 manager()->CreateTestingProfile("1 included"); 155 AddOmittedProfile("2 omitted"); 156 manager()->CreateTestingProfile("3 included"); 157 manager()->CreateTestingProfile("4 included"); 158 AddOmittedProfile("5 omitted"); 159 manager()->CreateTestingProfile("6 included"); 160 AddOmittedProfile("7 omitted"); 161 162 profile_list.RebuildMenu(); 163 ASSERT_EQ(4u, profile_list.GetNumberOfItems()); 164 165 const AvatarMenu::Item& item1 = profile_list.GetItemAt(0); 166 EXPECT_EQ(0u, item1.menu_index); 167 EXPECT_EQ(1u, item1.profile_index); 168 EXPECT_EQ(ASCIIToUTF16("1 included"), item1.name); 169 170 const AvatarMenu::Item& item2 = profile_list.GetItemAt(1); 171 EXPECT_EQ(1u, item2.menu_index); 172 EXPECT_EQ(3u, item2.profile_index); 173 EXPECT_EQ(ASCIIToUTF16("3 included"), item2.name); 174 175 const AvatarMenu::Item& item3 = profile_list.GetItemAt(2); 176 EXPECT_EQ(2u, item3.menu_index); 177 EXPECT_EQ(4u, item3.profile_index); 178 EXPECT_EQ(ASCIIToUTF16("4 included"), item3.name); 179 180 const AvatarMenu::Item& item4 = profile_list.GetItemAt(3); 181 EXPECT_EQ(3u, item4.menu_index); 182 EXPECT_EQ(6u, item4.profile_index); 183 EXPECT_EQ(ASCIIToUTF16("6 included"), item4.name); 184 185 EXPECT_EQ(0u, profile_list.MenuIndexFromProfileIndex(1)); 186 EXPECT_EQ(1u, profile_list.MenuIndexFromProfileIndex(3)); 187 EXPECT_EQ(2u, profile_list.MenuIndexFromProfileIndex(4)); 188 EXPECT_EQ(3u, profile_list.MenuIndexFromProfileIndex(6)); 189 } 190 191 TEST_F(ProfileListDesktopTest, ActiveItem) { 192 manager()->CreateTestingProfile("Test 1"); 193 manager()->CreateTestingProfile("Test 2"); 194 195 AvatarMenu* model = GetAvatarMenu(); 196 ASSERT_EQ(2U, model->GetNumberOfItems()); 197 // TODO(jeremy): Expand test to verify active profile index other than 0 198 // crbug.com/100871 199 ASSERT_EQ(0U, model->GetActiveProfileIndex()); 200 } 201 202 TEST_F(ProfileListDesktopTest, ModifyingNameResortsCorrectly) { 203 std::string name1("Alpha"); 204 std::string name2("Beta"); 205 std::string newname1("Gamma"); 206 207 manager()->CreateTestingProfile(name1); 208 manager()->CreateTestingProfile(name2); 209 210 AvatarMenu* model = GetAvatarMenu(); 211 EXPECT_EQ(0, change_count()); 212 213 ASSERT_EQ(2U, model->GetNumberOfItems()); 214 215 const AvatarMenu::Item& item1 = model->GetItemAt(0); 216 EXPECT_EQ(0U, item1.menu_index); 217 EXPECT_EQ(ASCIIToUTF16(name1), item1.name); 218 219 const AvatarMenu::Item& item2 = model->GetItemAt(1); 220 EXPECT_EQ(1U, item2.menu_index); 221 EXPECT_EQ(ASCIIToUTF16(name2), item2.name); 222 223 // Change name of the first profile, to trigger resorting of the profiles: 224 // now the first model should be named "beta", and the second be "gamma". 225 manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, 226 ASCIIToUTF16(newname1)); 227 const AvatarMenu::Item& item1next = model->GetItemAt(0); 228 EXPECT_GT(change_count(), 1); 229 EXPECT_EQ(0U, item1next.menu_index); 230 EXPECT_EQ(ASCIIToUTF16(name2), item1next.name); 231 232 const AvatarMenu::Item& item2next = model->GetItemAt(1); 233 EXPECT_EQ(1U, item2next.menu_index); 234 EXPECT_EQ(ASCIIToUTF16(newname1), item2next.name); 235 } 236 237 TEST_F(ProfileListDesktopTest, ChangeOnNotify) { 238 manager()->CreateTestingProfile("Test 1"); 239 manager()->CreateTestingProfile("Test 2"); 240 241 AvatarMenu* model = GetAvatarMenu(); 242 EXPECT_EQ(0, change_count()); 243 EXPECT_EQ(2U, model->GetNumberOfItems()); 244 245 manager()->CreateTestingProfile("Test 3"); 246 247 // Four changes happened via the call to CreateTestingProfile: adding the 248 // profile to the cache, setting the user name, rebuilding the list of 249 // profiles after the name change, and changing the avatar. 250 // On Windows, an extra change happens to set the shortcut name for the 251 // profile. 252 // TODO(michaelpg): Determine why five changes happen on ChromeOS and 253 // investigate other platforms. 254 EXPECT_GE(change_count(), 4); 255 ASSERT_EQ(3U, model->GetNumberOfItems()); 256 257 const AvatarMenu::Item& item1 = model->GetItemAt(0); 258 EXPECT_EQ(0U, item1.menu_index); 259 EXPECT_EQ(ASCIIToUTF16("Test 1"), item1.name); 260 261 const AvatarMenu::Item& item2 = model->GetItemAt(1); 262 EXPECT_EQ(1U, item2.menu_index); 263 EXPECT_EQ(ASCIIToUTF16("Test 2"), item2.name); 264 265 const AvatarMenu::Item& item3 = model->GetItemAt(2); 266 EXPECT_EQ(2U, item3.menu_index); 267 EXPECT_EQ(ASCIIToUTF16("Test 3"), item3.name); 268 } 269 270 TEST_F(ProfileListDesktopTest, ShowAvatarMenuInTrial) { 271 // If multiprofile mode is not enabled, the trial will not be enabled, so it 272 // isn't tested. 273 if (!profiles::IsMultipleProfilesEnabled()) 274 return; 275 276 base::FieldTrialList field_trial_list_(NULL); 277 base::FieldTrialList::CreateFieldTrial("ShowProfileSwitcher", "AlwaysShow"); 278 279 #if defined(OS_CHROMEOS) 280 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 281 #else 282 EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu()); 283 #endif 284 } 285 286 TEST_F(ProfileListDesktopTest, DontShowAvatarMenu) { 287 manager()->CreateTestingProfile("Test 1"); 288 289 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 290 291 // If multiprofile mode is enabled, there are no other cases when we wouldn't 292 // show the menu. 293 if (profiles::IsMultipleProfilesEnabled()) 294 return; 295 296 manager()->CreateTestingProfile("Test 2"); 297 298 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 299 } 300 301 TEST_F(ProfileListDesktopTest, ShowAvatarMenu) { 302 // If multiprofile mode is not enabled then the menu is never shown. 303 if (!profiles::IsMultipleProfilesEnabled()) 304 return; 305 306 manager()->CreateTestingProfile("Test 1"); 307 manager()->CreateTestingProfile("Test 2"); 308 309 #if defined(OS_CHROMEOS) 310 EXPECT_FALSE(AvatarMenu::ShouldShowAvatarMenu()); 311 #else 312 EXPECT_TRUE(AvatarMenu::ShouldShowAvatarMenu()); 313 #endif 314 } 315 316 TEST_F(ProfileListDesktopTest, SyncState) { 317 // If multiprofile mode is not enabled then the menu is never shown. 318 if (!profiles::IsMultipleProfilesEnabled()) 319 return; 320 321 manager()->CreateTestingProfile("Test 1"); 322 323 // Add a managed user profile. 324 ProfileInfoCache* cache = manager()->profile_info_cache(); 325 base::FilePath path = cache->GetUserDataDir().AppendASCII("p2"); 326 cache->AddProfileToCache(path, ASCIIToUTF16("Test 2"), base::string16(), 0, 327 "TEST_ID"); 328 cache->SetIsOmittedProfileAtIndex(cache->GetIndexOfProfileWithPath(path), 329 false); 330 331 AvatarMenu* model = GetAvatarMenu(); 332 model->RebuildMenu(); 333 EXPECT_EQ(2U, model->GetNumberOfItems()); 334 335 // Now check that the sync_state of a managed user shows the managed user 336 // avatar label instead. 337 base::string16 managed_user_label = 338 l10n_util::GetStringUTF16(IDS_MANAGED_USER_AVATAR_LABEL); 339 const AvatarMenu::Item& item1 = model->GetItemAt(0); 340 EXPECT_NE(item1.sync_state, managed_user_label); 341 342 const AvatarMenu::Item& item2 = model->GetItemAt(1); 343 EXPECT_EQ(item2.sync_state, managed_user_label); 344 } 345 346 } // namespace 347