Upstream version 8.37.180.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/login/users/user_manager.h"
20 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
21 #include "chrome/browser/chromeos/profiles/profile_helper.h"
22 #include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
23 #include "chrome/browser/chromeos/settings/cros_settings.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
26 #include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
27 #include "chrome/common/pref_names.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/user_metrics.h"
30 #include "content/public/browser/web_ui.h"
31 #include "grit/generated_resources.h"
32 #include "ui/base/l10n/l10n_util.h"
33
34 namespace chromeos {
35 namespace options {
36
37 namespace {
38
39 // List of settings that should be changeable by all users.
40 const char* kNonPrivilegedSettings[] = {
41     kSystemTimezone
42 };
43
44 // Returns true if |pref| can be controlled (e.g. by policy or owner).
45 bool IsSettingPrivileged(const std::string& pref) {
46   const char** end = kNonPrivilegedSettings + arraysize(kNonPrivilegedSettings);
47   return std::find(kNonPrivilegedSettings, end, pref) == end;
48 }
49
50 // Creates a user info dictionary to be stored in the |ListValue| that is
51 // passed to Javascript for the |kAccountsPrefUsers| preference.
52 base::DictionaryValue* CreateUserInfo(const std::string& username,
53                                       const std::string& display_email,
54                                       const std::string& display_name) {
55   base::DictionaryValue* user_dict = new base::DictionaryValue;
56   user_dict->SetString("username", username);
57   user_dict->SetString("name", display_email);
58   user_dict->SetString("email", display_name);
59
60   bool is_owner = UserManager::Get()->GetOwnerEmail() == username;
61   user_dict->SetBoolean("owner", is_owner);
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   notification_registrar_.Add(this,
92                               chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
93                               content::NotificationService::AllSources());
94 }
95
96 CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
97 }
98
99 void CoreChromeOSOptionsHandler::RegisterMessages() {
100   CoreOptionsHandler::RegisterMessages();
101   web_ui()->RegisterMessageCallback(
102       kSelectNetworkMessage,
103       base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
104                  base::Unretained(this)));
105 }
106
107 void CoreChromeOSOptionsHandler::InitializeHandler() {
108   // This function is both called on the initial page load and on each reload.
109   // For the latter case, forget the last selected network.
110   proxy_config_service_.SetCurrentNetwork(std::string());
111   // And clear the cached configuration.
112   proxy_config_service_.UpdateFromPrefs();
113
114   CoreOptionsHandler::InitializeHandler();
115
116   PrefService* profile_prefs = NULL;
117   Profile* profile = Profile::FromWebUI(web_ui());
118   if (!ProfileHelper::IsSigninProfile(profile)) {
119     profile_prefs = profile->GetPrefs();
120     ObservePref(prefs::kOpenNetworkConfiguration);
121   }
122   ObservePref(prefs::kProxy);
123   ObservePref(prefs::kDeviceOpenNetworkConfiguration);
124   proxy_config_service_.SetPrefs(profile_prefs,
125                                  g_browser_process->local_state());
126 }
127
128 void CoreChromeOSOptionsHandler::Observe(
129     int type,
130     const content::NotificationSource& source,
131     const content::NotificationDetails& details) {
132   // The only expected notification for now is this one.
133   DCHECK(type == chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED);
134
135   // Finish this asynchronously because the notification has to tricle in to all
136   // Chrome components before we can reliably read the status on the other end.
137   base::MessageLoop::current()->PostTask(FROM_HERE,
138       base::Bind(&CoreChromeOSOptionsHandler::NotifyOwnershipChanged,
139                  base::Unretained(this)));
140 }
141
142 void CoreChromeOSOptionsHandler::NotifyOwnershipChanged() {
143   for (SubscriptionMap::iterator it = pref_subscription_map_.begin();
144        it != pref_subscription_map_.end(); ++it) {
145     NotifySettingsChanged(it->first);
146   }
147 }
148
149 base::Value* CoreChromeOSOptionsHandler::FetchPref(
150     const std::string& pref_name) {
151   if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
152     base::Value *value = NULL;
153     proxy_cros_settings_parser::GetProxyPrefValue(
154         proxy_config_service_, pref_name, &value);
155     if (!value)
156       return base::Value::CreateNullValue();
157
158     return value;
159   }
160
161   if (!CrosSettings::IsCrosSettings(pref_name)) {
162     std::string controlling_pref =
163         pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
164     return CreateValueForPref(pref_name, controlling_pref);
165   }
166
167   const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
168   if (!pref_value)
169     return base::Value::CreateNullValue();
170
171   // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
172   // TODO(estade): seems that this should replicate CreateValueForPref less.
173   base::DictionaryValue* dict = new base::DictionaryValue;
174   if (pref_name == kAccountsPrefUsers)
175     dict->Set("value", CreateUsersWhitelist(pref_value));
176   else
177     dict->Set("value", pref_value->DeepCopy());
178
179   std::string controlled_by;
180   if (IsSettingPrivileged(pref_name)) {
181     policy::BrowserPolicyConnectorChromeOS* connector =
182         g_browser_process->platform_part()->browser_policy_connector_chromeos();
183     if (connector->IsEnterpriseManaged())
184       controlled_by = "policy";
185     else if (!ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui())))
186       controlled_by = "owner";
187   }
188   dict->SetBoolean("disabled", !controlled_by.empty());
189   if (!controlled_by.empty())
190     dict->SetString("controlledBy", controlled_by);
191   return dict;
192 }
193
194 void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
195   if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
196     // We observe those all the time.
197     return;
198   }
199   if (!CrosSettings::IsCrosSettings(pref_name))
200     return ::options::CoreOptionsHandler::ObservePref(pref_name);
201
202   linked_ptr<CrosSettings::ObserverSubscription> subscription(
203       CrosSettings::Get()->AddSettingsObserver(
204           pref_name.c_str(),
205           base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
206                      base::Unretained(this),
207                      pref_name)).release());
208   pref_subscription_map_.insert(make_pair(pref_name, subscription));
209 }
210
211 void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
212                                          const base::Value* value,
213                                          const std::string& metric) {
214   if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
215     proxy_cros_settings_parser::SetProxyPrefValue(
216         pref_name, value, &proxy_config_service_);
217     base::StringValue proxy_type(pref_name);
218     web_ui()->CallJavascriptFunction(
219         "options.internet.DetailsInternetPage.updateProxySettings",
220         proxy_type);
221     ProcessUserMetric(value, metric);
222     return;
223   }
224   if (!CrosSettings::IsCrosSettings(pref_name))
225     return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
226   CrosSettings::Get()->Set(pref_name, *value);
227
228   ProcessUserMetric(value, metric);
229 }
230
231 void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
232   if (proxy_cros_settings_parser::IsProxyPref(path))
233     return;  // We unregister those in the destructor.
234   // Unregister this instance from observing prefs of chrome os settings.
235   if (CrosSettings::IsCrosSettings(path))
236     pref_subscription_map_.erase(path);
237   else  // Call base class to handle regular preferences.
238     ::options::CoreOptionsHandler::StopObservingPref(path);
239 }
240
241 base::Value* CoreChromeOSOptionsHandler::CreateValueForPref(
242     const std::string& pref_name,
243     const std::string& controlling_pref_name) {
244   // The screen lock setting is shared if multiple users are logged in and at
245   // least one has chosen to require passwords.
246   if (pref_name == prefs::kEnableAutoScreenLock &&
247       UserManager::Get()->GetLoggedInUsers().size() > 1 &&
248       controlling_pref_name.empty()) {
249     PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
250     const PrefService::Preference* pref =
251         user_prefs->FindPreference(prefs::kEnableAutoScreenLock);
252
253     ash::SessionStateDelegate* delegate =
254         ash::Shell::GetInstance()->session_state_delegate();
255     if (pref && pref->IsUserModifiable() &&
256         delegate->ShouldLockScreenBeforeSuspending()) {
257       bool screen_lock = false;
258       bool success = pref->GetValue()->GetAsBoolean(&screen_lock);
259       DCHECK(success);
260       if (!screen_lock) {
261         // Screen lock is enabled for the session, but not in the user's
262         // preferences. Show the user's value in the checkbox, but indicate
263         // that the password requirement is enabled by some other user.
264         base::DictionaryValue* dict = new base::DictionaryValue;
265         dict->Set("value", pref->GetValue()->DeepCopy());
266         dict->SetString("controlledBy", "shared");
267         return dict;
268       }
269     }
270   }
271
272   return CoreOptionsHandler::CreateValueForPref(pref_name,
273                                                 controlling_pref_name);
274 }
275
276 void CoreChromeOSOptionsHandler::GetLocalizedValues(
277     base::DictionaryValue* localized_strings) {
278   DCHECK(localized_strings);
279   CoreOptionsHandler::GetLocalizedValues(localized_strings);
280
281   Profile* profile = Profile::FromWebUI(web_ui());
282   AddAccountUITweaksLocalizedValues(localized_strings, profile);
283
284   UserManager* user_manager = UserManager::Get();
285
286   // Check at load time whether this is a secondary user in a multi-profile
287   // session.
288   User* user = user_manager->GetUserByProfile(profile);
289   if (user && user->email() != user_manager->GetPrimaryUser()->email()) {
290     const std::string& primary_email = user_manager->GetPrimaryUser()->email();
291
292     // Set secondaryUser to show the shared icon by the network section header.
293     localized_strings->SetBoolean("secondaryUser", true);
294     localized_strings->SetString("secondaryUserBannerText",
295         l10n_util::GetStringFUTF16(
296             IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER,
297             base::ASCIIToUTF16(primary_email)));
298     localized_strings->SetString("controlledSettingShared",
299         l10n_util::GetStringFUTF16(
300             IDS_OPTIONS_CONTROLLED_SETTING_SHARED,
301             base::ASCIIToUTF16(primary_email)));
302     localized_strings->SetString("controlledSettingsShared",
303         l10n_util::GetStringFUTF16(
304             IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED,
305             base::ASCIIToUTF16(primary_email)));
306   } else {
307     localized_strings->SetBoolean("secondaryUser", false);
308     localized_strings->SetString("secondaryUserBannerText", base::string16());
309     localized_strings->SetString("controlledSettingShared", base::string16());
310     localized_strings->SetString("controlledSettingsShared", base::string16());
311   }
312
313   // Screen lock icon can show up as primary or secondary user.
314   localized_strings->SetString("screenLockShared",
315       l10n_util::GetStringUTF16(
316           IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK));
317
318   policy::BrowserPolicyConnectorChromeOS* connector =
319       g_browser_process->platform_part()->browser_policy_connector_chromeos();
320   if (connector->IsEnterpriseManaged()) {
321     // Managed machines have no "owner".
322     localized_strings->SetString("controlledSettingOwner", base::string16());
323   } else {
324     localized_strings->SetString("controlledSettingOwner",
325         l10n_util::GetStringFUTF16(
326             IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
327             base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
328   }
329 }
330
331 void CoreChromeOSOptionsHandler::SelectNetworkCallback(
332     const base::ListValue* args) {
333   std::string service_path;
334   if (args->GetSize() != 1 ||
335       !args->GetString(0, &service_path)) {
336     NOTREACHED();
337     return;
338   }
339   proxy_config_service_.SetCurrentNetwork(service_path);
340   NotifyProxyPrefsChanged();
341 }
342
343 void CoreChromeOSOptionsHandler::OnPreferenceChanged(
344     PrefService* service,
345     const std::string& pref_name) {
346   // Redetermine the current proxy settings and notify the UI if any of these
347   // preferences change.
348   if (pref_name == prefs::kOpenNetworkConfiguration ||
349       pref_name == prefs::kDeviceOpenNetworkConfiguration ||
350       pref_name == prefs::kProxy) {
351     NotifyProxyPrefsChanged();
352     return;
353   }
354   if (pref_name == prefs::kUseSharedProxies) {
355     // kProxy controls kUseSharedProxies and decides if it's managed by
356     // policy/extension.
357     NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
358     return;
359   }
360   ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
361 }
362
363 void CoreChromeOSOptionsHandler::NotifySettingsChanged(
364     const std::string& setting_name) {
365   DCHECK(CrosSettings::Get()->IsCrosSettings(setting_name));
366   scoped_ptr<base::Value> value(FetchPref(setting_name));
367   if (!value.get())
368     NOTREACHED();
369   DispatchPrefChangeNotification(setting_name, value.Pass());
370 }
371
372 void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
373   proxy_config_service_.UpdateFromPrefs();
374   for (size_t i = 0; i < kProxySettingsCount; ++i) {
375     base::Value* value = NULL;
376     proxy_cros_settings_parser::GetProxyPrefValue(
377         proxy_config_service_, kProxySettings[i], &value);
378     DCHECK(value);
379     scoped_ptr<base::Value> ptr(value);
380     DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
381   }
382 }
383
384 }  // namespace options
385 }  // namespace chromeos