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 "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 
     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 
     68 AvatarMenu::~AvatarMenu() {
     69 }
     70 
     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 
     82 AvatarMenu::Item::~Item() {
     83 }
     84 
     85 // static
     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 
    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 
    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 
    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::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 
    202 const gfx::Image& AvatarMenu::GetSupervisedUserIcon() const {
    203   return ResourceBundle::GetSharedInstance().GetNativeImageNamed(
    204       IDR_MANAGED_USER_ICON);
    205 }
    206 
    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 
    218 bool AvatarMenu::ShouldShowAddNewProfileLink() const {
    219   return menu_actions_->ShouldShowAddNewProfileLink();
    220 }
    221 
    222 bool AvatarMenu::ShouldShowEditProfileLink() const {
    223   return menu_actions_->ShouldShowEditProfileLink();
    224 }
    225 
    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