• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
6 
7 #include "ash/ash_switches.h"
8 #include "base/bind.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 "components/signin/core/common/profile_management_switches.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h"
30 #include "grit/generated_resources.h"
31 #include "grit/theme_resources.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h"
34 
35 #if defined(ENABLE_MANAGED_USERS)
36 #include "chrome/browser/supervised_user/supervised_user_service.h"
37 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
38 #endif
39 
40 using content::BrowserThread;
41 
42 namespace {
43 
44 // Constants for the show profile switcher experiment
45 const char kShowProfileSwitcherFieldTrialName[] = "ShowProfileSwitcher";
46 const char kAlwaysShowSwitcherGroupName[] = "AlwaysShow";
47 
48 }  // namespace
49 
AvatarMenu(ProfileInfoInterface * profile_cache,AvatarMenuObserver * observer,Browser * browser)50 AvatarMenu::AvatarMenu(ProfileInfoInterface* profile_cache,
51                        AvatarMenuObserver* observer,
52                        Browser* browser)
53     : profile_list_(ProfileList::Create(profile_cache)),
54       menu_actions_(AvatarMenuActions::Create()),
55       profile_info_(profile_cache),
56       observer_(observer),
57       browser_(browser) {
58   DCHECK(profile_info_);
59   // Don't DCHECK(browser_) so that unit tests can reuse this ctor.
60 
61   ActiveBrowserChanged(browser_);
62 
63   // Register this as an observer of the info cache.
64   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
65       content::NotificationService::AllSources());
66 }
67 
~AvatarMenu()68 AvatarMenu::~AvatarMenu() {
69 }
70 
Item(size_t menu_index,size_t profile_index,const gfx::Image & icon)71 AvatarMenu::Item::Item(size_t menu_index,
72                        size_t profile_index,
73                        const gfx::Image& icon)
74     : icon(icon),
75       active(false),
76       signed_in(false),
77       signin_required(false),
78       menu_index(menu_index),
79       profile_index(profile_index) {
80 }
81 
~Item()82 AvatarMenu::Item::~Item() {
83 }
84 
85 // static
ShouldShowAvatarMenu()86 bool AvatarMenu::ShouldShowAvatarMenu() {
87   if (base::FieldTrialList::FindFullName(kShowProfileSwitcherFieldTrialName) ==
88       kAlwaysShowSwitcherGroupName) {
89     // We should only be in this group when multi-profiles is enabled.
90     DCHECK(profiles::IsMultipleProfilesEnabled());
91     return true;
92   }
93 
94   // TODO: Eliminate this ifdef. Add a delegate interface for the menu which
95   // would also help remove the Browser dependency in AvatarMenuActions
96   // implementations.
97   if (profiles::IsMultipleProfilesEnabled()) {
98 #if defined(OS_CHROMEOS)
99     // On ChromeOS the menu will not be shown.
100     return false;
101 #else
102     return switches::IsNewAvatarMenu() ||
103            (g_browser_process->profile_manager() &&
104             g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
105 #endif
106   }
107   return false;
108 }
109 
CompareItems(const Item * item1,const Item * item2)110 bool AvatarMenu::CompareItems(const Item* item1, const Item* item2) {
111   return base::i18n::ToLower(item1->name).compare(
112       base::i18n::ToLower(item2->name)) < 0;
113 }
114 
SwitchToProfile(size_t index,bool always_create,ProfileMetrics::ProfileOpen metric)115 void AvatarMenu::SwitchToProfile(size_t index,
116                                  bool always_create,
117                                  ProfileMetrics::ProfileOpen metric) {
118   DCHECK(profiles::IsMultipleProfilesEnabled() ||
119          index == GetActiveProfileIndex());
120   const Item& item = GetItemAt(index);
121 
122   if (switches::IsNewProfileManagement()) {
123     // Don't open a browser window for signed-out profiles.
124     if (item.signin_required) {
125       chrome::ShowUserManager(item.profile_path);
126       return;
127     }
128   }
129 
130   base::FilePath path =
131       profile_info_->GetPathOfProfileAtIndex(item.profile_index);
132 
133   chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
134   if (browser_)
135     desktop_type = browser_->host_desktop_type();
136 
137   profiles::SwitchToProfile(path, desktop_type, always_create,
138                             profiles::ProfileSwitchingDoneCallback(),
139                             metric);
140 }
141 
AddNewProfile(ProfileMetrics::ProfileAdd type)142 void AvatarMenu::AddNewProfile(ProfileMetrics::ProfileAdd type) {
143   menu_actions_->AddNewProfile(type);
144 }
145 
EditProfile(size_t index)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;
149 
150   Profile* profile = g_browser_process->profile_manager()->GetProfileByPath(
151         profile_info_->GetPathOfProfileAtIndex(profile_index));
152 
153   menu_actions_->EditProfile(profile, profile_index);
154 }
155 
RebuildMenu()156 void AvatarMenu::RebuildMenu() {
157   profile_list_->RebuildMenu();
158 }
159 
GetNumberOfItems() const160 size_t AvatarMenu::GetNumberOfItems() const {
161   return profile_list_->GetNumberOfItems();
162 }
163 
GetItemAt(size_t index) const164 const AvatarMenu::Item& AvatarMenu::GetItemAt(size_t index) const {
165   return profile_list_->GetItemAt(index);
166 }
GetActiveProfileIndex()167 size_t AvatarMenu::GetActiveProfileIndex() {
168 
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)
172     return 0;
173 
174   Profile* active_profile = NULL;
175   if (!browser_)
176     active_profile = ProfileManager::GetLastUsedProfile();
177   else
178     active_profile = browser_->profile();
179 
180   size_t index =
181       profile_info_->GetIndexOfProfileWithPath(active_profile->GetPath());
182 
183   index = profile_list_->MenuIndexFromProfileIndex(index);
184   DCHECK_LT(index, profile_list_->GetNumberOfItems());
185   return index;
186 }
187 
GetSupervisedUserInformation() const188 base::string16 AvatarMenu::GetSupervisedUserInformation() const {
189   // |browser_| can be NULL in unit_tests.
190   if (browser_ && browser_->profile()->IsSupervised()) {
191 #if defined(ENABLE_MANAGED_USERS)
192     SupervisedUserService* service =
193         SupervisedUserServiceFactory::GetForProfile(browser_->profile());
194     base::string16 custodian =
195         base::UTF8ToUTF16(service->GetCustodianEmailAddress());
196     return l10n_util::GetStringFUTF16(IDS_MANAGED_USER_INFO, custodian);
197 #endif
198   }
199   return base::string16();
200 }
201 
GetSupervisedUserIcon() const202 const gfx::Image& AvatarMenu::GetSupervisedUserIcon() const {
203   return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
204       IDR_MANAGED_USER_ICON);
205 }
206 
ActiveBrowserChanged(Browser * browser)207 void AvatarMenu::ActiveBrowserChanged(Browser* browser) {
208   browser_ = browser;
209   menu_actions_->ActiveBrowserChanged(browser);
210 
211   // If browser is not NULL, get the path of its active profile.
212   base::FilePath path;
213   if (browser)
214     path = browser->profile()->GetPath();
215   profile_list_->ActiveProfilePathChanged(path);
216 }
217 
ShouldShowAddNewProfileLink() const218 bool AvatarMenu::ShouldShowAddNewProfileLink() const {
219   return menu_actions_->ShouldShowAddNewProfileLink();
220 }
221 
ShouldShowEditProfileLink() const222 bool AvatarMenu::ShouldShowEditProfileLink() const {
223   return menu_actions_->ShouldShowEditProfileLink();
224 }
225 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)226 void AvatarMenu::Observe(int type,
227                          const content::NotificationSource& source,
228                          const content::NotificationDetails& details) {
229   DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, type);
230   RebuildMenu();
231   if (observer_)
232     observer_->OnAvatarMenuChanged(this);
233 }
234