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