Commit 2086423e authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Handle InfoBar replacement.

Updates InfobarOverlayRequestCancelHandler to handle InfoBar
replacements.  When the corresponding request's InfoBar has been
replaced, the cancel handler creates an OverlayRequest for the
replacement and inserts it in the queue after the replaced InfoBar's
request.  Then, the existing request is cancelled, removing it from
the queue.

Bug: 1030357
Change-Id: Idff53a277c4115adb6075017db5aed4c4e3afac7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1960810
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726021}
parent 25abdbcd
...@@ -7,41 +7,56 @@ ...@@ -7,41 +7,56 @@
#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(OverlayRequest* request, InfobarOverlayRequestCancelHandler(
OverlayRequest* request,
OverlayRequestQueue* queue, OverlayRequestQueue* queue,
infobars::InfoBar* infobar); InfobarOverlayType type,
const InfobarOverlayRequestInserter* inserter);
~InfobarOverlayRequestCancelHandler() override; ~InfobarOverlayRequestCancelHandler() override;
private: private:
// Returns the InfoBar that the corresponding request was configured with.
infobars::InfoBar* infobar() const { return infobar_; }
// 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 {
public: public:
RemovalObserver(infobars::InfoBar* infobar, RemovalObserver(InfobarOverlayRequestCancelHandler* cancel_handler);
InfobarOverlayRequestCancelHandler* cancel_handler);
~RemovalObserver() override; ~RemovalObserver() override;
private: private:
// infobars::InfoBarManager::Observer: // infobars::InfoBarManager::Observer:
void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override; void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override;
void OnInfoBarReplaced(infobars::InfoBar* old_infobar,
infobars::InfoBar* new_infobar) override;
void OnManagerShuttingDown(infobars::InfoBarManager* manager) override; void OnManagerShuttingDown(infobars::InfoBarManager* manager) override;
private: private:
infobars::InfoBar* infobar_ = nullptr;
InfobarOverlayRequestCancelHandler* cancel_handler_ = nullptr; InfobarOverlayRequestCancelHandler* cancel_handler_ = nullptr;
ScopedObserver<infobars::InfoBarManager, infobars::InfoBarManager::Observer> ScopedObserver<infobars::InfoBarManager, infobars::InfoBarManager::Observer>
scoped_observer_; scoped_observer_;
}; };
InfobarOverlayType type_;
const InfobarOverlayRequestInserter* inserter_ = nullptr;
infobars::InfoBar* infobar_ = nullptr;
RemovalObserver removal_observer_; RemovalObserver removal_observer_;
}; };
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "base/logging.h" #include "base/logging.h"
#include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar.h"
#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.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_queue.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support." #error "This file requires ARC support."
...@@ -19,9 +23,16 @@ using infobars::InfoBarManager; ...@@ -19,9 +23,16 @@ using infobars::InfoBarManager;
InfobarOverlayRequestCancelHandler::InfobarOverlayRequestCancelHandler( InfobarOverlayRequestCancelHandler::InfobarOverlayRequestCancelHandler(
OverlayRequest* request, OverlayRequest* request,
OverlayRequestQueue* queue, OverlayRequestQueue* queue,
InfoBar* infobar) InfobarOverlayType type,
const InfobarOverlayRequestInserter* inserter)
: OverlayRequestCancelHandler(request, queue), : OverlayRequestCancelHandler(request, queue),
removal_observer_(infobar, this) {} type_(type),
inserter_(inserter),
infobar_(request->GetConfig<InfobarOverlayRequestConfig>()->infobar()),
removal_observer_(this) {
DCHECK(inserter_);
DCHECK(infobar_);
}
InfobarOverlayRequestCancelHandler::~InfobarOverlayRequestCancelHandler() = InfobarOverlayRequestCancelHandler::~InfobarOverlayRequestCancelHandler() =
default; default;
...@@ -30,17 +41,27 @@ void InfobarOverlayRequestCancelHandler::Cancel() { ...@@ -30,17 +41,27 @@ 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(
InfoBar* infobar,
InfobarOverlayRequestCancelHandler* cancel_handler) InfobarOverlayRequestCancelHandler* cancel_handler)
: infobar_(infobar), : cancel_handler_(cancel_handler), scoped_observer_(this) {
cancel_handler_(cancel_handler),
scoped_observer_(this) {
DCHECK(infobar_);
DCHECK(cancel_handler_); DCHECK(cancel_handler_);
InfoBarManager* manager = infobar_->owner(); InfoBarManager* manager = cancel_handler_->infobar()->owner();
DCHECK(manager); DCHECK(manager);
scoped_observer_.Add(manager); scoped_observer_.Add(manager);
} }
...@@ -51,8 +72,17 @@ InfobarOverlayRequestCancelHandler::RemovalObserver::~RemovalObserver() = ...@@ -51,8 +72,17 @@ InfobarOverlayRequestCancelHandler::RemovalObserver::~RemovalObserver() =
void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarRemoved( void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarRemoved(
infobars::InfoBar* infobar, infobars::InfoBar* infobar,
bool animate) { bool animate) {
if (infobar_ == infobar) if (cancel_handler_->infobar() == infobar)
cancel_handler_->Cancel();
}
void InfobarOverlayRequestCancelHandler::RemovalObserver::OnInfoBarReplaced(
InfoBar* old_infobar,
InfoBar* new_infobar) {
if (cancel_handler_->infobar() == old_infobar) {
cancel_handler_->InsertReplacementRequest(new_infobar);
cancel_handler_->Cancel(); cancel_handler_->Cancel();
}
} }
void InfobarOverlayRequestCancelHandler::RemovalObserver::OnManagerShuttingDown( void InfobarOverlayRequestCancelHandler::RemovalObserver::OnManagerShuttingDown(
......
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
#include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar.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/fake_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"
#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.h"
#include "ios/chrome/browser/overlays/public/overlay_request_queue.h" #include "ios/chrome/browser/overlays/public/overlay_request_queue.h"
#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" #include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
...@@ -26,23 +29,13 @@ using infobars::InfoBarManager; ...@@ -26,23 +29,13 @@ using infobars::InfoBarManager;
// Test fixture for InfobarOverlayRequestCancelHandler. // Test fixture for InfobarOverlayRequestCancelHandler.
class InfobarOverlayRequestCancelHandlerTest : public PlatformTest { class InfobarOverlayRequestCancelHandlerTest : public PlatformTest {
public: public:
InfobarOverlayRequestCancelHandlerTest() : PlatformTest() { InfobarOverlayRequestCancelHandlerTest()
: inserter_(&web_state_,
std::make_unique<FakeInfobarOverlayRequestFactory>()) {
// Set up WebState and InfoBarManager. // Set up WebState and InfoBarManager.
web_state_.SetNavigationManager( web_state_.SetNavigationManager(
std::make_unique<web::TestNavigationManager>()); std::make_unique<web::TestNavigationManager>());
InfoBarManagerImpl::CreateForWebState(&web_state_); InfoBarManagerImpl::CreateForWebState(&web_state_);
// Create a test InfoBar and add it to the manager.
std::unique_ptr<InfoBar> infobar = std::make_unique<FakeInfobarIOS>();
infobar_ = infobar.get();
manager()->AddInfoBar(std::move(infobar));
// Create a fake OverlayRequest and add it to the infobar banner queue using
// an infobar cancel handler.
std::unique_ptr<OverlayRequest> request =
OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr);
std::unique_ptr<OverlayRequestCancelHandler> cancel_handler =
std::make_unique<InfobarOverlayRequestCancelHandler>(request.get(),
queue(), infobar_);
queue()->AddRequest(std::move(request), std::move(cancel_handler));
} }
OverlayRequestQueue* queue() { OverlayRequestQueue* queue() {
...@@ -52,19 +45,53 @@ class InfobarOverlayRequestCancelHandlerTest : public PlatformTest { ...@@ -52,19 +45,53 @@ class InfobarOverlayRequestCancelHandlerTest : public PlatformTest {
InfoBarManager* manager() { InfoBarManager* manager() {
return InfoBarManagerImpl::FromWebState(&web_state_); return InfoBarManagerImpl::FromWebState(&web_state_);
} }
InfoBar* infobar() { return infobar_; } InfobarOverlayRequestInserter* inserter() { return &inserter_; }
// Returns the InfoBar used to create the front request in queue().
InfoBar* GetFrontRequestInfobar() {
OverlayRequest* front_request = queue()->front_request();
if (!front_request)
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_;
InfoBar* infobar_ = nullptr; 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
// from its InfoBarManager. // from its InfoBarManager.
TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) { TEST_F(InfobarOverlayRequestCancelHandlerTest, CancelForInfobarRemoval) {
ASSERT_TRUE(queue()->front_request()); std::unique_ptr<InfoBar> added_infobar = std::make_unique<FakeInfobarIOS>();
// Remove the InfoBar and verify that the request has been removed from the InfoBar* infobar = added_infobar.get();
// queue. manager()->AddInfoBar(std::move(added_infobar));
manager()->RemoveInfoBar(infobar()); inserter()->AddOverlayRequest(infobar, InfobarOverlayType::kBanner);
ASSERT_EQ(infobar, GetFrontRequestInfobar());
// Remove the InfoBar from its manager and verify that the request has been
// removed from the queue.
manager()->RemoveInfoBar(infobar);
EXPECT_FALSE(queue()->front_request()); EXPECT_FALSE(queue()->front_request());
} }
// Tests that the request is replaced if its corresponding InfoBar is replaced
// in its manager.
TEST_F(InfobarOverlayRequestCancelHandlerTest, 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());
}
...@@ -52,6 +52,6 @@ void InfobarOverlayRequestInserter::InsertOverlayRequest( ...@@ -52,6 +52,6 @@ void InfobarOverlayRequestInserter::InsertOverlayRequest(
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, std::make_unique<InfobarOverlayRequestCancelHandler>(request.get(), queue,
infobar); type, this);
queue->InsertRequest(index, std::move(request), std::move(cancel_handler)); queue->InsertRequest(index, std::move(request), std::move(cancel_handler));
} }
...@@ -23,6 +23,10 @@ class OverlayRequestCancelHandler { ...@@ -23,6 +23,10 @@ class OverlayRequestCancelHandler {
// Called by subclasses to cancel the associated request. // Called by subclasses to cancel the associated request.
void CancelRequest(); void CancelRequest();
// Accessors for the request and queue.
OverlayRequest* request() const { return request_; }
OverlayRequestQueue* queue() const { return queue_; }
private: private:
OverlayRequest* request_ = nullptr; OverlayRequest* request_ = nullptr;
OverlayRequestQueue* queue_ = nullptr; OverlayRequestQueue* queue_ = nullptr;
......
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