core_chromeos_options_handler.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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 "chrome/browser/browser_process.h"
15#include "chrome/browser/chromeos/login/user_manager.h"
16#include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
17#include "chrome/browser/chromeos/settings/cros_settings.h"
18#include "chrome/browser/policy/browser_policy_connector.h"
19#include "chrome/browser/profiles/profile.h"
20#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
21#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
22#include "chrome/common/chrome_notification_types.h"
23#include "chrome/common/pref_names.h"
24#include "content/public/browser/notification_details.h"
25#include "content/public/browser/notification_service.h"
26#include "content/public/browser/notification_source.h"
27#include "content/public/browser/user_metrics.h"
28#include "content/public/browser/web_ui.h"
29
30namespace chromeos {
31namespace options {
32
33namespace {
34
35// List of settings that should be changeable by all users.
36const char* kNonOwnerSettings[] = {
37    kSystemTimezone
38};
39
40// Returns true if |pref| should be only available to the owner.
41bool IsSettingOwnerOnly(const std::string& pref) {
42  const char** end = kNonOwnerSettings + arraysize(kNonOwnerSettings);
43  return std::find(kNonOwnerSettings, end, pref) == end;
44}
45
46// Returns true if |username| is the logged-in owner.
47bool IsLoggedInOwner(const std::string& username) {
48  UserManager* user_manager = UserManager::Get();
49  return user_manager->IsCurrentUserOwner() &&
50      user_manager->GetLoggedInUser()->email() == username;
51}
52
53// Creates a user info dictionary to be stored in the |ListValue| that is
54// passed to Javascript for the |kAccountsPrefUsers| preference.
55base::DictionaryValue* CreateUserInfo(const std::string& username,
56                                      const std::string& display_email,
57                                      const std::string& display_name) {
58  base::DictionaryValue* user_dict = new DictionaryValue;
59  user_dict->SetString("username", username);
60  user_dict->SetString("name", display_email);
61  user_dict->SetString("email", display_name);
62  user_dict->SetBoolean("owner", IsLoggedInOwner(username));
63  return user_dict;
64}
65
66// This function decorates the bare list of emails with some more information
67// needed by the UI to properly display the Accounts page.
68base::Value* CreateUsersWhitelist(const base::Value *pref_value) {
69  const base::ListValue* list_value =
70      static_cast<const base::ListValue*>(pref_value);
71  base::ListValue* user_list = new base::ListValue();
72  UserManager* user_manager = UserManager::Get();
73
74  for (base::ListValue::const_iterator i = list_value->begin();
75       i != list_value->end(); ++i) {
76    std::string email;
77    if ((*i)->GetAsString(&email)) {
78      // Translate email to the display email.
79      std::string display_email = user_manager->GetUserDisplayEmail(email);
80      // TODO(ivankr): fetch display name for existing users.
81      user_list->Append(CreateUserInfo(email, display_email, std::string()));
82    }
83  }
84  return user_list;
85}
86
87const char kSelectNetworkMessage[] = "selectNetwork";
88
89}  // namespace
90
91CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler() {
92}
93
94CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
95}
96
97void CoreChromeOSOptionsHandler::RegisterMessages() {
98  CoreOptionsHandler::RegisterMessages();
99  web_ui()->RegisterMessageCallback(
100      kSelectNetworkMessage,
101      base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
102                 base::Unretained(this)));
103}
104
105void CoreChromeOSOptionsHandler::InitializeHandler() {
106  // In case the options page is reloaded, forget the last selected network.
107  proxy_config_service_.SetCurrentNetwork(std::string());
108
109  CoreOptionsHandler::InitializeHandler();
110
111  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
112  proxy_prefs_.Init(prefs);
113  proxy_prefs_.Add(prefs::kProxy,
114                   base::Bind(&CoreChromeOSOptionsHandler::OnPreferenceChanged,
115                              base::Unretained(this),
116                              prefs));
117  proxy_config_service_.SetPrefs(prefs);
118}
119
120base::Value* CoreChromeOSOptionsHandler::FetchPref(
121    const std::string& pref_name) {
122  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
123    base::Value *value = NULL;
124    proxy_cros_settings_parser::GetProxyPrefValue(
125        proxy_config_service_, pref_name, &value);
126    if (!value)
127      return base::Value::CreateNullValue();
128
129    return value;
130  }
131  if (!CrosSettings::IsCrosSettings(pref_name)) {
132    std::string controlling_pref =
133        pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
134    return CreateValueForPref(pref_name, controlling_pref);
135  }
136
137  const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
138  if (!pref_value)
139    return base::Value::CreateNullValue();
140
141  // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
142  // TODO(estade): seems that this should replicate CreateValueForPref less.
143  DictionaryValue* dict = new DictionaryValue;
144  if (pref_name == kAccountsPrefUsers)
145    dict->Set("value", CreateUsersWhitelist(pref_value));
146  else
147    dict->Set("value", pref_value->DeepCopy());
148  if (g_browser_process->browser_policy_connector()->IsEnterpriseManaged())
149    dict->SetString("controlledBy", "policy");
150  dict->SetBoolean("disabled",
151                   IsSettingOwnerOnly(pref_name) &&
152                       !UserManager::Get()->IsCurrentUserOwner());
153  return dict;
154}
155
156void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
157  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
158    // We observe those all the time.
159    return;
160  }
161  if (!CrosSettings::IsCrosSettings(pref_name))
162    return ::options::CoreOptionsHandler::ObservePref(pref_name);
163  CrosSettings::Get()->AddSettingsObserver(pref_name.c_str(), this);
164}
165
166void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
167                                         const base::Value* value,
168                                         const std::string& metric) {
169  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
170    proxy_cros_settings_parser::SetProxyPrefValue(
171        pref_name, value, &proxy_config_service_);
172    base::StringValue proxy_type(pref_name);
173    web_ui()->CallJavascriptFunction(
174        "options.internet.DetailsInternetPage.updateProxySettings",
175        proxy_type);
176    ProcessUserMetric(value, metric);
177    return;
178  }
179  if (!CrosSettings::IsCrosSettings(pref_name))
180    return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
181  CrosSettings::Get()->Set(pref_name, *value);
182
183  ProcessUserMetric(value, metric);
184}
185
186void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
187  if (proxy_cros_settings_parser::IsProxyPref(path))
188    return;  // We unregister those in the destructor.
189  // Unregister this instance from observing prefs of chrome os settings.
190  if (CrosSettings::IsCrosSettings(path))
191    CrosSettings::Get()->RemoveSettingsObserver(path.c_str(), this);
192  else  // Call base class to handle regular preferences.
193    ::options::CoreOptionsHandler::StopObservingPref(path);
194}
195
196void CoreChromeOSOptionsHandler::GetLocalizedValues(
197    DictionaryValue* localized_strings) {
198  DCHECK(localized_strings);
199  CoreOptionsHandler::GetLocalizedValues(localized_strings);
200
201  AddAccountUITweaksLocalizedValues(localized_strings);
202}
203
204void CoreChromeOSOptionsHandler::Observe(
205    int type,
206    const content::NotificationSource& source,
207    const content::NotificationDetails& details) {
208  if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) {
209    NotifySettingsChanged(content::Details<std::string>(details).ptr());
210    return;
211  }
212  ::options::CoreOptionsHandler::Observe(type, source, details);
213}
214
215void CoreChromeOSOptionsHandler::SelectNetwork(
216    const std::string& service_path) {
217  proxy_config_service_.SetCurrentNetwork(service_path);
218  NotifyProxyPrefsChanged();
219}
220
221void CoreChromeOSOptionsHandler::SelectNetworkCallback(
222    const base::ListValue* args) {
223  std::string service_path;
224  if (args->GetSize() != 1 ||
225      !args->GetString(0, &service_path)) {
226    NOTREACHED();
227    return;
228  }
229  SelectNetwork(service_path);
230}
231
232void CoreChromeOSOptionsHandler::OnPreferenceChanged(
233    PrefService* service,
234    const std::string& pref_name) {
235  // Special handling for preferences kUseSharedProxies and kProxy, the latter
236  // controls the former and decides if it's managed by policy/extension.
237  const PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
238  if (service == pref_service &&
239      (proxy_prefs_.IsObserved(pref_name) ||
240       pref_name == prefs::kUseSharedProxies)) {
241    NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
242    return;
243  }
244  ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
245}
246
247void CoreChromeOSOptionsHandler::NotifySettingsChanged(
248    const std::string* setting_name) {
249  DCHECK(CrosSettings::Get()->IsCrosSettings(*setting_name));
250  scoped_ptr<base::Value> value(FetchPref(*setting_name));
251  if (!value.get())
252    NOTREACHED();
253  DispatchPrefChangeNotification(*setting_name, value.Pass());
254}
255
256void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
257  for (size_t i = 0; i < kProxySettingsCount; ++i) {
258    base::Value* value = NULL;
259    proxy_cros_settings_parser::GetProxyPrefValue(
260        proxy_config_service_, kProxySettings[i], &value);
261    DCHECK(value);
262    scoped_ptr<base::Value> ptr(value);
263    DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
264  }
265}
266
267}  // namespace options
268}  // namespace chromeos
269