Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / chromeos / core_chromeos_options_handler.cc
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 "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"
35
36 namespace chromeos {
37 namespace options {
38
39 namespace {
40
41 // List of settings that should be changeable by all users.
42 const char* kNonPrivilegedSettings[] = {
43     kSystemTimezone
44 };
45
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;
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 base::DictionaryValue;
58   user_dict->SetString("username", username);
59   user_dict->SetString("name", display_email);
60   user_dict->SetString("email", display_name);
61
62   bool is_owner = user_manager::UserManager::Get()->GetOwnerEmail() == username;
63   user_dict->SetBoolean("owner", is_owner);
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   user_manager::UserManager* user_manager = 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   notification_registrar_.Add(this,
94                               chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
95                               content::NotificationService::AllSources());
96 }
97
98 CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
99 }
100
101 void CoreChromeOSOptionsHandler::RegisterMessages() {
102   CoreOptionsHandler::RegisterMessages();
103   web_ui()->RegisterMessageCallback(
104       kSelectNetworkMessage,
105       base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
106                  base::Unretained(this)));
107 }
108
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();
115
116   CoreOptionsHandler::InitializeHandler();
117
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);
123   }
124   ObservePref(prefs::kProxy);
125   ObservePref(prefs::kDeviceOpenNetworkConfiguration);
126   proxy_config_service_.SetPrefs(profile_prefs,
127                                  g_browser_process->local_state());
128 }
129
130 void CoreChromeOSOptionsHandler::Observe(
131     int type,
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);
136
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)));
142 }
143
144 void CoreChromeOSOptionsHandler::NotifyOwnershipChanged() {
145   for (SubscriptionMap::iterator it = pref_subscription_map_.begin();
146        it != pref_subscription_map_.end(); ++it) {
147     NotifySettingsChanged(it->first);
148   }
149 }
150
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);
157     if (!value)
158       return base::Value::CreateNullValue();
159
160     return value;
161   }
162
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);
167   }
168
169   const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
170   if (!pref_value)
171     return base::Value::CreateNullValue();
172
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));
178   else
179     dict->Set("value", pref_value->DeepCopy());
180
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";
189   }
190   dict->SetBoolean("disabled", !controlled_by.empty());
191   if (!controlled_by.empty())
192     dict->SetString("controlledBy", controlled_by);
193   return dict;
194 }
195
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.
199     return;
200   }
201   if (!CrosSettings::IsCrosSettings(pref_name))
202     return ::options::CoreOptionsHandler::ObservePref(pref_name);
203
204   linked_ptr<CrosSettings::ObserverSubscription> subscription(
205       CrosSettings::Get()->AddSettingsObserver(
206           pref_name.c_str(),
207           base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
208                      base::Unretained(this),
209                      pref_name)).release());
210   pref_subscription_map_.insert(make_pair(pref_name, subscription));
211 }
212
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",
222         proxy_type);
223     ProcessUserMetric(value, metric);
224     return;
225   }
226   if (!CrosSettings::IsCrosSettings(pref_name))
227     return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
228   CrosSettings::Get()->Set(pref_name, *value);
229
230   ProcessUserMetric(value, metric);
231 }
232
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);
241 }
242
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);
254
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);
261       DCHECK(success);
262       if (!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");
269         return dict;
270       }
271     }
272   }
273
274   return CoreOptionsHandler::CreateValueForPref(pref_name,
275                                                 controlling_pref_name);
276 }
277
278 void CoreChromeOSOptionsHandler::GetLocalizedValues(
279     base::DictionaryValue* localized_strings) {
280   DCHECK(localized_strings);
281   CoreOptionsHandler::GetLocalizedValues(localized_strings);
282
283   Profile* profile = Profile::FromWebUI(web_ui());
284   AddAccountUITweaksLocalizedValues(localized_strings, profile);
285
286   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
287
288   // Check at load time whether this is a secondary user in a multi-profile
289   // session.
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();
293
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)));
308   } else {
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());
313   }
314
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));
319
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());
325   } else {
326     localized_strings->SetString("controlledSettingOwner",
327         l10n_util::GetStringFUTF16(
328             IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
329             base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
330   }
331
332   localized_strings->SetString(
333       "browserVersion",
334       l10n_util::GetStringFUTF16(IDS_ABOUT_PRODUCT_VERSION,
335                                  ::HelpHandler::BuildBrowserVersionString()));
336   localized_strings->SetBoolean("showVersion",
337                                 ::switches::AboutInSettingsEnabled());
338 }
339
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)) {
345     NOTREACHED();
346     return;
347   }
348   proxy_config_service_.SetCurrentNetwork(service_path);
349   NotifyProxyPrefsChanged();
350 }
351
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();
361     return;
362   }
363   if (pref_name == prefs::kUseSharedProxies) {
364     // kProxy controls kUseSharedProxies and decides if it's managed by
365     // policy/extension.
366     NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
367     return;
368   }
369   ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
370 }
371
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));
376   if (!value.get())
377     NOTREACHED();
378   DispatchPrefChangeNotification(setting_name, value.Pass());
379 }
380
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);
387     DCHECK(value);
388     scoped_ptr<base::Value> ptr(value);
389     DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
390   }
391 }
392
393 }  // namespace options
394 }  // namespace chromeos