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/avatar_menu_model.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/metrics/field_trial.h" 9 #include "base/strings/string16.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "chrome/browser/prefs/pref_service_syncable.h" 12 #include "chrome/browser/profiles/avatar_menu_model_observer.h" 13 #include "chrome/browser/profiles/profile_info_cache.h" 14 #include "chrome/browser/profiles/profiles_state.h" 15 #include "chrome/test/base/testing_browser_process.h" 16 #include "chrome/test/base/testing_profile_manager.h" 17 #include "grit/generated_resources.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 #include "ui/base/l10n/l10n_util.h" 20 21 namespace { 22 23 class MockObserver : public AvatarMenuModelObserver { 24 public: 25 MockObserver() : count_(0) {} 26 virtual ~MockObserver() {} 27 28 virtual void OnAvatarMenuModelChanged( 29 AvatarMenuModel* avatar_menu_model) OVERRIDE{ 30 ++count_; 31 } 32 33 int change_count() { return count_; } 34 35 private: 36 int count_; 37 }; 38 39 class AvatarMenuModelTest : public testing::Test { 40 public: 41 AvatarMenuModelTest() 42 : manager_(TestingBrowserProcess::GetGlobal()) { 43 } 44 45 virtual void SetUp() { 46 ASSERT_TRUE(manager_.SetUp()); 47 #if defined(OS_CHROMEOS) 48 // AvatarMenu and multiple profiles works after user logged in. 49 manager_.SetLoggedIn(true); 50 #endif 51 } 52 53 Browser* browser() { return NULL; } 54 55 TestingProfileManager* manager() { return &manager_; } 56 57 private: 58 TestingProfileManager manager_; 59 }; 60 61 TEST_F(AvatarMenuModelTest, InitialCreation) { 62 string16 name1(ASCIIToUTF16("Test 1")); 63 string16 name2(ASCIIToUTF16("Test 2")); 64 65 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 66 name1, 0, std::string()); 67 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 68 name2, 0, std::string()); 69 70 MockObserver observer; 71 EXPECT_EQ(0, observer.change_count()); 72 73 AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser()); 74 EXPECT_EQ(0, observer.change_count()); 75 76 ASSERT_EQ(2U, model.GetNumberOfItems()); 77 78 const AvatarMenuModel::Item& item1 = model.GetItemAt(0); 79 EXPECT_EQ(0U, item1.model_index); 80 EXPECT_EQ(name1, item1.name); 81 82 const AvatarMenuModel::Item& item2 = model.GetItemAt(1); 83 EXPECT_EQ(1U, item2.model_index); 84 EXPECT_EQ(name2, item2.name); 85 } 86 87 TEST_F(AvatarMenuModelTest, ActiveItem) { 88 string16 name1(ASCIIToUTF16("Test 1")); 89 string16 name2(ASCIIToUTF16("Test 2")); 90 91 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 92 name1, 0, std::string()); 93 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 94 name2, 0, std::string()); 95 96 MockObserver observer; 97 AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser()); 98 ASSERT_EQ(2U, model.GetNumberOfItems()); 99 // TODO(jeremy): Expand test to verify active profile index other than 0 100 // crbug.com/100871 101 ASSERT_EQ(0U, model.GetActiveProfileIndex()); 102 } 103 104 TEST_F(AvatarMenuModelTest, ModifyingNameResortsCorrectly) { 105 string16 name1(ASCIIToUTF16("Alpha")); 106 string16 name2(ASCIIToUTF16("Beta")); 107 string16 newname1(ASCIIToUTF16("Gamma")); 108 109 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 110 name1, 0, std::string()); 111 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 112 name2, 0, std::string()); 113 114 MockObserver observer; 115 AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser()); 116 EXPECT_EQ(0, observer.change_count()); 117 118 ASSERT_EQ(2U, model.GetNumberOfItems()); 119 120 const AvatarMenuModel::Item& item1 = model.GetItemAt(0); 121 EXPECT_EQ(0U, item1.model_index); 122 EXPECT_EQ(name1, item1.name); 123 124 const AvatarMenuModel::Item& item2 = model.GetItemAt(1); 125 EXPECT_EQ(1U, item2.model_index); 126 EXPECT_EQ(name2, item2.name); 127 128 // Change name of the first profile, to trigger resorting of the profiles: 129 // now the first model should be named "beta", and the second be "gamma". 130 manager()->profile_info_cache()->SetNameOfProfileAtIndex(0, newname1); 131 const AvatarMenuModel::Item& item1next = model.GetItemAt(0); 132 EXPECT_GT(observer.change_count(), 1); 133 EXPECT_EQ(0U, item1next.model_index); 134 EXPECT_EQ(name2, item1next.name); 135 136 const AvatarMenuModel::Item& item2next = model.GetItemAt(1); 137 EXPECT_EQ(1U, item2next.model_index); 138 EXPECT_EQ(newname1, item2next.name); 139 } 140 141 TEST_F(AvatarMenuModelTest, ChangeOnNotify) { 142 string16 name1(ASCIIToUTF16("Test 1")); 143 string16 name2(ASCIIToUTF16("Test 2")); 144 145 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 146 name1, 0, std::string()); 147 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 148 name2, 0, std::string()); 149 150 MockObserver observer; 151 EXPECT_EQ(0, observer.change_count()); 152 153 AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser()); 154 EXPECT_EQ(0, observer.change_count()); 155 EXPECT_EQ(2U, model.GetNumberOfItems()); 156 157 string16 name3(ASCIIToUTF16("Test 3")); 158 manager()->CreateTestingProfile("p3", scoped_ptr<PrefServiceSyncable>(), 159 name3, 0, std::string()); 160 161 // Four changes happened via the call to CreateTestingProfile: adding the 162 // profile to the cache, setting the user name, rebuilding the list of 163 // profiles after the name change, and changing the avatar. 164 // On Windows, an extra change happens to set the shortcut name for the 165 // profile. 166 EXPECT_GE(observer.change_count(), 4); 167 ASSERT_EQ(3U, model.GetNumberOfItems()); 168 169 const AvatarMenuModel::Item& item1 = model.GetItemAt(0); 170 EXPECT_EQ(0U, item1.model_index); 171 EXPECT_EQ(name1, item1.name); 172 173 const AvatarMenuModel::Item& item2 = model.GetItemAt(1); 174 EXPECT_EQ(1U, item2.model_index); 175 EXPECT_EQ(name2, item2.name); 176 177 const AvatarMenuModel::Item& item3 = model.GetItemAt(2); 178 EXPECT_EQ(2U, item3.model_index); 179 EXPECT_EQ(name3, item3.name); 180 } 181 182 TEST_F(AvatarMenuModelTest, ShowAvatarMenuInTrial) { 183 // If multiprofile mode is not enabled, the trial will not be enabled, so it 184 // isn't tested. 185 if (!profiles::IsMultipleProfilesEnabled()) 186 return; 187 188 base::FieldTrialList field_trial_list_(NULL); 189 base::FieldTrialList::CreateFieldTrial("ShowProfileSwitcher", "AlwaysShow"); 190 191 #if defined(OS_CHROMEOS) 192 EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu()); 193 #else 194 EXPECT_TRUE(AvatarMenuModel::ShouldShowAvatarMenu()); 195 #endif 196 } 197 198 TEST_F(AvatarMenuModelTest, DontShowAvatarMenu) { 199 string16 name1(ASCIIToUTF16("Test 1")); 200 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 201 name1, 0, std::string()); 202 203 EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu()); 204 205 // If multiprofile mode is enabled, there are no other cases when we wouldn't 206 // show the menu. 207 if (profiles::IsMultipleProfilesEnabled()) 208 return; 209 210 string16 name2(ASCIIToUTF16("Test 2")); 211 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 212 name2, 0, std::string()); 213 214 EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu()); 215 } 216 217 TEST_F(AvatarMenuModelTest, ShowAvatarMenu) { 218 // If multiprofile mode is not enabled then the menu is never shown. 219 if (!profiles::IsMultipleProfilesEnabled()) 220 return; 221 222 string16 name1(ASCIIToUTF16("Test 1")); 223 string16 name2(ASCIIToUTF16("Test 2")); 224 225 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 226 name1, 0, std::string()); 227 manager()->CreateTestingProfile("p2", scoped_ptr<PrefServiceSyncable>(), 228 name2, 0, std::string()); 229 230 #if defined(OS_CHROMEOS) 231 EXPECT_FALSE(AvatarMenuModel::ShouldShowAvatarMenu()); 232 #else 233 EXPECT_TRUE(AvatarMenuModel::ShouldShowAvatarMenu()); 234 #endif 235 } 236 237 TEST_F(AvatarMenuModelTest, SyncState) { 238 // If multiprofile mode is not enabled then the menu is never shown. 239 if (!profiles::IsMultipleProfilesEnabled()) 240 return; 241 242 manager()->CreateTestingProfile("p1", scoped_ptr<PrefServiceSyncable>(), 243 ASCIIToUTF16("Test 1"), 0, std::string()); 244 245 // Add a managed user profile. 246 ProfileInfoCache* cache = manager()->profile_info_cache(); 247 manager()->profile_info_cache()->AddProfileToCache( 248 cache->GetUserDataDir().AppendASCII("p2"), ASCIIToUTF16("Test 2"), 249 string16(), 0, "TEST_ID"); 250 MockObserver observer; 251 AvatarMenuModel model(manager()->profile_info_cache(), &observer, browser()); 252 EXPECT_EQ(2U, model.GetNumberOfItems()); 253 254 // Now check that the sync_state of a managed user shows the managed user 255 // avatar label instead. 256 base::string16 managed_user_label = 257 l10n_util::GetStringUTF16(IDS_MANAGED_USER_AVATAR_LABEL); 258 const AvatarMenuModel::Item& item1 = model.GetItemAt(0); 259 EXPECT_NE(item1.sync_state, managed_user_label); 260 261 const AvatarMenuModel::Item& item2 = model.GetItemAt(1); 262 EXPECT_EQ(item2.sync_state, managed_user_label); 263 } 264 265 } // namespace 266