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.
5 #include "chrome/browser/profiles/avatar_menu.h"
7 #include "ash/ash_switches.h"
9 #include "base/i18n/case_conversion.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/profiles/avatar_menu_actions.h"
15 #include "chrome/browser/profiles/avatar_menu_observer.h"
16 #include "chrome/browser/profiles/profile_list.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/profiles/profile_metrics.h"
19 #include "chrome/browser/profiles/profile_window.h"
20 #include "chrome/browser/profiles/profiles_state.h"
21 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_dialogs.h"
24 #include "chrome/browser/ui/host_desktop.h"
25 #include "chrome/browser/ui/startup/startup_browser_creator.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/notification_service.h"
29 #include "grit/generated_resources.h"
30 #include "grit/theme_resources.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
34 #if defined(ENABLE_MANAGED_USERS)
35 #include "chrome/browser/managed_mode/managed_user_service.h"
36 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
39 using content::BrowserThread;
43 // Constants for the show profile switcher experiment
44 const char kShowProfileSwitcherFieldTrialName[] = "ShowProfileSwitcher";
45 const char kAlwaysShowSwitcherGroupName[] = "AlwaysShow";
49 AvatarMenu::AvatarMenu(ProfileInfoInterface* profile_cache,
50 AvatarMenuObserver* observer,
52 : profile_list_(ProfileList::Create(profile_cache)),
53 menu_actions_(AvatarMenuActions::Create()),
54 profile_info_(profile_cache),
57 DCHECK(profile_info_);
58 // Don't DCHECK(browser_) so that unit tests can reuse this ctor.
60 ActiveBrowserChanged(browser_);
62 // Register this as an observer of the info cache.
63 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
64 content::NotificationService::AllSources());
67 AvatarMenu::~AvatarMenu() {
70 AvatarMenu::Item::Item(size_t menu_index,
72 const gfx::Image& icon)
76 signin_required(false),
77 menu_index(menu_index),
78 profile_index(profile_index) {
81 AvatarMenu::Item::~Item() {
85 bool AvatarMenu::ShouldShowAvatarMenu() {
86 if (base::FieldTrialList::FindFullName(kShowProfileSwitcherFieldTrialName) ==
87 kAlwaysShowSwitcherGroupName) {
88 // We should only be in this group when multi-profiles is enabled.
89 DCHECK(profiles::IsMultipleProfilesEnabled());
93 // TODO: Eliminate this ifdef. Add a delegate interface for the menu which
94 // would also help remove the Browser dependency in AvatarMenuActions
96 if (profiles::IsMultipleProfilesEnabled()) {
97 #if defined(OS_CHROMEOS)
98 // On ChromeOS the menu will be shown in M-31 mode when it is possible to
99 // have two users logged in at the same time.
100 return ash::switches::UseFullMultiProfileMode() &&
101 ChromeShellDelegate::instance() &&
102 ChromeShellDelegate::instance()->IsMultiProfilesEnabled();
104 return profiles::IsNewProfileManagementEnabled() ||
105 (g_browser_process->profile_manager() &&
106 g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
112 bool AvatarMenu::CompareItems(const Item* item1, const Item* item2) {
113 return base::i18n::ToLower(item1->name).compare(
114 base::i18n::ToLower(item2->name)) < 0;
117 void AvatarMenu::SwitchToProfile(size_t index, bool always_create) {
118 DCHECK(profiles::IsMultipleProfilesEnabled() ||
119 index == GetActiveProfileIndex());
120 const Item& item = GetItemAt(index);
122 if (profiles::IsNewProfileManagementEnabled()) {
123 // Don't open a browser window for signed-out profiles.
124 if (item.signin_required) {
125 chrome::ShowUserManager(item.profile_path);
130 base::FilePath path =
131 profile_info_->GetPathOfProfileAtIndex(item.profile_index);
133 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
135 desktop_type = browser_->host_desktop_type();
137 profiles::SwitchToProfile(path, desktop_type, always_create,
138 profiles::ProfileSwitchingDoneCallback());
139 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_ICON);
142 void AvatarMenu::AddNewProfile(ProfileMetrics::ProfileAdd type) {
143 menu_actions_->AddNewProfile(type);
146 void AvatarMenu::EditProfile(size_t index) {
147 // Get the index in the profile cache from the menu index.
148 size_t profile_index = profile_list_->GetItemAt(index).profile_index;
150 Profile* profile = g_browser_process->profile_manager()->GetProfileByPath(
151 profile_info_->GetPathOfProfileAtIndex(profile_index));
153 menu_actions_->EditProfile(profile, profile_index);
156 void AvatarMenu::RebuildMenu() {
157 profile_list_->RebuildMenu();
160 size_t AvatarMenu::GetNumberOfItems() const {
161 return profile_list_->GetNumberOfItems();
164 const AvatarMenu::Item& AvatarMenu::GetItemAt(size_t index) const {
165 return profile_list_->GetItemAt(index);
167 size_t AvatarMenu::GetActiveProfileIndex() {
169 // During singleton profile deletion, this function can be called with no
170 // profiles in the model - crbug.com/102278 .
171 if (profile_list_->GetNumberOfItems() == 0)
174 Profile* active_profile = NULL;
176 active_profile = ProfileManager::GetLastUsedProfile();
178 active_profile = browser_->profile();
181 profile_info_->GetIndexOfProfileWithPath(active_profile->GetPath());
183 index = profile_list_->MenuIndexFromProfileIndex(index);
184 DCHECK_LT(index, profile_list_->GetNumberOfItems());
188 base::string16 AvatarMenu::GetManagedUserInformation() const {
189 // |browser_| can be NULL in unit_tests.
190 if (browser_ && browser_->profile()->IsManaged()) {
191 #if defined(ENABLE_MANAGED_USERS)
192 ManagedUserService* service = ManagedUserServiceFactory::GetForProfile(
193 browser_->profile());
194 base::string16 custodian = UTF8ToUTF16(service->GetCustodianEmailAddress());
195 return l10n_util::GetStringFUTF16(IDS_MANAGED_USER_INFO, custodian);
198 return base::string16();
201 const gfx::Image& AvatarMenu::GetManagedUserIcon() const {
202 return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
203 IDR_MANAGED_USER_ICON);
206 void AvatarMenu::ActiveBrowserChanged(Browser* browser) {
208 menu_actions_->ActiveBrowserChanged(browser);
210 // If browser is not NULL, get the path of its active profile.
213 path = browser->profile()->GetPath();
214 profile_list_->ActiveProfilePathChanged(path);
217 bool AvatarMenu::ShouldShowAddNewProfileLink() const {
218 return menu_actions_->ShouldShowAddNewProfileLink();
221 bool AvatarMenu::ShouldShowEditProfileLink() const {
222 return menu_actions_->ShouldShowEditProfileLink();
225 void AvatarMenu::Observe(int type,
226 const content::NotificationSource& source,
227 const content::NotificationDetails& details) {
228 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, type);
231 observer_->OnAvatarMenuChanged(this);
234 content::WebContents* AvatarMenu::BeginSignOut() {
235 return menu_actions_->BeginSignOut();
238 void AvatarMenu::SetLogoutURL(const std::string& logout_url) {
239 menu_actions_->SetLogoutURL(logout_url);