// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/net/system_proxy_manager.h"

#include <string>

#include "ash/constants/ash_features.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/values.h"
#include "chrome/browser/ash/notifications/request_system_proxy_credentials_view.h"
#include "chrome/browser/ash/notifications/system_proxy_notification.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/login/login_display_host.h"
#include "chrome/browser/ui/login/login_handler.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "chromeos/ash/components/network/network_event_log.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/proxy/proxy_config_service_impl.h"
#include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
#include "chromeos/ash/experiences/arc/arc_prefs.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/host_port_pair.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/http/http_auth_scheme.h"
#include "net/http/http_util.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "ui/aura/window.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"

namespace ash {

namespace {

const char kSystemProxyService[] = "system-proxy-service";

// A `content::LoginDelegate` implementation that returns to the caller the
// proxy credentials set by the policy `SystemProxySettings`.
class SystemProxyLoginHandler : public content::LoginDelegate {
 public:
  SystemProxyLoginHandler() = default;
  ~SystemProxyLoginHandler() override = default;

  SystemProxyLoginHandler(const SystemProxyLoginHandler&) = delete;
  SystemProxyLoginHandler& operator=(const SystemProxyLoginHandler&) = delete;

  void AuthenticateWithCredentials(
      const std::string& username,
      const std::string& password,
      content::LoginDelegate::LoginAuthRequiredCallback
          auth_required_callback) {
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(&SystemProxyLoginHandler::InvokeWithCredentials,
                       weak_factory_.GetWeakPtr(), username, password,
                       std::move(auth_required_callback)));
  }

 private:
  void InvokeWithCredentials(const std::string& username,
                             const std::string& password,
                             content::LoginDelegate::LoginAuthRequiredCallback
                                 auth_required_callback) {
    std::move(auth_required_callback)
        .Run(std::make_optional<net::AuthCredentials>(
            base::UTF8ToUTF16(username), base::UTF8ToUTF16(password)));
  }

  base::WeakPtrFactory<SystemProxyLoginHandler> weak_factory_{this};
};

// If system-proxy is enabled via policy, it can be used by both Chrome OS
// system services and the PlayStore. If enabled via flag, system-proxy can only
// be used by system services which explicitly ask to use system-proxy for HTTP
// proxy authentication. Otherwise, system-proxy is disabled.
SystemProxyManager::SystemProxyState DetermineSystemProxyState(
    bool policy_enabled) {
  if (policy_enabled)
    return SystemProxyManager::SystemProxyState::kEnabledForAll;

  if (base::FeatureList::IsEnabled(features::kSystemProxyForSystemServices)) {
    return SystemProxyManager::SystemProxyState::kEnabledForSystemServices;
  }
  return SystemProxyManager::SystemProxyState::kDisabled;
}

SystemProxyManager* g_system_proxy_manager_ = nullptr;

}  // namespace

SystemProxyManager::SystemProxyManager(PrefService* local_state) {
  // Connect to System-proxy signals.
  SystemProxyClient::Get()->SetWorkerActiveSignalCallback(base::BindRepeating(
      &SystemProxyManager::OnWorkerActive, weak_factory_.GetWeakPtr()));
  SystemProxyClient::Get()->SetAuthenticationRequiredSignalCallback(
      base::BindRepeating(&SystemProxyManager::OnAuthenticationRequired,
                          weak_factory_.GetWeakPtr()));
  SystemProxyClient::Get()->ConnectToWorkerSignals();
  local_state_ = local_state;

  // Listen to pref changes.
  local_state_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
  local_state_pref_change_registrar_->Init(local_state_);
  local_state_pref_change_registrar_->Add(
      prefs::kKerberosEnabled,
      base::BindRepeating(&SystemProxyManager::OnKerberosEnabledChanged,
                          weak_factory_.GetWeakPtr()));
  DCHECK(NetworkHandler::IsInitialized());
  network_state_handler_observer_.Observe(
      NetworkHandler::Get()->network_state_handler());

  system_proxy_state_ = DetermineSystemProxyState(/*policy_enabled=*/false);

  // Start the system-proxy worker that authenticates system services.
  if (system_proxy_state_ == SystemProxyState::kEnabledForSystemServices) {
    SendPolicyAuthenticationCredentials(/*username=*/"",
                                        /*password=*/"",
                                        /*force_send=*/true);
  }
}

