Commit 94c8ccce authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Add overlay support for password infobar modal UI

Added in this CL:
- Response info types for password modal delegate callbacks.
- Coordinator and mediator classes to handle UI setup.
- Update mock passwords delegate to set the URL.

Bug: 1030357
Change-Id: Ia5b375869234b26b36df6220a1b2908847723e18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1995635
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Auto-Submit: Kurt Horimoto <kkhorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732544}
parent d330a8b0
......@@ -8,6 +8,8 @@ source_set("infobar_modal") {
"infobar_modal_overlay_responses.mm",
"password_infobar_modal_overlay_request_config.h",
"password_infobar_modal_overlay_request_config.mm",
"password_infobar_modal_overlay_responses.h",
"password_infobar_modal_overlay_responses.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
......
// 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 IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_RESPONSES_H_
#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_RESPONSES_H_
#import <Foundation/Foundation.h>
#include "ios/chrome/browser/overlays/public/overlay_response_info.h"
namespace password_infobar_modal_responses {
// Response info used to create dispatched OverlayResponses that update the
// credentials using the provided username and password.
class UpdateCredentialsInfo
: public OverlayResponseInfo<UpdateCredentialsInfo> {
public:
~UpdateCredentialsInfo() override;
// The username for the credentials being updated.
NSString* username() const { return username_; }
// The password for the credentials being updated.
NSString* password() const { return password_; }
private:
OVERLAY_USER_DATA_SETUP(UpdateCredentialsInfo);
UpdateCredentialsInfo(NSString* username, NSString* password);
NSString* username_ = nil;
NSString* password_ = nil;
};
// Response info used to create dispatched OverlayResponses that notify the
// password infobar to never save credentials.
DEFINE_STATELESS_OVERLAY_RESPONSE_INFO(NeverSaveCredentials);
// Response info used to create dispatched OverlayResponses that notify the
// password infobar to present the password settings.
DEFINE_STATELESS_OVERLAY_RESPONSE_INFO(PresentPasswordSettings);
} // password_infobar_modal_responses
#endif // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_RESPONSES_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.
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_responses.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace password_infobar_modal_responses {
#pragma mark - UpdateCredentialsInfo
OVERLAY_USER_DATA_SETUP_IMPL(UpdateCredentialsInfo);
UpdateCredentialsInfo::UpdateCredentialsInfo(NSString* username,
NSString* password)
: username_([username copy]), password_([password copy]) {}
UpdateCredentialsInfo::~UpdateCredentialsInfo() = default;
#pragma mark - NeverSaveCredentials
OVERLAY_USER_DATA_SETUP_IMPL(NeverSaveCredentials);
#pragma mark - PresentPasswordSettings
OVERLAY_USER_DATA_SETUP_IMPL(PresentPasswordSettings);
} // password_infobar_modal_responses
......@@ -21,5 +21,6 @@ source_set("test") {
"//ios/chrome/browser/passwords:infobar_delegates",
"//testing/gmock",
"//testing/gtest",
"//url",
]
}
......@@ -11,6 +11,7 @@
#include "components/autofill/core/common/password_form.h"
#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
// Mock queue observer.
class MockIOSChromeSavePasswordInfoBarDelegate
......@@ -23,10 +24,11 @@ class MockIOSChromeSavePasswordInfoBarDelegate
~MockIOSChromeSavePasswordInfoBarDelegate() override;
// Factory method that creates a mock save password delegate for pending
// with credentials |username| and |password|.
// with credentials |username| and |password| for the page at |url|.
static std::unique_ptr<MockIOSChromeSavePasswordInfoBarDelegate> Create(
NSString* username,
NSString* password);
NSString* password,
const GURL& url = GURL::EmptyGURL());
MOCK_METHOD0(InfoBarDismissed, void());
MOCK_METHOD0(Accept, bool());
......@@ -34,10 +36,12 @@ class MockIOSChromeSavePasswordInfoBarDelegate
MOCK_METHOD0(InfobarDismissed, void());
private:
explicit MockIOSChromeSavePasswordInfoBarDelegate(
std::unique_ptr<autofill::PasswordForm> form);
MockIOSChromeSavePasswordInfoBarDelegate(
std::unique_ptr<autofill::PasswordForm> form,
std::unique_ptr<GURL> url);
std::unique_ptr<autofill::PasswordForm> form_;
std::unique_ptr<GURL> url_;
};
#endif // IOS_CHROME_BROWSER_PASSWORDS_TEST_MOCK_IOS_CHROME_SAVE_PASSWORDS_INFOBAR_DELEGATE_H_
......@@ -15,12 +15,14 @@
namespace {
std::unique_ptr<password_manager::PasswordFormManagerForUI> CreateFormManager(
autofill::PasswordForm* form) {
DCHECK(form);
autofill::PasswordForm* form,
GURL* url) {
std::unique_ptr<password_manager::MockPasswordFormManagerForUI> form_manager =
std::make_unique<password_manager::MockPasswordFormManagerForUI>();
EXPECT_CALL(*form_manager, GetPendingCredentials())
.WillRepeatedly(testing::ReturnRef(*form));
EXPECT_CALL(*form_manager, GetOrigin())
.WillRepeatedly(testing::ReturnRef(*url));
EXPECT_CALL(*form_manager, GetMetricsRecorder())
.WillRepeatedly(testing::Return(nullptr));
EXPECT_CALL(*form_manager, GetCredentialSource())
......@@ -33,23 +35,26 @@ std::unique_ptr<password_manager::PasswordFormManagerForUI> CreateFormManager(
// static
std::unique_ptr<MockIOSChromeSavePasswordInfoBarDelegate>
MockIOSChromeSavePasswordInfoBarDelegate::Create(NSString* username,
NSString* password) {
NSString* password,
const GURL& url) {
std::unique_ptr<autofill::PasswordForm> form =
std::make_unique<autofill::PasswordForm>();
form->username_value = base::SysNSStringToUTF16(username);
form->password_value = base::SysNSStringToUTF16(password);
return base::WrapUnique(
new MockIOSChromeSavePasswordInfoBarDelegate(std::move(form)));
return base::WrapUnique(new MockIOSChromeSavePasswordInfoBarDelegate(
std::move(form), std::make_unique<GURL>(url)));
}
MockIOSChromeSavePasswordInfoBarDelegate::
MockIOSChromeSavePasswordInfoBarDelegate(
std::unique_ptr<autofill::PasswordForm> form)
std::unique_ptr<autofill::PasswordForm> form,
std::unique_ptr<GURL> url)
: IOSChromeSavePasswordInfoBarDelegate(
/*is_sync_user=*/false,
/*password_update=*/false,
CreateFormManager(form.get())),
form_(std::move(form)) {}
CreateFormManager(form.get(), url.get())),
form_(std::move(form)),
url_(std::move(url)) {}
MockIOSChromeSavePasswordInfoBarDelegate::
~MockIOSChromeSavePasswordInfoBarDelegate() = default;
# 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.
source_set("test") {
testonly = true
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"fake_infobar_password_modal_consumer.h",
"fake_infobar_password_modal_consumer.mm",
]
deps = [ "//ios/chrome/browser/ui/infobars/modals" ]
}
// 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 IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_TEST_FAKE_INFOBAR_PASSWORD_MODAL_CONSUMER_H_
#define IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_TEST_FAKE_INFOBAR_PASSWORD_MODAL_CONSUMER_H_
#import "ios/chrome/browser/ui/infobars/modals/infobar_password_modal_consumer.h"
@interface FakeInfobarPasswordModalConsumer
: NSObject <InfobarPasswordModalConsumer>
// Allow read access to values passed to InfobarPasswwordModalConsumer
// interface.
@property(nonatomic, copy) NSString* username;
@property(nonatomic, copy) NSString* maskedPassword;
@property(nonatomic, copy) NSString* unmaskedPassword;
@property(nonatomic, copy) NSString* detailsTextMessage;
@property(nonatomic, copy) NSString* URL;
@property(nonatomic, copy) NSString* saveButtonText;
@property(nonatomic, copy) NSString* cancelButtonText;
@property(nonatomic, assign) BOOL currentCredentialsSaved;
@end
#endif // IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_TEST_FAKE_INFOBAR_PASSWORD_MODAL_CONSUMER_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.
#import "ios/chrome/browser/ui/infobars/modals/test/fake_infobar_password_modal_consumer.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation FakeInfobarPasswordModalConsumer
@end
......@@ -8,7 +8,7 @@ source_set("infobar_modal") {
configs += [ "//build/config/compiler:enable_arc" ]
deps = []
deps = [ "//ios/chrome/browser/ui/overlays/infobar_modal/passwords" ]
}
source_set("coordinators") {
......
......@@ -4,6 +4,8 @@
#import "ios/chrome/browser/ui/overlays/infobar_modal/infobar_modal_supported_overlay_coordinator_classes.h"
#import "ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
......@@ -12,7 +14,7 @@ namespace infobar_modal {
NSArray<Class>* GetSupportedOverlayCoordinatorClasses() {
// TODO(crbug.com/1030357): Add overlay coordinator classes when converted.
return @[];
return @ [[PasswordInfobarModalOverlayCoordinator class]];
}
} // infobar_modal
# 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.
source_set("passwords") {
sources = [
"password_infobar_modal_overlay_coordinator.h",
"password_infobar_modal_overlay_coordinator.mm",
"password_infobar_modal_overlay_mediator.h",
"password_infobar_modal_overlay_mediator.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
"//base",
"//ios/chrome/browser/overlays",
"//ios/chrome/browser/overlays/public/common/infobars",
"//ios/chrome/browser/overlays/public/infobar_modal",
"//ios/chrome/browser/ui/infobars/modals",
"//ios/chrome/browser/ui/overlays:coordinators",
"//ios/chrome/browser/ui/overlays/infobar_modal:coordinators",
"//ios/chrome/browser/ui/overlays/infobar_modal:mediators",
]
}
source_set("unit_tests") {
testonly = true
sources = [ "password_infobar_modal_overlay_mediator_unittest.mm" ]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
":passwords",
"//base/test:test_support",
"//components/infobars/core",
"//components/infobars/core:feature_flags",
"//ios/chrome/browser/infobars",
"//ios/chrome/browser/infobars/test",
"//ios/chrome/browser/overlays",
"//ios/chrome/browser/overlays/public/infobar_modal",
"//ios/chrome/browser/overlays/test",
"//ios/chrome/browser/passwords/test",
"//ios/chrome/browser/passwords/test",
"//ios/chrome/browser/ui/infobars/modals/test",
"//ios/chrome/browser/ui/infobars/test",
"//ios/chrome/browser/ui/overlays/test",
"//testing/gmock",
"//testing/gtest",
"//third_party/ocmock",
"//ui/base",
"//url",
]
}
// 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 IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_COORDINATOR_H_
#import "ios/chrome/browser/ui/overlays/infobar_modal/infobar_modal_overlay_coordinator.h"
// A coordinator that displays the password infobar modal UI using
// OverlayPresenter.
@interface PasswordInfobarModalOverlayCoordinator
: InfobarModalOverlayCoordinator
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_COORDINATOR_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.
#import "ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_coordinator.h"
#include "base/logging.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h"
#import "ios/chrome/browser/ui/overlays/infobar_modal/infobar_modal_overlay_coordinator+modal_configuration.h"
#import "ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using password_modal::PasswordAction;
namespace {
// Returns the InfobarType that should be used to construct the
// InfobarPasswordTableViewController for |action|.
InfobarType GetTableViewInfobarType(PasswordAction action) {
switch (action) {
case PasswordAction::kSave:
return InfobarType::kInfobarTypePasswordSave;
case PasswordAction::kUpdate:
return InfobarType::kInfobarTypePasswordUpdate;
}
}
} // namespace
@interface PasswordInfobarModalOverlayCoordinator ()
// Redefine ModalConfiguration properties as readwrite.
@property(nonatomic, readwrite) OverlayRequestMediator* modalMediator;
@property(nonatomic, readwrite) UIViewController* modalViewController;
// The request's config.
@property(nonatomic, readonly) PasswordInfobarModalOverlayRequestConfig* config;
@end
@implementation PasswordInfobarModalOverlayCoordinator
#pragma mark - Accessors
- (PasswordInfobarModalOverlayRequestConfig*)config {
return self.request
? self.request
->GetConfig<PasswordInfobarModalOverlayRequestConfig>()
: nullptr;
}
#pragma mark - Public
+ (const OverlayRequestSupport*)requestSupport {
return PasswordInfobarModalOverlayRequestConfig::RequestSupport();
}
@end
@implementation PasswordInfobarModalOverlayCoordinator (ModalConfiguration)
- (void)configureModal {
DCHECK(!self.modalMediator);
DCHECK(!self.modalViewController);
PasswordInfobarModalOverlayMediator* modalMediator =
[[PasswordInfobarModalOverlayMediator alloc]
initWithRequest:self.request];
InfobarPasswordTableViewController* modalViewController =
[[InfobarPasswordTableViewController alloc]
initWithDelegate:modalMediator
type:GetTableViewInfobarType(self.config->action())];
modalMediator.consumer = modalViewController;
self.modalMediator = modalMediator;
self.modalViewController = modalViewController;
}
- (void)resetModal {
DCHECK(self.modalMediator);
DCHECK(self.modalViewController);
self.modalMediator = nil;
self.modalViewController = nil;
}
@end
// 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 IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_MEDIATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_MEDIATOR_H_
#import "ios/chrome/browser/ui/infobars/modals/infobar_password_modal_consumer.h"
#import "ios/chrome/browser/ui/infobars/modals/infobar_password_modal_delegate.h"
#import "ios/chrome/browser/ui/overlays/infobar_modal/infobar_modal_overlay_mediator.h"
// Mediator that configures the modal UI for a passwords infobar.
@interface PasswordInfobarModalOverlayMediator
: InfobarModalOverlayMediator <InfobarPasswordModalDelegate>
// The consumer that is configured by this mediator. Setting to a new value
// configures the new consumer.
@property(nonatomic) id<InfobarPasswordModalConsumer> consumer;
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_MODAL_PASSWORDS_PASSWORD_INFOBAR_MODAL_OVERLAY_MEDIATOR_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.
#import "ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_responses.h"
#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h"
#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
#include "ios/chrome/browser/overlays/public/overlay_response.h"
#import "ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using password_infobar_modal_responses::UpdateCredentialsInfo;
using password_infobar_modal_responses::NeverSaveCredentials;
using password_infobar_modal_responses::PresentPasswordSettings;
@interface PasswordInfobarModalOverlayMediator ()
// The save password modal config from the request.
@property(nonatomic, readonly) PasswordInfobarModalOverlayRequestConfig* config;
@end
@implementation PasswordInfobarModalOverlayMediator
#pragma mark - Accessors
- (PasswordInfobarModalOverlayRequestConfig*)config {
return self.request
? self.request
->GetConfig<PasswordInfobarModalOverlayRequestConfig>()
: nullptr;
}
- (void)setConsumer:(id<InfobarPasswordModalConsumer>)consumer {
if (_consumer == consumer)
return;
_consumer = consumer;
PasswordInfobarModalOverlayRequestConfig* config = self.config;
if (!_consumer || !config)
return;
[_consumer setUsername:config->username()];
NSString* password = config->password();
[_consumer setMaskedPassword:[@"" stringByPaddingToLength:password.length
withString:@"•"
startingAtIndex:0]];
[_consumer setUnmaskedPassword:password];
[_consumer setDetailsTextMessage:config->details_text()];
[_consumer setSaveButtonText:config->save_button_text()];
[_consumer setCancelButtonText:config->cancel_button_text()];
[_consumer setURL:config->url()];
[_consumer setCurrentCredentialsSaved:config->is_current_password_saved()];
}
#pragma mark - OverlayRequestMediator
+ (const OverlayRequestSupport*)requestSupport {
return PasswordInfobarModalOverlayRequestConfig::RequestSupport();
}
#pragma mark - InfobarPasswordModalDelegate
- (void)updateCredentialsWithUsername:(NSString*)username
password:(NSString*)password {
// Receiving this delegate callback when the request is null means that the
// update credentials button was tapped after the request was cancelled, but
// before the modal UI has finished being dismissed.
if (!self.request)
return;
[self dispatchResponse:OverlayResponse::CreateWithInfo<UpdateCredentialsInfo>(
username, password)];
[self modalInfobarButtonWasAccepted:nil];
}
- (void)neverSaveCredentialsForCurrentSite {
// Receiving this delegate callback when the request is null means that the
// never save credentials button was tapped after the request was cancelled,
// but before the modal UI has finished being dismissed.
if (!self.request)
return;
[self
dispatchResponse:OverlayResponse::CreateWithInfo<NeverSaveCredentials>()];
[self dismissInfobarModal:nil];
}
- (void)presentPasswordSettings {
// Receiving this delegate callback when the request is null means that the
// present passwords settings button was tapped after the request was
// cancelled, but before the modal UI has finished being dismissed.
if (!self.request)
return;
[self dispatchResponse:OverlayResponse::CreateWithInfo<
PresentPasswordSettings>()];
[self dismissInfobarModal:nil];
}
@end
// 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.
#import "ios/chrome/browser/ui/overlays/infobar_modal/passwords/password_infobar_modal_overlay_mediator.h"
#import "base/bind.h"
#include "base/strings/sys_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/infobars/core/infobar_feature.h"
#include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/infobar_modal_overlay_responses.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_responses.h"
#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h"
#include "ios/chrome/browser/overlays/public/overlay_response.h"
#include "ios/chrome/browser/overlays/test/fake_overlay_request_callback_installer.h"
#import "ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
#import "ios/chrome/browser/ui/infobars/modals/test/fake_infobar_password_modal_consumer.h"
#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using password_infobar_modal_responses::UpdateCredentialsInfo;
using password_infobar_modal_responses::NeverSaveCredentials;
using password_infobar_modal_responses::PresentPasswordSettings;
namespace {
// Consts used in tests.
const char kUrlSpec[] = "http://chromium.test";
NSString* const kUsername = @"username";
NSString* const kPassword = @"password";
NSString* const kMaskedPassword = @"••••••••";
}
// Test fixture for PasswordInfobarModalOverlayMediator.
class PasswordInfobarModalOverlayMediatorTest : public PlatformTest {
public:
PasswordInfobarModalOverlayMediatorTest()
: url_(kUrlSpec),
infobar_([[FakeInfobarUIDelegate alloc] init],
MockIOSChromeSavePasswordInfoBarDelegate::Create(kUsername,
kPassword,
url_)),
callback_installer_(&callback_receiver_,
{InfobarModalMainActionResponse::ResponseSupport(),
NeverSaveCredentials::ResponseSupport(),
PresentPasswordSettings::ResponseSupport()}),
delegate_(
OCMStrictProtocolMock(@protocol(OverlayRequestMediatorDelegate))) {
scoped_feature_list_.InitWithFeatures({kIOSInfobarUIReboot}, {});
request_ = OverlayRequest::CreateWithConfig<
PasswordInfobarModalOverlayRequestConfig>(&infobar_);
callback_installer_.InstallCallbacks(request_.get());
mediator_ = [[PasswordInfobarModalOverlayMediator alloc]
initWithRequest:request_.get()];
mediator_.delegate = delegate_;
}
~PasswordInfobarModalOverlayMediatorTest() override {
EXPECT_CALL(callback_receiver_, CompletionCallback(request_.get()));
EXPECT_OCMOCK_VERIFY(delegate_);
}
MockIOSChromeSavePasswordInfoBarDelegate& mock_delegate() {
return *static_cast<MockIOSChromeSavePasswordInfoBarDelegate*>(
infobar_.delegate());
}
protected:
base::test::ScopedFeatureList scoped_feature_list_;
GURL url_;
InfoBarIOS infobar_;
MockOverlayRequestCallbackReceiver callback_receiver_;
FakeOverlayRequestCallbackInstaller callback_installer_;
std::unique_ptr<OverlayRequest> request_;
id<OverlayRequestMediatorDelegate> delegate_ = nil;
PasswordInfobarModalOverlayMediator* mediator_ = nil;
};
// Tests that a PasswordInfobarModalOverlayMediator correctly sets up its
// consumer.
TEST_F(PasswordInfobarModalOverlayMediatorTest, SetUpConsumer) {
FakeInfobarPasswordModalConsumer* consumer =
[[FakeInfobarPasswordModalConsumer alloc] init];
mediator_.consumer = consumer;
EXPECT_NSEQ(kUsername, consumer.username);
EXPECT_NSEQ(kMaskedPassword, consumer.maskedPassword);
EXPECT_NSEQ(kPassword, consumer.unmaskedPassword);
EXPECT_NSEQ(mock_delegate().GetDetailsMessageText(),
consumer.detailsTextMessage);
EXPECT_NSEQ(mock_delegate().GetURLHostText(), consumer.URL);
EXPECT_NSEQ(base::SysUTF16ToNSString(mock_delegate().GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_OK)),
consumer.saveButtonText);
EXPECT_NSEQ(base::SysUTF16ToNSString(mock_delegate().GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_CANCEL)),
consumer.cancelButtonText);
EXPECT_EQ(mock_delegate().IsCurrentPasswordSaved(),
consumer.currentCredentialsSaved);
}
// Tests that |-updateCredentialsWithUsername:password:| dispatches an
// UpdateCredentials response before accepting the infobar and dismissing the
// overlay.
TEST_F(PasswordInfobarModalOverlayMediatorTest, UpdateCredentials) {
// Since the UpdateCredentials response is not stateless, it is verified using
// a block rather than the mock callback receiver.
__block NSString* username = nil;
__block NSString* password = nil;
request_->GetCallbackManager()->AddDispatchCallback(
OverlayDispatchCallback(base::BindRepeating(^(OverlayResponse* response) {
UpdateCredentialsInfo* info =
response->GetInfo<UpdateCredentialsInfo>();
ASSERT_TRUE(info);
username = info->username();
password = info->password();
}),
UpdateCredentialsInfo::ResponseSupport()));
// Notify the mediator to update the credentials. In addition to dispatching
// the UpdateCredentialsInfo response, this should also trigger the main
// action and dismissal.
EXPECT_CALL(
callback_receiver_,
DispatchCallback(request_.get(),
InfobarModalMainActionResponse::ResponseSupport()));
OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
[mediator_ updateCredentialsWithUsername:kUsername password:kPassword];
// Verify that the update credentials callback was executed with the passed
// username and password.
EXPECT_NSEQ(kUsername, username);
EXPECT_NSEQ(kPassword, password);
}
// Tests that |-neverSaveCredentialsForCurrentSite| dispatches a
// NeverSaveCredentials response then stops the overlay.
TEST_F(PasswordInfobarModalOverlayMediatorTest, NeverSaveCredentials) {
EXPECT_CALL(callback_receiver_,
DispatchCallback(request_.get(),
NeverSaveCredentials::ResponseSupport()));
OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
[mediator_ neverSaveCredentialsForCurrentSite];
}
// Tests that |-presentPasswordSettings| dispatches a PresentPasswordSettings
// response then stops the overlay.
TEST_F(PasswordInfobarModalOverlayMediatorTest, PresentPasswordSettings) {
EXPECT_CALL(callback_receiver_,
DispatchCallback(request_.get(),
PresentPasswordSettings::ResponseSupport()));
OCMExpect([delegate_ stopOverlayForMediator:mediator_]);
[mediator_ presentPasswordSettings];
}
......@@ -267,6 +267,7 @@ test("ios_chrome_unittests") {
"//ios/chrome/browser/ui/overlays/infobar_banner:unit_tests",
"//ios/chrome/browser/ui/overlays/infobar_banner/passwords:unit_tests",
"//ios/chrome/browser/ui/overlays/infobar_modal:unit_tests",
"//ios/chrome/browser/ui/overlays/infobar_modal/passwords:unit_tests",
"//ios/chrome/browser/ui/overlays/web_content_area/app_launcher:unit_tests",
"//ios/chrome/browser/ui/overlays/web_content_area/http_auth_dialogs:unit_tests",
"//ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs:unit_tests",
......
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