Commit 60844759 authored by Chris Lu's avatar Chris Lu Committed by Commit Bot

[ios] Add UpdatePasswordInfobarBannerOverlayRequestConfig

Each OverlayInteractionHandler needs its own distinct RequestConfig,
because the handler's callback installer tie its callbacks to
the RequestConfig. Thus, if two InteractionHandlers have the same
config, then the banner action response will trigger both handler's
callback methods. This creates a behavior where presenting the modal
from a banner adds two modal requests into the queue.

Bug: 1124587
Change-Id: I83b807017e754ea3935090cdf6e7c3a46b8ef2db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2397977
Commit-Queue: Chris Lu <thegreenfrog@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805563}
parent 30f128d4
......@@ -56,6 +56,7 @@ source_set("unit_tests") {
"//ios/chrome/browser/main:test_support",
"//ios/chrome/browser/overlays",
"//ios/chrome/browser/overlays/public/common/infobars",
"//ios/chrome/browser/overlays/public/infobar_banner",
"//ios/chrome/browser/overlays/public/infobar_modal",
"//ios/chrome/browser/overlays/test",
"//ios/chrome/browser/passwords:infobar_delegates",
......
......@@ -14,7 +14,8 @@ class IOSChromeSavePasswordInfoBarDelegate;
class PasswordInfobarBannerInteractionHandler
: public InfobarBannerInteractionHandler {
public:
PasswordInfobarBannerInteractionHandler();
PasswordInfobarBannerInteractionHandler(
const OverlayRequestSupport* request_support);
~PasswordInfobarBannerInteractionHandler() override;
// InfobarBannerInteractionHandler:
......
......@@ -20,9 +20,9 @@
#pragma mark - InfobarBannerInteractionHandler
PasswordInfobarBannerInteractionHandler::
PasswordInfobarBannerInteractionHandler()
: InfobarBannerInteractionHandler(
SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport()) {}
PasswordInfobarBannerInteractionHandler(
const OverlayRequestSupport* request_support)
: InfobarBannerInteractionHandler(request_support) {}
PasswordInfobarBannerInteractionHandler::
~PasswordInfobarBannerInteractionHandler() = default;
......
......@@ -10,6 +10,7 @@
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/infobars/overlays/infobar_overlay_util.h"
#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
#import "ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
......@@ -25,7 +26,9 @@
// Test fixture for PasswordInfobarBannerInteractionHandler.
class PasswordInfobarBannerInteractionHandlerTest : public PlatformTest {
public:
PasswordInfobarBannerInteractionHandlerTest() {
PasswordInfobarBannerInteractionHandlerTest()
: handler_(
SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport()) {
scoped_feature_list_.InitWithFeatures({kIOSInfobarUIReboot},
{kInfobarUIRebootOnlyiOS13});
web_state_.SetNavigationManager(
......
......@@ -17,7 +17,8 @@ PasswordInfobarInteractionHandler::PasswordInfobarInteractionHandler(
Browser* browser)
: InfobarInteractionHandler(
InfobarType::kInfobarTypePasswordSave,
std::make_unique<PasswordInfobarBannerInteractionHandler>(),
std::make_unique<PasswordInfobarBannerInteractionHandler>(
SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport()),
/*sheet_handler=*/nullptr,
std::make_unique<PasswordInfobarModalInteractionHandler>(browser)) {}
......
......@@ -8,6 +8,7 @@
#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h"
#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_modal_interaction_handler.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -17,7 +18,9 @@ UpdatePasswordInfobarInteractionHandler::
UpdatePasswordInfobarInteractionHandler(Browser* browser)
: InfobarInteractionHandler(
InfobarType::kInfobarTypePasswordUpdate,
std::make_unique<PasswordInfobarBannerInteractionHandler>(),
std::make_unique<PasswordInfobarBannerInteractionHandler>(
UpdatePasswordInfobarBannerOverlayRequestConfig::
RequestSupport()),
/*sheet_handler=*/nullptr,
std::make_unique<PasswordInfobarModalInteractionHandler>(browser)) {}
......
......@@ -9,6 +9,7 @@
#import "ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/translate_infobar_banner_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/translate_infobar_modal_overlay_request_config.h"
......@@ -29,10 +30,11 @@ InfobarOverlayRequestFactoryImpl::InfobarOverlayRequestFactoryImpl() {
CreateFactory<SavePasswordInfobarBannerOverlayRequestConfig>(),
/*detail_sheet_factory=*/nullptr,
CreateFactory<PasswordInfobarModalOverlayRequestConfig>());
SetUpFactories(InfobarType::kInfobarTypePasswordUpdate,
CreateFactory<SavePasswordInfobarBannerOverlayRequestConfig>(),
/*detail_sheet_factory=*/nullptr,
CreateFactory<PasswordInfobarModalOverlayRequestConfig>());
SetUpFactories(
InfobarType::kInfobarTypePasswordUpdate,
CreateFactory<UpdatePasswordInfobarBannerOverlayRequestConfig>(),
/*detail_sheet_factory=*/nullptr,
CreateFactory<PasswordInfobarModalOverlayRequestConfig>());
SetUpFactories(InfobarType::kInfobarTypeTranslate,
CreateFactory<TranslateBannerRequestConfig>(),
/*detail_sheet_factory=*/nullptr,
......
......@@ -21,6 +21,7 @@
#import "ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/translate_infobar_banner_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/translate_infobar_modal_overlay_request_config.h"
......@@ -101,8 +102,9 @@ TEST_F(InfobarOverlayRequestFactoryImplTest, UpdatePasswords) {
// Test banner request creation.
std::unique_ptr<OverlayRequest> banner_request =
factory()->CreateInfobarRequest(&infobar, InfobarOverlayType::kBanner);
EXPECT_TRUE(banner_request
->GetConfig<SavePasswordInfobarBannerOverlayRequestConfig>());
EXPECT_TRUE(
banner_request
->GetConfig<UpdatePasswordInfobarBannerOverlayRequestConfig>());
// Test modal request creation.
std::unique_ptr<OverlayRequest> modal_request =
......
......@@ -16,6 +16,8 @@ source_set("infobar_banner") {
"save_password_infobar_banner_overlay.mm",
"translate_infobar_banner_overlay_request_config.h",
"translate_infobar_banner_overlay_request_config.mm",
"update_password_infobar_banner_overlay.h",
"update_password_infobar_banner_overlay.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_BANNER_UPDATE_PASSWORD_INFOBAR_BANNER_OVERLAY_H_
#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_UPDATE_PASSWORD_INFOBAR_BANNER_OVERLAY_H_
#include "ios/chrome/browser/overlays/public/overlay_request_config.h"
#include "ios/chrome/browser/overlays/public/overlay_user_data.h"
namespace infobars {
class InfoBar;
}
class IOSChromeSavePasswordInfoBarDelegate;
// Configuration object for OverlayRequests for the banner UI for an InfoBar
// with a IOSChromeSavePasswordInfoBarDelegate that is updating a password.
class UpdatePasswordInfobarBannerOverlayRequestConfig
: public OverlayRequestConfig<
UpdatePasswordInfobarBannerOverlayRequestConfig> {
public:
~UpdatePasswordInfobarBannerOverlayRequestConfig() override;
// The infobar delegate's message text.
NSString* message() const { return message_; }
// The username for which passwords are being update.
NSString* username() const { return username_; }
// The text to show on the banner's confirm button.
NSString* button_text() const { return button_text_; }
// The name of the banner's icon image.
NSString* icon_image_name() const { return icon_image_name_; }
// The length of the password being updated.
size_t password_length() const { return password_length_; }
private:
OVERLAY_USER_DATA_SETUP(UpdatePasswordInfobarBannerOverlayRequestConfig);
explicit UpdatePasswordInfobarBannerOverlayRequestConfig(
infobars::InfoBar* infobar);
// OverlayUserData:
void CreateAuxiliaryData(base::SupportsUserData* user_data) override;
// The InfoBar causing this banner.
infobars::InfoBar* infobar_ = nullptr;
// Configuration data extracted from |infobar_|'s update passwords delegate.
NSString* message_ = nil;
NSString* username_ = nil;
NSString* button_text_ = nil;
NSString* icon_image_name_ = nil;
size_t password_length_ = 0;
};
#endif // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_UPDATE_PASSWORD_INFOBAR_BANNER_OVERLAY_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_banner/update_password_infobar_banner_overlay.h"
#include "base/check.h"
#include "base/strings/sys_string_conversions.h"
#include "components/infobars/core/infobar.h"
#include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using infobars::InfoBar;
namespace {
// The name of the icon image for the update passwords banner.
NSString* const kIconImageName = @"password_key";
}
OVERLAY_USER_DATA_SETUP_IMPL(UpdatePasswordInfobarBannerOverlayRequestConfig);
UpdatePasswordInfobarBannerOverlayRequestConfig::
UpdatePasswordInfobarBannerOverlayRequestConfig(InfoBar* infobar)
: infobar_(infobar) {
DCHECK(infobar_);
IOSChromeSavePasswordInfoBarDelegate* delegate =
IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
infobar_->delegate());
message_ = base::SysUTF16ToNSString(delegate->GetMessageText());
username_ = delegate->GetUserNameText();
button_text_ = base::SysUTF16ToNSString(
delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
icon_image_name_ = kIconImageName;
password_length_ = delegate->GetPasswordText().length;
}
UpdatePasswordInfobarBannerOverlayRequestConfig::
~UpdatePasswordInfobarBannerOverlayRequestConfig() = default;
void UpdatePasswordInfobarBannerOverlayRequestConfig::CreateAuxiliaryData(
base::SupportsUserData* user_data) {
InfobarOverlayRequestConfig::CreateForUserData(
user_data, static_cast<InfoBarIOS*>(infobar_),
InfobarOverlayType::kBanner, false);
}
......@@ -19,6 +19,7 @@
#import "ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/translate/translate_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator+subclassing.h"
......@@ -47,6 +48,7 @@
+ (NSArray<Class>*)supportedMediatorClasses {
return @[
[SavePasswordInfobarBannerOverlayMediator class],
[UpdatePasswordInfobarBannerOverlayMediator class],
[ConfirmInfobarBannerOverlayMediator class],
[TranslateInfobarBannerOverlayMediator class],
[SaveCardInfobarBannerOverlayMediator class],
......
......@@ -6,6 +6,8 @@ source_set("passwords") {
sources = [
"save_password_infobar_banner_overlay_mediator.h",
"save_password_infobar_banner_overlay_mediator.mm",
"update_password_infobar_banner_overlay_mediator.h",
"update_password_infobar_banner_overlay_mediator.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
......@@ -23,7 +25,10 @@ source_set("passwords") {
source_set("unit_tests") {
testonly = true
sources = [ "save_password_infobar_banner_overlay_mediator_unittest.mm" ]
sources = [
"save_password_infobar_banner_overlay_mediator_unittest.mm",
"update_password_infobar_banner_overlay_mediator_unittest.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_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_UPDATE_PASSWORD_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_UPDATE_PASSWORD_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h"
// Mediator that configures an infobar banner for an update passwords infobar.
@interface UpdatePasswordInfobarBannerOverlayMediator
: InfobarBannerOverlayMediator
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_PASSWORDS_UPDATE_PASSWORD_INFOBAR_BANNER_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_banner/passwords/update_password_infobar_banner_overlay_mediator.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h"
#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h"
#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface UpdatePasswordInfobarBannerOverlayMediator ()
// The update password banner config from the request.
@property(nonatomic, readonly)
UpdatePasswordInfobarBannerOverlayRequestConfig* config;
@end
@implementation UpdatePasswordInfobarBannerOverlayMediator
#pragma mark - Accessors
- (UpdatePasswordInfobarBannerOverlayRequestConfig*)config {
return self.request ? self.request->GetConfig<
UpdatePasswordInfobarBannerOverlayRequestConfig>()
: nullptr;
}
#pragma mark - OverlayRequestMediator
+ (const OverlayRequestSupport*)requestSupport {
return UpdatePasswordInfobarBannerOverlayRequestConfig::RequestSupport();
}
@end
@implementation UpdatePasswordInfobarBannerOverlayMediator (ConsumerSupport)
- (void)configureConsumer {
UpdatePasswordInfobarBannerOverlayRequestConfig* config = self.config;
if (!self.consumer || !config)
return;
NSString* title = config->message();
NSString* username = config->username();
NSString* password = [@"" stringByPaddingToLength:config->password_length()
withString:@"•"
startingAtIndex:0];
NSString* bannerAccessibilityLabel =
[NSString stringWithFormat:@"%@, %@, %@", title, username,
l10n_util::GetNSString(
IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
[self.consumer setBannerAccessibilityLabel:bannerAccessibilityLabel];
[self.consumer setButtonText:config->button_text()];
[self.consumer setIconImage:[UIImage imageNamed:config->icon_image_name()]];
[self.consumer setPresentsModal:YES];
[self.consumer setTitleText:title];
[self.consumer
setSubtitleText:[NSString stringWithFormat:@"%@ %@", username, password]];
}
@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_banner/passwords/update_password_infobar_banner_overlay_mediator.h"
#include "base/feature_list.h"
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/common/password_form.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_feature.h"
#include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h"
#include "ios/chrome/browser/overlays/public/overlay_response.h"
#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
#import "ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
#import "ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h"
#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
#include "ios/chrome/grit/ios_strings.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Constants used in tests.
NSString* const kUsername = @"username";
NSString* const kPassword = @"12345";
}
// Test fixture for UpdatePasswordInfobarBannerOverlayMediator.
class UpdatePasswordInfobarBannerOverlayMediatorTest : public PlatformTest {
public:
UpdatePasswordInfobarBannerOverlayMediatorTest() {
feature_list_.InitWithFeatures({kIOSInfobarUIReboot},
{kInfobarUIRebootOnlyiOS13});
}
private:
base::test::ScopedFeatureList feature_list_;
};
// Tests that a UpdatePasswordInfobarBannerOverlayMediator correctly sets up its
// consumer.
TEST_F(UpdatePasswordInfobarBannerOverlayMediatorTest, SetUpConsumer) {
// Create an InfoBarIOS with a IOSChromeSavePasswordInfoBarDelegate.
FakeInfobarUIDelegate* ui_delegate = [[FakeInfobarUIDelegate alloc] init];
std::unique_ptr<IOSChromeSavePasswordInfoBarDelegate> passed_delegate =
MockIOSChromeSavePasswordInfoBarDelegate::Create(kUsername, kPassword);
IOSChromeSavePasswordInfoBarDelegate* delegate = passed_delegate.get();
InfoBarIOS infobar(ui_delegate, std::move(passed_delegate));
// Package the infobar into an OverlayRequest, then create a mediator that
// uses this request in order to set up a fake consumer.
std::unique_ptr<OverlayRequest> request = OverlayRequest::CreateWithConfig<
UpdatePasswordInfobarBannerOverlayRequestConfig>(&infobar);
UpdatePasswordInfobarBannerOverlayMediator* mediator =
[[UpdatePasswordInfobarBannerOverlayMediator alloc]
initWithRequest:request.get()];
FakeInfobarBannerConsumer* consumer =
[[FakeInfobarBannerConsumer alloc] init];
mediator.consumer = consumer;
// Verify that the infobar was set up properly.
NSString* title = base::SysUTF16ToNSString(delegate->GetMessageText());
NSString* password = [@"" stringByPaddingToLength:kPassword.length
withString:@"•"
startingAtIndex:0];
NSString* subtitle =
[NSString stringWithFormat:@"%@ %@", kUsername, password];
NSString* bannerAccessibilityLabel =
[NSString stringWithFormat:@"%@, %@, %@", title, kUsername,
l10n_util::GetNSString(
IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
EXPECT_NSEQ(bannerAccessibilityLabel, consumer.bannerAccessibilityLabel);
EXPECT_NSEQ(base::SysUTF16ToNSString(
delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)),
consumer.buttonText);
EXPECT_NSEQ(title, consumer.titleText);
EXPECT_NSEQ(subtitle, consumer.subtitleText);
EXPECT_NSEQ([UIImage imageNamed:@"password_key"], consumer.iconImage);
EXPECT_TRUE(consumer.presentsModal);
}
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