SystemProxyManager::~SystemProxyManager() {
  if (IsEnabled()) {
    SendShutDownRequest(system_proxy::TrafficOrigin::ALL);
  }
  DCHECK(NetworkHandler::IsInitialized());
}

// static
void SystemProxyManager::Initialize(PrefService* local_state) {
  g_system_proxy_manager_ = new SystemProxyManager(local_state);
}

// static
SystemProxyManager* SystemProxyManager::Get() {
  return g_system_proxy_manager_;
}

// static
void SystemProxyManager::Shutdown() {
  if (g_system_proxy_manager_) {
    delete g_system_proxy_manager_;
    g_system_proxy_manager_ = nullptr;
  }
}

std::string SystemProxyManager::SystemServicesProxyPacString(
    chromeos::SystemProxyOverride system_proxy_override) const {
  if (system_proxy_override == chromeos::SystemProxyOverride::kOptOut ||
      system_services_address_.empty()) {
    return std::string();
  }

  if (system_proxy_state_ == SystemProxyState::kEnabledForAll ||
      (system_proxy_state_ == SystemProxyState::kEnabledForSystemServices &&
       system_proxy_override == chromeos::SystemProxyOverride::kOptIn)) {
    return "PROXY " + system_services_address_;
  }

  return std::string();
}

void SystemProxyManager::StartObservingPrimaryProfilePrefs(Profile* profile) {
  primary_profile_ = profile;
  extension_prefs_util_ = std::make_unique<extensions::PrefsUtil>(profile);
  // Listen to pref changes.
  profile_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
  profile_pref_change_registrar_->Init(primary_profile_->GetPrefs());
  profile_pref_change_registrar_->Add(
      prefs::kKerberosActivePrincipalName,
      base::BindRepeating(&SystemProxyManager::OnKerberosAccountChanged,
                          base::Unretained(this)));
  profile_pref_change_registrar_->Add(
      arc::prefs::kArcEnabled,
      base::BindRepeating(&SystemProxyManager::OnArcEnabledChanged,
                          weak_factory_.GetWeakPtr()));
  profile_pref_change_registrar_->Add(
      proxy_config::prefs::kProxy,
      base::BindRepeating(&SystemProxyManager::OnProxyConfigChanged,
                          base::Unretained(this)));
  if (IsEnabled()) {
    OnProxyConfigChanged();
    OnKerberosAccountChanged();
  }

  if (system_proxy_state_ == SystemProxyState::kEnabledForAll) {
    OnArcEnabledChanged();
  }
}

void SystemProxyManager::StopObservingPrimaryProfilePrefs() {
  profile_pref_change_registrar_->RemoveAll();
  profile_pref_change_registrar_.reset();
  extension_prefs_util_.reset();
  primary_profile_ = nullptr;
}

void SystemProxyManager::ClearUserCredentials() {
  if (!IsEnabled()) {
    return;
  }

  system_proxy::ClearUserCredentialsRequest request;
  SystemProxyClient::Get()->ClearUserCredentials(
      request, base::BindOnce(&SystemProxyManager::OnClearUserCredentials,
                              weak_factory_.GetWeakPtr()));
}

void SystemProxyManager::SetPolicySettings(
    bool system_proxy_enabled,
    const std::string& system_services_username,
    const std::string& system_services_password,
    const std::vector<std::string>& auth_schemes) {
  system_services_username_ = system_services_username;
  system_services_password_ = system_services_password;
  policy_credentials_auth_schemes_ = auth_schemes;

  if (system_proxy_state_ == SystemProxyState::kDisabled &&
      !system_proxy_enabled) {
    return;  // nothing to do
  }

  system_proxy_state_ = DetermineSystemProxyState(system_proxy_enabled);

  if (system_proxy_state_ == SystemProxyState::kDisabled) {
    system_services_address_.clear();
    SetUserTrafficProxyPref(std::string());
    CloseAuthenticationUI();
    SendShutDownRequest(system_proxy::TrafficOrigin::ALL);
    return;
  }

  if (system_proxy_state_ == SystemProxyState::kEnabledForSystemServices) {
    // Start the system-proxy worker for system services and make sure the
    // system-proxy worker for ARC is shut down.
    SendPolicyAuthenticationCredentials(/*username=*/"",
                                        /*password=*/"",
                                        /*force_send=*/true);
    SetUserTrafficProxyPref(std::string());
    SendShutDownRequest(system_proxy::TrafficOrigin::USER);
  }

  if (IsManagedProxyConfigured() &&
      system_proxy_state_ == SystemProxyState::kEnabledForAll) {
    // Force send the configuration in case the credentials hand't changed, but
    // `policy_credentials_auth_schemes_` has.
    SendPolicyAuthenticationCredentials(system_services_username_,
                                        system_services_password_,
                                        /*force_send=*/true);
  } else {
    // To avoid leaking the policy set credentials, don't send them to
    // System-proxy if there's no managed proxy on the network.
    // Note: When SystemProxyManager is starting, the credentials are empty and
    // they were never sent before. We need to force send them, otherwise
    // `SendPolicyAuthenticationCredentials` will detect that no change to the
    // credentials occurred and will not trigger a D-Bus request. This means the
    // worker service for Chrome OS system services will not be started.
    SendPolicyAuthenticationCredentials(/*username=*/"",
                                        /*password=*/"",
                                        /*force_send=*/true);
  }

  // Fire once to cover the case where the SystemProxySetting policy is set
  // during a user session.
  if (IsArcEnabled() &&
      system_proxy_state_ == SystemProxyState::kEnabledForAll) {
    OnArcEnabledChanged();
  }
}

