Commit e3d09540 authored by Andreea Costinas's avatar Andreea Costinas Committed by Commit Bot

system-proxy: Create authentication dialogue

Currently, System-proxy requests proxy authentication credentials from
the Network Service. This means the user has to first to login into the
Browser and then use the Play Store for navigation.

This CL creates a proxy authentication dialogue for System-proxy to
request credentials for a remote proxy without going trough the Browser.

Bug:1112722
TEST=unittests

Change-Id: I263a38c8be4cbbdf0891e515500cd9e5584c63fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352828
Commit-Queue: Andreea-Elena Costinas <acostinas@google.com>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarOmar Morsi <omorsi@google.com>
Cr-Commit-Position: refs/heads/master@{#799586}
parent 771d7f9e
......@@ -5702,4 +5702,27 @@ You can manage this account’s settings by installing the Family Link app on yo
<message name="IDS_CUSTOM_TABS_ACTION_MENU_ACCESSIBLE_NAME" desc="Accessible name for the overflow menu of the Chrome Custom Tab toolbar.">
Action menu button
</message>
<!-- Strings for the System-proxy authentication dialog that requests proxy credentials for network traffic at OS level (outside the Browser) -->
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_TITLE" desc="Title for the dialog.">
Sign in
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_OK_BUTTON" desc="Text for the OK button.">
Sign in
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_TEXT" desc="Text for the dialog informing users that the remote proxy requires authentication.">
The proxy <ph name="PROXY_SERVER">$1<ex>http://localhost:3128</ex></ph> requires a username and password.
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_PRIVACY_WARNING" desc="Text for the privacy disclosure section on the dialog.">
Your connection is not private for all network traffic
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_USERNAME_LABEL" desc="Text for the label associated with the username input.">
Username
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_PASSWORD_LABEL" desc="Text for the label associated with the password input.">
Password
</message>
<message name="IDS_SYSTEM_PROXY_AUTH_DIALOG_ERROR_LABEL" desc="Text for the error label that informs users that the authentication attempt failed.">
Unable to connect to the proxy
</message>
</grit-part>
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
6102aa43999807804f4af6bf78d850fba98cdd84
\ No newline at end of file
......@@ -2629,6 +2629,8 @@ source_set("chromeos") {
"ui/passphrase_textfield.h",
"ui/request_pin_view.cc",
"ui/request_pin_view.h",
"ui/request_system_proxy_credentials_view.cc",
"ui/request_system_proxy_credentials_view.h",
"ui/screen_capture_notification_ui_chromeos.cc",
"ui/screen_capture_notification_ui_chromeos.h",
"ui/tpm_auto_update_notification.cc",
......@@ -3543,6 +3545,7 @@ source_set("unit_tests") {
"ui/low_disk_notification_unittest.cc",
"ui/mock_adb_sideloading_policy_change_notification.cc",
"ui/mock_adb_sideloading_policy_change_notification.h",
"ui/request_system_proxy_credentials_view_unittest.cc",
"usb/cros_usb_detector_unittest.cc",
"wilco_dtc_supportd/testing_wilco_dtc_supportd_bridge_wrapper.cc",
"wilco_dtc_supportd/testing_wilco_dtc_supportd_bridge_wrapper.h",
......
......@@ -5,11 +5,17 @@
#include "chrome/browser/chromeos/policy/system_proxy_manager.h"
#include "base/bind.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/ui/request_system_proxy_credentials_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/pref_names.h"
#include "chromeos/dbus/system_proxy/system_proxy_client.h"
#include "chromeos/network/network_event_log.h"
......@@ -27,6 +33,10 @@
#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/gfx/native_widget_types.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
namespace {
const char kSystemProxyService[] = "system-proxy-service";
......@@ -138,6 +148,7 @@ void SystemProxyManager::OnSystemProxySettingsPolicyChanged() {
weak_factory_.GetWeakPtr()));
system_services_address_.clear();
SetUserTrafficProxyPref(std::string());
CloseAuthenticationDialog();
return;
}
......@@ -207,6 +218,31 @@ bool SystemProxyManager::IsArcEnabled() const {
primary_profile_->GetPrefs()->GetBoolean(arc::prefs::kArcEnabled);
}
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 (!system_proxy_enabled_) {
return;
}
system_proxy::Credentials user_credentials;
user_credentials.set_username(username);
user_credentials.set_password(password);
system_proxy::SetAuthenticationDetailsRequest request;
request.set_traffic_type(system_proxy::TrafficOrigin::ALL);
*request.mutable_credentials() = user_credentials;
*request.mutable_protection_space() = protection_space;
chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
weak_factory_.GetWeakPtr()));
}
void SystemProxyManager::SendKerberosAuthenticationDetails() {
if (!system_proxy_enabled_) {
return;
......@@ -227,6 +263,13 @@ void SystemProxyManager::SendKerberosAuthenticationDetails() {
weak_factory_.GetWeakPtr()));
}
void SystemProxyManager::SendEmptyCredentials(
const system_proxy::ProtectionSpace& protection_space) {
SendUserAuthenticationCredentials(protection_space,
/*username=*/std::string(),
/*password=*/std::string());
}
void SystemProxyManager::SetSystemProxyEnabledForTest(bool enabled) {
system_proxy_enabled_ = enabled;
}
......@@ -293,8 +336,7 @@ void SystemProxyManager::OnAuthenticationRequired(
system_proxy::ProtectionSpace protection_space =
details.proxy_protection_space();
if (!primary_profile_) {
LookupProxyAuthCredentialsCallback(protection_space,
/* credentials = */ base::nullopt);
SendEmptyCredentials(protection_space);
return;
}
......@@ -307,8 +349,7 @@ void SystemProxyManager::OnAuthenticationRequired(
protection_space.origin(), net::ProxyServer::Scheme::SCHEME_HTTP);
if (!proxy_server.is_valid()) {
LookupProxyAuthCredentialsCallback(protection_space,
/* credentials = */ base::nullopt);
SendEmptyCredentials(protection_space);
return;
}
content::BrowserContext::GetDefaultStoragePartition(primary_profile_)
......@@ -335,20 +376,61 @@ void SystemProxyManager::LookupProxyAuthCredentialsCallback(
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 (active_auth_dialog_ &&
active_auth_dialog_->GetProxyServer() == protection_space.origin()) {
CloseAuthenticationDialog();
}
}
SendUserAuthenticationCredentials(protection_space, username, password);
}
system_proxy::Credentials user_credentials;
user_credentials.set_username(username);
user_credentials.set_password(password);
void SystemProxyManager::ShowAuthenticationDialog(
const system_proxy::ProtectionSpace& protection_space,
bool show_error_label) {
if (active_auth_dialog_)
return;
system_proxy::SetAuthenticationDetailsRequest request;
request.set_traffic_type(system_proxy::TrafficOrigin::ALL);
*request.mutable_credentials() = user_credentials;
*request.mutable_protection_space() = protection_space;
active_auth_dialog_ = new chromeos::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();
}
chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
weak_factory_.GetWeakPtr()));
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::CloseAuthenticationDialog() {
if (!auth_widget_)
return;
// Also deletes the |auth_widget_| instance.
auth_widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
}
} // namespace policy
......@@ -16,11 +16,19 @@
#include "chromeos/dbus/system_proxy/system_proxy_service.pb.h"
#include "net/base/auth.h"
namespace chromeos {
class RequestSystemProxyCredentialsView;
}
namespace system_proxy {
class SetAuthenticationDetailsResponse;
class ShutDownResponse;
} // namespace system_proxy
namespace views {
class Widget;
}
class PrefRegistrySimple;
class PrefService;
class PrefChangeRegistrar;
......@@ -77,7 +85,22 @@ class SystemProxyManager {
void SetUserTrafficProxyPref(const std::string& user_traffic_address);
bool IsArcEnabled() const;
// Sends the authentication details for |protection_space| to System-proxy via
// D-Bus.
void SendUserAuthenticationCredentials(
const system_proxy::ProtectionSpace& protection_space,
const std::string& username,
const std::string& password);
// Send the Kerberos enabled state and active principal name to System-proxy
// via D-Bus.
void SendKerberosAuthenticationDetails();
// Sends empty credentials for |protection_space| to System-proxy via D-Bus.
// This can mean that a user is not signed into Chrome OS or they didn't
// provide proxy authentication credentials. In this case, System-proxy will
// forward the authentication failure (HTTP 407 status code) to the Chrome OS
// client.
void SendEmptyCredentials(
const system_proxy::ProtectionSpace& protection_space);
// Once a trusted set of policies is established, this function calls
// the System-proxy dbus client to start/shutdown the daemon and, if
......@@ -100,6 +123,20 @@ class SystemProxyManager {
const system_proxy::ProtectionSpace& protection_space,
const base::Optional<net::AuthCredentials>& credentials);
// Shows a dialog which prompts the user to introduce proxy authentication
// credentials for OS level traffic. If |show_error_label| is true, the
// dialog will show a label that indicates the previous attempt to
// authenticate has failed due to invalid credentials.
void ShowAuthenticationDialog(
const system_proxy::ProtectionSpace& protection_space,
bool show_error_label);
void OnDialogAccepted(const system_proxy::ProtectionSpace& protection_space);
void OnDialogCanceled(const system_proxy::ProtectionSpace& protection_space);
void OnDialogClosed(const system_proxy::ProtectionSpace& protection_space);
// Closes the authentication dialog if shown.
void CloseAuthenticationDialog();
chromeos::CrosSettings* cros_settings_;
std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
system_proxy_subscription_;
......@@ -112,6 +149,11 @@ class SystemProxyManager {
// Local state prefs, not owned.
PrefService* local_state_ = nullptr;
// Owned by |auth_widget_|.
chromeos::RequestSystemProxyCredentialsView* active_auth_dialog_ = nullptr;
// Owned by the UI code (NativeWidget).
views::Widget* auth_widget_ = nullptr;
// Primary profile, not owned.
Profile* primary_profile_ = nullptr;
......
// Copyright 2020 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/chromeos/ui/request_system_proxy_credentials_view.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/i18n/number_formatting.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/ui/passphrase_textfield.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/grit/generated_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/widget/widget.h"
namespace chromeos {
RequestSystemProxyCredentialsView::RequestSystemProxyCredentialsView(
const std::string& proxy_server,
bool show_error_label,
base::OnceClosure view_destruction_callback)
: window_title_(
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_TITLE)),
proxy_server_(proxy_server),
show_error_label_(show_error_label),
view_destruction_callback_(std::move(view_destruction_callback)) {
Init();
}
RequestSystemProxyCredentialsView::~RequestSystemProxyCredentialsView() {
std::move(view_destruction_callback_).Run();
}
views::View* RequestSystemProxyCredentialsView::GetInitiallyFocusedView() {
return username_textfield_;
}
base::string16 RequestSystemProxyCredentialsView::GetWindowTitle() const {
return window_title_;
}
bool RequestSystemProxyCredentialsView::ShouldShowCloseButton() const {
return false;
}
const std::string& RequestSystemProxyCredentialsView::GetProxyServer() const {
return proxy_server_;
}
base::string16 RequestSystemProxyCredentialsView::GetUsername() const {
return username_textfield_->GetText();
}
base::string16 RequestSystemProxyCredentialsView::GetPassword() const {
return password_textfield_->GetText();
}
void RequestSystemProxyCredentialsView::Init() {
const views::LayoutProvider* provider = views::LayoutProvider::Get();
SetBorder(views::CreateEmptyBorder(
provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT)));
SetButtonLabel(
ui::DIALOG_BUTTON_OK,
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_OK_BUTTON));
views::GridLayout* layout =
SetLayoutManager(std::make_unique<views::GridLayout>());
int column_view_set_id = 0;
views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
100, views::GridLayout::ColumnSize::kUsePreferred, 0,
0);
layout->StartRow(0, column_view_set_id);
auto info_label = std::make_unique<views::Label>(l10n_util::GetStringFUTF16(
IDS_SYSTEM_PROXY_AUTH_DIALOG_TEXT, base::ASCIIToUTF16(GetProxyServer())));
info_label->SetEnabled(true);
info_label->SetTextStyle(views::style::STYLE_PRIMARY);
layout->AddView(std::move(info_label));
layout->StartRow(0, column_view_set_id);
auto info_label_privacy = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_PRIVACY_WARNING));
info_label_privacy->SetEnabled(true);
info_label_privacy->SetTextStyle(views::style::STYLE_SECONDARY);
layout->AddView(std::move(info_label_privacy));
column_view_set_id++;
column_set = layout->AddColumnSet(column_view_set_id);
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
const int label_padding =
provider->GetDistanceMetric(views::DISTANCE_RELATED_LABEL_HORIZONTAL);
column_set->AddPaddingColumn(0, label_padding);
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1.0,
views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
const int unrelated_vertical_spacing =
provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL);
layout->StartRowWithPadding(1.0, column_view_set_id, 0,
unrelated_vertical_spacing);
auto username_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_USERNAME_LABEL));
username_label->SetEnabled(true);
auto username_textfield = std::make_unique<views::Textfield>();
username_textfield->SetEnabled(true);
username_textfield->SetAssociatedLabel(
layout->AddView(std::move(username_label)));
username_textfield_ = layout->AddView(std::move(username_textfield));
const int related_vertical_spacing =
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
layout->StartRowWithPadding(1.0, column_view_set_id, 0,
related_vertical_spacing);
auto password_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_PASSWORD_LABEL));
password_label->SetEnabled(true);
auto password_textfield = std::make_unique<PassphraseTextfield>();
password_textfield->SetEnabled(true);
password_textfield->SetAssociatedLabel(
layout->AddView(std::move(password_label)));
password_textfield_ = layout->AddView(std::move(password_textfield));
column_view_set_id++;
column_set = layout->AddColumnSet(column_view_set_id);
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
column_set->AddPaddingColumn(0, label_padding);
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
1.0, views::GridLayout::ColumnSize::kUsePreferred, 0,
0);
layout->StartRowWithPadding(1.0, column_view_set_id, 0,
related_vertical_spacing);
auto error_icon = std::make_unique<views::ImageView>();
const int kIconSize = 18;
error_icon->SetImage(
gfx::CreateVectorIcon(vector_icons::kInfoOutlineIcon, kIconSize,
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_AlertSeverityHigh)));
error_icon->SetImageSize(gfx::Size(kIconSize, kIconSize));
error_icon->SetVisible(show_error_label_);
layout->AddView(std::move(error_icon));
auto error_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_SYSTEM_PROXY_AUTH_DIALOG_ERROR_LABEL));
error_label->SetEnabled(true);
error_label->SetVisible(show_error_label_);
error_label->SetEnabledColor(error_label->GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_AlertSeverityHigh));
error_label_ = layout->AddView(std::move(error_label));
}
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROME_BROWSER_CHROMEOS_UI_REQUEST_SYSTEM_PROXY_CREDENTIALS_VIEW_H_
#define CHROME_BROWSER_CHROMEOS_UI_REQUEST_SYSTEM_PROXY_CREDENTIALS_VIEW_H_
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/strings/string16.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/view.h"
#include "ui/views/window/dialog_delegate.h"
namespace views {
class Label;
class Textfield;
} // namespace views
namespace chromeos {
// A dialog box for requesting proxy authentication credentials for network
// traffic at OS level (outside the browser).
class RequestSystemProxyCredentialsView final
: public views::DialogDelegateView {
public:
RequestSystemProxyCredentialsView(
const std::string& proxy_server,
bool show_error_label,
base::OnceClosure view_destruction_callback);
RequestSystemProxyCredentialsView(const RequestSystemProxyCredentialsView&) =
delete;
RequestSystemProxyCredentialsView& operator=(
const RequestSystemProxyCredentialsView&) = delete;
~RequestSystemProxyCredentialsView() override;
// views::DialogDelegateView
views::View* GetInitiallyFocusedView() override;
base::string16 GetWindowTitle() const override;
bool ShouldShowCloseButton() const override;
// Returns the proxy server for which the dialog is asking for credentials,
// in the format scheme://host:port.
const std::string& GetProxyServer() const;
base::string16 GetUsername() const;
base::string16 GetPassword() const;
views::Textfield* username_textfield_for_testing() {
return username_textfield_;
}
views::Textfield* password_textfield_for_testing() {
return password_textfield_;
}
views::Label* error_label_for_testing() { return error_label_; }
private:
void Init();
const base::string16 window_title_;
views::Textfield* username_textfield_ = nullptr;
views::Textfield* password_textfield_ = nullptr;
views::Label* error_label_ = nullptr;
const std::string proxy_server_;
const bool show_error_label_;
base::OnceClosure view_destruction_callback_;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_UI_REQUEST_SYSTEM_PROXY_CREDENTIALS_VIEW_H_
// Copyright 2020 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/chromeos/ui/request_system_proxy_credentials_view.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
namespace {
constexpr char kProxy[] = "http://localserver";
constexpr char kUsername[] = "testuser";
constexpr char kPassword[] = "testpwd";
} // namespace
namespace chromeos {
class RequestSystemProxyCredentialsViewTest : public BrowserWithTestWindowTest {
public:
RequestSystemProxyCredentialsViewTest()
: BrowserWithTestWindowTest(Browser::TYPE_NORMAL) {}
RequestSystemProxyCredentialsViewTest(
const RequestSystemProxyCredentialsViewTest&) = delete;
RequestSystemProxyCredentialsViewTest& operator=(
const RequestSystemProxyCredentialsViewTest&) = delete;
~RequestSystemProxyCredentialsViewTest() override = default;
void TearDown() override {
active_widget_->CloseNow();
BrowserWithTestWindowTest::TearDown();
}
protected:
void CreateDialog(bool show_error) {
system_proxy_dialog_ = new chromeos::RequestSystemProxyCredentialsView(
kProxy, show_error, base::DoNothing());
system_proxy_dialog_->SetAcceptCallback(
base::BindRepeating(&RequestSystemProxyCredentialsViewTest::OnAccept,
base::Unretained(this)));
system_proxy_dialog_->SetCancelCallback(
base::BindRepeating(&RequestSystemProxyCredentialsViewTest::OnCancel,
base::Unretained(this)));
active_widget_ = views::DialogDelegate::CreateDialogWidget(
system_proxy_dialog_, GetContext(), /*parent=*/nullptr);
active_widget_->Show();
}
void OnAccept() { accepted_ = true; }
void OnCancel() { canceled_ = true; }
bool accepted_ = false;
bool canceled_ = false;
// Owned by |active_widget_|.
chromeos::RequestSystemProxyCredentialsView* system_proxy_dialog_ = nullptr;
private:
// Owned by the UI code (NativeWidget).
views::Widget* active_widget_ = nullptr;
};
// Tests that clicking "OK" in the UI will result in calling the
// |system_proxy_dialog_.accept_callback_| with the user entered
// credentials as arguments.
TEST_F(RequestSystemProxyCredentialsViewTest, AcceptCallback) {
CreateDialog(/*show_error=*/false);
system_proxy_dialog_->username_textfield_for_testing()->SetText(
base::ASCIIToUTF16(kUsername));
system_proxy_dialog_->password_textfield_for_testing()->SetText(
base::ASCIIToUTF16(kPassword));
// Simulate pressing the "OK" button.
system_proxy_dialog_->Accept();
EXPECT_TRUE(accepted_);
EXPECT_EQ(base::UTF16ToUTF8(system_proxy_dialog_->GetUsername()), kUsername);
EXPECT_EQ(base::UTF16ToUTF8(system_proxy_dialog_->GetPassword()), kPassword);
}
TEST_F(RequestSystemProxyCredentialsViewTest, CancelCallback) {
CreateDialog(/*show_error=*/false);
system_proxy_dialog_->Cancel();
EXPECT_TRUE(canceled_);
}
TEST_F(RequestSystemProxyCredentialsViewTest, GetProxyServer) {
CreateDialog(/*show_error=*/false);
EXPECT_EQ(system_proxy_dialog_->GetProxyServer(), kProxy);
}
TEST_F(RequestSystemProxyCredentialsViewTest, GetWindowTitle) {
CreateDialog(/*show_error=*/false);
EXPECT_EQ(system_proxy_dialog_->GetWindowTitle(),
base::ASCIIToUTF16("Sign in"));
}
TEST_F(RequestSystemProxyCredentialsViewTest, ErrorLabelHidden) {
CreateDialog(/*show_error=*/false);
EXPECT_FALSE(system_proxy_dialog_->error_label_for_testing()->GetVisible());
}
TEST_F(RequestSystemProxyCredentialsViewTest, ErrorLabelVisible) {
CreateDialog(/*show_error=*/true);
EXPECT_TRUE(system_proxy_dialog_->error_label_for_testing()->GetVisible());
}
} // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment