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.
5 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
9 #include "ash/session_state_delegate.h"
10 #include "ash/shell.h"
11 #include "base/bind.h"
12 #include "base/prefs/pref_change_registrar.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/sys_info.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chromeos/login/user_manager.h"
19 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
22 #include "chrome/browser/chromeos/settings/cros_settings.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
25 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
26 #include "chrome/common/pref_names.h"
27 #include "content/public/browser/user_metrics.h"
28 #include "content/public/browser/web_ui.h"
29 #include "grit/generated_resources.h"
30 #include "ui/base/l10n/l10n_util.h"
37 // List of settings that should be changeable by all users.
38 const char* kNonOwnerSettings[] = {
42 // Returns true if |pref| should be only available to the owner.
43 bool IsSettingOwnerOnly(const std::string& pref) {
44 const char** end = kNonOwnerSettings + arraysize(kNonOwnerSettings);
45 return std::find(kNonOwnerSettings, end, pref) == end;
48 // Creates a user info dictionary to be stored in the |ListValue| that is
49 // passed to Javascript for the |kAccountsPrefUsers| preference.
50 base::DictionaryValue* CreateUserInfo(const std::string& username,
51 const std::string& display_email,
52 const std::string& display_name) {
53 base::DictionaryValue* user_dict = new base::DictionaryValue;
54 user_dict->SetString("username", username);
55 user_dict->SetString("name", display_email);
56 user_dict->SetString("email", display_name);
58 bool is_owner = UserManager::Get()->GetOwnerEmail() == username;
59 user_dict->SetBoolean("owner", is_owner);
63 // This function decorates the bare list of emails with some more information
64 // needed by the UI to properly display the Accounts page.
65 base::Value* CreateUsersWhitelist(const base::Value *pref_value) {
66 const base::ListValue* list_value =
67 static_cast<const base::ListValue*>(pref_value);
68 base::ListValue* user_list = new base::ListValue();
69 UserManager* user_manager = UserManager::Get();
71 for (base::ListValue::const_iterator i = list_value->begin();
72 i != list_value->end(); ++i) {
74 if ((*i)->GetAsString(&email)) {
75 // Translate email to the display email.
76 std::string display_email = user_manager->GetUserDisplayEmail(email);
77 // TODO(ivankr): fetch display name for existing users.
78 user_list->Append(CreateUserInfo(email, display_email, std::string()));
84 const char kSelectNetworkMessage[] = "selectNetwork";
88 CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler() {
91 CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
94 void CoreChromeOSOptionsHandler::RegisterMessages() {
95 CoreOptionsHandler::RegisterMessages();
96 web_ui()->RegisterMessageCallback(
97 kSelectNetworkMessage,
98 base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
99 base::Unretained(this)));
102 void CoreChromeOSOptionsHandler::InitializeHandler() {
103 // This function is both called on the initial page load and on each reload.
104 // For the latter case, forget the last selected network.
105 proxy_config_service_.SetCurrentNetwork(std::string());
106 // And clear the cached configuration.
107 proxy_config_service_.UpdateFromPrefs();
109 CoreOptionsHandler::InitializeHandler();
111 PrefService* profile_prefs = NULL;
112 Profile* profile = Profile::FromWebUI(web_ui());
113 if (!ProfileHelper::IsSigninProfile(profile)) {
114 profile_prefs = profile->GetPrefs();
115 ObservePref(prefs::kOpenNetworkConfiguration);
117 ObservePref(prefs::kProxy);
118 ObservePref(prefs::kDeviceOpenNetworkConfiguration);
119 proxy_config_service_.SetPrefs(profile_prefs,
120 g_browser_process->local_state());
123 base::Value* CoreChromeOSOptionsHandler::FetchPref(
124 const std::string& pref_name) {
125 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
126 base::Value *value = NULL;
127 proxy_cros_settings_parser::GetProxyPrefValue(
128 proxy_config_service_, pref_name, &value);
130 return base::Value::CreateNullValue();
135 if (!CrosSettings::IsCrosSettings(pref_name)) {
136 std::string controlling_pref =
137 pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
138 return CreateValueForPref(pref_name, controlling_pref);
141 const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
143 return base::Value::CreateNullValue();
145 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
146 // TODO(estade): seems that this should replicate CreateValueForPref less.
147 base::DictionaryValue* dict = new base::DictionaryValue;
148 if (pref_name == kAccountsPrefUsers)
149 dict->Set("value", CreateUsersWhitelist(pref_value));
151 dict->Set("value", pref_value->DeepCopy());
152 policy::BrowserPolicyConnectorChromeOS* connector =
153 g_browser_process->platform_part()->browser_policy_connector_chromeos();
154 if (connector->IsEnterpriseManaged()) {
155 dict->SetBoolean("disabled", true);
156 dict->SetString("controlledBy", "policy");
158 bool controlled_by_owner = IsSettingOwnerOnly(pref_name) &&
159 !ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui()));
160 dict->SetBoolean("disabled", controlled_by_owner);
161 if (controlled_by_owner)
162 dict->SetString("controlledBy", "owner");
167 void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
168 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
169 // We observe those all the time.
172 if (!CrosSettings::IsCrosSettings(pref_name))
173 return ::options::CoreOptionsHandler::ObservePref(pref_name);
175 linked_ptr<CrosSettings::ObserverSubscription> subscription(
176 CrosSettings::Get()->AddSettingsObserver(
178 base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
179 base::Unretained(this),
180 pref_name)).release());
181 pref_subscription_map_.insert(make_pair(pref_name, subscription));
184 void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
185 const base::Value* value,
186 const std::string& metric) {
187 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
188 proxy_cros_settings_parser::SetProxyPrefValue(
189 pref_name, value, &proxy_config_service_);
190 base::StringValue proxy_type(pref_name);
191 web_ui()->CallJavascriptFunction(
192 "options.internet.DetailsInternetPage.updateProxySettings",
194 ProcessUserMetric(value, metric);
197 if (!CrosSettings::IsCrosSettings(pref_name))
198 return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
199 CrosSettings::Get()->Set(pref_name, *value);
201 ProcessUserMetric(value, metric);
204 void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
205 if (proxy_cros_settings_parser::IsProxyPref(path))
206 return; // We unregister those in the destructor.
207 // Unregister this instance from observing prefs of chrome os settings.
208 if (CrosSettings::IsCrosSettings(path))
209 pref_subscription_map_.erase(path);
210 else // Call base class to handle regular preferences.
211 ::options::CoreOptionsHandler::StopObservingPref(path);
214 base::Value* CoreChromeOSOptionsHandler::CreateValueForPref(
215 const std::string& pref_name,
216 const std::string& controlling_pref_name) {
217 // The screen lock setting is shared if multiple users are logged in and at
218 // least one has chosen to require passwords.
219 if (pref_name == prefs::kEnableAutoScreenLock &&
220 UserManager::Get()->GetLoggedInUsers().size() > 1 &&
221 controlling_pref_name.empty()) {
222 PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
223 const PrefService::Preference* pref =
224 user_prefs->FindPreference(prefs::kEnableAutoScreenLock);
226 ash::SessionStateDelegate* delegate =
227 ash::Shell::GetInstance()->session_state_delegate();
228 if (pref && pref->IsUserModifiable() &&
229 delegate->ShouldLockScreenBeforeSuspending()) {
230 bool screen_lock = false;
231 bool success = pref->GetValue()->GetAsBoolean(&screen_lock);
234 // Screen lock is enabled for the session, but not in the user's
235 // preferences. Show the user's value in the checkbox, but indicate
236 // that the password requirement is enabled by some other user.
237 base::DictionaryValue* dict = new base::DictionaryValue;
238 dict->Set("value", pref->GetValue()->DeepCopy());
239 dict->SetString("controlledBy", "shared");
245 return CoreOptionsHandler::CreateValueForPref(pref_name,
246 controlling_pref_name);
249 void CoreChromeOSOptionsHandler::GetLocalizedValues(
250 base::DictionaryValue* localized_strings) {
251 DCHECK(localized_strings);
252 CoreOptionsHandler::GetLocalizedValues(localized_strings);
254 Profile* profile = Profile::FromWebUI(web_ui());
255 AddAccountUITweaksLocalizedValues(localized_strings, profile);
257 UserManager* user_manager = UserManager::Get();
259 // Check at load time whether this is a secondary user in a multi-profile
261 User* user = user_manager->GetUserByProfile(profile);
262 if (user && user->email() != user_manager->GetPrimaryUser()->email()) {
263 const std::string& primary_email = user_manager->GetPrimaryUser()->email();
265 // Set secondaryUser to show the shared icon by the network section header.
266 localized_strings->SetBoolean("secondaryUser", true);
267 localized_strings->SetString("secondaryUserBannerText",
268 l10n_util::GetStringFUTF16(
269 IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER,
270 base::ASCIIToUTF16(primary_email)));
271 localized_strings->SetString("controlledSettingShared",
272 l10n_util::GetStringFUTF16(
273 IDS_OPTIONS_CONTROLLED_SETTING_SHARED,
274 base::ASCIIToUTF16(primary_email)));
275 localized_strings->SetString("controlledSettingsShared",
276 l10n_util::GetStringFUTF16(
277 IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED,
278 base::ASCIIToUTF16(primary_email)));
280 localized_strings->SetBoolean("secondaryUser", false);
281 localized_strings->SetString("secondaryUserBannerText", base::string16());
282 localized_strings->SetString("controlledSettingShared", base::string16());
283 localized_strings->SetString("controlledSettingsShared", base::string16());
286 // Screen lock icon can show up as primary or secondary user.
287 localized_strings->SetString("screenLockShared",
288 l10n_util::GetStringUTF16(
289 IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK));
291 policy::BrowserPolicyConnectorChromeOS* connector =
292 g_browser_process->platform_part()->browser_policy_connector_chromeos();
293 if (connector->IsEnterpriseManaged()) {
294 // Managed machines have no "owner".
295 localized_strings->SetString("controlledSettingOwner", base::string16());
297 localized_strings->SetString("controlledSettingOwner",
298 l10n_util::GetStringFUTF16(
299 IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
300 base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
304 void CoreChromeOSOptionsHandler::SelectNetworkCallback(
305 const base::ListValue* args) {
306 std::string service_path;
307 if (args->GetSize() != 1 ||
308 !args->GetString(0, &service_path)) {
312 proxy_config_service_.SetCurrentNetwork(service_path);
313 NotifyProxyPrefsChanged();
316 void CoreChromeOSOptionsHandler::OnPreferenceChanged(
317 PrefService* service,
318 const std::string& pref_name) {
319 // Redetermine the current proxy settings and notify the UI if any of these
320 // preferences change.
321 if (pref_name == prefs::kOpenNetworkConfiguration ||
322 pref_name == prefs::kDeviceOpenNetworkConfiguration ||
323 pref_name == prefs::kProxy) {
324 NotifyProxyPrefsChanged();
327 if (pref_name == prefs::kUseSharedProxies) {
328 // kProxy controls kUseSharedProxies and decides if it's managed by
330 NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
333 ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
336 void CoreChromeOSOptionsHandler::NotifySettingsChanged(
337 const std::string& setting_name) {
338 DCHECK(CrosSettings::Get()->IsCrosSettings(setting_name));
339 scoped_ptr<base::Value> value(FetchPref(setting_name));
342 DispatchPrefChangeNotification(setting_name, value.Pass());
345 void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
346 proxy_config_service_.UpdateFromPrefs();
347 for (size_t i = 0; i < kProxySettingsCount; ++i) {
348 base::Value* value = NULL;
349 proxy_cros_settings_parser::GetProxyPrefValue(
350 proxy_config_service_, kProxySettings[i], &value);
352 scoped_ptr<base::Value> ptr(value);
353 DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
357 } // namespace options
358 } // namespace chromeos