void SystemProxyManager::OnKerberosEnabledChanged() {
  SendKerberosAuthenticationDetails();
}

void SystemProxyManager::OnKerberosAccountChanged() {
  if (!local_state_->GetBoolean(prefs::kKerberosEnabled)) {
    return;
  }
  SendKerberosAuthenticationDetails();
}

void SystemProxyManager::OnArcEnabledChanged() {
  if (system_proxy_state_ != SystemProxyState::kEnabledForAll) {
    return;
  }

  if (!IsArcEnabled()) {
    system_proxy::ShutDownRequest request;
    request.set_traffic_type(system_proxy::TrafficOrigin::USER);
    SystemProxyClient::Get()->ShutDownProcess(
        request, base::BindOnce(&SystemProxyManager::OnShutDownProcess,
                                weak_factory_.GetWeakPtr()));
    return;
  }

  if (local_state_->GetBoolean(prefs::kKerberosEnabled)) {
    SendKerberosAuthenticationDetails();
    return;
  }

  system_proxy::SetAuthenticationDetailsRequest request;
  request.set_traffic_type(system_proxy::TrafficOrigin::USER);
  SystemProxyClient::Get()->SetAuthenticationDetails(
      request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
                              weak_factory_.GetWeakPtr()));
}

bool SystemProxyManager::IsArcEnabled() const {
  return primary_profile_ &&
         primary_profile_->GetPrefs()->GetBoolean(arc::prefs::kArcEnabled);
}

bool SystemProxyManager::IsEnabled() const {
  return system_proxy_state_ != SystemProxyState::kDisabled;
}

void SystemProxyManager::SendUserAuthenticationCredentials(
    const system_proxy::ProtectionSpace& protection_space,
    const std::string& username,
    const std::string& password) {
  // System-proxy is started via d-bus activation, meaning the first d-bus call
  // will start the daemon. Check that System-proxy was not disabled by policy
  // while looking for credentials so we don't accidentally restart it.
  if (!IsEnabled()) {
    return;
  }

  system_proxy::Credentials user_credentials;
  user_credentials.set_username(username);
  user_credentials.set_password(password);

  system_proxy::SetAuthenticationDetailsRequest request;
  request.set_traffic_type(
      IsArcEnabled() && system_proxy_state_ == SystemProxyState::kEnabledForAll
          ? system_proxy::TrafficOrigin::ALL
          : system_proxy::TrafficOrigin::SYSTEM);
  *request.mutable_credentials() = user_credentials;
  *request.mutable_protection_space() = protection_space;

  SystemProxyClient::Get()->SetAuthenticationDetails(
      request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
                              weak_factory_.GetWeakPtr()));
}

void SystemProxyManager::SendPolicyAuthenticationCredentials(
    const std::string& username,
    const std::string& password,
    bool force_send) {
  if (!IsEnabled())
    return;

  if (!force_send &&
      (last_sent_username_ == username && last_sent_password_ == password)) {
    // Credentials were already sent.
    return;
  }

  last_sent_username_ = username;
  last_sent_password_ = password;

  system_proxy::SetAuthenticationDetailsRequest request;
  system_proxy::Credentials credentials;
  credentials.set_username(username);
  credentials.set_password(password);
  for (const auto& auth_scheme : policy_credentials_auth_schemes_) {
    credentials.add_policy_credentials_auth_schemes(auth_scheme);
  }
  *request.mutable_credentials() = credentials;

  request.set_traffic_type(system_proxy::TrafficOrigin::SYSTEM);

  SystemProxyClient::Get()->SetAuthenticationDetails(
      request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
                              weak_factory_.GetWeakPtr()));
}

