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