core_chromeos_options_handler.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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/ui/webui/options/chromeos/core_chromeos_options_handler.h" 6 7#include <string> 8 9#include "base/bind.h" 10#include "base/prefs/pref_change_registrar.h" 11#include "base/strings/string_number_conversions.h" 12#include "base/strings/string_util.h" 13#include "base/strings/utf_string_conversions.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/chromeos/login/user_manager.h" 16#include "chrome/browser/chromeos/proxy_cros_settings_parser.h" 17#include "chrome/browser/chromeos/settings/cros_settings.h" 18#include "chrome/browser/policy/browser_policy_connector.h" 19#include "chrome/browser/profiles/profile.h" 20#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h" 21#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h" 22#include "chrome/common/chrome_notification_types.h" 23#include "chrome/common/pref_names.h" 24#include "content/public/browser/notification_details.h" 25#include "content/public/browser/notification_service.h" 26#include "content/public/browser/notification_source.h" 27#include "content/public/browser/user_metrics.h" 28#include "content/public/browser/web_ui.h" 29 30namespace chromeos { 31namespace options { 32 33namespace { 34 35// List of settings that should be changeable by all users. 36const char* kNonOwnerSettings[] = { 37 kSystemTimezone 38}; 39 40// Returns true if |pref| should be only available to the owner. 41bool IsSettingOwnerOnly(const std::string& pref) { 42 const char** end = kNonOwnerSettings + arraysize(kNonOwnerSettings); 43 return std::find(kNonOwnerSettings, end, pref) == end; 44} 45 46// Returns true if |username| is the logged-in owner. 47bool IsLoggedInOwner(const std::string& username) { 48 UserManager* user_manager = UserManager::Get(); 49 return user_manager->IsCurrentUserOwner() && 50 user_manager->GetLoggedInUser()->email() == username; 51} 52 53// Creates a user info dictionary to be stored in the |ListValue| that is 54// passed to Javascript for the |kAccountsPrefUsers| preference. 55base::DictionaryValue* CreateUserInfo(const std::string& username, 56 const std::string& display_email, 57 const std::string& display_name) { 58 base::DictionaryValue* user_dict = new DictionaryValue; 59 user_dict->SetString("username", username); 60 user_dict->SetString("name", display_email); 61 user_dict->SetString("email", display_name); 62 user_dict->SetBoolean("owner", IsLoggedInOwner(username)); 63 return user_dict; 64} 65 66// This function decorates the bare list of emails with some more information 67// needed by the UI to properly display the Accounts page. 68base::Value* CreateUsersWhitelist(const base::Value *pref_value) { 69 const base::ListValue* list_value = 70 static_cast<const base::ListValue*>(pref_value); 71 base::ListValue* user_list = new base::ListValue(); 72 UserManager* user_manager = UserManager::Get(); 73 74 for (base::ListValue::const_iterator i = list_value->begin(); 75 i != list_value->end(); ++i) { 76 std::string email; 77 if ((*i)->GetAsString(&email)) { 78 // Translate email to the display email. 79 std::string display_email = user_manager->GetUserDisplayEmail(email); 80 // TODO(ivankr): fetch display name for existing users. 81 user_list->Append(CreateUserInfo(email, display_email, std::string())); 82 } 83 } 84 return user_list; 85} 86 87const char kSelectNetworkMessage[] = "selectNetwork"; 88 89} // namespace 90 91CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler() { 92} 93 94CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() { 95} 96 97void CoreChromeOSOptionsHandler::RegisterMessages() { 98 CoreOptionsHandler::RegisterMessages(); 99 web_ui()->RegisterMessageCallback( 100 kSelectNetworkMessage, 101 base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback, 102 base::Unretained(this))); 103} 104 105void CoreChromeOSOptionsHandler::InitializeHandler() { 106 // In case the options page is reloaded, forget the last selected network. 107 proxy_config_service_.SetCurrentNetwork(std::string()); 108 109 CoreOptionsHandler::InitializeHandler(); 110 111 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 112 proxy_prefs_.Init(prefs); 113 proxy_prefs_.Add(prefs::kProxy, 114 base::Bind(&CoreChromeOSOptionsHandler::OnPreferenceChanged, 115 base::Unretained(this), 116 prefs)); 117 proxy_config_service_.SetPrefs(prefs); 118} 119 120base::Value* CoreChromeOSOptionsHandler::FetchPref( 121 const std::string& pref_name) { 122 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) { 123 base::Value *value = NULL; 124 proxy_cros_settings_parser::GetProxyPrefValue( 125 proxy_config_service_, pref_name, &value); 126 if (!value) 127 return base::Value::CreateNullValue(); 128 129 return value; 130 } 131 if (!CrosSettings::IsCrosSettings(pref_name)) { 132 std::string controlling_pref = 133 pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string(); 134 return CreateValueForPref(pref_name, controlling_pref); 135 } 136 137 const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name); 138 if (!pref_value) 139 return base::Value::CreateNullValue(); 140 141 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 142 // TODO(estade): seems that this should replicate CreateValueForPref less. 143 DictionaryValue* dict = new DictionaryValue; 144 if (pref_name == kAccountsPrefUsers) 145 dict->Set("value", CreateUsersWhitelist(pref_value)); 146 else 147 dict->Set("value", pref_value->DeepCopy()); 148 if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) 149 dict->SetString("controlledBy", "policy"); 150 dict->SetBoolean("disabled", 151 IsSettingOwnerOnly(pref_name) && 152 !UserManager::Get()->IsCurrentUserOwner()); 153 return dict; 154} 155 156void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) { 157 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) { 158 // We observe those all the time. 159 return; 160 } 161 if (!CrosSettings::IsCrosSettings(pref_name)) 162 return ::options::CoreOptionsHandler::ObservePref(pref_name); 163 CrosSettings::Get()->AddSettingsObserver(pref_name.c_str(), this); 164} 165 166void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name, 167 const base::Value* value, 168 const std::string& metric) { 169 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) { 170 proxy_cros_settings_parser::SetProxyPrefValue( 171 pref_name, value, &proxy_config_service_); 172 base::StringValue proxy_type(pref_name); 173 web_ui()->CallJavascriptFunction( 174 "options.internet.DetailsInternetPage.updateProxySettings", 175 proxy_type); 176 ProcessUserMetric(value, metric); 177 return; 178 } 179 if (!CrosSettings::IsCrosSettings(pref_name)) 180 return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric); 181 CrosSettings::Get()->Set(pref_name, *value); 182 183 ProcessUserMetric(value, metric); 184} 185 186void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) { 187 if (proxy_cros_settings_parser::IsProxyPref(path)) 188 return; // We unregister those in the destructor. 189 // Unregister this instance from observing prefs of chrome os settings. 190 if (CrosSettings::IsCrosSettings(path)) 191 CrosSettings::Get()->RemoveSettingsObserver(path.c_str(), this); 192 else // Call base class to handle regular preferences. 193 ::options::CoreOptionsHandler::StopObservingPref(path); 194} 195 196void CoreChromeOSOptionsHandler::GetLocalizedValues( 197 DictionaryValue* localized_strings) { 198 DCHECK(localized_strings); 199 CoreOptionsHandler::GetLocalizedValues(localized_strings); 200 201 AddAccountUITweaksLocalizedValues(localized_strings); 202} 203 204void CoreChromeOSOptionsHandler::Observe( 205 int type, 206 const content::NotificationSource& source, 207 const content::NotificationDetails& details) { 208 if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) { 209 NotifySettingsChanged(content::Details<std::string>(details).ptr()); 210 return; 211 } 212 ::options::CoreOptionsHandler::Observe(type, source, details); 213} 214 215void CoreChromeOSOptionsHandler::SelectNetwork( 216 const std::string& service_path) { 217 proxy_config_service_.SetCurrentNetwork(service_path); 218 NotifyProxyPrefsChanged(); 219} 220 221void CoreChromeOSOptionsHandler::SelectNetworkCallback( 222 const base::ListValue* args) { 223 std::string service_path; 224 if (args->GetSize() != 1 || 225 !args->GetString(0, &service_path)) { 226 NOTREACHED(); 227 return; 228 } 229 SelectNetwork(service_path); 230} 231 232void CoreChromeOSOptionsHandler::OnPreferenceChanged( 233 PrefService* service, 234 const std::string& pref_name) { 235 // Special handling for preferences kUseSharedProxies and kProxy, the latter 236 // controls the former and decides if it's managed by policy/extension. 237 const PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs(); 238 if (service == pref_service && 239 (proxy_prefs_.IsObserved(pref_name) || 240 pref_name == prefs::kUseSharedProxies)) { 241 NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy); 242 return; 243 } 244 ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name); 245} 246 247void CoreChromeOSOptionsHandler::NotifySettingsChanged( 248 const std::string* setting_name) { 249 DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name)); 250 scoped_ptr<base::Value> value(FetchPref(*setting_name)); 251 if (!value.get()) 252 NOTREACHED(); 253 DispatchPrefChangeNotification(*setting_name, value.Pass()); 254} 255 256void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() { 257 for (size_t i = 0; i < kProxySettingsCount; ++i) { 258 base::Value* value = NULL; 259 proxy_cros_settings_parser::GetProxyPrefValue( 260 proxy_config_service_, kProxySettings[i], &value); 261 DCHECK(value); 262 scoped_ptr<base::Value> ptr(value); 263 DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass()); 264 } 265} 266 267} // namespace options 268} // namespace chromeos 269