void SystemProxyManager::SendKerberosAuthenticationDetails() {
  if (!IsEnabled()) {
    return;
  }

  system_proxy::SetAuthenticationDetailsRequest request;
  request.set_traffic_type(
      IsArcEnabled() && system_proxy_state_ == SystemProxyState::kEnabledForAll
          ? system_proxy::TrafficOrigin::ALL
          : system_proxy::TrafficOrigin::SYSTEM);
  request.set_kerberos_enabled(
      local_state_->GetBoolean(prefs::kKerberosEnabled));
  if (primary_profile_) {
    request.set_active_principal_name(
        primary_profile_->GetPrefs()
            ->GetValue(prefs::kKerberosActivePrincipalName)
            // TODO (https://crbug.com/1344857) Maybe call GetString directly.
            .GetString());
  }
  SystemProxyClient::Get()->SetAuthenticationDetails(
      request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
                              weak_factory_.GetWeakPtr()));
}

void SystemProxyManager::SendEmptyCredentials(
    const system_proxy::ProtectionSpace& protection_space) {
  SendUserAuthenticationCredentials(protection_space,
                                    /*username=*/std::string(),
                                    /*password=*/std::string());
}

void SystemProxyManager::SendShutDownRequest(
    system_proxy::TrafficOrigin traffic) {
  system_proxy::ShutDownRequest request;
  request.set_traffic_type(traffic);
  SystemProxyClient::Get()->ShutDownProcess(
      request, base::BindOnce(&SystemProxyManager::OnShutDownProcess,
                              weak_factory_.GetWeakPtr()));
}

void SystemProxyManager::SetSystemProxyEnabledForTest(bool enabled) {
  system_proxy_state_ =
      enabled ? SystemProxyState::kEnabledForAll : SystemProxyState::kDisabled;
}

void SystemProxyManager::SetSystemServicesProxyUrlForTest(
    const std::string& local_proxy_url) {
  system_services_address_ = local_proxy_url;
}

void SystemProxyManager::SetSendAuthDetailsClosureForTest(
    base::RepeatingClosure closure) {
  send_auth_details_closure_for_test_ = closure;
}

RequestSystemProxyCredentialsView*
SystemProxyManager::GetActiveAuthDialogForTest() {
  return active_auth_dialog_;
}

void SystemProxyManager::CloseAuthDialogForTest() {
  DCHECK(auth_widget_);
  auth_widget_->CloseNow();
}

// static
void SystemProxyManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
  registry->RegisterStringPref(prefs::kSystemProxyUserTrafficHostAndPort,
                               /*default_value=*/std::string());
}

bool SystemProxyManager::CanUsePolicyCredentials(
    const net::AuthChallengeInfo& auth_info,
    bool first_auth_attempt) {
  if (!auth_info.is_proxy || !first_auth_attempt) {
    return false;
  }
  if (!LoginState::IsInitialized() ||
      (!LoginState::Get()->IsManagedGuestSessionUser() &&
       !LoginState::Get()->IsKioskSession())) {
    VLOG(1) << "Only kiosk app and MGS can reuse the policy provided proxy "
               "credentials for authentication";
    return false;
  }

  if (system_proxy_state_ != SystemProxyState::kEnabledForAll ||
      system_services_username_.empty() || system_services_password_.empty()) {
    return false;
  }

  if (!IsManagedProxyConfigured())
    return false;

  if (!policy_credentials_auth_schemes_.empty()) {
    if (!base::Contains(policy_credentials_auth_schemes_, auth_info.scheme)) {
      VLOG(1) << "Auth scheme not allowed by policy";
      return false;
    }
  }
  return true;
}

std::unique_ptr<content::LoginDelegate> SystemProxyManager::CreateLoginDelegate(
    content::LoginDelegate::LoginAuthRequiredCallback auth_required_callback) {
  auto login_delegate = std::make_unique<SystemProxyLoginHandler>();
  login_delegate->AuthenticateWithCredentials(
      system_services_username_, system_services_password_,
      std::move(auth_required_callback));
  return std::move(login_delegate);
}

