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