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