void SystemProxyManager::OnSetAuthenticationDetails(
    const system_proxy::SetAuthenticationDetailsResponse& response) {
  if (response.has_error_message()) {
    NET_LOG(ERROR)
        << "Failed to set system traffic credentials for system proxy: "
        << kSystemProxyService << ", Error: " << response.error_message();
  }
  if (send_auth_details_closure_for_test_)
    send_auth_details_closure_for_test_.Run();
}

// This function is called when the default network changes or when any of its
// properties change.
void SystemProxyManager::DefaultNetworkChanged(const NetworkState* network) {
  if (!network)
    return;
  OnProxyConfigChanged();
}

void SystemProxyManager::OnProxyConfigChanged() {
  if (!IsManagedProxyConfigured()) {
    SendPolicyAuthenticationCredentials(/*username=*/"", /*password=*/"",
                                        /*force_send=*/false);
    return;
  }
  SendPolicyAuthenticationCredentials(system_services_username_,
                                      system_services_password_,
                                      /*force_send=*/false);
}

bool SystemProxyManager::IsManagedProxyConfigured() {
  DCHECK(NetworkHandler::IsInitialized());
  NetworkHandler* network_handler = NetworkHandler::Get();
  base::Value::Dict proxy_settings;

  // |ui_proxy_config_service| may be missing in tests. If the device is offline
  // (no network connected) the |DefaultNetwork| is null.
  if (NetworkHandler::HasUiProxyConfigService() &&
      network_handler->network_state_handler()->DefaultNetwork()) {
    // Check if proxy is enforced by user policy, force installed extension or
    // ONC policies. This will only read managed settings.
    NetworkHandler::GetUiProxyConfigService()->MergeEnforcedProxyConfig(
        network_handler->network_state_handler()->DefaultNetwork()->guid(),
        &proxy_settings);
  }
  if (proxy_settings.empty())
    return false;  // no managed proxy set

  if (IsProxyConfiguredByUserViaExtension())
    return false;
  // Proxy was configured by the admin
  return true;
}

bool SystemProxyManager::IsProxyConfiguredByUserViaExtension() {
  if (!extension_prefs_util_)
    return false;

  std::optional<extensions::api::settings_private::PrefObject> pref =
      extension_prefs_util_->GetPref(proxy_config::prefs::kProxy);
  return pref && pref->extension_can_be_disabled &&
         *pref->extension_can_be_disabled;
}

void SystemProxyManager::OnShutDownProcess(
    const system_proxy::ShutDownResponse& response) {
  if (response.has_error_message() && !response.error_message().empty()) {
    NET_LOG(ERROR) << "Failed to shutdown system proxy process: "
                   << kSystemProxyService
                   << ", error: " << response.error_message();
  }
}

void SystemProxyManager::OnClearUserCredentials(
    const system_proxy::ClearUserCredentialsResponse& response) {
  if (response.has_error_message() && !response.error_message().empty()) {
    NET_LOG(ERROR) << "Failed to clear user credentials: "
                   << kSystemProxyService
                   << ", error: " << response.error_message();
  }
}

void SystemProxyManager::OnWorkerActive(
    const system_proxy::WorkerActiveSignalDetails& details) {
  if (details.traffic_origin() == system_proxy::TrafficOrigin::SYSTEM) {
    system_services_address_ = details.local_proxy_url();
    return;
  }
  if (system_proxy_state_ != SystemProxyState::kEnabledForAll)
    return;

  SetUserTrafficProxyPref(details.local_proxy_url());
}

void SystemProxyManager::SetUserTrafficProxyPref(
    const std::string& user_traffic_address) {
  if (!primary_profile_) {
    return;
  }
  primary_profile_->GetPrefs()->SetString(
      prefs::kSystemProxyUserTrafficHostAndPort, user_traffic_address);
}

