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