Home | History | Annotate | Download | only in profiles
      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 "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"
     33 
     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"
     37 #endif
     38 
     39 using content::BrowserThread;
     40 
     41 namespace {
     42 
     43 // Constants for the show profile switcher experiment
     44 const char kShowProfileSwitcherFieldTrialName[] = "ShowProfileSwitcher";
     45 const char kAlwaysShowSwitcherGroupName[] = "AlwaysShow";
     46 
     47 }  // namespace
     48 
     49 AvatarMenu::AvatarMenu(ProfileInfoInterface* profile_cache,
     50                        AvatarMenuObserver* observer,
     51                        Browser* browser)
     52     : profile_list_(ProfileList::Create(profile_cache)),
     53       menu_actions_(AvatarMenuActions::Create()),
     54       profile_info_(profile_cache),
     55       observer_(observer),
     56       browser_(browser) {
     57   DCHECK(profile_info_);
     58   // Don't DCHECK(browser_) so that unit tests can reuse this ctor.
     59 
     60   ActiveBrowserChanged(browser_);
     61 
     62   // Register this as an observer of the info cache.
     63   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
     64       content::NotificationService::AllSources());
     65 }
     66 
     67 AvatarMenu::~AvatarMenu() {
     68 }
     69 
     70 AvatarMenu::Item::Item(size_t menu_index,
     71                        size_t profile_index,
     72                        const gfx::Image& icon)
     73     : icon(icon),
     74       active(false),
     75       signed_in(false),
     76       signin_required(false),
     77       menu_index(menu_index),
     78       profile_index(profile_index) {
     79 }
     80 
     81 AvatarMenu::Item::~Item() {
     82 }
     83 
     84 // static
     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());
     90     return true;
     91   }
     92 
     93   // TODO: Eliminate this ifdef. Add a delegate interface for the menu which
     94   // would also help remove the Browser dependency in AvatarMenuActions
     95   // implementations.
     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();
    103 #else
    104     return profiles::IsNewProfileManagementEnabled() ||
    105            (g_browser_process->profile_manager() &&
    106             g_browser_process->profile_manager()->GetNumberOfProfiles() > 1);
    107 #endif
    108   }
    109   return false;
    110 }
    111 
    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;
    115 }
    116 
    117 void AvatarMenu::SwitchToProfile(size_t index, bool always_create) {
    118   DCHECK(profiles::IsMultipleProfilesEnabled() ||
    119          index == GetActiveProfileIndex());
    120   const Item& item = GetItemAt(index);
    121 
    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);
    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   ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_ICON);
    140 }
    141 
    142 void AvatarMenu::AddNewProfile(ProfileMetrics::ProfileAdd type) {
    143   menu_actions_->AddNewProfile(type);
    144 }
    145 
    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 
    156 void AvatarMenu::RebuildMenu() {
    157   profile_list_->RebuildMenu();
    158 }
    159 
    160 size_t AvatarMenu::GetNumberOfItems() const {
    161   return profile_list_->GetNumberOfItems();
    162 }
    163 
    164 const AvatarMenu::Item& AvatarMenu::GetItemAt(size_t index) const {
    165   return profile_list_->GetItemAt(index);
    166 }
    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 
    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);
    196 #endif
    197   }
    198   return base::string16();
    199 }
    200 
    201 const gfx::Image& AvatarMenu::GetManagedUserIcon() const {
    202   return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
    203       IDR_MANAGED_USER_ICON);
    204 }
    205 
    206 void AvatarMenu::ActiveBrowserChanged(Browser* browser) {
    207   browser_ = browser;
    208   menu_actions_->ActiveBrowserChanged(browser);
    209 
    210   // If browser is not NULL, get the path of its active profile.
    211   base::FilePath path;
    212   if (browser)
    213     path = browser->profile()->GetPath();
    214   profile_list_->ActiveProfilePathChanged(path);
    215 }
    216 
    217 bool AvatarMenu::ShouldShowAddNewProfileLink() const {
    218   return menu_actions_->ShouldShowAddNewProfileLink();
    219 }
    220 
    221 bool AvatarMenu::ShouldShowEditProfileLink() const {
    222   return menu_actions_->ShouldShowEditProfileLink();
    223 }
    224 
    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);
    229   RebuildMenu();
    230   if (observer_)
    231     observer_->OnAvatarMenuChanged(this);
    232 }
    233