// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"

#include <string>

#include "ash/session/session_state_delegate.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/proxy_cros_settings_parser.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
#include "chrome/browser/ui/webui/help/help_handler.h"
#include "chrome/browser/ui/webui/options/chromeos/accounts_options_handler.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace chromeos {
namespace options {

namespace {

// List of settings that should be changeable by all users.
const char* kNonPrivilegedSettings[] = {
    kSystemTimezone
};

// Returns true if |pref| can be controlled (e.g. by policy or owner).
bool IsSettingPrivileged(const std::string& pref) {
  const char** end = kNonPrivilegedSettings + arraysize(kNonPrivilegedSettings);
  return std::find(kNonPrivilegedSettings, end, pref) == end;
}

// Creates a user info dictionary to be stored in the |ListValue| that is
// passed to Javascript for the |kAccountsPrefUsers| preference.
base::DictionaryValue* CreateUserInfo(const std::string& username,
                                      const std::string& display_email,
                                      const std::string& display_name) {
  base::DictionaryValue* user_dict = new base::DictionaryValue;
  user_dict->SetString("username", username);
  user_dict->SetString("name", display_email);
  user_dict->SetString("email", display_name);

  bool is_owner = user_manager::UserManager::Get()->GetOwnerEmail() == username;
  user_dict->SetBoolean("owner", is_owner);
  return user_dict;
}

// This function decorates the bare list of emails with some more information
// needed by the UI to properly display the Accounts page.
base::Value* CreateUsersWhitelist(const base::Value *pref_value) {
  const base::ListValue* list_value =
      static_cast<const base::ListValue*>(pref_value);
  base::ListValue* user_list = new base::ListValue();
  user_manager::UserManager* user_manager = user_manager::UserManager::Get();

  for (base::ListValue::const_iterator i = list_value->begin();
       i != list_value->end(); ++i) {
    std::string email;
    if ((*i)->GetAsString(&email)) {
      // Translate email to the display email.
      std::string display_email = user_manager->GetUserDisplayEmail(email);
      // TODO(ivankr): fetch display name for existing users.
      user_list->Append(CreateUserInfo(email, display_email, std::string()));
    }
  }
  return user_list;
}

const char kSelectNetworkMessage[] = "selectNetwork";

}  // namespace

CoreChromeOSOptionsHandler::CoreChromeOSOptionsHandler() {
  notification_registrar_.Add(this,
                              chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
                              content::NotificationService::AllSources());
}

CoreChromeOSOptionsHandler::~CoreChromeOSOptionsHandler() {
}

void CoreChromeOSOptionsHandler::RegisterMessages() {
  CoreOptionsHandler::RegisterMessages();
  web_ui()->RegisterMessageCallback(
      kSelectNetworkMessage,
      base::Bind(&CoreChromeOSOptionsHandler::SelectNetworkCallback,
                 base::Unretained(this)));
}

void CoreChromeOSOptionsHandler::InitializeHandler() {
  // This function is both called on the initial page load and on each reload.
  // For the latter case, forget the last selected network.
  proxy_config_service_.SetCurrentNetwork(std::string());
  // And clear the cached configuration.
  proxy_config_service_.UpdateFromPrefs();

  CoreOptionsHandler::InitializeHandler();

  PrefService* profile_prefs = NULL;
  Profile* profile = Profile::FromWebUI(web_ui());
  if (!ProfileHelper::IsSigninProfile(profile)) {
    profile_prefs = profile->GetPrefs();
    ObservePref(prefs::kOpenNetworkConfiguration);
  }
  ObservePref(prefs::kProxy);
  ObservePref(prefs::kDeviceOpenNetworkConfiguration);
  proxy_config_service_.SetPrefs(profile_prefs,
                                 g_browser_process->local_state());
}

void CoreChromeOSOptionsHandler::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  // The only expected notification for now is this one.
  DCHECK(type == chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED);

  // Finish this asynchronously because the notification has to tricle in to all
  // Chrome components before we can reliably read the status on the other end.
  base::MessageLoop::current()->PostTask(FROM_HERE,
      base::Bind(&CoreChromeOSOptionsHandler::NotifyOwnershipChanged,
                 base::Unretained(this)));
}

void CoreChromeOSOptionsHandler::NotifyOwnershipChanged() {
  for (SubscriptionMap::iterator it = pref_subscription_map_.begin();
       it != pref_subscription_map_.end(); ++it) {
    NotifySettingsChanged(it->first);
  }
}

