blob: d224d8d17b5c236018821d34b401f47d99591073 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/profiles/profile_list_desktop.h"
#include <memory>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/avatar_menu_observer.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_list.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/account_id/account_id.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
using base::ASCIIToUTF16;
namespace {
class MockObserver : public AvatarMenuObserver {
public:
MockObserver() : count_(0) {}
~MockObserver() override {}
void OnAvatarMenuChanged(AvatarMenu* avatar_menu) override { ++count_; }
int change_count() const { return count_; }
private:
int count_;
DISALLOW_COPY_AND_ASSIGN(MockObserver);
};
class ProfileListDesktopTest : public testing::Test {
public:
ProfileListDesktopTest()
: manager_(TestingBrowserProcess::GetGlobal()) {
}
void SetUp() override {
ASSERT_TRUE(manager_.SetUp());
}
AvatarMenu* GetAvatarMenu() {
// Reset the MockObserver.
mock_observer_.reset(new MockObserver());
EXPECT_EQ(0, change_count());
// Reset the menu.
avatar_menu_.reset(new AvatarMenu(
manager()->profile_attributes_storage(),
mock_observer_.get(),
NULL));
avatar_menu_->RebuildMenu();
EXPECT_EQ(0, change_count());
return avatar_menu_.get();
}
TestingProfileManager* manager() { return &manager_; }
void AddOmittedProfile(const std::string& name) {
ProfileAttributesStorage* storage = manager()->profile_attributes_storage();
storage->AddProfile(manager()->profiles_dir().AppendASCII(name),
ASCIIToUTF16(name), std::string(), base::string16(), 0,
"TEST_ID", EmptyAccountId());
}
int change_count() const { return mock_observer_->change_count(); }
private:
content::TestBrowserThreadBundle thread_bundle_;
TestingProfileManager manager_;
std::unique_ptr<MockObserver> mock_observer_;
std::unique_ptr<AvatarMenu> avatar_menu_;
DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopTest);
};
TEST_F(ProfileListDesktopTest, InitialCreation) {
manager()->CreateTestingProfile("Test 1");
manager()->CreateTestingProfile("Test 2");
AvatarMenu* menu = GetAvatarMenu();
EXPECT_EQ(0, change_count());
ASSERT_EQ(2U, menu->GetNumberOfItems());
const AvatarMenu::Item& item1 = menu->GetItemAt(0);
EXPECT_EQ(0U, item1.menu_index);
EXPECT_EQ(ASCIIToUTF16("Test 1"), item1.name);
const AvatarMenu::Item& item2 = menu->GetItemAt(1);
EXPECT_EQ(1U, item2.menu_index);
EXPECT_EQ(ASCIIToUTF16("Test 2"), item2.name);
}
TEST_F(ProfileListDesktopTest, NoOmittedProfiles) {
ProfileListDesktop
profile_list_desktop(manager()->profile_attributes_storage());
ProfileList* profile_list = &profile_list_desktop;
// Profiles are stored and listed alphabetically.
std::vector<std::string> profile_names = {"0 included",
"1 included",
"2 included",
"3 included"};
size_t profile_count = profile_names.size();
// Add the profiles.
for (const std::string profile_name : profile_names)
manager()->CreateTestingProfile(profile_name);
// Rebuild avatar menu.
profile_list->RebuildMenu();
ASSERT_EQ(profile_count, profile_list->GetNumberOfItems());
// Verify contents in avatar menu.
for (size_t i = 0u; i < profile_count; ++i) {
const AvatarMenu::Item& item = profile_list->GetItemAt(i);
EXPECT_EQ(i, item.menu_index);
EXPECT_EQ(ASCIIToUTF16(profile_names[i]), item.name);
EXPECT_EQ(i, profile_list->MenuIndexFromProfilePath(item.profile_path));
}
}
TEST_F(ProfileListDesktopTest, WithOmittedProfiles) {
ProfileListDesktop
profile_list_desktop(manager()->profile_attributes_storage());
ProfileList* profile_list = &profile_list_desktop;
// Profiles are stored and listed alphabetically.
std::vector<std::string> profile_names = {"0 omitted",
"1 included",
"2 omitted",
"3 included",
"4 included",
"5 omitted",
"6 included",
"7 omitted"};
// Add the profiles.
std::vector<size_t> included_profile_indices;
for (size_t i = 0u; i < profile_names.size(); ++i) {
if (profile_names[i].find("included") != std::string::npos) {
manager()->CreateTestingProfile(profile_names[i]);
included_profile_indices.push_back(i);
} else {
AddOmittedProfile(profile_names[i]);
}
}
// Rebuild avatar menu.
size_t included_profile_count = included_profile_indices.size();
profile_list->RebuildMenu();
ASSERT_EQ(included_profile_count, profile_list->GetNumberOfItems());
// Verify contents in avatar menu.
for (size_t i = 0u; i < included_profile_count; ++i) {
const AvatarMenu::Item& item = profile_list->GetItemAt(i);
EXPECT_EQ(i, item.menu_index);
EXPECT_EQ(ASCIIToUTF16(profile_names[included_profile_indices[i]]),
item.name);
EXPECT_EQ(i, profile_list->MenuIndexFromProfilePath(item.profile_path));
}
}
TEST_F(ProfileListDesktopTest, ActiveItem) {
manager()->CreateTestingProfile("Test 1");
manager()->CreateTestingProfile("Test 2");
AvatarMenu* menu = GetAvatarMenu();
ASSERT_EQ(2u, menu->GetNumberOfItems());
// TODO(jeremy): Expand test to verify active profile index other than 0
// crbug.com/100871
ASSERT_EQ(0u, menu->GetActiveProfileIndex());
}
TEST_F(ProfileListDesktopTest, ModifyingNameResortsCorrectly) {
std::string name1("Alpha");
std::string name2("Beta");
std::string newname1("Gamma");
TestingProfile* profile1 = manager()->CreateTestingProfile(name1);
manager()->CreateTestingProfile(name2);
AvatarMenu* menu = GetAvatarMenu();
EXPECT_EQ(0, change_count());
ASSERT_EQ(2u, menu->GetNumberOfItems());
const AvatarMenu::Item& item1 = menu->GetItemAt(0u);
EXPECT_EQ(0u, item1.menu_index);
EXPECT_EQ(ASCIIToUTF16(name1), item1.name);
const AvatarMenu::Item& item2 = menu->GetItemAt(1u);
EXPECT_EQ(1u, item2.menu_index);
EXPECT_EQ(ASCIIToUTF16(name2), item2.name);
// Change the name of the first profile, and this triggers the resorting of
// the avatar menu.
ProfileAttributesEntry* entry;
ASSERT_TRUE(manager()->profile_attributes_storage()->
GetProfileAttributesWithPath(profile1->GetPath(), &entry));
entry->SetName(ASCIIToUTF16(newname1));
EXPECT_EQ(1, change_count());
// Now the first menu item should be named "beta", and the second be "gamma".
const AvatarMenu::Item& item1next = menu->GetItemAt(0u);
EXPECT_EQ(0u, item1next.menu_index);
EXPECT_EQ(ASCIIToUTF16(name2), item1next.name);
const AvatarMenu::Item& item2next = menu->GetItemAt(1u);
EXPECT_EQ(1u, item2next.menu_index);
EXPECT_EQ(ASCIIToUTF16(newname1), item2next.name);
}
TEST_F(ProfileListDesktopTest, ChangeOnNotify) {
manager()->CreateTestingProfile("Test 1");
manager()->CreateTestingProfile("Test 2");
AvatarMenu* menu = GetAvatarMenu();
EXPECT_EQ(0, change_count());
EXPECT_EQ(2u, menu->GetNumberOfItems());
manager()->CreateTestingProfile("Test 3");
// Three changes happened via the call to CreateTestingProfile: adding the
// profile to the attributes storage, setting the user name (which rebuilds
// the list of profiles after the name change) and changing the avatar.
// On Windows, an extra change happens to set the shortcut name for the
// profile.
EXPECT_GE(3, change_count());
ASSERT_EQ(3u, menu->GetNumberOfItems());
const AvatarMenu::Item& item1 = menu->GetItemAt(0u);
EXPECT_EQ(0u, item1.menu_index);
EXPECT_EQ(ASCIIToUTF16("Test 1"), item1.name);
const AvatarMenu::Item& item2 = menu->GetItemAt(1u);
EXPECT_EQ(1u, item2.menu_index);
EXPECT_EQ(ASCIIToUTF16("Test 2"), item2.name);
const AvatarMenu::Item& item3 = menu->GetItemAt(2u);
EXPECT_EQ(2u, item3.menu_index);
EXPECT_EQ(ASCIIToUTF16("Test 3"), item3.name);
}
TEST_F(ProfileListDesktopTest, SyncState) {
// If multiprofile mode is not enabled then the menu is never shown.
if (!profiles::IsMultipleProfilesEnabled())
return;
manager()->CreateTestingProfile("Test 1");
// Add a managed user profile.
ProfileAttributesStorage* storage = manager()->profile_attributes_storage();
base::FilePath path = manager()->profiles_dir().AppendASCII("p2");
storage->AddProfile(path, ASCIIToUTF16("Test 2"), std::string(),
base::string16(), 0u, "TEST_ID", EmptyAccountId());
ProfileAttributesEntry* entry;
ASSERT_TRUE(storage->GetProfileAttributesWithPath(path, &entry));
entry->SetIsOmitted(false);
AvatarMenu* menu = GetAvatarMenu();
menu->RebuildMenu();
EXPECT_EQ(2u, menu->GetNumberOfItems());
// Now check that the username of a supervised user shows the supervised
// user avatar label instead.
base::string16 supervised_user_label =
l10n_util::GetStringUTF16(IDS_LEGACY_SUPERVISED_USER_AVATAR_LABEL);
const AvatarMenu::Item& item1 = menu->GetItemAt(0u);
EXPECT_NE(item1.username, supervised_user_label);
const AvatarMenu::Item& item2 = menu->GetItemAt(1u);
EXPECT_EQ(item2.username, supervised_user_label);
}
} // namespace