15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/location.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/values.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/browser_process.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/browser_process_platform_part.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_core.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_store.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/policy/core/common/policy_map.h" 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/policy/core/common/policy_types.h" 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user.h" 246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h" 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user_type.h" 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "policy/policy_constants.h" 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace chromeos { 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ChromeUserSelectionScreen::ChromeUserSelectionScreen() 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : handler_initialized_(false), 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_(this) { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_local_account_policy_service_ = g_browser_process->platform_part()-> 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) browser_policy_connector_chromeos()->GetDeviceLocalAccountPolicyService(); 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_local_account_policy_service_->AddObserver(this); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ChromeUserSelectionScreen::~ChromeUserSelectionScreen() { 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_local_account_policy_service_->RemoveObserver(this); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::Init(const user_manager::UserList& users, 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool show_guest) { 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserSelectionScreen::Init(users, show_guest); 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Retrieve the current policy for all users. 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (user_manager::UserList::const_iterator it = users.begin(); 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) it != users.end(); ++it) { 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnPolicyUpdated((*it)->GetUserID()); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::SendUserList() { 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UserSelectionScreen::SendUserList(); 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_initialized_ = true; 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::OnPolicyUpdated(const std::string& user_id) { 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy::DeviceLocalAccountPolicyBroker* broker = 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_local_account_policy_service_->GetBrokerForUser(user_id); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!broker) 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CheckForPublicSessionDisplayNameChange(broker); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CheckForPublicSessionLocalePolicyChange(broker); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::OnDeviceLocalAccountsChanged() { 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Nothing to do here. When the list of device-local accounts changes, the 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // entire UI is reloaded. 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::CheckForPublicSessionDisplayNameChange( 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy::DeviceLocalAccountPolicyBroker* broker) { 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& user_id = broker->user_id(); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& display_name = broker->GetDisplayName(); 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (display_name == public_session_display_names_[user_id]) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public_session_display_names_[user_id] = display_name; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!handler_initialized_) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!display_name.empty()) { 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If a new display name was set by policy, notify the UI about it. 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_->SetPublicSessionDisplayName(user_id, display_name); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // When no display name is set by policy, the |User|, owned by |UserManager|, 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // decides what display name to use. However, the order in which |UserManager| 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // and |this| are informed of the display name change is undefined. Post a 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // task that will update the UI after the UserManager is guaranteed to have 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // been informed of the change. 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoop::current()->PostTask( 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&ChromeUserSelectionScreen::SetPublicSessionDisplayName, 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_factory_.GetWeakPtr(), 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_id)); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::CheckForPublicSessionLocalePolicyChange( 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy::DeviceLocalAccountPolicyBroker* broker) { 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& user_id = broker->user_id(); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const policy::PolicyMap::Entry* entry = 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) broker->core()->store()->policy_map().Get(policy::key::kSessionLocales); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Parse the list of recommended locales set by policy. 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<std::string> new_recommended_locales; 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::ListValue const* list = NULL; 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (entry && 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry->level == policy::POLICY_LEVEL_RECOMMENDED && 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry->value && 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry->value->GetAsList(&list)) { 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (base::ListValue::const_iterator it = list->begin(); it != list->end(); 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++it) { 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string locale; 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!(*it)->GetAsString(&locale)) { 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_recommended_locales.clear(); 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_recommended_locales.push_back(locale); 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<std::string>& recommended_locales = 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public_session_recommended_locales_[user_id]; 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (new_recommended_locales != recommended_locales) 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetPublicSessionLocales(user_id, new_recommended_locales); 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (new_recommended_locales.empty()) 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public_session_recommended_locales_.erase(user_id); 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) recommended_locales = new_recommended_locales; 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::SetPublicSessionDisplayName( 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& user_id) { 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const user_manager::User* user = 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager::Get()->FindUser(user_id); 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_->SetPublicSessionDisplayName( 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_id, 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::UTF16ToUTF8(user->GetDisplayName())); 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromeUserSelectionScreen::SetPublicSessionLocales( 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& user_id, 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::vector<std::string>& recommended_locales) { 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!handler_initialized_) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Construct the list of available locales. This list consists of the 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // recommended locales, followed by all others. 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<base::ListValue> available_locales = 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) GetUILanguageList(&recommended_locales, std::string()); 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Set the initially selected locale to the first recommended locale that is 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // actually available or the current UI locale if none of them are available. 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string default_locale = FindMostRelevantLocale( 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) recommended_locales, 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *available_locales.get(), 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) g_browser_process->GetApplicationLocale()); 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Set a flag to indicate whether the list of recommended locales contains at 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // least two entries. This is used to decide whether the public session pod 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // expands to its basic form (for zero or one recommended locales) or the 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // advanced form (two or more recommended locales). 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const bool two_or_more_recommended_locales = recommended_locales.size() >= 2; 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Notify the UI. 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_->SetPublicSessionLocales(user_id, 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) available_locales.Pass(), 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_locale, 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) two_or_more_recommended_locales); 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace chromeos 185