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/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/chrome_notification_types.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/help/help_handler.h"
26 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/user_manager/user_manager.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/user_metrics.h"
32 #include "content/public/browser/web_ui.h"
33 #include "grit/generated_resources.h"
34 #include "ui/base/l10n/l10n_util.h"
41 // List of settings that should be changeable by all users.
42 const char* kNonPrivilegedSettings[] = {
46 // Returns true if |pref| can be controlled (e.g. by policy or owner).
47 bool IsSettingPrivileged(const std::string& pref) {
48 const char** end = kNonPrivilegedSettings + arraysize(kNonPrivilegedSettings);
49 return std::find(kNonPrivilegedSettings, end, pref) == end;
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 base::DictionaryValue;
58 user_dict->SetString("username", username);
59 user_dict->SetString("name", display_email);
60 user_dict->SetString("email", display_name);
62 bool is_owner = user_manager::UserManager::Get()->GetOwnerEmail() == username;
63 user_dict->SetBoolean("owner", is_owner);
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 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
75 for (base::ListValue::const_iterator i = list_value->begin();
76 i != list_value->end(); ++i) {
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()));
88 const char kSelectNetworkMessage[] = "selectNetwork";
92 CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler() {
93 notification_registrar_.Add(this,
94 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
95 content::NotificationService::AllSources());
98 CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
101 void CoreChromeOSOptionsHandler::RegisterMessages() {
102 CoreOptionsHandler::RegisterMessages();
103 web_ui()->RegisterMessageCallback(
104 kSelectNetworkMessage,
105 base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
106 base::Unretained(this)));
109 void CoreChromeOSOptionsHandler::InitializeHandler() {
110 // This function is both called on the initial page load and on each reload.
111 // For the latter case, forget the last selected network.
112 proxy_config_service_.SetCurrentNetwork(std::string());
113 // And clear the cached configuration.
114 proxy_config_service_.UpdateFromPrefs();
116 CoreOptionsHandler::InitializeHandler();
118 PrefService* profile_prefs = NULL;
119 Profile* profile = Profile::FromWebUI(web_ui());
120 if (!ProfileHelper::IsSigninProfile(profile)) {
121 profile_prefs = profile->GetPrefs();
122 ObservePref(prefs::kOpenNetworkConfiguration);
124 ObservePref(prefs::kProxy);
125 ObservePref(prefs::kDeviceOpenNetworkConfiguration);
126 proxy_config_service_.SetPrefs(profile_prefs,
127 g_browser_process->local_state());
130 void CoreChromeOSOptionsHandler::Observe(
132 const content::NotificationSource& source,
133 const content::NotificationDetails& details) {
134 // The only expected notification for now is this one.
135 DCHECK(type == chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED);
137 // Finish this asynchronously because the notification has to tricle in to all
138 // Chrome components before we can reliably read the status on the other end.
139 base::MessageLoop::current()->PostTask(FROM_HERE,
140 base::Bind(&CoreChromeOSOptionsHandler::NotifyOwnershipChanged,
141 base::Unretained(this)));
144 void CoreChromeOSOptionsHandler::NotifyOwnershipChanged() {
145 for (SubscriptionMap::iterator it = pref_subscription_map_.begin();
146 it != pref_subscription_map_.end(); ++it) {
147 NotifySettingsChanged(it->first);
151 base::Value* CoreChromeOSOptionsHandler::FetchPref(
152 const std::string& pref_name) {
153 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
154 base::Value *value = NULL;
155 proxy_cros_settings_parser::GetProxyPrefValue(
156 proxy_config_service_, pref_name, &value);
158 return base::Value::CreateNullValue();
163 if (!CrosSettings::IsCrosSettings(pref_name)) {
164 std::string controlling_pref =
165 pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
166 return CreateValueForPref(pref_name, controlling_pref);
169 const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
171 return base::Value::CreateNullValue();
173 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
174 // TODO(estade): seems that this should replicate CreateValueForPref less.
175 base::DictionaryValue* dict = new base::DictionaryValue;
176 if (pref_name == kAccountsPrefUsers)
177 dict->Set("value", CreateUsersWhitelist(pref_value));
179 dict->Set("value", pref_value->DeepCopy());
181 std::string controlled_by;
182 if (IsSettingPrivileged(pref_name)) {
183 policy::BrowserPolicyConnectorChromeOS* connector =
184 g_browser_process->platform_part()->browser_policy_connector_chromeos();
185 if (connector->IsEnterpriseManaged())
186 controlled_by = "policy";
187 else if (!ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui())))
188 controlled_by = "owner";
190 dict->SetBoolean("disabled", !controlled_by.empty());
191 if (!controlled_by.empty())
192 dict->SetString("controlledBy", controlled_by);
196 void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
197 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
198 // We observe those all the time.
201 if (!CrosSettings::IsCrosSettings(pref_name))
202 return ::options::CoreOptionsHandler::ObservePref(pref_name);
204 linked_ptr<CrosSettings::ObserverSubscription> subscription(
205 CrosSettings::Get()->AddSettingsObserver(
207 base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
208 base::Unretained(this),
209 pref_name)).release());
210 pref_subscription_map_.insert(make_pair(pref_name, subscription));
213 void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
214 const base::Value* value,
215 const std::string& metric) {
216 if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
217 proxy_cros_settings_parser::SetProxyPrefValue(
218 pref_name, value, &proxy_config_service_);
219 base::StringValue proxy_type(pref_name);
220 web_ui()->CallJavascriptFunction(
221 "options.internet.DetailsInternetPage.updateProxySettings",
223 ProcessUserMetric(value, metric);
226 if (!CrosSettings::IsCrosSettings(pref_name))
227 return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
228 CrosSettings::Get()->Set(pref_name, *value);
230 ProcessUserMetric(value, metric);
233 void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
234 if (proxy_cros_settings_parser::IsProxyPref(path))
235 return; // We unregister those in the destructor.
236 // Unregister this instance from observing prefs of chrome os settings.
237 if (CrosSettings::IsCrosSettings(path))
238 pref_subscription_map_.erase(path);
239 else // Call base class to handle regular preferences.
240 ::options::CoreOptionsHandler::StopObservingPref(path);
243 base::Value* CoreChromeOSOptionsHandler::CreateValueForPref(
244 const std::string& pref_name,
245 const std::string& controlling_pref_name) {
246 // The screen lock setting is shared if multiple users are logged in and at
247 // least one has chosen to require passwords.
248 if (pref_name == prefs::kEnableAutoScreenLock &&
249 user_manager::UserManager::Get()->GetLoggedInUsers().size() > 1 &&
250 controlling_pref_name.empty()) {
251 PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
252 const PrefService::Preference* pref =
253 user_prefs->FindPreference(prefs::kEnableAutoScreenLock);
255 ash::SessionStateDelegate* delegate =
256 ash::Shell::GetInstance()->session_state_delegate();
257 if (pref && pref->IsUserModifiable() &&
258 delegate->ShouldLockScreenBeforeSuspending()) {
259 bool screen_lock = false;
260 bool success = pref->GetValue()->GetAsBoolean(&screen_lock);
263 // Screen lock is enabled for the session, but not in the user's
264 // preferences. Show the user's value in the checkbox, but indicate
265 // that the password requirement is enabled by some other user.
266 base::DictionaryValue* dict = new base::DictionaryValue;
267 dict->Set("value", pref->GetValue()->DeepCopy());
268 dict->SetString("controlledBy", "shared");
274 return CoreOptionsHandler::CreateValueForPref(pref_name,
275 controlling_pref_name);
278 void CoreChromeOSOptionsHandler::GetLocalizedValues(
279 base::DictionaryValue* localized_strings) {
280 DCHECK(localized_strings);
281 CoreOptionsHandler::GetLocalizedValues(localized_strings);
283 Profile* profile = Profile::FromWebUI(web_ui());
284 AddAccountUITweaksLocalizedValues(localized_strings, profile);
286 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
288 // Check at load time whether this is a secondary user in a multi-profile
290 user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
291 if (user && user->email() != user_manager->GetPrimaryUser()->email()) {
292 const std::string& primary_email = user_manager->GetPrimaryUser()->email();
294 // Set secondaryUser to show the shared icon by the network section header.
295 localized_strings->SetBoolean("secondaryUser", true);
296 localized_strings->SetString("secondaryUserBannerText",
297 l10n_util::GetStringFUTF16(
298 IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER,
299 base::ASCIIToUTF16(primary_email)));
300 localized_strings->SetString("controlledSettingShared",
301 l10n_util::GetStringFUTF16(
302 IDS_OPTIONS_CONTROLLED_SETTING_SHARED,
303 base::ASCIIToUTF16(primary_email)));
304 localized_strings->SetString("controlledSettingsShared",
305 l10n_util::GetStringFUTF16(
306 IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED,
307 base::ASCIIToUTF16(primary_email)));
309 localized_strings->SetBoolean("secondaryUser", false);
310 localized_strings->SetString("secondaryUserBannerText", base::string16());
311 localized_strings->SetString("controlledSettingShared", base::string16());
312 localized_strings->SetString("controlledSettingsShared", base::string16());
315 // Screen lock icon can show up as primary or secondary user.
316 localized_strings->SetString("screenLockShared",
317 l10n_util::GetStringUTF16(
318 IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK));
320 policy::BrowserPolicyConnectorChromeOS* connector =
321 g_browser_process->platform_part()->browser_policy_connector_chromeos();
322 if (connector->IsEnterpriseManaged()) {
323 // Managed machines have no "owner".
324 localized_strings->SetString("controlledSettingOwner", base::string16());
326 localized_strings->SetString("controlledSettingOwner",
327 l10n_util::GetStringFUTF16(
328 IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
329 base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
332 localized_strings->SetString(
334 l10n_util::GetStringFUTF16(IDS_ABOUT_PRODUCT_VERSION,
335 ::HelpHandler::BuildBrowserVersionString()));
336 localized_strings->SetBoolean("showVersion",
337 ::switches::AboutInSettingsEnabled());
340 void CoreChromeOSOptionsHandler::SelectNetworkCallback(
341 const base::ListValue* args) {
342 std::string service_path;
343 if (args->GetSize() != 1 ||
344 !args->GetString(0, &service_path)) {
348 proxy_config_service_.SetCurrentNetwork(service_path);
349 NotifyProxyPrefsChanged();
352 void CoreChromeOSOptionsHandler::OnPreferenceChanged(
353 PrefService* service,
354 const std::string& pref_name) {
355 // Redetermine the current proxy settings and notify the UI if any of these
356 // preferences change.
357 if (pref_name == prefs::kOpenNetworkConfiguration ||
358 pref_name == prefs::kDeviceOpenNetworkConfiguration ||
359 pref_name == prefs::kProxy) {
360 NotifyProxyPrefsChanged();
363 if (pref_name == prefs::kUseSharedProxies) {
364 // kProxy controls kUseSharedProxies and decides if it's managed by
366 NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
369 ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
372 void CoreChromeOSOptionsHandler::NotifySettingsChanged(
373 const std::string& setting_name) {
374 DCHECK(CrosSettings::Get()->IsCrosSettings(setting_name));
375 scoped_ptr<base::Value> value(FetchPref(setting_name));
378 DispatchPrefChangeNotification(setting_name, value.Pass());
381 void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
382 proxy_config_service_.UpdateFromPrefs();
383 for (size_t i = 0; i < kProxySettingsCount; ++i) {
384 base::Value* value = NULL;
385 proxy_cros_settings_parser::GetProxyPrefValue(
386 proxy_config_service_, kProxySettings[i], &value);
388 scoped_ptr<base::Value> ptr(value);
389 DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
393 } // namespace options
394 } // namespace chromeos