Commit 9592863c authored by Mohamed Amir Yosef's avatar Mohamed Amir Yosef Committed by Commit Bot

[Passwords] Introduce SaveConfirmationBubbleController

This CL is one of many refactoring CLs that would split the
ManagePasswordsBubbleModel into different controllers one per view.

Bug: 1044034
Change-Id: Id42888f911937e2eaf9241fd89c9257f042a48c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2016650Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734958}
parent a417e491
......@@ -1053,6 +1053,8 @@ jumbo_static_library("ui") {
"passwords/bubble_controllers/auto_sign_in_bubble_controller.h",
"passwords/bubble_controllers/password_bubble_controller_base.cc",
"passwords/bubble_controllers/password_bubble_controller_base.h",
"passwords/bubble_controllers/save_confirmation_bubble_controller.cc",
"passwords/bubble_controllers/save_confirmation_bubble_controller.h",
"passwords/credential_leak_dialog_controller.h",
"passwords/credential_leak_dialog_controller_impl.cc",
"passwords/credential_leak_dialog_controller_impl.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/ui/passwords/bubble_controllers/save_confirmation_bubble_controller.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
#include "ui/base/l10n/l10n_util.h"
namespace metrics_util = password_manager::metrics_util;
SaveConfirmationBubbleController::SaveConfirmationBubbleController(
base::WeakPtr<PasswordsModelDelegate> delegate,
ManagePasswordsBubbleModel::DisplayReason display_reason)
: PasswordBubbleControllerBase(
std::move(delegate),
/*display_disposition=*/display_reason ==
ManagePasswordsBubbleModel::AUTOMATIC
? metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION
: metrics_util::MANUAL_GENERATED_PASSWORD_CONFIRMATION),
dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION) {
base::string16 link = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK);
size_t offset = 0;
save_confirmation_text_ = l10n_util::GetStringFUTF16(
IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT, link, &offset);
save_confirmation_link_range_ = gfx::Range(offset, offset + link.length());
}
SaveConfirmationBubbleController::~SaveConfirmationBubbleController() {
if (!interaction_reported_)
OnBubbleClosing();
}
void SaveConfirmationBubbleController::
OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer referrer) {
dismissal_reason_ = metrics_util::CLICKED_PASSWORDS_DASHBOARD;
if (delegate_)
delegate_->NavigateToPasswordManagerAccountDashboard(referrer);
}
base::string16 SaveConfirmationBubbleController::GetTitle() const {
return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CONFIRM_SAVED_TITLE);
}
void SaveConfirmationBubbleController::ReportInteractions() {
metrics_util::LogGeneralUIDismissalReason(dismissal_reason_);
// Record UKM statistics on dismissal reason.
if (metrics_recorder_)
metrics_recorder_->RecordUIDismissalReason(dismissal_reason_);
}
// 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_UI_PASSWORDS_BUBBLE_CONTROLLERS_SAVE_CONFIRMATION_BUBBLE_CONTROLLER_H_
#define CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_SAVE_CONFIRMATION_BUBBLE_CONTROLLER_H_
#include "chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h"
#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
#include "components/password_manager/core/browser/manage_passwords_referrer.h"
#include "ui/gfx/range/range.h"
// This controller provides data and actions for the
// PasswordSaveConfirmationView.
class SaveConfirmationBubbleController : public PasswordBubbleControllerBase {
public:
SaveConfirmationBubbleController(
base::WeakPtr<PasswordsModelDelegate> delegate,
ManagePasswordsBubbleModel::DisplayReason display_reason);
~SaveConfirmationBubbleController() override;
// Called by the view code when the navigate to passwords.google.com link is
// clicked by the user.
void OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer referrer);
const base::string16& save_confirmation_text() const {
return save_confirmation_text_;
}
const gfx::Range& save_confirmation_link_range() const {
return save_confirmation_link_range_;
}
private:
// PasswordBubbleControllerBase methods:
base::string16 GetTitle() const override;
void ReportInteractions() override;
base::string16 save_confirmation_text_;
gfx::Range save_confirmation_link_range_;
// Dismissal reason for a password bubble.
password_manager::metrics_util::UIDismissalReason dismissal_reason_;
};
#endif // CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_SAVE_CONFIRMATION_BUBBLE_CONTROLLER_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/ui/passwords/bubble_controllers/save_confirmation_bubble_controller.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h"
#include "components/password_manager/core/browser/manage_passwords_referrer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::Return;
namespace {
constexpr char kUIDismissalReasonGeneralMetric[] =
"PasswordManager.UIDismissalReason";
} // namespace
class SaveConfirmationBubbleControllerTest : public ::testing::Test {
public:
SaveConfirmationBubbleControllerTest() {
mock_delegate_ =
std::make_unique<testing::NiceMock<PasswordsModelDelegateMock>>();
ON_CALL(*mock_delegate_, GetPasswordFormMetricsRecorder())
.WillByDefault(Return(nullptr));
}
~SaveConfirmationBubbleControllerTest() override = default;
PasswordsModelDelegateMock* delegate() { return mock_delegate_.get(); }
SaveConfirmationBubbleController* controller() { return controller_.get(); }
void Init();
void DestroyController();
private:
std::unique_ptr<PasswordsModelDelegateMock> mock_delegate_;
std::unique_ptr<SaveConfirmationBubbleController> controller_;
};
void SaveConfirmationBubbleControllerTest::Init() {
EXPECT_CALL(*delegate(), OnBubbleShown());
controller_.reset(new SaveConfirmationBubbleController(
mock_delegate_->AsWeakPtr(), ManagePasswordsBubbleModel::AUTOMATIC));
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(delegate()));
}
void SaveConfirmationBubbleControllerTest::DestroyController() {
controller_.reset();
}
TEST_F(SaveConfirmationBubbleControllerTest,
NavigateToDashboardWithBubbleClosing) {
Init();
controller()->OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
base::HistogramTester histogram_tester;
EXPECT_CALL(*delegate(), OnBubbleHidden());
controller()->OnBubbleClosing();
DestroyController();
histogram_tester.ExpectUniqueSample(
kUIDismissalReasonGeneralMetric,
password_manager::metrics_util::CLICKED_PASSWORDS_DASHBOARD, 1);
}
TEST_F(SaveConfirmationBubbleControllerTest,
NavigateToDashboardWithoutBubbleClosing) {
Init();
controller()->OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
base::HistogramTester histogram_tester;
EXPECT_CALL(*delegate(), OnBubbleHidden());
DestroyController();
histogram_tester.ExpectUniqueSample(
kUIDismissalReasonGeneralMetric,
password_manager::metrics_util::CLICKED_PASSWORDS_DASHBOARD, 1);
}
......@@ -212,23 +212,11 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
kCredentialManagementAPI;
UpdatePendingStateTitle();
} else if (state_ == password_manager::ui::CONFIRMATION_STATE) {
title_ =
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CONFIRM_SAVED_TITLE);
} else if (state_ == password_manager::ui::MANAGE_STATE) {
local_credentials_ = DeepCopyForms(delegate_->GetCurrentForms());
UpdateManageStateTitle();
}
if (state_ == password_manager::ui::CONFIRMATION_STATE) {
base::string16 link = l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK);
size_t offset;
save_confirmation_text_ = l10n_util::GetStringFUTF16(
IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT, link, &offset);
save_confirmation_link_range_ = gfx::Range(offset, offset + link.length());
}
password_manager::metrics_util::UIDisplayDisposition display_disposition =
metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING;
if (display_reason == USER_ACTION) {
......@@ -243,9 +231,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
display_disposition = metrics_util::MANUAL_MANAGE_PASSWORDS;
break;
case password_manager::ui::CONFIRMATION_STATE:
display_disposition =
metrics_util::MANUAL_GENERATED_PASSWORD_CONFIRMATION;
break;
case password_manager::ui::CREDENTIAL_REQUEST_STATE:
case password_manager::ui::AUTO_SIGNIN_STATE:
case password_manager::ui::CHROME_SIGN_IN_PROMO_STATE:
......@@ -263,9 +248,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE;
break;
case password_manager::ui::CONFIRMATION_STATE:
display_disposition =
metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION;
break;
case password_manager::ui::AUTO_SIGNIN_STATE:
case password_manager::ui::MANAGE_STATE:
case password_manager::ui::CREDENTIAL_REQUEST_STATE:
......@@ -343,15 +325,6 @@ void ManagePasswordsBubbleModel::OnManageClicked(
delegate_->NavigateToPasswordManagerSettingsPage(referrer);
}
void ManagePasswordsBubbleModel::
OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer referrer) {
interaction_keeper_->set_dismissal_reason(
metrics_util::CLICKED_PASSWORDS_DASHBOARD);
if (delegate_)
delegate_->NavigateToPasswordManagerAccountDashboard(referrer);
}
void ManagePasswordsBubbleModel::OnPasswordAction(
const autofill::PasswordForm& password_form,
PasswordAction action) {
......
......@@ -16,7 +16,6 @@
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/statistics_table.h"
#include "components/password_manager/core/common/password_manager_ui.h"
#include "ui/gfx/range/range.h"
namespace content {
class WebContents;
......@@ -67,11 +66,6 @@ class ManagePasswordsBubbleModel {
// Called by the view code when the manage button is clicked by the user.
void OnManageClicked(password_manager::ManagePasswordsReferrer referrer);
// Called by the view code when the navigate to passwords.google.com link is
// clicked by the user.
void OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer referrer);
// Called by the view code to delete or add a password form to the
// PasswordStore.
void OnPasswordAction(const autofill::PasswordForm& password_form,
......@@ -97,12 +91,6 @@ class ManagePasswordsBubbleModel {
const std::vector<autofill::PasswordForm>& local_credentials() const {
return local_credentials_;
}
const base::string16& save_confirmation_text() const {
return save_confirmation_text_;
}
const gfx::Range& save_confirmation_link_range() const {
return save_confirmation_link_range_;
}
bool are_passwords_revealed_when_bubble_is_opened() const {
return are_passwords_revealed_when_bubble_is_opened_;
......@@ -167,8 +155,6 @@ class ManagePasswordsBubbleModel {
base::string16 title_;
autofill::PasswordForm pending_password_;
std::vector<autofill::PasswordForm> local_credentials_;
base::string16 save_confirmation_text_;
gfx::Range save_confirmation_link_range_;
// Responsible for recording all the interactions required.
std::unique_ptr<InteractionKeeper> interaction_keeper_;
......
......@@ -38,9 +38,9 @@
using net::test_server::BasicHttpResponse;
using net::test_server::HttpRequest;
using net::test_server::HttpResponse;
using testing::_;
using testing::Eq;
using testing::Field;
using testing::_;
namespace {
......
......@@ -129,7 +129,8 @@ PasswordBubbleViewBase::PasswordBubbleViewBase(
PasswordsModelDelegateFromWebContents(web_contents);
// Create the model only for the states that hasn't been migrated to using the
// bubble controllers.
if (delegate->GetState() != password_manager::ui::AUTO_SIGNIN_STATE) {
if (delegate->GetState() != password_manager::ui::AUTO_SIGNIN_STATE &&
delegate->GetState() != password_manager::ui::CONFIRMATION_STATE) {
model_ = std::make_unique<ManagePasswordsBubbleModel>(
delegate, reason == AUTOMATIC
? ManagePasswordsBubbleModel::AUTOMATIC
......
......@@ -6,6 +6,7 @@
#include <memory>
#include "chrome/browser/ui/passwords/passwords_model_delegate.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "chrome/grit/generated_resources.h"
......@@ -22,18 +23,22 @@ PasswordSaveConfirmationView::PasswordSaveConfirmationView(
: PasswordBubbleViewBase(web_contents,
anchor_view,
reason,
/*auto_dismissable=*/false) {
/*auto_dismissable=*/false),
controller_(PasswordsModelDelegateFromWebContents(web_contents),
reason == AUTOMATIC
? ManagePasswordsBubbleModel::AUTOMATIC
: ManagePasswordsBubbleModel::USER_ACTION) {
SetLayoutManager(std::make_unique<views::FillLayout>());
DialogDelegate::set_buttons(ui::DIALOG_BUTTON_NONE);
auto label = std::make_unique<views::StyledLabel>(
model()->save_confirmation_text(), this);
controller_.save_confirmation_text(), this);
label->SetTextContext(CONTEXT_BODY_TEXT_LARGE);
label->SetDefaultTextStyle(views::style::STYLE_SECONDARY);
auto link_style = views::StyledLabel::RangeStyleInfo::CreateForLink();
link_style.disable_line_wrapping = false;
label->AddStyleRange(model()->save_confirmation_link_range(), link_style);
label->AddStyleRange(controller_.save_confirmation_link_range(), link_style);
AddChildView(label.release());
}
......@@ -41,12 +46,12 @@ PasswordSaveConfirmationView::PasswordSaveConfirmationView(
PasswordSaveConfirmationView::~PasswordSaveConfirmationView() = default;
PasswordBubbleControllerBase* PasswordSaveConfirmationView::GetController() {
return nullptr;
return &controller_;
}
const PasswordBubbleControllerBase*
PasswordSaveConfirmationView::GetController() const {
return nullptr;
return &controller_;
}
bool PasswordSaveConfirmationView::ShouldShowCloseButton() const {
......@@ -57,8 +62,8 @@ void PasswordSaveConfirmationView::StyledLabelLinkClicked(
views::StyledLabel* label,
const gfx::Range& range,
int event_flags) {
DCHECK_EQ(range, model()->save_confirmation_link_range());
model()->OnNavigateToPasswordManagerAccountDashboardLinkClicked(
DCHECK_EQ(range, controller_.save_confirmation_link_range());
controller_.OnNavigateToPasswordManagerAccountDashboardLinkClicked(
password_manager::ManagePasswordsReferrer::
kPasswordGenerationConfirmation);
CloseBubble();
......
......@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_VIEWS_PASSWORDS_PASSWORD_SAVE_CONFIRMATION_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_PASSWORDS_PASSWORD_SAVE_CONFIRMATION_VIEW_H_
#include "chrome/browser/ui/passwords/bubble_controllers/save_confirmation_bubble_controller.h"
#include "chrome/browser/ui/views/passwords/password_bubble_view_base.h"
#include "ui/views/controls/styled_label_listener.h"
#include "ui/views/view.h"
......@@ -33,6 +34,8 @@ class PasswordSaveConfirmationView : public PasswordBubbleViewBase,
bool ShouldShowCloseButton() const override;
gfx::Size CalculatePreferredSize() const override;
SaveConfirmationBubbleController controller_;
DISALLOW_COPY_AND_ASSIGN(PasswordSaveConfirmationView);
};
......
......@@ -4032,6 +4032,7 @@ test("unit_tests") {
"../browser/ui/omnibox/clipboard_utils_unittest.cc",
"../browser/ui/page_info/permission_menu_model_unittest.cc",
"../browser/ui/passwords/bubble_controllers/auto_sign_in_bubble_controller_unittest.cc",
"../browser/ui/passwords/bubble_controllers/save_confirmation_bubble_controller_unittest.cc",
"../browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc",
"../browser/ui/passwords/credential_manager_dialog_controller_impl_unittest.cc",
"../browser/ui/passwords/manage_passwords_bubble_model_unittest.cc",
......
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