Commit 81fc6eaf authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Handle adding modal requests for banner interaction for passwords.

This CL adds support for presenting the password infobar modal UI via
the banner interaction handler.  In order to accomplish this, the
InfobarOverlayRequestInserter was converted into a WebStateUserData so
that it can be accessed from OverlayRequest callbacks.  Additionally,
this CL updates InfobarOverlayRequestFactoryImpl to add a factory that
creates requests for modal UI.

If an infobar is replaced while modal UI is displayed, modal UI for the
replacement infobar should not immediately be shown; it needs to be
accessed via interaction with the infobar banner or the badge.  In order
to implement this behavior, InfobarOverlayRequestCancelHandler was
refactored to be a superclass that does not perform any request
replacement logic.  The replacement logic is now moved to a banner-
specific subclass that will show the replacement infobar's banner if
the banner for the replaced infobar is visible.

Bug: 1030357
Change-Id: I085110b8198029584fd94b8b55427d2e41e07bf5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2003258
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737170}
parent b3323c75
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
source_set("overlays") { source_set("overlays") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
sources = [ sources = [
"infobar_banner_overlay_request_cancel_handler.h",
"infobar_banner_overlay_request_cancel_handler.mm",
"infobar_overlay_request_cancel_handler.h", "infobar_overlay_request_cancel_handler.h",
"infobar_overlay_request_cancel_handler.mm", "infobar_overlay_request_cancel_handler.mm",
"infobar_overlay_request_factory.h", "infobar_overlay_request_factory.h",
...@@ -17,6 +19,7 @@ source_set("overlays") { ...@@ -17,6 +19,7 @@ source_set("overlays") {
] ]
public_deps = [ ":overlay_type" ] public_deps = [ ":overlay_type" ]
deps = [ deps = [
":util",
"//base", "//base",
"//components/infobars/core", "//components/infobars/core",
"//ios/chrome/browser/infobars", "//ios/chrome/browser/infobars",
...@@ -24,6 +27,7 @@ source_set("overlays") { ...@@ -24,6 +27,7 @@ source_set("overlays") {
"//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays",
"//ios/chrome/browser/overlays/public/common/infobars", "//ios/chrome/browser/overlays/public/common/infobars",
"//ios/chrome/browser/overlays/public/infobar_banner", "//ios/chrome/browser/overlays/public/infobar_banner",
"//ios/chrome/browser/overlays/public/infobar_modal",
"//ios/chrome/browser/passwords:infobar_delegates", "//ios/chrome/browser/passwords:infobar_delegates",
"//ios/chrome/browser/ui/infobars:infobars_ui", "//ios/chrome/browser/ui/infobars:infobars_ui",
"//ios/web/public", "//ios/web/public",
...@@ -71,6 +75,7 @@ source_set("unit_tests") { ...@@ -71,6 +75,7 @@ source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
sources = [ sources = [
"infobar_banner_overlay_request_cancel_handler_unittest.mm",
"infobar_overlay_request_cancel_handler_unittest.mm", "infobar_overlay_request_cancel_handler_unittest.mm",
"infobar_overlay_request_factory_impl_unittest.mm", "infobar_overlay_request_factory_impl_unittest.mm",
"infobar_overlay_request_inserter_unittest.mm", "infobar_overlay_request_inserter_unittest.mm",
...@@ -79,7 +84,7 @@ source_set("unit_tests") { ...@@ -79,7 +84,7 @@ source_set("unit_tests") {
deps = [ deps = [
":overlays", ":overlays",
":test_support", ":test_support",
"//base/test:test_support", ":util",
"//base/test:test_support", "//base/test:test_support",
"//components/password_manager/core/browser:test_support", "//components/password_manager/core/browser:test_support",
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
...@@ -89,8 +94,10 @@ source_set("unit_tests") { ...@@ -89,8 +94,10 @@ source_set("unit_tests") {
"//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays",
"//ios/chrome/browser/overlays/public/common/infobars", "//ios/chrome/browser/overlays/public/common/infobars",
"//ios/chrome/browser/overlays/public/infobar_banner", "//ios/chrome/browser/overlays/public/infobar_banner",
"//ios/chrome/browser/overlays/public/infobar_modal",
"//ios/chrome/browser/overlays/test", "//ios/chrome/browser/overlays/test",
"//ios/chrome/browser/passwords:infobar_delegates", "//ios/chrome/browser/passwords:infobar_delegates",
"//ios/chrome/browser/passwords/test",
"//ios/chrome/browser/ui/infobars:feature_flags", "//ios/chrome/browser/ui/infobars:feature_flags",
"//ios/chrome/browser/ui/infobars/test", "//ios/chrome/browser/ui/infobars/test",
"//ios/chrome/test:test_support", "//ios/chrome/test:test_support",
......
...@@ -18,6 +18,7 @@ source_set("passwords") { ...@@ -18,6 +18,7 @@ source_set("passwords") {
"//base", "//base",
"//ios/chrome/browser/infobars", "//ios/chrome/browser/infobars",
"//ios/chrome/browser/infobars:public", "//ios/chrome/browser/infobars:public",
"//ios/chrome/browser/infobars/overlays",
"//ios/chrome/browser/infobars/overlays:util", "//ios/chrome/browser/infobars/overlays:util",
"//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers", "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers",
"//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common", "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common",
...@@ -46,6 +47,8 @@ source_set("unit_tests") { ...@@ -46,6 +47,8 @@ source_set("unit_tests") {
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/infobars", "//ios/chrome/browser/infobars",
"//ios/chrome/browser/infobars:public", "//ios/chrome/browser/infobars:public",
"//ios/chrome/browser/infobars/overlays",
"//ios/chrome/browser/infobars/overlays:util",
"//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/test", "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/test",
"//ios/chrome/browser/infobars/test", "//ios/chrome/browser/infobars/test",
"//ios/chrome/browser/main:test_support", "//ios/chrome/browser/main:test_support",
......
...@@ -6,7 +6,11 @@ ...@@ -6,7 +6,11 @@
#include "base/logging.h" #include "base/logging.h"
#include "ios/chrome/browser/infobars/infobar_ios.h" #include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_cancel_handler.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h" #import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#include "ios/chrome/browser/overlays/public/overlay_request_queue.h"
#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h" #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -41,8 +45,8 @@ void PasswordInfobarBannerInteractionHandler::MainButtonTapped( ...@@ -41,8 +45,8 @@ void PasswordInfobarBannerInteractionHandler::MainButtonTapped(
void PasswordInfobarBannerInteractionHandler::ShowModalButtonTapped( void PasswordInfobarBannerInteractionHandler::ShowModalButtonTapped(
InfoBarIOS* infobar, InfoBarIOS* infobar,
web::WebState* web_state) { web::WebState* web_state) {
// TODO(crbug.com/1033154): Add support for showing modal UI via InfobarOverlayRequestInserter::FromWebState(web_state)->AddOverlayRequest(
// OverlayPresenter. infobar, InfobarOverlayType::kModal);
} }
void PasswordInfobarBannerInteractionHandler::BannerDismissedByUser( void PasswordInfobarBannerInteractionHandler::BannerDismissedByUser(
......
...@@ -6,10 +6,14 @@ ...@@ -6,10 +6,14 @@
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "components/infobars/core/infobar_feature.h" #include "components/infobars/core/infobar_feature.h"
#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h" #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
#import "ios/chrome/browser/overlays/public/overlay_request_queue.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/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h" #import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
#import "ios/web/public/test/fakes/test_navigation_manager.h"
#import "ios/web/public/test/fakes/test_web_state.h" #import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/platform_test.h" #include "testing/platform_test.h"
...@@ -20,42 +24,51 @@ ...@@ -20,42 +24,51 @@
// Test fixture for PasswordInfobarBannerInteractionHandler. // Test fixture for PasswordInfobarBannerInteractionHandler.
class PasswordInfobarBannerInteractionHandlerTest : public PlatformTest { class PasswordInfobarBannerInteractionHandlerTest : public PlatformTest {
public: public:
PasswordInfobarBannerInteractionHandlerTest() PasswordInfobarBannerInteractionHandlerTest() {
: infobar_(
[[FakeInfobarUIDelegate alloc] init],
MockIOSChromeSavePasswordInfoBarDelegate::Create(@"username",
@"password")) {
scoped_feature_list_.InitWithFeatures({kIOSInfobarUIReboot}, {}); scoped_feature_list_.InitWithFeatures({kIOSInfobarUIReboot}, {});
web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>());
InfobarOverlayRequestInserter::CreateForWebState(&web_state_);
InfoBarManagerImpl::CreateForWebState(&web_state_);
FakeInfobarUIDelegate* ui_delegate = [[FakeInfobarUIDelegate alloc] init];
ui_delegate.infobarType = InfobarType::kInfobarTypePasswordSave;
std::unique_ptr<InfoBarIOS> infobar = std::make_unique<InfoBarIOS>(
ui_delegate, MockIOSChromeSavePasswordInfoBarDelegate::Create(
@"username", @"password"));
infobar_ = infobar.get();
InfoBarManagerImpl::FromWebState(&web_state_)
->AddInfoBar(std::move(infobar));
} }
MockIOSChromeSavePasswordInfoBarDelegate& mock_delegate() { MockIOSChromeSavePasswordInfoBarDelegate& mock_delegate() {
return *static_cast<MockIOSChromeSavePasswordInfoBarDelegate*>( return *static_cast<MockIOSChromeSavePasswordInfoBarDelegate*>(
infobar_.delegate()); infobar_->delegate());
} }
protected: protected:
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
PasswordInfobarBannerInteractionHandler handler_; PasswordInfobarBannerInteractionHandler handler_;
web::TestWebState web_state_; web::TestWebState web_state_;
InfoBarIOS infobar_; InfoBarIOS* infobar_;
}; };
// Tests that BannerVisibilityChanged() calls InfobarPresenting() and // Tests that BannerVisibilityChanged() calls InfobarPresenting() and
// InfobarDismissed() on the mock delegate. // InfobarDismissed() on the mock delegate.
TEST_F(PasswordInfobarBannerInteractionHandlerTest, Presentation) { TEST_F(PasswordInfobarBannerInteractionHandlerTest, Presentation) {
EXPECT_CALL(mock_delegate(), InfobarPresenting(true)); EXPECT_CALL(mock_delegate(), InfobarPresenting(true));
handler_.BannerVisibilityChanged(&infobar_, true); handler_.BannerVisibilityChanged(infobar_, true);
EXPECT_CALL(mock_delegate(), InfobarDismissed()); EXPECT_CALL(mock_delegate(), InfobarDismissed());
handler_.BannerVisibilityChanged(&infobar_, false); handler_.BannerVisibilityChanged(infobar_, false);
} }
// Tests MainButtonTapped() calls Accept() on the mock delegate and resets // Tests MainButtonTapped() calls Accept() on the mock delegate and resets
// the infobar to be accepted. // the infobar to be accepted.
TEST_F(PasswordInfobarBannerInteractionHandlerTest, MainButton) { TEST_F(PasswordInfobarBannerInteractionHandlerTest, MainButton) {
ASSERT_FALSE(infobar_.accepted()); ASSERT_FALSE(infobar_->accepted());
EXPECT_CALL(mock_delegate(), Accept()).WillOnce(testing::Return(true)); EXPECT_CALL(mock_delegate(), Accept()).WillOnce(testing::Return(true));
handler_.MainButtonTapped(&infobar_); handler_.MainButtonTapped(infobar_);
EXPECT_TRUE(infobar_.accepted()); EXPECT_TRUE(infobar_->accepted());
} }
// Tests that pressing the modal button calls adds an OverlayRequest for the // Tests that pressing the modal button calls adds an OverlayRequest for the
...@@ -64,14 +77,16 @@ TEST_F(PasswordInfobarBannerInteractionHandlerTest, ShowModal) { ...@@ -64,14 +77,16 @@ TEST_F(PasswordInfobarBannerInteractionHandlerTest, ShowModal) {
OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState( OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
&web_state_, OverlayModality::kInfobarModal); &web_state_, OverlayModality::kInfobarModal);
ASSERT_EQ(0U, queue->size()); ASSERT_EQ(0U, queue->size());
handler_.ShowModalButtonTapped(&infobar_, &web_state_); handler_.ShowModalButtonTapped(infobar_, &web_state_);
// TODO(crbug.com/1033154): Verify that modal request has been added once
// modal passwords UI is implemented. OverlayRequest* modal_request = queue->front_request();
EXPECT_TRUE(modal_request);
EXPECT_EQ(infobar_, GetOverlayRequestInfobar(modal_request));
} }
// Tests that BannerVisibilityChanged() calls InfobarPresenting() and // Tests that BannerVisibilityChanged() calls InfobarPresenting() and
// InfobarDismissed() on the mock delegate. // InfobarDismissed() on the mock delegate.
TEST_F(PasswordInfobarBannerInteractionHandlerTest, UserInitiatedDismissal) { TEST_F(PasswordInfobarBannerInteractionHandlerTest, UserInitiatedDismissal) {
EXPECT_CALL(mock_delegate(), InfoBarDismissed()); EXPECT_CALL(mock_delegate(), InfoBarDismissed());
handler_.BannerDismissedByUser(&infobar_); handler_.BannerDismissedByUser(infobar_);
} }
// 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_INFOBARS_OVERLAYS_INFOBAR_BANNER_OVERLAY_REQUEST_CANCEL_HANDLER_H_
#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_INFOBAR_BANNER_OVERLAY_REQUEST_CANCEL_HANDLER_H_
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_cancel_handler.h"
class InfobarOverlayRequestInserter;
// A cancel handler for Infobar banner UI OverlayRequests.
class InfobarBannerOverlayRequestCancelHandler
: public InfobarOverlayRequestCancelHandler {
public:
// Constructor for a handler that cancels |request| from |queue|. |inserter|
// is used to insert replacement requests when an infobar is replaced.
InfobarBannerOverlayRequestCancelHandler(
OverlayRequest* request,
OverlayRequestQueue* queue,
const InfobarOverlayRequestInserter* inserter);
~InfobarBannerOverlayRequestCancelHandler() override;
private:
// InfobarOverlayRequestCancelHandler:
void HandleReplacement(infobars::InfoBar* replacement) override;
const InfobarOverlayRequestInserter* inserter_ = nullptr;
};
#endif // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_INFOBAR_BANNER_OVERLAY_REQUEST_CANCEL_HANDLER_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/infobars/overlays/infobar_banner_overlay_request_cancel_handler.h"
#include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
#include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using infobars::InfoBar;
InfobarBannerOverlayRequestCancelHandler::
InfobarBannerOverlayRequestCancelHandler(
OverlayRequest* request,
OverlayRequestQueue* queue,
const InfobarOverlayRequestInserter* inserter)
: InfobarOverlayRequestCancelHandler(request, queue), inserter_(inserter) {
DCHECK(inserter_);
}
InfobarBannerOverlayRequestCancelHandler::
~InfobarBannerOverlayRequestCancelHandler() = default;
void InfobarBannerOverlayRequestCancelHandler::HandleReplacement(
InfoBar* replacement) {
// If an infobar is replaced while a request for its banner is in the queue,
// a request for the replacement's banner should be inserted in back of the
// handler's request.
size_t index = 0;
while (index < queue()->size()) {
if (GetOverlayRequestInfobar(queue()->GetRequest(index)) == infobar())
break;
++index;
}
DCHECK_LT(index, queue()->size());
inserter_->InsertOverlayRequest(replacement, InfobarOverlayType::kBanner,
index + 1);
}
// 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/infobars/overlays/infobar_banner_overlay_request_cancel_handler.h"
#include "components/infobars/core/infobar.h"
#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
#include "ios/chrome/browser/infobars/test/fake_infobar_delegate.h"
#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h"
#include "ios/chrome/browser/overlays/public/overlay_request_queue.h"
#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
#import "ios/web/public/test/fakes/test_navigation_manager.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using infobars::InfoBar;
using infobars::InfoBarDelegate;
using infobars::InfoBarManager;
// Test fixture for InfobarBannerOverlayRequestCancelHandler.
class InfobarBannerOverlayRequestCancelHandlerTest : public PlatformTest {
public:
InfobarBannerOverlayRequestCancelHandlerTest() {
// Set up WebState and InfoBarManager.
web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>());
InfobarOverlayRequestInserter::CreateForWebState(
&web_state_, std::make_unique<FakeInfobarOverlayRequestFactory>());
InfoBarManagerImpl::CreateForWebState(&web_state_);
}
OverlayRequestQueue* queue() {
return OverlayRequestQueue::FromWebState(&web_state_,
OverlayModality::kInfobarBanner);
}
InfoBarManager* manager() {
return InfoBarManagerImpl::FromWebState(&web_state_);
}
InfobarOverlayRequestInserter* inserter() {
return InfobarOverlayRequestInserter::FromWebState(&web_state_);
}
// Returns the InfoBar used to create the front request in queue().
InfoBar* GetFrontRequestInfobar() {
OverlayRequest* front_request = queue()->front_request();
return front_request ? GetOverlayRequestInfobar(front_request) : nullptr;
}
private:
web::TestWebState web_state_;
};
// Tests that the request is replaced if its corresponding InfoBar is replaced
// in its manager.
TEST_F(InfobarBannerOverlayRequestCancelHandlerTest,
CancelForInfobarReplacement) {
std::unique_ptr<InfoBar> first_passed_infobar =
std::make_unique<FakeInfobarIOS>();
InfoBar* first_infobar = first_passed_infobar.get();
manager()->AddInfoBar(std::move(first_passed_infobar));
inserter()->AddOverlayRequest(first_infobar, InfobarOverlayType::kBanner);
ASSERT_EQ(first_infobar, GetFrontRequestInfobar());
// Replace with a new infobar and verify that the request has been replaced.
std::unique_ptr<InfoBar> second_passed_infobar =
std::make_unique<FakeInfobarIOS>();
InfoBar* second_infobar = second_passed_infobar.get();
manager()->ReplaceInfoBar(first_infobar, std::move(second_passed_infobar));
EXPECT_EQ(second_infobar, GetFrontRequestInfobar());
EXPECT_EQ(1U, queue()->size());
}
...@@ -7,33 +7,28 @@ ...@@ -7,33 +7,28 @@
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "components/infobars/core/infobar_manager.h" #include "components/infobars/core/infobar_manager.h"
#include "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
#import "ios/chrome/browser/overlays/public/overlay_request_cancel_handler.h" #import "ios/chrome/browser/overlays/public/overlay_request_cancel_handler.h"
class InfobarOverlayRequestInserter;
// OverlayRequestCancelHandler that cancels its OverlayRequest when its InfoBar // OverlayRequestCancelHandler that cancels its OverlayRequest when its InfoBar
// is removed from its InfoBarManager. // is removed from its InfoBarManager.
class InfobarOverlayRequestCancelHandler : public OverlayRequestCancelHandler { class InfobarOverlayRequestCancelHandler : public OverlayRequestCancelHandler {
public: public:
InfobarOverlayRequestCancelHandler( InfobarOverlayRequestCancelHandler(OverlayRequest* request,
OverlayRequest* request, OverlayRequestQueue* queue);
OverlayRequestQueue* queue,
InfobarOverlayType type,
const InfobarOverlayRequestInserter* inserter);
~InfobarOverlayRequestCancelHandler() override; ~InfobarOverlayRequestCancelHandler() override;
private: protected:
// Returns the InfoBar that the corresponding request was configured with. // Returns the InfoBar that the corresponding request was configured with.
infobars::InfoBar* infobar() const { return infobar_; } infobars::InfoBar* infobar() const { return infobar_; }
// Called when the infobar triggering |request| was replaced in its manager.
// Default implementation does nothing.
virtual void HandleReplacement(infobars::InfoBar* replacement);
private:
// Cancels the request for InfoBar removal. // Cancels the request for InfoBar removal.
void Cancel(); void Cancel();
// Inserts an OverlayRequest for |replacement| behind the cancel handler's
// request.
void InsertReplacementRequest(infobars::InfoBar* replacement);
// Helper object that triggers cancellation when its InfoBar is removed from // Helper object that triggers cancellation when its InfoBar is removed from
// its InfoBarManager. // its InfoBarManager.
class RemovalObserver : public infobars::InfoBarManager::Observer { class RemovalObserver : public infobars::InfoBarManager::Observer {
...@@ -54,8 +49,6 @@ class InfobarOverlayRequestCancelHandler : public OverlayRequestCancelHandler { ...@@ -54,8 +49,6 @@ class InfobarOverlayRequestCancelHandler : public OverlayRequestCancelHandler {
scoped_observer_; scoped_observer_;
}; };
InfobarOverlayType type_;
const InfobarOverlayRequestInserter* inserter_ = nullptr;
infobars::InfoBar* infobar_ = nullptr; infobars::InfoBar* infobar_ = nullptr;
RemovalObserver removal_observer_; RemovalObserver removal_observer_;
}; };
......
...@@ -7,8 +7,7 @@ ...@@ -7,8 +7,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar.h"
#include "ios/chrome/browser/infobars/infobar_ios.h" #include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" #include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
#import "ios/chrome/browser/overlays/public/overlay_request.h" #import "ios/chrome/browser/overlays/public/overlay_request.h"
#import "ios/chrome/browser/overlays/public/overlay_request_queue.h" #import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
...@@ -23,39 +22,27 @@ using infobars::InfoBarManager; ...@@ -23,39 +22,27 @@ using infobars::InfoBarManager;
InfobarOverlayRequestCancelHandler::InfobarOverlayRequestCancelHandler( InfobarOverlayRequestCancelHandler::InfobarOverlayRequestCancelHandler(
OverlayRequest* request, OverlayRequest* request,
OverlayRequestQueue* queue, OverlayRequestQueue* queue)
InfobarOverlayType type,
const InfobarOverlayRequestInserter* inserter)
: OverlayRequestCancelHandler(request, queue), : OverlayRequestCancelHandler(request, queue),
type_(type), infobar_(GetOverlayRequestInfobar(request)),
inserter_(inserter),
infobar_(request->GetConfig<InfobarOverlayRequestConfig>()->infobar()),
removal_observer_(this) { removal_observer_(this) {
DCHECK(inserter_);
DCHECK(infobar_); DCHECK(infobar_);
} }
InfobarOverlayRequestCancelHandler::~InfobarOverlayRequestCancelHandler() = InfobarOverlayRequestCancelHandler::~InfobarOverlayRequestCancelHandler() =
default; default;
#pragma mark - Protected
void InfobarOverlayRequestCancelHandler::HandleReplacement(
InfoBar* replacement) {}
#pragma mark - Private
void InfobarOverlayRequestCancelHandler::Cancel() { void InfobarOverlayRequestCancelHandler::Cancel() {
CancelRequest(); CancelRequest();
} }
void InfobarOverlayRequestCancelHandler::InsertReplacementRequest(
InfoBar* replacement) {
size_t index = 0;
while (index < queue()->size()) {
InfobarOverlayRequestConfig* config =
queue()->GetRequest(index)->GetConfig<InfobarOverlayRequestConfig>();
if (config->infobar() == infobar())
break;
++index;
}
DCHECK_LT(index, queue()->size());
inserter_->InsertOverlayRequest(replacement, type_, index + 1);
}
#pragma mark - InfobarOverlayRequestCancelHandler::RemovalObserver #pragma mark - InfobarOverlayRequestCancelHandler::RemovalObserver
InfobarOverlayRequestCancelHandler::RemovalObserver::RemovalObserver( InfobarOverlayRequestCancelHandler::RemovalObserver::RemovalObserver(
...@@ -75,19 +62,25 @@ void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarRemoved( ...@@ -75,19 +62,25 @@ void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarRemoved(
bool animate) { bool animate) {
if (cancel_handler_->infobar() == infobar) if (cancel_handler_->infobar() == infobar)
cancel_handler_->Cancel(); cancel_handler_->Cancel();
// The cancel handler is destroyed after Cancel(), so no code can be added
// after this call.
} }
void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarReplaced( void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarReplaced(
InfoBar* old_infobar, InfoBar* old_infobar,
InfoBar* new_infobar) { InfoBar* new_infobar) {
if (cancel_handler_->infobar() == old_infobar) { if (cancel_handler_->infobar() == old_infobar) {
cancel_handler_->InsertReplacementRequest(new_infobar); cancel_handler_->HandleReplacement(new_infobar);
cancel_handler_->Cancel(); cancel_handler_->Cancel();
// The cancel handler is destroyed after Cancel(), so no code can be added
// after this call.
} }
} }
void InfobarOverlayRequestCancelHandler::RemovalObserver::OnManagerShuttingDown( void InfobarOverlayRequestCancelHandler::RemovalObserver::OnManagerShuttingDown(
infobars::InfoBarManager* manager) { infobars::InfoBarManager* manager) {
cancel_handler_->Cancel();
scoped_observer_.Remove(manager); scoped_observer_.Remove(manager);
cancel_handler_->Cancel();
// The cancel handler is destroyed after Cancel(), so no code can be added
// after this call.
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "ios/chrome/browser/infobars/infobar_manager_impl.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
#include "ios/chrome/browser/infobars/test/fake_infobar_delegate.h" #include "ios/chrome/browser/infobars/test/fake_infobar_delegate.h"
#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h" #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
...@@ -29,39 +30,33 @@ using infobars::InfoBarManager; ...@@ -29,39 +30,33 @@ using infobars::InfoBarManager;
// Test fixture for InfobarOverlayRequestCancelHandler. // Test fixture for InfobarOverlayRequestCancelHandler.
class InfobarOverlayRequestCancelHandlerTest : public PlatformTest { class InfobarOverlayRequestCancelHandlerTest : public PlatformTest {
public: public:
InfobarOverlayRequestCancelHandlerTest() InfobarOverlayRequestCancelHandlerTest() {
: inserter_(&web_state_,
std::make_unique<FakeInfobarOverlayRequestFactory>()) {
// Set up WebState and InfoBarManager.
web_state_.SetNavigationManager( web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>()); std::make_unique<web::TestNavigationManager>());
InfobarOverlayRequestInserter::CreateForWebState(
&web_state_, std::make_unique<FakeInfobarOverlayRequestFactory>());
InfoBarManagerImpl::CreateForWebState(&web_state_); InfoBarManagerImpl::CreateForWebState(&web_state_);
} }
OverlayRequestQueue* queue() { OverlayRequestQueue* queue() {
return OverlayRequestQueue::FromWebState(&web_state_, return OverlayRequestQueue::FromWebState(&web_state_,
OverlayModality::kInfobarBanner); OverlayModality::kInfobarModal);
} }
InfoBarManager* manager() { InfoBarManager* manager() {
return InfoBarManagerImpl::FromWebState(&web_state_); return InfoBarManagerImpl::FromWebState(&web_state_);
} }
InfobarOverlayRequestInserter* inserter() { return &inserter_; } InfobarOverlayRequestInserter* inserter() {
return InfobarOverlayRequestInserter::FromWebState(&web_state_);
}
// Returns the InfoBar used to create the front request in queue(). // Returns the InfoBar used to create the front request in queue().
InfoBar* GetFrontRequestInfobar() { InfoBar* GetFrontRequestInfobar() {
OverlayRequest* front_request = queue()->front_request(); OverlayRequest* front_request = queue()->front_request();
if (!front_request) return front_request ? GetOverlayRequestInfobar(front_request) : nullptr;
return nullptr;
InfobarOverlayRequestConfig* config =
front_request->GetConfig<InfobarOverlayRequestConfig>();
if (!config)
return nullptr;
return config->infobar();
} }
private: private:
web::TestWebState web_state_; web::TestWebState web_state_;
InfobarOverlayRequestInserter inserter_;
}; };
// Tests that the request is cancelled when its corresponding InfoBar is removed // Tests that the request is cancelled when its corresponding InfoBar is removed
...@@ -70,7 +65,7 @@ TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) { ...@@ -70,7 +65,7 @@ TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) {
std::unique_ptr<InfoBar> added_infobar = std::make_unique<FakeInfobarIOS>(); std::unique_ptr<InfoBar> added_infobar = std::make_unique<FakeInfobarIOS>();
InfoBar* infobar = added_infobar.get(); InfoBar* infobar = added_infobar.get();
manager()->AddInfoBar(std::move(added_infobar)); manager()->AddInfoBar(std::move(added_infobar));
inserter()->AddOverlayRequest(infobar, InfobarOverlayType::kBanner); inserter()->AddOverlayRequest(infobar, InfobarOverlayType::kModal);
ASSERT_EQ(infobar, GetFrontRequestInfobar()); ASSERT_EQ(infobar, GetFrontRequestInfobar());
// Remove the InfoBar from its manager and verify that the request has been // Remove the InfoBar from its manager and verify that the request has been
// removed from the queue. // removed from the queue.
...@@ -78,20 +73,16 @@ TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) { ...@@ -78,20 +73,16 @@ TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) {
EXPECT_FALSE(queue()->front_request()); EXPECT_FALSE(queue()->front_request());
} }
// Tests that the request is replaced if its corresponding InfoBar is replaced // Tests that the request is cancelled if its corresponding InfoBar is replaced
// in its manager. // in its manager.
TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarReplacement) { TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarReplacement) {
std::unique_ptr<InfoBar> first_passed_infobar = std::unique_ptr<InfoBar> first_passed_infobar =
std::make_unique<FakeInfobarIOS>(); std::make_unique<FakeInfobarIOS>();
InfoBar* first_infobar = first_passed_infobar.get(); InfoBar* first_infobar = first_passed_infobar.get();
manager()->AddInfoBar(std::move(first_passed_infobar)); manager()->AddInfoBar(std::move(first_passed_infobar));
inserter()->AddOverlayRequest(first_infobar, InfobarOverlayType::kBanner); inserter()->AddOverlayRequest(first_infobar, InfobarOverlayType::kModal);
ASSERT_EQ(first_infobar, GetFrontRequestInfobar()); ASSERT_EQ(first_infobar, GetFrontRequestInfobar());
// Replace with a new infobar and verify that the request has been replaced. // Replace with a new infobar and verify that the request has been cancelled.
std::unique_ptr<InfoBar> second_passed_infobar = manager()->ReplaceInfoBar(first_infobar, std::make_unique<FakeInfobarIOS>());
std::make_unique<FakeInfobarIOS>(); EXPECT_FALSE(queue()->front_request());
InfoBar* second_infobar = second_passed_infobar.get();
manager()->ReplaceInfoBar(first_infobar, std::move(second_passed_infobar));
EXPECT_EQ(second_infobar, GetFrontRequestInfobar());
EXPECT_EQ(1U, queue()->size());
} }
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h" #include "ios/chrome/browser/overlays/public/overlay_request.h"
class InfoBarIOS;
// Implementation of InfobarOverlayRequestFactory. // Implementation of InfobarOverlayRequestFactory.
class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory { class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory {
public: public:
...@@ -33,7 +35,7 @@ class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory { ...@@ -33,7 +35,7 @@ class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory {
virtual ~FactoryHelper() = default; virtual ~FactoryHelper() = default;
virtual std::unique_ptr<OverlayRequest> CreateInfobarRequest( virtual std::unique_ptr<OverlayRequest> CreateInfobarRequest(
infobars::InfoBar* infobar) const = 0; InfoBarIOS* infobar) const = 0;
}; };
// Template for a helper objects used to create OverlayRequests. // Template for a helper objects used to create OverlayRequests.
...@@ -47,7 +49,7 @@ class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory { ...@@ -47,7 +49,7 @@ class InfobarOverlayRequestFactoryImpl : public InfobarOverlayRequestFactory {
// CreationHelperBase: // CreationHelperBase:
std::unique_ptr<OverlayRequest> CreateInfobarRequest( std::unique_ptr<OverlayRequest> CreateInfobarRequest(
infobars::InfoBar* infobar) const override { InfoBarIOS* infobar) const override {
return OverlayRequest::CreateWithConfig<RequestConfigType>(infobar); return OverlayRequest::CreateWithConfig<RequestConfigType>(infobar);
} }
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#import "ios/chrome/browser/infobars/infobar_ios.h" #import "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h" #import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h" #import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -13,7 +14,6 @@ ...@@ -13,7 +14,6 @@
#endif #endif
using infobars::InfoBar; using infobars::InfoBar;
using infobars::InfoBarDelegate;
InfobarOverlayRequestFactoryImpl::InfobarOverlayRequestFactoryImpl() { InfobarOverlayRequestFactoryImpl::InfobarOverlayRequestFactoryImpl() {
// Create the factory helpers for the supported infobar types. // Create the factory helpers for the supported infobar types.
...@@ -21,7 +21,8 @@ InfobarOverlayRequestFactoryImpl::InfobarOverlayRequestFactoryImpl() { ...@@ -21,7 +21,8 @@ InfobarOverlayRequestFactoryImpl::InfobarOverlayRequestFactoryImpl() {
// types. // types.
SetUpFactories(InfobarType::kInfobarTypePasswordSave, SetUpFactories(InfobarType::kInfobarTypePasswordSave,
CreateFactory<SavePasswordInfobarBannerOverlayRequestConfig>(), CreateFactory<SavePasswordInfobarBannerOverlayRequestConfig>(),
/*detail_sheet_factory=*/nullptr, /*modal_factory=*/nullptr); /*detail_sheet_factory=*/nullptr,
CreateFactory<PasswordInfobarModalOverlayRequestConfig>());
} }
InfobarOverlayRequestFactoryImpl::~InfobarOverlayRequestFactoryImpl() = default; InfobarOverlayRequestFactoryImpl::~InfobarOverlayRequestFactoryImpl() = default;
...@@ -35,7 +36,7 @@ InfobarOverlayRequestFactoryImpl::CreateInfobarRequest( ...@@ -35,7 +36,7 @@ InfobarOverlayRequestFactoryImpl::CreateInfobarRequest(
// It is an error to call this for an InfobarType/InfobarOverlayType combo // It is an error to call this for an InfobarType/InfobarOverlayType combo
// that has not been added to the factory storages. // that has not been added to the factory storages.
return factory_storages_[infobar_ios->InfobarUIDelegate().infobarType][type] return factory_storages_[infobar_ios->InfobarUIDelegate().infobarType][type]
->CreateInfobarRequest(infobar); ->CreateInfobarRequest(infobar_ios);
} }
void InfobarOverlayRequestFactoryImpl::SetUpFactories( void InfobarOverlayRequestFactoryImpl::SetUpFactories(
......
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
#include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h" #include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
#include "ios/chrome/browser/infobars/infobar_ios.h" #include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h" #import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.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/test/fake_infobar_ui_delegate.h" #import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -43,19 +45,24 @@ class InfobarOverlayRequestFactoryImplTest : public PlatformTest { ...@@ -43,19 +45,24 @@ class InfobarOverlayRequestFactoryImplTest : public PlatformTest {
TEST_F(InfobarOverlayRequestFactoryImplTest, SavePasswords) { TEST_F(InfobarOverlayRequestFactoryImplTest, SavePasswords) {
FakeInfobarUIDelegate* ui_delegate = [[FakeInfobarUIDelegate alloc] init]; FakeInfobarUIDelegate* ui_delegate = [[FakeInfobarUIDelegate alloc] init];
ui_delegate.infobarType = InfobarType::kInfobarTypePasswordSave; ui_delegate.infobarType = InfobarType::kInfobarTypePasswordSave;
std::unique_ptr<password_manager::MockPasswordFormManagerForUI> form_manager = GURL url("https://chromium.test");
std::make_unique<password_manager::MockPasswordFormManagerForUI>();
autofill::PasswordForm form;
EXPECT_CALL(*form_manager, GetPendingCredentials())
.WillRepeatedly(testing::ReturnRef(form));
std::unique_ptr<InfoBarDelegate> delegate = std::unique_ptr<InfoBarDelegate> delegate =
std::make_unique<IOSChromeSavePasswordInfoBarDelegate>( MockIOSChromeSavePasswordInfoBarDelegate::Create(@"username", @"password",
false, false, std::move(form_manager)); url);
InfoBarIOS infobar(ui_delegate, std::move(delegate)); InfoBarIOS infobar(ui_delegate, std::move(delegate));
std::unique_ptr<OverlayRequest> request =
// Test banner request creation.
std::unique_ptr<OverlayRequest> banner_request =
factory()->CreateInfobarRequest(&infobar, InfobarOverlayType::kBanner); factory()->CreateInfobarRequest(&infobar, InfobarOverlayType::kBanner);
EXPECT_TRUE(banner_request
->GetConfig<SavePasswordInfobarBannerOverlayRequestConfig>());
// Test modal request creation.
std::unique_ptr<OverlayRequest> modal_request =
factory()->CreateInfobarRequest(&infobar, InfobarOverlayType::kModal);
EXPECT_TRUE( EXPECT_TRUE(
request->GetConfig<SavePasswordInfobarBannerOverlayRequestConfig>()); modal_request->GetConfig<PasswordInfobarModalOverlayRequestConfig>());
// TODO(crbug.com/1033154): Add additional tests for other // TODO(crbug.com/1033154): Add additional tests for other
// InfobarOverlayTypes. // InfobarOverlayTypes.
} }
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include <map> #include <map>
#include <memory> #include <memory>
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl.h"
#include "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h" #include "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
#include "ios/web/public/web_state_user_data.h"
namespace infobars { namespace infobars {
class InfoBar; class InfoBar;
...@@ -21,15 +23,17 @@ class WebState; ...@@ -21,15 +23,17 @@ class WebState;
// Helper object that creates OverlayRequests for InfoBars and inserts them into // Helper object that creates OverlayRequests for InfoBars and inserts them into
// a WebState's OverlayRequestQueues. // a WebState's OverlayRequestQueues.
class InfobarOverlayRequestInserter { class InfobarOverlayRequestInserter
: public web::WebStateUserData<InfobarOverlayRequestInserter> {
public: public:
// Constructor for an inserter that uses |factory| to construct // Creates an inserter for |web_state| that uses |request_factory| to create
// OverlayRequests to insert into |web_state|'s OverlayRequestQueues. Both // inserted requests.
// |web_state| and |factory| must be non-null. static void CreateForWebState(
InfobarOverlayRequestInserter(
web::WebState* web_state, web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> factory); std::unique_ptr<InfobarOverlayRequestFactory> request_factory =
~InfobarOverlayRequestInserter(); std::make_unique<InfobarOverlayRequestFactoryImpl>());
~InfobarOverlayRequestInserter() override;
// Creates an OverlayRequest for |type| configured with |infobar| and adds it // Creates an OverlayRequest for |type| configured with |infobar| and adds it
// to the back of the OverlayRequestQueue at |type|'s modality. // to the back of the OverlayRequestQueue at |type|'s modality.
...@@ -44,6 +48,16 @@ class InfobarOverlayRequestInserter { ...@@ -44,6 +48,16 @@ class InfobarOverlayRequestInserter {
size_t index) const; size_t index) const;
private: private:
friend class web::WebStateUserData<InfobarOverlayRequestInserter>;
WEB_STATE_USER_DATA_KEY_DECL();
// Constructor for an inserter that uses |factory| to construct
// OverlayRequests to insert into |web_state|'s OverlayRequestQueues. Both
// |web_state| and |factory| must be non-null.
InfobarOverlayRequestInserter(
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> factory);
// The WebState whose queues are being inserted into. // The WebState whose queues are being inserted into.
web::WebState* web_state_ = nullptr; web::WebState* web_state_ = nullptr;
// The factory used to create OverlayRequests. // The factory used to create OverlayRequests.
......
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "ios/chrome/browser/infobars/infobar_ios.h" #include "ios/chrome/browser/infobars/infobar_ios.h"
#import "ios/chrome/browser/infobars/overlays/infobar_banner_overlay_request_cancel_handler.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_cancel_handler.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_cancel_handler.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h"
#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
...@@ -17,6 +19,20 @@ ...@@ -17,6 +19,20 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
WEB_STATE_USER_DATA_KEY_IMPL(InfobarOverlayRequestInserter)
// static
void InfobarOverlayRequestInserter::CreateForWebState(
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> request_factory) {
DCHECK(web_state);
if (!FromWebState(web_state)) {
web_state->SetUserData(UserDataKey(),
base::WrapUnique(new InfobarOverlayRequestInserter(
web_state, std::move(request_factory))));
}
}
InfobarOverlayRequestInserter::InfobarOverlayRequestInserter( InfobarOverlayRequestInserter::InfobarOverlayRequestInserter(
web::WebState* web_state, web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> factory) std::unique_ptr<InfobarOverlayRequestFactory> factory)
...@@ -51,8 +67,18 @@ void InfobarOverlayRequestInserter::InsertOverlayRequest( ...@@ -51,8 +67,18 @@ void InfobarOverlayRequestInserter::InsertOverlayRequest(
DCHECK_EQ(static_cast<InfoBarIOS*>(infobar), DCHECK_EQ(static_cast<InfoBarIOS*>(infobar),
request->GetConfig<InfobarOverlayRequestConfig>()->infobar()); request->GetConfig<InfobarOverlayRequestConfig>()->infobar());
OverlayRequestQueue* queue = queues_.at(type); OverlayRequestQueue* queue = queues_.at(type);
std::unique_ptr<OverlayRequestCancelHandler> cancel_handler = std::unique_ptr<OverlayRequestCancelHandler> cancel_handler;
std::make_unique<InfobarOverlayRequestCancelHandler>(request.get(), queue, switch (type) {
type, this); case InfobarOverlayType::kBanner:
cancel_handler =
std::make_unique<InfobarBannerOverlayRequestCancelHandler>(
request.get(), queue, this);
break;
case InfobarOverlayType::kDetailSheet:
case InfobarOverlayType::kModal:
cancel_handler = std::make_unique<InfobarOverlayRequestCancelHandler>(
request.get(), queue);
break;
}
queue->InsertRequest(index, std::move(request), std::move(cancel_handler)); queue->InsertRequest(index, std::move(request), std::move(cancel_handler));
} }
...@@ -27,16 +27,18 @@ using infobars::InfoBarManager; ...@@ -27,16 +27,18 @@ using infobars::InfoBarManager;
// Test fixture for InfobarOverlayRequestInserter. // Test fixture for InfobarOverlayRequestInserter.
class InfobarOverlayRequestInserterTest : public PlatformTest { class InfobarOverlayRequestInserterTest : public PlatformTest {
public: public:
InfobarOverlayRequestInserterTest() InfobarOverlayRequestInserterTest() {
: inserter_(&web_state_,
std::make_unique<FakeInfobarOverlayRequestFactory>()) {
web_state_.SetNavigationManager( web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>()); std::make_unique<web::TestNavigationManager>());
InfobarOverlayRequestInserter::CreateForWebState(
&web_state_, std::make_unique<FakeInfobarOverlayRequestFactory>());
InfoBarManagerImpl::CreateForWebState(&web_state_); InfoBarManagerImpl::CreateForWebState(&web_state_);
} }
// Accessors. // Accessors.
InfobarOverlayRequestInserter* inserter() { return &inserter_; } InfobarOverlayRequestInserter* inserter() {
return InfobarOverlayRequestInserter::FromWebState(&web_state_);
}
InfoBarManager* manager() { InfoBarManager* manager() {
return InfoBarManagerImpl::FromWebState(&web_state_); return InfoBarManagerImpl::FromWebState(&web_state_);
} }
...@@ -58,7 +60,6 @@ class InfobarOverlayRequestInserterTest : public PlatformTest { ...@@ -58,7 +60,6 @@ class InfobarOverlayRequestInserterTest : public PlatformTest {
private: private:
web::TestWebState web_state_; web::TestWebState web_state_;
InfobarOverlayRequestInserter inserter_;
}; };
// Tests that the inserter adds banner OverlayRequests to the correct queue. // Tests that the inserter adds banner OverlayRequests to the correct queue.
......
...@@ -9,10 +9,8 @@ ...@@ -9,10 +9,8 @@
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "components/infobars/core/infobar_manager.h" #include "components/infobars/core/infobar_manager.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#import "ios/web/public/web_state_user_data.h" #import "ios/web/public/web_state_user_data.h"
class InfobarOverlayRequestFactory;
class InfobarOverlayRequestInserter; class InfobarOverlayRequestInserter;
// Helper class that creates OverlayRequests for the banner UI for InfoBars // Helper class that creates OverlayRequests for the banner UI for InfoBars
...@@ -22,23 +20,14 @@ class InfobarOverlayTabHelper ...@@ -22,23 +20,14 @@ class InfobarOverlayTabHelper
public: public:
~InfobarOverlayTabHelper() override; ~InfobarOverlayTabHelper() override;
// Creates an InfobarOverlayTabHelper scoped to |web_state| that creates
// OverlayRequests for InfoBars added to |web_state|'s InfoBarManagerImpl
// using |request_factory|.
static void CreateForWebState(
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> request_factory);
private: private:
InfobarOverlayTabHelper(
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> request_factory);
friend class web::WebStateUserData<InfobarOverlayTabHelper>; friend class web::WebStateUserData<InfobarOverlayTabHelper>;
InfobarOverlayTabHelper(web::WebState* web_state);
WEB_STATE_USER_DATA_KEY_DECL(); WEB_STATE_USER_DATA_KEY_DECL();
// Getter for the request inserter. // Getter for the request inserter.
const InfobarOverlayRequestInserter* request_inserter() const { const InfobarOverlayRequestInserter* request_inserter() const {
return &request_inserter_; return request_inserter_;
} }
// Helper object that schedules OverlayRequests for the banner UI for InfoBars // Helper object that schedules OverlayRequests for the banner UI for InfoBars
...@@ -62,7 +51,7 @@ class InfobarOverlayTabHelper ...@@ -62,7 +51,7 @@ class InfobarOverlayTabHelper
}; };
// The inserter used to add infobar OverlayRequests to the WebState's queue. // The inserter used to add infobar OverlayRequests to the WebState's queue.
InfobarOverlayRequestInserter request_inserter_; InfobarOverlayRequestInserter* request_inserter_;
// The scheduler used to create OverlayRequests for InfoBars added to the // The scheduler used to create OverlayRequests for InfoBars added to the
// corresponding WebState's InfoBarManagerImpl. // corresponding WebState's InfoBarManagerImpl.
OverlayRequestScheduler request_scheduler_; OverlayRequestScheduler request_scheduler_;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "ios/chrome/browser/infobars/infobar_manager_impl.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h" #include "ios/chrome/browser/overlays/public/overlay_request.h"
#import "ios/chrome/browser/overlays/public/overlay_request_queue.h" #import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
...@@ -21,22 +22,8 @@ using infobars::InfoBarManager; ...@@ -21,22 +22,8 @@ using infobars::InfoBarManager;
WEB_STATE_USER_DATA_KEY_IMPL(InfobarOverlayTabHelper) WEB_STATE_USER_DATA_KEY_IMPL(InfobarOverlayTabHelper)
// static InfobarOverlayTabHelper::InfobarOverlayTabHelper(web::WebState* web_state)
void InfobarOverlayTabHelper::CreateForWebState( : request_inserter_(InfobarOverlayRequestInserter::FromWebState(web_state)),
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> request_factory) {
DCHECK(web_state);
if (!FromWebState(web_state)) {
web_state->SetUserData(UserDataKey(),
base::WrapUnique(new InfobarOverlayTabHelper(
web_state, std::move(request_factory))));
}
}
InfobarOverlayTabHelper::InfobarOverlayTabHelper(
web::WebState* web_state,
std::unique_ptr<InfobarOverlayRequestFactory> request_factory)
: request_inserter_(web_state, std::move(request_factory)),
request_scheduler_(web_state, this) {} request_scheduler_(web_state, this) {}
InfobarOverlayTabHelper::~InfobarOverlayTabHelper() = default; InfobarOverlayTabHelper::~InfobarOverlayTabHelper() = default;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ios/chrome/browser/infobars/infobar_manager_impl.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#include "ios/chrome/browser/infobars/test/fake_infobar_delegate.h" #include "ios/chrome/browser/infobars/test/fake_infobar_delegate.h"
#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h" #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
#include "ios/chrome/browser/overlays/public/overlay_request.h" #include "ios/chrome/browser/overlays/public/overlay_request.h"
...@@ -35,8 +36,9 @@ class InfobarOverlayTabHelperTest : public PlatformTest { ...@@ -35,8 +36,9 @@ class InfobarOverlayTabHelperTest : public PlatformTest {
web_state_.SetNavigationManager( web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>()); std::make_unique<web::TestNavigationManager>());
InfoBarManagerImpl::CreateForWebState(&web_state_); InfoBarManagerImpl::CreateForWebState(&web_state_);
InfobarOverlayTabHelper::CreateForWebState( InfobarOverlayRequestInserter::CreateForWebState(
&web_state_, std::make_unique<FakeInfobarOverlayRequestFactory>()); &web_state_, std::make_unique<FakeInfobarOverlayRequestFactory>());
InfobarOverlayTabHelper::CreateForWebState(&web_state_);
} }
// Returns the front request of |web_state_|'s OverlayRequestQueue. // Returns the front request of |web_state_|'s OverlayRequestQueue.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h" #include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h"
#import "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/infobars/infobar_manager_impl.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_factory_impl.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_tab_helper.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_tab_helper.h"
#import "ios/chrome/browser/itunes_urls/itunes_urls_handler_tab_helper.h" #import "ios/chrome/browser/itunes_urls/itunes_urls_handler_tab_helper.h"
#import "ios/chrome/browser/network_activity/network_activity_indicator_tab_helper.h" #import "ios/chrome/browser/network_activity/network_activity_indicator_tab_helper.h"
...@@ -95,8 +96,8 @@ void AttachTabHelpers(web::WebState* web_state, bool for_prerender) { ...@@ -95,8 +96,8 @@ void AttachTabHelpers(web::WebState* web_state, bool for_prerender) {
IOSTaskTabHelper::CreateForWebState(web_state); IOSTaskTabHelper::CreateForWebState(web_state);
if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) { if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) {
InfobarOverlayTabHelper::CreateForWebState( InfobarOverlayRequestInserter::CreateForWebState(web_state);
web_state, std::make_unique<InfobarOverlayRequestFactoryImpl>()); InfobarOverlayTabHelper::CreateForWebState(web_state);
} }
if (base::FeatureList::IsEnabled(kCaptivePortalMetrics)) { if (base::FeatureList::IsEnabled(kCaptivePortalMetrics)) {
......
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