Commit ddcd0fc0 authored by Mohamed Amir Yosef's avatar Mohamed Amir Yosef Committed by Commit Bot

[Passwords] Introduce ItemsBubbleController

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

Bug: 1044034
Change-Id: Ic4ee0a4bbf79c4a28f2434ebd8dacb1733bc690e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2019265Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735397}
parent 6bd2b7db
...@@ -1056,6 +1056,8 @@ jumbo_static_library("ui") { ...@@ -1056,6 +1056,8 @@ jumbo_static_library("ui") {
"passwords/bubble_controllers/auto_sign_in_bubble_controller.h", "passwords/bubble_controllers/auto_sign_in_bubble_controller.h",
"passwords/bubble_controllers/generation_confirmation_bubble_controller.cc", "passwords/bubble_controllers/generation_confirmation_bubble_controller.cc",
"passwords/bubble_controllers/generation_confirmation_bubble_controller.h", "passwords/bubble_controllers/generation_confirmation_bubble_controller.h",
"passwords/bubble_controllers/items_bubble_controller.cc",
"passwords/bubble_controllers/items_bubble_controller.h",
"passwords/bubble_controllers/password_bubble_controller_base.cc", "passwords/bubble_controllers/password_bubble_controller_base.cc",
"passwords/bubble_controllers/password_bubble_controller_base.h", "passwords/bubble_controllers/password_bubble_controller_base.h",
"passwords/credential_leak_dialog_controller.h", "passwords/credential_leak_dialog_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/items_bubble_controller.h"
#include "chrome/browser/password_manager/password_store_utils.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.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 "components/password_manager/core/browser/password_store.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
namespace metrics_util = password_manager::metrics_util;
namespace {
std::vector<autofill::PasswordForm> DeepCopyForms(
const std::vector<std::unique_ptr<autofill::PasswordForm>>& forms) {
std::vector<autofill::PasswordForm> result;
result.reserve(forms.size());
std::transform(forms.begin(), forms.end(), std::back_inserter(result),
[](const std::unique_ptr<autofill::PasswordForm>& form) {
return *form;
});
return result;
}
} // namespace
ItemsBubbleController::ItemsBubbleController(
base::WeakPtr<PasswordsModelDelegate> delegate)
: PasswordBubbleControllerBase(
std::move(delegate),
/*display_disposition=*/metrics_util::MANUAL_MANAGE_PASSWORDS),
dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION) {
local_credentials_ = DeepCopyForms(delegate_->GetCurrentForms());
GetManagePasswordsDialogTitleText(GetWebContents()->GetVisibleURL(),
delegate_->GetOrigin(),
!local_credentials_.empty(), &title_);
}
ItemsBubbleController::~ItemsBubbleController() {
if (!interaction_reported_)
OnBubbleClosing();
}
void ItemsBubbleController::OnManageClicked(
password_manager::ManagePasswordsReferrer referrer) {
dismissal_reason_ = metrics_util::CLICKED_MANAGE;
if (delegate_)
delegate_->NavigateToPasswordManagerSettingsPage(referrer);
}
void ItemsBubbleController::OnPasswordAction(
const autofill::PasswordForm& password_form,
ManagePasswordsBubbleModel::PasswordAction action) {
Profile* profile = GetProfile();
if (!profile)
return;
password_manager::PasswordStore* password_store =
GetPasswordStore(profile, password_form.IsUsingAccountStore()).get();
DCHECK(password_store);
if (action == ManagePasswordsBubbleModel::REMOVE_PASSWORD)
password_store->RemoveLogin(password_form);
else
password_store->AddLogin(password_form);
}
void ItemsBubbleController::ReportInteractions() {
metrics_util::LogGeneralUIDismissalReason(dismissal_reason_);
// Record UKM statistics on dismissal reason.
if (metrics_recorder_)
metrics_recorder_->RecordUIDismissalReason(dismissal_reason_);
}
base::string16 ItemsBubbleController::GetTitle() const {
return title_;
}
// 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_ITEMS_BUBBLE_CONTROLLER_H_
#define CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_ITEMS_BUBBLE_CONTROLLER_H_
#include "chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
#include "components/password_manager/core/browser/manage_passwords_referrer.h"
class PasswordsModelDelegate;
// This controller provides data and actions for the PasswordItemsView.
class ItemsBubbleController : public PasswordBubbleControllerBase {
public:
explicit ItemsBubbleController(
base::WeakPtr<PasswordsModelDelegate> delegate);
~ItemsBubbleController() override;
// 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 to delete or add a password form to the
// PasswordStore.
void OnPasswordAction(const autofill::PasswordForm& password_form,
ManagePasswordsBubbleModel::PasswordAction action);
// Returns the available credentials which match the current site.
const std::vector<autofill::PasswordForm>& local_credentials() const {
return local_credentials_;
}
private:
// PasswordBubbleControllerBase methods:
base::string16 GetTitle() const override;
void ReportInteractions() override;
std::vector<autofill::PasswordForm> local_credentials_;
base::string16 title_;
// Dismissal reason for a password bubble.
password_manager::metrics_util::UIDismissalReason dismissal_reason_;
};
#endif // CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_ITEMS_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/items_bubble_controller.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h"
#include "chrome/test/base/testing_profile.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::Return;
using ::testing::ReturnRef;
namespace {
constexpr char kUIDismissalReasonGeneralMetric[] =
"PasswordManager.UIDismissalReason";
constexpr char kSiteOrigin[] = "http://example.com/login/";
} // namespace
class ItemsBubbleControllerTest : public ::testing::Test {
public:
ItemsBubbleControllerTest() {
test_web_contents_ =
content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
mock_delegate_ =
std::make_unique<testing::NiceMock<PasswordsModelDelegateMock>>();
ON_CALL(*mock_delegate_, GetPasswordFormMetricsRecorder())
.WillByDefault(Return(nullptr));
PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
profile(),
base::BindRepeating(
&password_manager::BuildPasswordStore<
content::BrowserContext,
testing::StrictMock<password_manager::MockPasswordStore>>));
}
~ItemsBubbleControllerTest() override = default;
static std::vector<std::unique_ptr<autofill::PasswordForm>> GetCurrentForms();
PasswordsModelDelegateMock* delegate() { return mock_delegate_.get(); }
ItemsBubbleController* controller() { return controller_.get(); }
TestingProfile* profile() { return &profile_; }
password_manager::MockPasswordStore* GetStore() {
return static_cast<password_manager::MockPasswordStore*>(
PasswordStoreFactory::GetInstance()
->GetForProfile(profile(), ServiceAccessType::EXPLICIT_ACCESS)
.get());
}
void Init();
void DestroyController();
private:
content::BrowserTaskEnvironment task_environment_;
content::RenderViewHostTestEnabler rvh_enabler_;
TestingProfile profile_;
std::unique_ptr<content::WebContents> test_web_contents_;
std::unique_ptr<PasswordsModelDelegateMock> mock_delegate_;
std::unique_ptr<ItemsBubbleController> controller_;
};
void ItemsBubbleControllerTest::Init() {
std::vector<std::unique_ptr<autofill::PasswordForm>> forms =
GetCurrentForms();
EXPECT_CALL(*delegate(), GetCurrentForms()).WillOnce(ReturnRef(forms));
GURL origin(kSiteOrigin);
EXPECT_CALL(*delegate(), GetOrigin()).WillOnce(ReturnRef(origin));
EXPECT_CALL(*delegate(), GetWebContents())
.WillRepeatedly(Return(test_web_contents_.get()));
EXPECT_CALL(*delegate(), OnBubbleShown());
controller_.reset(new ItemsBubbleController(mock_delegate_->AsWeakPtr()));
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(delegate()));
EXPECT_CALL(*delegate(), GetWebContents())
.WillRepeatedly(Return(test_web_contents_.get()));
}
void ItemsBubbleControllerTest::DestroyController() {
controller_.reset();
}
// static
std::vector<std::unique_ptr<autofill::PasswordForm>>
ItemsBubbleControllerTest::GetCurrentForms() {
autofill::PasswordForm form1;
form1.origin = GURL(kSiteOrigin);
form1.signon_realm = kSiteOrigin;
form1.username_value = base::ASCIIToUTF16("User1");
form1.password_value = base::ASCIIToUTF16("123456");
autofill::PasswordForm form2;
form2.origin = GURL(kSiteOrigin);
form2.signon_realm = kSiteOrigin;
form2.username_value = base::ASCIIToUTF16("User2");
form2.password_value = base::ASCIIToUTF16("654321");
std::vector<std::unique_ptr<autofill::PasswordForm>> forms;
forms.push_back(std::make_unique<autofill::PasswordForm>(form1));
forms.push_back(std::make_unique<autofill::PasswordForm>(form2));
return forms;
}
TEST_F(ItemsBubbleControllerTest, OnManageClicked) {
Init();
EXPECT_CALL(
*delegate(),
NavigateToPasswordManagerSettingsPage(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble));
controller()->OnManageClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
base::HistogramTester histogram_tester;
DestroyController();
histogram_tester.ExpectUniqueSample(
kUIDismissalReasonGeneralMetric,
password_manager::metrics_util::CLICKED_MANAGE, 1);
}
TEST_F(ItemsBubbleControllerTest, OnPasswordActionAddPassword) {
Init();
autofill::PasswordForm form;
form.origin = GURL(kSiteOrigin);
form.signon_realm = kSiteOrigin;
form.username_value = base::ASCIIToUTF16("User");
form.password_value = base::ASCIIToUTF16("123456");
EXPECT_CALL(*GetStore(), AddLogin(form));
controller()->OnPasswordAction(form,
ManagePasswordsBubbleModel::ADD_PASSWORD);
}
TEST_F(ItemsBubbleControllerTest, OnPasswordActionRemovePassword) {
Init();
autofill::PasswordForm form;
form.origin = GURL(kSiteOrigin);
form.signon_realm = kSiteOrigin;
form.username_value = base::ASCIIToUTF16("User");
form.password_value = base::ASCIIToUTF16("123456");
EXPECT_CALL(*GetStore(), RemoveLogin(form));
controller()->OnPasswordAction(form,
ManagePasswordsBubbleModel::REMOVE_PASSWORD);
}
TEST_F(ItemsBubbleControllerTest, ShouldReturnLocalCredentials) {
Init();
std::vector<autofill::PasswordForm> local_credentials =
controller()->local_credentials();
std::vector<std::unique_ptr<autofill::PasswordForm>>
expected_local_credentials = ItemsBubbleControllerTest::GetCurrentForms();
EXPECT_EQ(local_credentials.size(), expected_local_credentials.size());
for (size_t i = 0; i < local_credentials.size(); i++) {
EXPECT_EQ(local_credentials[i], *expected_local_credentials[i]);
}
}
...@@ -212,9 +212,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( ...@@ -212,9 +212,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
kCredentialManagementAPI; kCredentialManagementAPI;
UpdatePendingStateTitle(); UpdatePendingStateTitle();
} else if (state_ == password_manager::ui::MANAGE_STATE) {
local_credentials_ = DeepCopyForms(delegate_->GetCurrentForms());
UpdateManageStateTitle();
} }
password_manager::metrics_util::UIDisplayDisposition display_disposition = password_manager::metrics_util::UIDisplayDisposition display_disposition =
...@@ -228,8 +225,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( ...@@ -228,8 +225,6 @@ ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
display_disposition = metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE; display_disposition = metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE;
break; break;
case password_manager::ui::MANAGE_STATE: case password_manager::ui::MANAGE_STATE:
display_disposition = metrics_util::MANUAL_MANAGE_PASSWORDS;
break;
case password_manager::ui::CONFIRMATION_STATE: case password_manager::ui::CONFIRMATION_STATE:
case password_manager::ui::CREDENTIAL_REQUEST_STATE: case password_manager::ui::CREDENTIAL_REQUEST_STATE:
case password_manager::ui::AUTO_SIGNIN_STATE: case password_manager::ui::AUTO_SIGNIN_STATE:
...@@ -318,29 +313,6 @@ void ManagePasswordsBubbleModel::OnSaveClicked() { ...@@ -318,29 +313,6 @@ void ManagePasswordsBubbleModel::OnSaveClicked() {
} }
} }
void ManagePasswordsBubbleModel::OnManageClicked(
password_manager::ManagePasswordsReferrer referrer) {
interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_MANAGE);
if (delegate_)
delegate_->NavigateToPasswordManagerSettingsPage(referrer);
}
void ManagePasswordsBubbleModel::OnPasswordAction(
const autofill::PasswordForm& password_form,
PasswordAction action) {
Profile* profile = GetProfile();
if (!profile)
return;
password_manager::PasswordStore* password_store =
GetPasswordStore(profile, password_form.IsUsingAccountStore()).get();
DCHECK(password_store);
if (action == REMOVE_PASSWORD)
password_store->RemoveLogin(password_form);
else
password_store->AddLogin(password_form);
}
void ManagePasswordsBubbleModel::OnSignInToChromeClicked( void ManagePasswordsBubbleModel::OnSignInToChromeClicked(
const AccountInfo& account, const AccountInfo& account,
bool is_default_promo_account) { bool is_default_promo_account) {
...@@ -457,8 +429,3 @@ void ManagePasswordsBubbleModel::UpdatePendingStateTitle() { ...@@ -457,8 +429,3 @@ void ManagePasswordsBubbleModel::UpdatePendingStateTitle() {
GetSavePasswordDialogTitleTextAndLinkRange(GetWebContents()->GetVisibleURL(), GetSavePasswordDialogTitleTextAndLinkRange(GetWebContents()->GetVisibleURL(),
origin_, type, &title_); origin_, type, &title_);
} }
void ManagePasswordsBubbleModel::UpdateManageStateTitle() {
GetManagePasswordsDialogTitleText(GetWebContents()->GetVisibleURL(), origin_,
!local_credentials_.empty(), &title_);
}
...@@ -63,14 +63,6 @@ class ManagePasswordsBubbleModel { ...@@ -63,14 +63,6 @@ class ManagePasswordsBubbleModel {
// Called by the view code when the save/update button is clicked by the user. // Called by the view code when the save/update button is clicked by the user.
void OnSaveClicked(); void OnSaveClicked();
// 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 to delete or add a password form to the
// PasswordStore.
void OnPasswordAction(const autofill::PasswordForm& password_form,
PasswordAction action);
// Called by the view when the "Sign in" button or the "Sync to" button in the // Called by the view when the "Sign in" button or the "Sync to" button in the
// promo bubble is clicked. // promo bubble is clicked.
void OnSignInToChromeClicked(const AccountInfo& account, void OnSignInToChromeClicked(const AccountInfo& account,
...@@ -87,10 +79,6 @@ class ManagePasswordsBubbleModel { ...@@ -87,10 +79,6 @@ class ManagePasswordsBubbleModel {
const autofill::PasswordForm& pending_password() const { const autofill::PasswordForm& pending_password() const {
return pending_password_; return pending_password_;
} }
// Returns the available credentials which match the current site.
const std::vector<autofill::PasswordForm>& local_credentials() const {
return local_credentials_;
}
bool are_passwords_revealed_when_bubble_is_opened() const { bool are_passwords_revealed_when_bubble_is_opened() const {
return are_passwords_revealed_when_bubble_is_opened_; return are_passwords_revealed_when_bubble_is_opened_;
...@@ -146,8 +134,6 @@ class ManagePasswordsBubbleModel { ...@@ -146,8 +134,6 @@ class ManagePasswordsBubbleModel {
class InteractionKeeper; class InteractionKeeper;
// Updates |title_| for the PENDING_PASSWORD_STATE. // Updates |title_| for the PENDING_PASSWORD_STATE.
void UpdatePendingStateTitle(); void UpdatePendingStateTitle();
// Updates |title_| for the MANAGE_STATE.
void UpdateManageStateTitle();
// URL of the page from where this bubble was triggered. // URL of the page from where this bubble was triggered.
GURL origin_; GURL origin_;
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "base/test/simple_test_clock.h" #include "base/test/simple_test_clock.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h" #include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "components/password_manager/core/browser/mock_password_store.h" #include "components/password_manager/core/browser/mock_password_store.h"
...@@ -30,7 +29,6 @@ ...@@ -30,7 +29,6 @@
#include "components/password_manager/core/common/password_manager_ui.h" #include "components/password_manager/core/common/password_manager_ui.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/account_info.h"
#include "components/sync/driver/test_sync_service.h"
#include "components/ukm/test_ukm_recorder.h" #include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h" #include "content/public/test/browser_task_environment.h"
...@@ -62,13 +60,6 @@ constexpr char kUIDismissalReasonSaveMetric[] = ...@@ -62,13 +60,6 @@ constexpr char kUIDismissalReasonSaveMetric[] =
constexpr char kUIDismissalReasonUpdateMetric[] = constexpr char kUIDismissalReasonUpdateMetric[] =
"PasswordManager.UpdateUIDismissalReason"; "PasswordManager.UpdateUIDismissalReason";
enum class SyncedTypes { ALL, NONE };
std::unique_ptr<KeyedService> TestingSyncFactoryFunction(
content::BrowserContext* context) {
return std::make_unique<syncer::TestSyncService>();
}
MATCHER_P(AccountEq, expected, "") { MATCHER_P(AccountEq, expected, "") {
return expected.account_id == arg.account_id && expected.email == arg.email && return expected.account_id == arg.account_id && expected.email == arg.email &&
expected.gaia == arg.gaia; expected.gaia == arg.gaia;
...@@ -131,7 +122,6 @@ class ManagePasswordsBubbleModelTest : public ::testing::Test { ...@@ -131,7 +122,6 @@ class ManagePasswordsBubbleModelTest : public ::testing::Test {
void PretendPasswordWaiting(ManagePasswordsBubbleModel::DisplayReason reason = void PretendPasswordWaiting(ManagePasswordsBubbleModel::DisplayReason reason =
ManagePasswordsBubbleModel::AUTOMATIC); ManagePasswordsBubbleModel::AUTOMATIC);
void PretendUpdatePasswordWaiting(); void PretendUpdatePasswordWaiting();
void PretendManagingPasswords();
void DestroyModelAndVerifyControllerExpectations(); void DestroyModelAndVerifyControllerExpectations();
void DestroyModelExpectReason( void DestroyModelExpectReason(
...@@ -193,14 +183,6 @@ void ManagePasswordsBubbleModelTest::PretendUpdatePasswordWaiting() { ...@@ -193,14 +183,6 @@ void ManagePasswordsBubbleModelTest::PretendUpdatePasswordWaiting() {
ManagePasswordsBubbleModel::AUTOMATIC); ManagePasswordsBubbleModel::AUTOMATIC);
} }
void ManagePasswordsBubbleModelTest::PretendManagingPasswords() {
std::vector<std::unique_ptr<autofill::PasswordForm>> forms =
GetCurrentForms();
EXPECT_CALL(*controller(), GetCurrentForms()).WillOnce(ReturnRef(forms));
SetUpWithState(password_manager::ui::MANAGE_STATE,
ManagePasswordsBubbleModel::USER_ACTION);
}
void ManagePasswordsBubbleModelTest:: void ManagePasswordsBubbleModelTest::
DestroyModelAndVerifyControllerExpectations() { DestroyModelAndVerifyControllerExpectations() {
EXPECT_CALL(*controller(), OnBubbleHidden()); EXPECT_CALL(*controller(), OnBubbleHidden());
...@@ -312,20 +294,6 @@ TEST_F(ManagePasswordsBubbleModelTest, ClickNever) { ...@@ -312,20 +294,6 @@ TEST_F(ManagePasswordsBubbleModelTest, ClickNever) {
DestroyModelExpectReason(password_manager::metrics_util::CLICKED_NEVER); DestroyModelExpectReason(password_manager::metrics_util::CLICKED_NEVER);
} }
TEST_F(ManagePasswordsBubbleModelTest, ClickManage) {
PretendManagingPasswords();
EXPECT_CALL(
*controller(),
NavigateToPasswordManagerSettingsPage(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble));
model()->OnManageClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
EXPECT_EQ(password_manager::ui::MANAGE_STATE, model()->state());
DestroyModelExpectReason(password_manager::metrics_util::CLICKED_MANAGE);
}
TEST_F(ManagePasswordsBubbleModelTest, ClickUpdate) { TEST_F(ManagePasswordsBubbleModelTest, ClickUpdate) {
PretendUpdatePasswordWaiting(); PretendUpdatePasswordWaiting();
...@@ -460,37 +428,6 @@ TEST_F(ManagePasswordsBubbleModelTest, SignInPromoDismiss) { ...@@ -460,37 +428,6 @@ TEST_F(ManagePasswordsBubbleModelTest, SignInPromoDismiss) {
} }
#endif // !defined(OS_CHROMEOS) #endif // !defined(OS_CHROMEOS)
class ManagePasswordsBubbleModelManageLinkTest
: public ManagePasswordsBubbleModelTest,
public ::testing::WithParamInterface<SyncedTypes> {};
TEST_P(ManagePasswordsBubbleModelManageLinkTest, OnManageClicked) {
syncer::TestSyncService* sync_service = static_cast<syncer::TestSyncService*>(
ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile(), base::BindRepeating(&TestingSyncFactoryFunction)));
syncer::ModelTypeSet types;
if (GetParam() == SyncedTypes::ALL) {
types = syncer::ModelTypeSet::All();
}
sync_service->SetPreferredDataTypes(types);
sync_service->SetActiveDataTypes(types);
PretendManagingPasswords();
EXPECT_CALL(
*controller(),
NavigateToPasswordManagerSettingsPage(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble));
model()->OnManageClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
}
INSTANTIATE_TEST_SUITE_P(Default,
ManagePasswordsBubbleModelManageLinkTest,
::testing::Values(SyncedTypes::ALL,
SyncedTypes::NONE));
// Verify that URL keyed metrics are properly recorded. // Verify that URL keyed metrics are properly recorded.
TEST_F(ManagePasswordsBubbleModelTest, RecordUKMs) { TEST_F(ManagePasswordsBubbleModelTest, RecordUKMs) {
using BubbleDismissalReason = using BubbleDismissalReason =
......
...@@ -131,7 +131,8 @@ PasswordBubbleViewBase::PasswordBubbleViewBase( ...@@ -131,7 +131,8 @@ PasswordBubbleViewBase::PasswordBubbleViewBase(
// Create the model only for the states that hasn't been migrated to using the // Create the model only for the states that hasn't been migrated to using the
// bubble controllers. // 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) { delegate->GetState() != password_manager::ui::CONFIRMATION_STATE &&
delegate->GetState() != password_manager::ui::MANAGE_STATE) {
model_ = std::make_unique<ManagePasswordsBubbleModel>( model_ = std::make_unique<ManagePasswordsBubbleModel>(
delegate, reason == AUTOMATIC delegate, reason == AUTOMATIC
? ManagePasswordsBubbleModel::AUTOMATIC ? ManagePasswordsBubbleModel::AUTOMATIC
......
...@@ -10,8 +10,10 @@ ...@@ -10,8 +10,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/passwords/bubble_controllers/items_bubble_controller.h"
#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
#include "chrome/browser/ui/passwords/passwords_model_delegate.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/chrome_typography.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
...@@ -245,16 +247,16 @@ PasswordItemsView::PasswordItemsView(content::WebContents* web_contents, ...@@ -245,16 +247,16 @@ PasswordItemsView::PasswordItemsView(content::WebContents* web_contents,
: PasswordBubbleViewBase(web_contents, : PasswordBubbleViewBase(web_contents,
anchor_view, anchor_view,
reason, reason,
/*easily_dismissable=*/true) { /*easily_dismissable=*/true),
controller_(PasswordsModelDelegateFromWebContents(web_contents)) {
DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK); DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK);
DialogDelegate::SetExtraView(CreateManageButton(this)); DialogDelegate::SetExtraView(CreateManageButton(this));
DCHECK_EQ(password_manager::ui::MANAGE_STATE, model()->state());
if (model()->local_credentials().empty()) { if (controller_.local_credentials().empty()) {
// A LayoutManager is required for GetHeightForWidth() even without content. // A LayoutManager is required for GetHeightForWidth() even without content.
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
} else { } else {
for (auto& password_form : model()->local_credentials()) { for (auto& password_form : controller_.local_credentials()) {
password_rows_.push_back( password_rows_.push_back(
std::make_unique<PasswordRow>(this, &password_form)); std::make_unique<PasswordRow>(this, &password_form));
} }
...@@ -266,18 +268,18 @@ PasswordItemsView::PasswordItemsView(content::WebContents* web_contents, ...@@ -266,18 +268,18 @@ PasswordItemsView::PasswordItemsView(content::WebContents* web_contents,
PasswordItemsView::~PasswordItemsView() = default; PasswordItemsView::~PasswordItemsView() = default;
PasswordBubbleControllerBase* PasswordItemsView::GetController() { PasswordBubbleControllerBase* PasswordItemsView::GetController() {
return nullptr; return &controller_;
} }
const PasswordBubbleControllerBase* PasswordItemsView::GetController() const { const PasswordBubbleControllerBase* PasswordItemsView::GetController() const {
return nullptr; return &controller_;
} }
void PasswordItemsView::RecreateLayout() { void PasswordItemsView::RecreateLayout() {
// This method should only be used when we have password rows, otherwise the // This method should only be used when we have password rows, otherwise the
// dialog should only show the no-passwords title and doesn't need to be // dialog should only show the no-passwords title and doesn't need to be
// recreated. // recreated.
DCHECK(!model()->local_credentials().empty()); DCHECK(!controller_.local_credentials().empty());
RemoveAllChildViews(true); RemoveAllChildViews(true);
...@@ -307,7 +309,7 @@ void PasswordItemsView::NotifyPasswordFormAction( ...@@ -307,7 +309,7 @@ void PasswordItemsView::NotifyPasswordFormAction(
RecreateLayout(); RecreateLayout();
// After the view is consistent, notify the model that the password needs to // After the view is consistent, notify the model that the password needs to
// be updated (either removed or put back into the store, as appropriate. // be updated (either removed or put back into the store, as appropriate.
model()->OnPasswordAction(password_form, action); controller_.OnPasswordAction(password_form, action);
} }
bool PasswordItemsView::ShouldShowCloseButton() const { bool PasswordItemsView::ShouldShowCloseButton() const {
...@@ -323,7 +325,7 @@ gfx::Size PasswordItemsView::CalculatePreferredSize() const { ...@@ -323,7 +325,7 @@ gfx::Size PasswordItemsView::CalculatePreferredSize() const {
void PasswordItemsView::ButtonPressed(views::Button* sender, void PasswordItemsView::ButtonPressed(views::Button* sender,
const ui::Event& event) { const ui::Event& event) {
model()->OnManageClicked( controller_.OnManageClicked(
password_manager::ManagePasswordsReferrer::kManagePasswordsBubble); password_manager::ManagePasswordsReferrer::kManagePasswordsBubble);
CloseBubble(); CloseBubble();
} }
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/passwords/bubble_controllers/items_bubble_controller.h"
#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
#include "chrome/browser/ui/views/passwords/password_bubble_view_base.h" #include "chrome/browser/ui/views/passwords/password_bubble_view_base.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
...@@ -62,6 +63,8 @@ class PasswordItemsView : public PasswordBubbleViewBase, ...@@ -62,6 +63,8 @@ class PasswordItemsView : public PasswordBubbleViewBase,
std::vector<std::unique_ptr<PasswordRow>> password_rows_; std::vector<std::unique_ptr<PasswordRow>> password_rows_;
ItemsBubbleController controller_;
DISALLOW_COPY_AND_ASSIGN(PasswordItemsView); DISALLOW_COPY_AND_ASSIGN(PasswordItemsView);
}; };
......
...@@ -4042,6 +4042,7 @@ test("unit_tests") { ...@@ -4042,6 +4042,7 @@ test("unit_tests") {
"../browser/ui/page_info/permission_menu_model_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/auto_sign_in_bubble_controller_unittest.cc",
"../browser/ui/passwords/bubble_controllers/generation_confirmation_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/generation_confirmation_bubble_controller_unittest.cc",
"../browser/ui/passwords/bubble_controllers/items_bubble_controller_unittest.cc",
"../browser/ui/passwords/credential_leak_dialog_controller_impl_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/credential_manager_dialog_controller_impl_unittest.cc",
"../browser/ui/passwords/manage_passwords_bubble_model_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