void SystemProxyManager::OnAuthenticationRequired(
    const system_proxy::AuthenticationRequiredDetails& details) {
  system_proxy::ProtectionSpace protection_space =
      details.proxy_protection_space();

  if (!primary_profile_) {
    SendEmptyCredentials(protection_space);
    return;
  }

  // The previous authentication attempt failed.
  if (details.has_bad_cached_credentials() &&
      details.bad_cached_credentials()) {
    ShowAuthenticationNotification(protection_space,
                                   details.bad_cached_credentials());
    return;
  }

  // TODO(acostinas,chromium:1104818) |protection_space.origin()| is in a
  // URI-like format which may be incompatible between Chrome and libcurl, which
  // is used on the Chrome OS side. We should change |origin()| to be a PAC
  // string (a more "standard" way of representing proxies) and call
  // |FromPacString()| to create |proxy_server|.
  net::ProxyServer proxy_server = net::ProxyUriToProxyServer(
      protection_space.origin(), net::ProxyServer::Scheme::SCHEME_HTTP);

  if (!proxy_server.is_valid()) {
    SendEmptyCredentials(protection_space);
    return;
  }
  primary_profile_->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->LookupProxyAuthCredentials(
          proxy_server, protection_space.scheme(),
          net::HttpUtil::Unquote(protection_space.realm()),
          base::BindOnce(
              &SystemProxyManager::LookupProxyAuthCredentialsCallback,
              weak_factory_.GetWeakPtr(), protection_space));
}

void SystemProxyManager::LookupProxyAuthCredentialsCallback(
    const system_proxy::ProtectionSpace& protection_space,
    const std::optional<net::AuthCredentials>& credentials) {
  if (!credentials) {
    // Ask the user for credentials
    ShowAuthenticationNotification(protection_space, /*show_error=*/false);
    return;
  }

  std::string username;
  std::string password;
  if (credentials) {
    username = base::UTF16ToUTF8(credentials->username());
    password = base::UTF16ToUTF8(credentials->password());

    // If there's a dialog requesting credentials for this proxy, close it.
    if (notification_handler_ ||
        (active_auth_dialog_ &&
         active_auth_dialog_->GetProxyServer() == protection_space.origin())) {
      CloseAuthenticationUI();
    }
  }
  SendUserAuthenticationCredentials(protection_space, username, password);
}

void SystemProxyManager::ShowAuthenticationNotification(
    const system_proxy::ProtectionSpace& protection_space,
    bool show_error) {
  if (active_auth_dialog_)
    return;
  notification_handler_ = std::make_unique<SystemProxyNotification>(
      protection_space, show_error,
      base::BindOnce(&SystemProxyManager::ShowAuthenticationDialog,
                     weak_factory_.GetWeakPtr()));
  notification_handler_->Show();
}

void SystemProxyManager::ShowAuthenticationDialog(
    const system_proxy::ProtectionSpace& protection_space,
    bool show_error_label) {
  if (active_auth_dialog_)
    return;

  if (notification_handler_)
    notification_handler_->Close();

  active_auth_dialog_ = new RequestSystemProxyCredentialsView(
      protection_space.origin(), show_error_label,
      base::BindOnce(&SystemProxyManager::OnDialogClosed,
                     weak_factory_.GetWeakPtr(), protection_space));

  active_auth_dialog_->SetAcceptCallback(
      base::BindRepeating(&SystemProxyManager::OnDialogAccepted,
                          weak_factory_.GetWeakPtr(), protection_space));
  active_auth_dialog_->SetCancelCallback(
      base::BindRepeating(&SystemProxyManager::OnDialogCanceled,
                          weak_factory_.GetWeakPtr(), protection_space));

  auth_widget_ = views::DialogDelegate::CreateDialogWidget(
      active_auth_dialog_, /*context=*/nullptr, /*parent=*/nullptr);
  auth_widget_->Show();
}

void SystemProxyManager::OnDialogAccepted(
    const system_proxy::ProtectionSpace& protection_space) {
  SendUserAuthenticationCredentials(
      protection_space, base::UTF16ToUTF8(active_auth_dialog_->GetUsername()),
      base::UTF16ToUTF8(active_auth_dialog_->GetPassword()));
}

void SystemProxyManager::OnDialogCanceled(
    const system_proxy::ProtectionSpace& protection_space) {
  SendEmptyCredentials(protection_space);
}

void SystemProxyManager::OnDialogClosed(
    const system_proxy::ProtectionSpace& protection_space) {
  active_auth_dialog_ = nullptr;
  auth_widget_ = nullptr;
}

void SystemProxyManager::CloseAuthenticationUI() {
  // Closes the notification if shown.
  if (notification_handler_) {
    notification_handler_->Close();
    notification_handler_.reset();
  }
  if (!auth_widget_)
    return;
  // Also deletes the |auth_widget_| instance.
  auth_widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
}

}  // namespace ash