base::Value* CoreChromeOSOptionsHandler::FetchPref(
    const std::string& pref_name) {
  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
    base::Value *value = NULL;
    proxy_cros_settings_parser::GetProxyPrefValue(
        proxy_config_service_, pref_name, &value);
    if (!value)
      return base::Value::CreateNullValue();

    return value;
  }

  if (!CrosSettings::IsCrosSettings(pref_name)) {
    std::string controlling_pref =
        pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
    return CreateValueForPref(pref_name, controlling_pref);
  }

  const base::Value* pref_value = CrosSettings::Get()->GetPref(pref_name);
  if (!pref_value)
    return base::Value::CreateNullValue();

  // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
  // TODO(estade): seems that this should replicate CreateValueForPref less.
  base::DictionaryValue* dict = new base::DictionaryValue;
  if (pref_name == kAccountsPrefUsers)
    dict->Set("value", CreateUsersWhitelist(pref_value));
  else
    dict->Set("value", pref_value->DeepCopy());

  std::string controlled_by;
  if (IsSettingPrivileged(pref_name)) {
    policy::BrowserPolicyConnectorChromeOS* connector =
        g_browser_process->platform_part()->browser_policy_connector_chromeos();
    if (connector->IsEnterpriseManaged())
      controlled_by = "policy";
    else if (!ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui())))
      controlled_by = "owner";
  }
  dict->SetBoolean("disabled", !controlled_by.empty());
  if (!controlled_by.empty())
    dict->SetString("controlledBy", controlled_by);
  return dict;
}

void CoreChromeOSOptionsHandler::ObservePref(const std::string& pref_name) {
  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
    // We observe those all the time.
    return;
  }
  if (!CrosSettings::IsCrosSettings(pref_name))
    return ::options::CoreOptionsHandler::ObservePref(pref_name);

  linked_ptr<CrosSettings::ObserverSubscription> subscription(
      CrosSettings::Get()->AddSettingsObserver(
          pref_name.c_str(),
          base::Bind(&CoreChromeOSOptionsHandler::NotifySettingsChanged,
                     base::Unretained(this),
                     pref_name)).release());
  pref_subscription_map_.insert(make_pair(pref_name, subscription));
}

void CoreChromeOSOptionsHandler::SetPref(const std::string& pref_name,
                                         const base::Value* value,
                                         const std::string& metric) {
  if (proxy_cros_settings_parser::IsProxyPref(pref_name)) {
    proxy_cros_settings_parser::SetProxyPrefValue(
        pref_name, value, &proxy_config_service_);
    base::StringValue proxy_type(pref_name);
    web_ui()->CallJavascriptFunction(
        "options.internet.DetailsInternetPage.updateProxySettings",
        proxy_type);
    ProcessUserMetric(value, metric);
    return;
  }
  if (!CrosSettings::IsCrosSettings(pref_name))
    return ::options::CoreOptionsHandler::SetPref(pref_name, value, metric);
  CrosSettings::Get()->Set(pref_name, *value);

  ProcessUserMetric(value, metric);
}

void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
  if (proxy_cros_settings_parser::IsProxyPref(path))
    return;  // We unregister those in the destructor.
  // Unregister this instance from observing prefs of chrome os settings.
  if (CrosSettings::IsCrosSettings(path))
    pref_subscription_map_.erase(path);
  else  // Call base class to handle regular preferences.
    ::options::CoreOptionsHandler::StopObservingPref(path);
}

base::Value* CoreChromeOSOptionsHandler::CreateValueForPref(
    const std::string& pref_name,
    const std::string& controlling_pref_name) {
  // The screen lock setting is shared if multiple users are logged in and at
  // least one has chosen to require passwords.
  if (pref_name == prefs::kEnableAutoScreenLock &&
      user_manager::UserManager::Get()->GetLoggedInUsers().size() > 1 &&
      controlling_pref_name.empty()) {
    PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
    const PrefService::Preference* pref =
        user_prefs->FindPreference(prefs::kEnableAutoScreenLock);

    ash::SessionStateDelegate* delegate =
        ash::Shell::GetInstance()->session_state_delegate();
    if (pref && pref->IsUserModifiable() &&
        delegate->ShouldLockScreenBeforeSuspending()) {
      bool screen_lock = false;
      bool success = pref->GetValue()->GetAsBoolean(&screen_lock);
      DCHECK(success);
      if (!screen_lock) {
        // Screen lock is enabled for the session, but not in the user's
        // preferences. Show the user's value in the checkbox, but indicate
        // that the password requirement is enabled by some other user.
        base::DictionaryValue* dict = new base::DictionaryValue;
        dict->Set("value", pref->GetValue()->DeepCopy());
        dict->SetString("controlledBy", "shared");
        return dict;
      }
    }
  }

  return CoreOptionsHandler::CreateValueForPref(pref_name,
                                                controlling_pref_name);
}

