1// Copyright 2014 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/chromeos/login/screens/chrome_user_selection_screen.h" 6 7#include "base/bind.h" 8#include "base/location.h" 9#include "base/logging.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/message_loop/message_loop.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/values.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/browser_process_platform_part.h" 16#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 17#include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" 18#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" 19#include "components/policy/core/common/cloud/cloud_policy_core.h" 20#include "components/policy/core/common/cloud/cloud_policy_store.h" 21#include "components/policy/core/common/policy_map.h" 22#include "components/policy/core/common/policy_types.h" 23#include "components/user_manager/user.h" 24#include "components/user_manager/user_manager.h" 25#include "components/user_manager/user_type.h" 26#include "policy/policy_constants.h" 27 28namespace chromeos { 29 30ChromeUserSelectionScreen::ChromeUserSelectionScreen() 31 : handler_initialized_(false), 32 weak_factory_(this) { 33 device_local_account_policy_service_ = g_browser_process->platform_part()-> 34 browser_policy_connector_chromeos()->GetDeviceLocalAccountPolicyService(); 35 device_local_account_policy_service_->AddObserver(this); 36} 37 38ChromeUserSelectionScreen::~ChromeUserSelectionScreen() { 39 device_local_account_policy_service_->RemoveObserver(this); 40} 41 42void ChromeUserSelectionScreen::Init(const user_manager::UserList& users, 43 bool show_guest) { 44 UserSelectionScreen::Init(users, show_guest); 45 46 // Retrieve the current policy for all users. 47 for (user_manager::UserList::const_iterator it = users.begin(); 48 it != users.end(); ++it) { 49 if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) 50 OnPolicyUpdated((*it)->GetUserID()); 51 } 52} 53 54void ChromeUserSelectionScreen::SendUserList() { 55 UserSelectionScreen::SendUserList(); 56 handler_initialized_ = true; 57} 58 59void ChromeUserSelectionScreen::OnPolicyUpdated(const std::string& user_id) { 60 policy::DeviceLocalAccountPolicyBroker* broker = 61 device_local_account_policy_service_->GetBrokerForUser(user_id); 62 if (!broker) 63 return; 64 65 CheckForPublicSessionDisplayNameChange(broker); 66 CheckForPublicSessionLocalePolicyChange(broker); 67} 68 69void ChromeUserSelectionScreen::OnDeviceLocalAccountsChanged() { 70 // Nothing to do here. When the list of device-local accounts changes, the 71 // entire UI is reloaded. 72} 73 74void ChromeUserSelectionScreen::CheckForPublicSessionDisplayNameChange( 75 policy::DeviceLocalAccountPolicyBroker* broker) { 76 const std::string& user_id = broker->user_id(); 77 const std::string& display_name = broker->GetDisplayName(); 78 if (display_name == public_session_display_names_[user_id]) 79 return; 80 81 public_session_display_names_[user_id] = display_name; 82 83 if (!handler_initialized_) 84 return; 85 86 if (!display_name.empty()) { 87 // If a new display name was set by policy, notify the UI about it. 88 handler_->SetPublicSessionDisplayName(user_id, display_name); 89 return; 90 } 91 92 // When no display name is set by policy, the |User|, owned by |UserManager|, 93 // decides what display name to use. However, the order in which |UserManager| 94 // and |this| are informed of the display name change is undefined. Post a 95 // task that will update the UI after the UserManager is guaranteed to have 96 // been informed of the change. 97 base::MessageLoop::current()->PostTask( 98 FROM_HERE, 99 base::Bind(&ChromeUserSelectionScreen::SetPublicSessionDisplayName, 100 weak_factory_.GetWeakPtr(), 101 user_id)); 102} 103 104void ChromeUserSelectionScreen::CheckForPublicSessionLocalePolicyChange( 105 policy::DeviceLocalAccountPolicyBroker* broker) { 106 const std::string& user_id = broker->user_id(); 107 const policy::PolicyMap::Entry* entry = 108 broker->core()->store()->policy_map().Get(policy::key::kSessionLocales); 109 110 // Parse the list of recommended locales set by policy. 111 std::vector<std::string> new_recommended_locales; 112 base::ListValue const* list = NULL; 113 if (entry && 114 entry->level == policy::POLICY_LEVEL_RECOMMENDED && 115 entry->value && 116 entry->value->GetAsList(&list)) { 117 for (base::ListValue::const_iterator it = list->begin(); it != list->end(); 118 ++it) { 119 std::string locale; 120 if (!(*it)->GetAsString(&locale)) { 121 NOTREACHED(); 122 new_recommended_locales.clear(); 123 break; 124 } 125 new_recommended_locales.push_back(locale); 126 } 127 } 128 129 std::vector<std::string>& recommended_locales = 130 public_session_recommended_locales_[user_id]; 131 132 if (new_recommended_locales != recommended_locales) 133 SetPublicSessionLocales(user_id, new_recommended_locales); 134 135 if (new_recommended_locales.empty()) 136 public_session_recommended_locales_.erase(user_id); 137 else 138 recommended_locales = new_recommended_locales; 139} 140 141void ChromeUserSelectionScreen::SetPublicSessionDisplayName( 142 const std::string& user_id) { 143 const user_manager::User* user = 144 user_manager::UserManager::Get()->FindUser(user_id); 145 if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) 146 return; 147 148 handler_->SetPublicSessionDisplayName( 149 user_id, 150 base::UTF16ToUTF8(user->GetDisplayName())); 151} 152 153void ChromeUserSelectionScreen::SetPublicSessionLocales( 154 const std::string& user_id, 155 const std::vector<std::string>& recommended_locales) { 156 if (!handler_initialized_) 157 return; 158 159 // Construct the list of available locales. This list consists of the 160 // recommended locales, followed by all others. 161 scoped_ptr<base::ListValue> available_locales = 162 GetUILanguageList(&recommended_locales, std::string()); 163 164 // Set the initially selected locale to the first recommended locale that is 165 // actually available or the current UI locale if none of them are available. 166 const std::string default_locale = FindMostRelevantLocale( 167 recommended_locales, 168 *available_locales.get(), 169 g_browser_process->GetApplicationLocale()); 170 171 // Set a flag to indicate whether the list of recommended locales contains at 172 // least two entries. This is used to decide whether the public session pod 173 // expands to its basic form (for zero or one recommended locales) or the 174 // advanced form (two or more recommended locales). 175 const bool two_or_more_recommended_locales = recommended_locales.size() >= 2; 176 177 // Notify the UI. 178 handler_->SetPublicSessionLocales(user_id, 179 available_locales.Pass(), 180 default_locale, 181 two_or_more_recommended_locales); 182} 183 184} // namespace chromeos 185