void CoreChromeOSOptionsHandler::GetLocalizedValues(
    base::DictionaryValue* localized_strings) {
  DCHECK(localized_strings);
  CoreOptionsHandler::GetLocalizedValues(localized_strings);

  Profile* profile = Profile::FromWebUI(web_ui());
  AddAccountUITweaksLocalizedValues(localized_strings, profile);

  user_manager::UserManager* user_manager = user_manager::UserManager::Get();

  // Check at load time whether this is a secondary user in a multi-profile
  // session.
  user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile);
  if (user && user->email() != user_manager->GetPrimaryUser()->email()) {
    const std::string& primary_email = user_manager->GetPrimaryUser()->email();

    // Set secondaryUser to show the shared icon by the network section header.
    localized_strings->SetBoolean("secondaryUser", true);
    localized_strings->SetString("secondaryUserBannerText",
        l10n_util::GetStringFUTF16(
            IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER,
            base::ASCIIToUTF16(primary_email)));
    localized_strings->SetString("controlledSettingShared",
        l10n_util::GetStringFUTF16(
            IDS_OPTIONS_CONTROLLED_SETTING_SHARED,
            base::ASCIIToUTF16(primary_email)));
    localized_strings->SetString("controlledSettingsShared",
        l10n_util::GetStringFUTF16(
            IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED,
            base::ASCIIToUTF16(primary_email)));
  } else {
    localized_strings->SetBoolean("secondaryUser", false);
    localized_strings->SetString("secondaryUserBannerText", base::string16());
    localized_strings->SetString("controlledSettingShared", base::string16());
    localized_strings->SetString("controlledSettingsShared", base::string16());
  }

  // Screen lock icon can show up as primary or secondary user.
  localized_strings->SetString("screenLockShared",
      l10n_util::GetStringUTF16(
          IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK));

  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (connector->IsEnterpriseManaged()) {
    // Managed machines have no "owner".
    localized_strings->SetString("controlledSettingOwner", base::string16());
  } else {
    localized_strings->SetString("controlledSettingOwner",
        l10n_util::GetStringFUTF16(
            IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
            base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
  }

  localized_strings->SetString(
      "browserVersion",
      l10n_util::GetStringFUTF16(IDS_ABOUT_PRODUCT_VERSION,
                                 ::HelpHandler::BuildBrowserVersionString()));
  localized_strings->SetBoolean("showVersion",
                                ::switches::AboutInSettingsEnabled());
}

void CoreChromeOSOptionsHandler::SelectNetworkCallback(
    const base::ListValue* args) {
  std::string service_path;
  if (args->GetSize() != 1 ||
      !args->GetString(0, &service_path)) {
    NOTREACHED();
    return;
  }
  proxy_config_service_.SetCurrentNetwork(service_path);
  NotifyProxyPrefsChanged();
}

void CoreChromeOSOptionsHandler::OnPreferenceChanged(
    PrefService* service,
    const std::string& pref_name) {
  // Redetermine the current proxy settings and notify the UI if any of these
  // preferences change.
  if (pref_name == prefs::kOpenNetworkConfiguration ||
      pref_name == prefs::kDeviceOpenNetworkConfiguration ||
      pref_name == prefs::kProxy) {
    NotifyProxyPrefsChanged();
    return;
  }
  if (pref_name == prefs::kUseSharedProxies) {
    // kProxy controls kUseSharedProxies and decides if it's managed by
    // policy/extension.
    NotifyPrefChanged(prefs::kUseSharedProxies, prefs::kProxy);
    return;
  }
  ::options::CoreOptionsHandler::OnPreferenceChanged(service, pref_name);
}

void CoreChromeOSOptionsHandler::NotifySettingsChanged(
    const std::string& setting_name) {
  DCHECK(CrosSettings::Get()->IsCrosSettings(setting_name));
  scoped_ptr<base::Value> value(FetchPref(setting_name));
  if (!value.get())
    NOTREACHED();
  DispatchPrefChangeNotification(setting_name, value.Pass());
}

void CoreChromeOSOptionsHandler::NotifyProxyPrefsChanged() {
  proxy_config_service_.UpdateFromPrefs();
  for (size_t i = 0; i < kProxySettingsCount; ++i) {
    base::Value* value = NULL;
    proxy_cros_settings_parser::GetProxyPrefValue(
        proxy_config_service_, kProxySettings[i], &value);
    DCHECK(value);
    scoped_ptr<base::Value> ptr(value);
    DispatchPrefChangeNotification(kProxySettings[i], ptr.Pass());
  }
}

}  // namespace options
}  // namespace chromeos
