Commit 6e3ace00 authored by Rohit Rao's avatar Rohit Rao Committed by Commit Bot

[ios] Deletes unused code that was migrated from ios/clean.

BUG=None

Change-Id: I3a14f465f152e9b1b514802723093e9702edc001
Reviewed-on: https://chromium-review.googlesource.com/c/1326487Reviewed-by: default avataredchin <edchin@chromium.org>
Reviewed-by: default avatarKurt Horimoto <kkhorimoto@chromium.org>
Commit-Queue: edchin <edchin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606834}
parent e826ee95
......@@ -111,7 +111,6 @@ source_set("browser_state_impl") {
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/browser_list:browser_list_impl",
"//ios/chrome/browser/ui/fullscreen",
"//ios/chrome/browser/ui/overlays",
"//ios/chrome/browser/ui/voice",
"//ios/chrome/browser/undo",
"//ios/chrome/browser/unified_consent",
......
......@@ -57,7 +57,6 @@
#include "ios/chrome/browser/ui/browser_list/browser_list_factory.h"
#include "ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h"
#include "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
#import "ios/chrome/browser/ui/overlays/overlay_service_factory.h"
#import "ios/chrome/browser/ui/voice/text_to_speech_playback_controller_factory.h"
#include "ios/chrome/browser/undo/bookmark_undo_service_factory.h"
#include "ios/chrome/browser/web_data_service_factory.h"
......@@ -131,7 +130,6 @@ void EnsureBrowserStateKeyedServiceFactoriesBuilt() {
UrlLanguageHistogramFactory::GetInstance();
BrowserDownloadServiceFactory::GetInstance();
FullscreenControllerFactory::GetInstance();
OverlayServiceFactory::GetInstance();
TextToSpeechPlaybackControllerFactory::GetInstance();
WebStateListWebUsageEnablerFactory::GetInstance();
}
......@@ -2,23 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("coordinators") {
sources = [
"browser_coordinator+internal.h",
"browser_coordinator.h",
"browser_coordinator.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
"//base",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/ui/browser_list",
]
}
source_set("chrome_coordinators") {
sources = [
"chrome_coordinator.h",
......@@ -31,43 +14,3 @@ source_set("chrome_coordinators") {
"//base",
]
}
source_set("test_support") {
testonly = true
sources = [
"browser_coordinator_test.h",
"browser_coordinator_test.mm",
"browser_coordinator_test_util.h",
"browser_coordinator_test_util.mm",
"test_browser_coordinator.h",
"test_browser_coordinator.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
":coordinators",
"//base",
"//base/test:test_support",
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/web_state_list:test_support",
"//ios/web/public/test",
"//testing/gtest",
]
}
source_set("unit_tests") {
testonly = true
sources = [
"browser_coordinator_unittest.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
":coordinators",
":test_support",
"//ios/chrome/browser/ui/commands",
]
}
// Copyright 2016 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_COORDINATORS_BROWSER_COORDINATOR_INTERNAL_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_INTERNAL_H_
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
// Internal API for subclasses and categories of BrowserCoordinator.
@interface BrowserCoordinator (Internal)
// Managed view controller of this object. Subclasses must define a
// property named |viewController| that has the specific UIViewController
// subclass they use; the subclass API will be able to access that view
// controller through this property.
@property(nonatomic, readonly) UIViewController* viewController;
// The child coordinators of this coordinator. To add or remove from this set,
// use the -addChildCoordinator: and -removeChildCoordinator: methods.
@property(nonatomic, readonly) NSSet<BrowserCoordinator*>* children;
// The coordinator that added this coordinator as a child, if any.
@property(nonatomic, readonly) BrowserCoordinator* parentCoordinator;
// YES if the receiver has been started; NO (the default) otherwise. Stopping
// the receiver resets this property to NO.
@property(nonatomic, readonly, getter=isStarted) BOOL started;
// Adds |coordinator| as a child, taking ownership of it, setting the receiver's
// viewController (if any) as the child's baseViewController, and setting
// the receiver's |browser| as the child's |browser|.
- (void)addChildCoordinator:(BrowserCoordinator*)childCoordinator;
// Removes |coordinator| as a child, relinquishing ownership of it. If
// |coordinator| isn't a child of the receiver, this method does nothing.
- (void)removeChildCoordinator:(BrowserCoordinator*)childCoordinator;
// Called when this coordinator is added to a parent coordinator.
- (void)wasAddedToParentCoordinator:(BrowserCoordinator*)parentCoordinator;
// Called when this coordinator is going to be removed from its parent
// coordinator.
- (void)willBeRemovedFromParentCoordinator;
// Called when this coordinator's UIViewController has finished being presented.
- (void)viewControllerWasActivated;
// Called when this coordinator's UIViewController has finished being dismissed.
- (void)viewControllerWasDeactivated;
// Called when a child coordinator did start. This is a blank template method.
// Subclasses can override this method when they need to know when their
// children start.
- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator;
// Called when a child coordinator will stop. This is a blank template method.
// Subclasses can override this method when they need to know when their
// children start.
- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator;
@end
#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_INTERNAL_H_
// Copyright 2016 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_COORDINATORS_BROWSER_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_H_
#import <UIKit/UIKit.h>
class Browser;
@class CommandDispatcher;
// Enum for defining the "mode" of the coordinator -- the way that its view
// controller is positioned in the view controller hierarchy. There's no
// property in the base class for this value, but subclasses may define a 'mode'
// property if they need to vary behavior or configuration based on the mode. In
// that case, the default should always be UNDEFINED.
typedef NS_ENUM(NSInteger, BrowserCoordinatorMode) {
UNDEFINED = 0,
PRESENTED, // The view controller is presented.
CONTAINED // The view controller is contained.
};
// An object that manages a UI component via a view controller.
// This is the public interface to this class; subclasses should also import
// the Internal category header (browser_coordinator+internal.h). This header
// file declares all the methods and properties a subclass must either override,
// call, or reset.
@interface BrowserCoordinator : NSObject
// The browser object used by this coordinator and passed into any child
// coordinators added to it. This is a weak pointer, and setting this property
// doesn't transfer ownership of the browser.
@property(nonatomic, assign) Browser* browser;
// The dispatcher this object should use to register and send commands.
// By default this is populated with the parent coordinator's dispatcher.
@property(nonatomic, strong) CommandDispatcher* dispatcher;
// self.dispatcher cast to |id|. Subclasses should redefine this property
// to conform to whatever protocols its view controllers and mediators expect.
@property(nonatomic, readonly) id callableDispatcher;
// The basic lifecycle methods for coordinators are -start and -stop. These
// implementations notify the parent coordinator when this coordinator did start
// and will stop. Child classes are expected to override and call the superclass
// method at the end of -start and at the beginning of -stop.
// If the receiver is already started, -start is a no-op. If the receiver is
// already stopped or never started, -stop is a no-op. In those cases, the
// overriding implementations can early return withotu calling the superclass
// method:
// SubCoordinator.mm:
// - (void)start {
// if (self.started) return;
// ...
// [super start];
// }
// Starts the user interaction managed by the receiver. Typical implementations
// will create a view controller and then use |baseViewController| to present
// it. This method needs to be called at the end of the overriding
// implementation.
// Starting a started coordinator is a no-op in this implementation.
- (void)start NS_REQUIRES_SUPER;
// Stops the user interaction managed by the receiver. This method needs to be
// called at the beginning of the overriding implementation.
// Calling stop on a coordinator transitively calls stop on its children.
// Stopping a non-started or stopped coordinator is a no-op in this
// implementation.
- (void)stop NS_REQUIRES_SUPER;
@end
#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_H_
// Copyright 2016 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/coordinators/browser_coordinator.h"
#import "base/ios/block_types.h"
#import "base/logging.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Enum class describing the current coordinator and consumer state.
enum class ActivationState {
DEACTIVATED, // The coordinator has been stopped or has never been started.
// its UIViewController has been fully dismissed.
ACTIVATING, // The coordinator has been started, but its UIViewController
// hasn't finished being presented.
ACTIVATED, // The coordinator has been started and its UIViewController has
// finished being presented.
DEACTIVATING, // The coordinator has been stopped, but its UIViewController
// hasn't finished being dismissed.
};
// Returns the presentation state to use after |current_state|.
ActivationState GetNextActivationState(ActivationState current_state) {
switch (current_state) {
case ActivationState::DEACTIVATED:
return ActivationState::ACTIVATING;
case ActivationState::ACTIVATING:
return ActivationState::ACTIVATED;
case ActivationState::ACTIVATED:
return ActivationState::DEACTIVATING;
case ActivationState::DEACTIVATING:
return ActivationState::DEACTIVATED;
}
}
}
@interface BrowserCoordinator ()
// The coordinator's presentation state.
@property(nonatomic, assign) ActivationState activationState;
// Child coordinators owned by this object.
@property(nonatomic, strong)
NSMutableSet<BrowserCoordinator*>* childCoordinators;
// Parent coordinator of this object, if any.
@property(nonatomic, readwrite, weak) BrowserCoordinator* parentCoordinator;
// Updates |activationState| to the next appropriate value after the in-
// progress transition animation finishes. If there is no animation occurring,
// the state is updated immediately.
- (void)updateActivationStateAfterTransition;
@end
@implementation BrowserCoordinator
@synthesize browser = _browser;
@synthesize dispatcher = _dispatcher;
@synthesize activationState = _activationState;
@synthesize childCoordinators = _childCoordinators;
@synthesize parentCoordinator = _parentCoordinator;
- (instancetype)init {
if (self = [super init]) {
_activationState = ActivationState::DEACTIVATED;
_childCoordinators = [NSMutableSet set];
}
return self;
}
- (void)dealloc {
for (BrowserCoordinator* child in self.children) {
[self removeChildCoordinator:child];
}
}
#pragma mark - Accessors
- (BOOL)isStarted {
return self.activationState == ActivationState::ACTIVATING ||
self.activationState == ActivationState::ACTIVATED;
}
- (void)setActivationState:(ActivationState)state {
if (_activationState == state)
return;
DCHECK_EQ(state, GetNextActivationState(_activationState))
<< "Unexpected activation state. Probably from calling |-stop| while"
<< "ACTIVATING or |-start| while DEACTIVATING.";
_activationState = state;
if (_activationState == ActivationState::DEACTIVATED) {
[self viewControllerWasDeactivated];
} else if (_activationState == ActivationState::ACTIVATED) {
[self viewControllerWasActivated];
}
}
#pragma mark - Public API
- (id)callableDispatcher {
return self.dispatcher;
}
- (void)start {
if (self.started)
return;
self.activationState = ActivationState::ACTIVATING;
[self.parentCoordinator childCoordinatorDidStart:self];
[self updateActivationStateAfterTransition];
}
- (void)stop {
if (!self.started)
return;
[self.parentCoordinator childCoordinatorWillStop:self];
self.activationState = ActivationState::DEACTIVATING;
for (BrowserCoordinator* child in self.children) {
[child stop];
}
[self updateActivationStateAfterTransition];
}
#pragma mark - Private
- (void)updateActivationStateAfterTransition {
DCHECK(self.activationState == ActivationState::ACTIVATING ||
self.activationState == ActivationState::DEACTIVATING);
ActivationState nextState = GetNextActivationState(self.activationState);
id<UIViewControllerTransitionCoordinator> transitionCoordinator =
self.viewController.transitionCoordinator;
if (transitionCoordinator) {
__weak BrowserCoordinator* weakSelf = self;
[transitionCoordinator animateAlongsideTransition:nil
completion:^(id context) {
weakSelf.activationState =
nextState;
}];
} else {
self.activationState = nextState;
}
}
@end
@implementation BrowserCoordinator (Internal)
// Concrete implementations must implement a |viewController| property.
@dynamic viewController;
- (NSSet*)children {
return [self.childCoordinators copy];
}
- (void)addChildCoordinator:(BrowserCoordinator*)childCoordinator {
CHECK([self respondsToSelector:@selector(viewController)])
<< "BrowserCoordinator implementations must provide a viewController "
"property.";
[self.childCoordinators addObject:childCoordinator];
childCoordinator.parentCoordinator = self;
childCoordinator.browser = self.browser;
childCoordinator.dispatcher = self.dispatcher;
[childCoordinator wasAddedToParentCoordinator:self];
}
- (void)removeChildCoordinator:(BrowserCoordinator*)childCoordinator {
if (![self.childCoordinators containsObject:childCoordinator])
return;
// Remove the grand-children first.
for (BrowserCoordinator* grandChild in childCoordinator.children) {
[childCoordinator removeChildCoordinator:grandChild];
}
// Remove the child.
[childCoordinator willBeRemovedFromParentCoordinator];
[self.childCoordinators removeObject:childCoordinator];
childCoordinator.parentCoordinator = nil;
childCoordinator.browser = nil;
}
- (void)wasAddedToParentCoordinator:(BrowserCoordinator*)parentCoordinator {
// Default implementation is a no-op.
}
- (void)willBeRemovedFromParentCoordinator {
// Default implementation is a no-op.
}
- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
// Default implementation is a no-op.
}
- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator {
// Default implementation is a no-op.
}
- (void)viewControllerWasActivated {
// Default implementation is a no-op.
}
- (void)viewControllerWasDeactivated {
// Default implementation is a no-op.
}
@end
// Copyright 2017 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_COORDINATORS_BROWSER_COORDINATOR_TEST_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_TEST_H_
#include <memory>
#include "ios/web/public/test/test_web_thread_bundle.h"
#include "testing/platform_test.h"
class Browser;
class TestChromeBrowserState;
class WebStateListDelegate;
class BrowserCoordinatorTest : public PlatformTest {
protected:
BrowserCoordinatorTest();
~BrowserCoordinatorTest() override;
Browser* GetBrowser() { return browser_.get(); }
private:
web::TestWebThreadBundle thread_bundle_;
std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
std::unique_ptr<WebStateListDelegate> delegate_;
std::unique_ptr<Browser> browser_;
DISALLOW_COPY_AND_ASSIGN(BrowserCoordinatorTest);
};
#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_TEST_H_
// Copyright 2017 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/coordinators/browser_coordinator_test.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
BrowserCoordinatorTest::BrowserCoordinatorTest() {
// Initialize the browser.
chrome_browser_state_ = TestChromeBrowserState::Builder().Build();
delegate_ = std::make_unique<FakeWebStateListDelegate>();
browser_ =
std::make_unique<Browser>(chrome_browser_state_.get(), delegate_.get());
}
BrowserCoordinatorTest::~BrowserCoordinatorTest() = default;
// Copyright 2017 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_COORDINATORS_BROWSER_COORDINATOR_TEST_UTIL_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_TEST_UTIL_H_
@class BrowserCoordinator;
// Waits for |coordinator|'s UI to finish being presented.
void WaitForBrowserCoordinatorActivation(BrowserCoordinator* coordinator);
// Waits for |coordinator|'s UI to finish being dismissed.
void WaitForBrowserCoordinatorDeactivation(BrowserCoordinator* coordinator);
#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_BROWSER_COORDINATOR_TEST_UTIL_H_
// Copyright 2017 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/coordinators/browser_coordinator_test_util.h"
#import "base/test/ios/wait_util.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
void WaitForBrowserCoordinatorActivation(BrowserCoordinator* coordinator) {
ASSERT_TRUE(coordinator);
UIViewController* view_controller = coordinator.viewController;
ASSERT_TRUE(view_controller);
EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForUIElementTimeout, ^bool {
return view_controller.presentingViewController &&
!view_controller.beingPresented;
}));
}
void WaitForBrowserCoordinatorDeactivation(BrowserCoordinator* coordinator) {
ASSERT_TRUE(coordinator);
UIViewController* view_controller = coordinator.viewController;
EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForUIElementTimeout, ^bool {
return !view_controller.presentingViewController &&
!view_controller.beingDismissed;
}));
}
// Copyright 2017 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/coordinators/browser_coordinator.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface TestCoordinator : BrowserCoordinator
@property(nonatomic) UIViewController* viewController;
@property(nonatomic, copy) void (^stopHandler)();
@property(nonatomic) BOOL wasAddedCalled;
@property(nonatomic) BOOL willBeRemovedCalled;
@property(nonatomic, copy) void (^willBeRemovedHandler)();
@property(nonatomic) BOOL removeCalled;
@property(nonatomic) BOOL childDidStartCalled;
@property(nonatomic) BOOL childWillStopCalled;
@end
@implementation TestCoordinator
@synthesize viewController = _viewController;
@synthesize stopHandler = _stopHandler;
@synthesize wasAddedCalled = _wasAddedCalled;
@synthesize willBeRemovedCalled = _willBeRemovedCalled;
@synthesize willBeRemovedHandler = _willBeRemovedHandler;
@synthesize removeCalled = _removeCalled;
@synthesize childDidStartCalled = _childDidStartCalled;
@synthesize childWillStopCalled = _childWillStopCalled;
- (instancetype)init {
if (!(self = [super init]))
return nil;
_viewController = [[UIViewController alloc] init];
return self;
}
- (void)stop {
[super stop];
if (self.stopHandler)
self.stopHandler();
}
- (void)wasAddedToParentCoordinator:(BrowserCoordinator*)parentCoordinator {
[super wasAddedToParentCoordinator:parentCoordinator];
self.wasAddedCalled = YES;
}
- (void)willBeRemovedFromParentCoordinator {
[super willBeRemovedFromParentCoordinator];
self.willBeRemovedCalled = YES;
if (self.willBeRemovedHandler)
self.willBeRemovedHandler();
}
- (void)removeChildCoordinator:(BrowserCoordinator*)childCoordinator {
[super removeChildCoordinator:childCoordinator];
self.removeCalled = YES;
}
- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
[super childCoordinatorDidStart:childCoordinator];
self.childDidStartCalled = YES;
}
- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator {
[super childCoordinatorWillStop:childCoordinator];
self.childWillStopCalled = YES;
}
@end
@interface NonOverlayableCoordinator : TestCoordinator
@end
@implementation NonOverlayableCoordinator
- (BOOL)canAddOverlayCoordinator:(BrowserCoordinator*)overlayCoordinator {
return NO;
}
@end
// Tests that -stop isn't called when a BrowserCoordinator is destroyed.
TEST_F(BrowserCoordinatorTest, TestDontStopOnDealloc) {
__block BOOL called = NO;
{
TestCoordinator* coordinator = [[TestCoordinator alloc] init];
coordinator.stopHandler = ^{
called = YES;
};
}
EXPECT_FALSE(called);
}
// Test that parents know who their children are, and that children know who
// their parent is.
TEST_F(BrowserCoordinatorTest, TestChildren) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
[parent addChildCoordinator:child];
EXPECT_TRUE([parent.children containsObject:child]);
EXPECT_EQ(parent, child.parentCoordinator);
[parent removeChildCoordinator:child];
EXPECT_FALSE([parent.children containsObject:child]);
EXPECT_EQ(nil, child.parentCoordinator);
TestCoordinator* otherParent = [[TestCoordinator alloc] init];
TestCoordinator* otherChild = [[TestCoordinator alloc] init];
[otherParent addChildCoordinator:otherChild];
// -removeChildCoordinator of a non-child should have no affect.
[parent removeChildCoordinator:otherChild];
EXPECT_TRUE([otherParent.children containsObject:otherChild]);
EXPECT_EQ(otherParent, otherChild.parentCoordinator);
}
TEST_F(BrowserCoordinatorTest, AddedRemoved) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
// Add to the parent.
EXPECT_FALSE(child.wasAddedCalled);
EXPECT_FALSE(child.willBeRemovedCalled);
[parent addChildCoordinator:child];
EXPECT_TRUE(child.wasAddedCalled);
EXPECT_FALSE(child.willBeRemovedCalled);
// Remove from the parent.
[parent removeChildCoordinator:child];
EXPECT_TRUE(child.willBeRemovedCalled);
}
// Tests that the didState/willStop methods are called.
TEST_F(BrowserCoordinatorTest, DidStartWillStop) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
[parent addChildCoordinator:child];
EXPECT_FALSE(parent.childDidStartCalled);
EXPECT_FALSE(parent.childWillStopCalled);
[child start];
EXPECT_TRUE(parent.childDidStartCalled);
EXPECT_FALSE(parent.childWillStopCalled);
[child stop];
EXPECT_TRUE(parent.childDidStartCalled);
EXPECT_TRUE(parent.childWillStopCalled);
}
// Tests that calling -stop on a coordinator also recursively stops any children
// of that coordinator that have been started.
TEST_F(BrowserCoordinatorTest, StopStopsStartedChildren) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
[parent addChildCoordinator:child];
[parent start];
[child start];
__block BOOL called = NO;
child.stopHandler = ^{
called = YES;
};
EXPECT_FALSE(called);
// Call stop on the parent.
[parent stop];
// It should have called stop on the child.
EXPECT_TRUE(called);
}
// Tests that calling -stop on a coordinator does *not* call -stop on children
// that haven't been started.
TEST_F(BrowserCoordinatorTest, StopStopsNonStartedChildren) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
[parent addChildCoordinator:child];
[parent start];
__block BOOL called = NO;
child.stopHandler = ^{
called = YES;
};
EXPECT_FALSE(called);
// Call stop on the parent.
[parent stop];
// It should not have called stop on the child.
EXPECT_TRUE(called);
}
// Tests that removing a child also sets the child's browser to nil, even if
// the child itself isn't nil.
TEST_F(BrowserCoordinatorTest, BrowserIsNilAfterCoordinatorIsRemoved) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
parent.browser = GetBrowser();
[parent addChildCoordinator:child];
EXPECT_NE(nil, child.browser);
// Remove the child.
[parent removeChildCoordinator:child];
EXPECT_EQ(nil, child.browser);
}
// Tests that children are recursively removed.
TEST_F(BrowserCoordinatorTest, RemoveRemovesGrandChildren) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
TestCoordinator* grandChild = [[TestCoordinator alloc] init];
[child addChildCoordinator:grandChild];
[parent addChildCoordinator:child];
EXPECT_FALSE(grandChild.willBeRemovedCalled);
EXPECT_FALSE(child.removeCalled);
// Remove the child.
[parent removeChildCoordinator:child];
EXPECT_TRUE(grandChild.willBeRemovedCalled);
EXPECT_TRUE(child.removeCalled);
}
// Tests that grandchildren are removed before -willRemove is called on the
// child.
TEST_F(BrowserCoordinatorTest,
RemoveRemovesGrandChildThenCallWillRemoveOnChild) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
TestCoordinator* grandChild = [[TestCoordinator alloc] init];
[child addChildCoordinator:grandChild];
[parent addChildCoordinator:child];
EXPECT_FALSE(grandChild.willBeRemovedCalled);
EXPECT_FALSE(child.removeCalled);
__weak TestCoordinator* weakChild = child;
child.willBeRemovedHandler = ^{
EXPECT_TRUE(grandChild.willBeRemovedCalled);
EXPECT_TRUE(weakChild.removeCalled);
};
// Remove the child.
[parent removeChildCoordinator:child];
EXPECT_TRUE(child.willBeRemovedCalled);
}
// Tests that multiple grandchildren are removed.
TEST_F(BrowserCoordinatorTest, RemoveChildWithMultipleGrandChildren) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
TestCoordinator* child = [[TestCoordinator alloc] init];
TestCoordinator* grandChild1 = [[TestCoordinator alloc] init];
TestCoordinator* grandChild2 = [[TestCoordinator alloc] init];
[child addChildCoordinator:grandChild1];
[child addChildCoordinator:grandChild2];
[parent addChildCoordinator:child];
// Remove the child.
[parent removeChildCoordinator:child];
}
// Tests that children inherit the dispatcher of the parent when it's nil.
TEST_F(BrowserCoordinatorTest, NilDispatcherInherited) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
EXPECT_EQ(nil, parent.dispatcher);
TestCoordinator* child = [[TestCoordinator alloc] init];
EXPECT_EQ(nil, child.dispatcher);
[parent addChildCoordinator:child];
EXPECT_EQ(nil, child.dispatcher);
}
// Tests that children inherit the dispatcher of the parent when it's nonnil.
TEST_F(BrowserCoordinatorTest, DispatcherInherited) {
TestCoordinator* parent = [[TestCoordinator alloc] init];
EXPECT_EQ(nil, parent.dispatcher);
TestCoordinator* child = [[TestCoordinator alloc] init];
EXPECT_EQ(nil, child.dispatcher);
parent.dispatcher = [[CommandDispatcher alloc] init];
[parent addChildCoordinator:child];
EXPECT_EQ(parent.dispatcher, child.dispatcher);
}
// Copyright 2017 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_COORDINATORS_TEST_BROWSER_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_COORDINATORS_TEST_BROWSER_COORDINATOR_H_
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
// A test version of BrowserCoordinator. This class backs its |viewController|
// property using a default UIViewController. It can be used as a parent
// coordinator with no functionality in tests for coordinator lifecycle events.
@interface TestBrowserCoordinator : BrowserCoordinator
@end
#endif // IOS_CHROME_BROWSER_UI_COORDINATORS_TEST_BROWSER_COORDINATOR_H_
// Copyright 2017 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/coordinators/test_browser_coordinator.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface TestBrowserCoordinator () {
// The test parent view controller.
UIViewController* _viewController;
}
@end
@implementation TestBrowserCoordinator
- (instancetype)init {
if (self = [super init])
_viewController = [[UIViewController alloc] init];
return self;
}
@end
@implementation TestBrowserCoordinator (Internal)
- (UIViewController*)viewController {
return _viewController;
}
@end
......@@ -2,20 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("main_content") {
sources = [
"main_content_coordinator.h",
"main_content_coordinator.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
group("main_content") {
deps = [
":main_content_ui",
":main_content_ui_broadcasting_util",
"//base",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/coordinators",
]
}
......@@ -56,7 +46,6 @@ source_set("main_content_ui_broadcasting_util") {
source_set("unit_tests") {
testonly = true
sources = [
"main_content_coordinator_unittest.mm",
"main_content_ui_broadcasting_util_unittest.mm",
"main_content_ui_state_unittest.mm",
]
......@@ -71,8 +60,6 @@ source_set("unit_tests") {
"//base/test:test_support",
"//ios/chrome/browser/ui/broadcaster",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/coordinators",
"//ios/chrome/browser/ui/coordinators:test_support",
"//ios/chrome/browser/ui/main_content/test",
"//ios/chrome/browser/ui/util",
"//ios/chrome/browser/web_state_list",
......
// Copyright 2017 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_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui.h"
// A coordinator that displays the main content view of the browser. This
// should be subclassed by any coordinator that displays the scrollable content
// related to the current URL.
@interface MainContentCoordinator : BrowserCoordinator
// The view controller used to display the main content area.
@property(nonatomic, readonly) UIViewController<MainContentUI>* viewController;
@end
#endif // IOS_CHROME_BROWSER_UI_MAIN_CONTENT_MAIN_CONTENT_COORDINATOR_H_
// Copyright 2017 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/main_content/main_content_coordinator.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface MainContentCoordinator ()
// Starts or stops broadcasting UI state from |viewController|.
- (void)startBroadcastingUI;
- (void)stopBroadcastingUI;
@end
@implementation MainContentCoordinator
#pragma mark - Accessors
- (UIViewController<MainContentUI>*)viewController {
// Subclasses implement.
NOTREACHED();
return nil;
}
#pragma mark - BrowserCoordinator
- (void)start {
[super start];
[self startBroadcastingUI];
}
- (void)stop {
[self stopBroadcastingUI];
[super stop];
}
- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
if ([childCoordinator isKindOfClass:[self class]])
[self stopBroadcastingUI];
}
- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator {
if ([childCoordinator isKindOfClass:[self class]])
[self startBroadcastingUI];
}
#pragma mark - Private
- (void)startBroadcastingUI {
StartBroadcastingMainContentUI(self.viewController,
self.browser->broadcaster());
}
- (void)stopBroadcastingUI {
StopBroadcastingMainContentUI(self.browser->broadcaster());
}
@end
// Copyright 2017 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/main_content/main_content_coordinator.h"
#import "base/mac/foundation_util.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test.h"
#import "ios/chrome/browser/ui/coordinators/test_browser_coordinator.h"
#import "ios/chrome/browser/ui/main_content/main_content_ui_state.h"
#import "ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.h"
#import "ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h"
#import "ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
#pragma mark - TestMainContentViewController
// Test implementation of MainContentViewController.
@interface TestMainContentViewController : UIViewController<MainContentUI>
@property(nonatomic, readonly) TestMainContentUIState* mainContentUIState;
@end
@implementation TestMainContentViewController
@synthesize mainContentUIState = _mainContentUIState;
- (instancetype)init {
if (self = [super init])
_mainContentUIState = [[TestMainContentUIState alloc] init];
return self;
}
@end
#pragma mark - TestMainContentCoordinator
// Test version of MainContentCoordinator.
@interface TestMainContentCoordinator : MainContentCoordinator
@property(nonatomic, readonly) TestMainContentViewController* viewController;
@end
@implementation TestMainContentCoordinator
@synthesize viewController = _viewController;
- (instancetype)init {
if (self = [super init])
_viewController = [[TestMainContentViewController alloc] init];
return self;
}
@end
#pragma mark - MainContentCoordinatorTest
// Test fixture for MainContentCoordinator.
class MainContentCoordinatorTest : public BrowserCoordinatorTest {
protected:
MainContentCoordinatorTest()
: BrowserCoordinatorTest(),
parent_([[TestBrowserCoordinator alloc] init]) {
parent_.browser = GetBrowser();
}
// The coordinator to use as the parent for MainContentCoordinators.
BrowserCoordinator* parent() { return parent_; }
private:
__strong BrowserCoordinator* parent_;
DISALLOW_COPY_AND_ASSIGN(MainContentCoordinatorTest);
};
// Tests that a MainContentCoordinator's ui forwader starts broadcasting
// when started.
TEST_F(MainContentCoordinatorTest, BroadcastAfterStarting) {
// Start a MainContentCoordinator and verify that its UI is being broadcasted.
TestMainContentCoordinator* coordinator =
[[TestMainContentCoordinator alloc] init];
[parent() addChildCoordinator:coordinator];
[coordinator start];
VerifyMainContentUIBroadcast(coordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(),
true /*should_broadcast*/);
// Stop the coordinator and verify that its UI is no longer being broadcasted.
[coordinator stop];
[parent() removeChildCoordinator:coordinator];
VerifyMainContentUIBroadcast(coordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(),
false /*should_broadcast*/);
}
// Tests that a MainContentCoordinator's ui forwader stops broadcasting when
// a child MainContentCoordinator is started.
TEST_F(MainContentCoordinatorTest, StopBroadcastingForChildren) {
// Start a MainContentCoordinator and start a child MainContentCoordinator,
// then verify that the child's UI is being broadcast, not the parent's.
TestMainContentCoordinator* parentMainCoordinator =
[[TestMainContentCoordinator alloc] init];
[parent() addChildCoordinator:parentMainCoordinator];
[parentMainCoordinator start];
TestMainContentCoordinator* childMainCoordinator =
[[TestMainContentCoordinator alloc] init];
[parentMainCoordinator addChildCoordinator:childMainCoordinator];
[childMainCoordinator start];
VerifyMainContentUIBroadcast(
childMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), true /*should_broadcast*/);
VerifyMainContentUIBroadcast(
parentMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), false /*should_broadcast*/);
// Stop the child coordinator and verify that the parent's UI is being
// broadcast instead.
[childMainCoordinator stop];
[parentMainCoordinator removeChildCoordinator:childMainCoordinator];
VerifyMainContentUIBroadcast(
childMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), false /*should_broadcast*/);
VerifyMainContentUIBroadcast(
parentMainCoordinator.viewController.mainContentUIState,
GetBrowser()->broadcaster(), true /*should_broadcast*/);
[parentMainCoordinator stop];
[parent() removeChildCoordinator:parentMainCoordinator];
}
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("overlays") {
sources = [
"overlay_coordinator.h",
"overlay_service.h",
"overlay_service_factory.h",
"overlay_service_observer.h",
"overlay_service_observer_bridge.h",
"overlay_service_observer_bridge.mm",
]
deps = [
":overlays_internal",
"//base",
"//components/keyed_service/core",
"//components/keyed_service/ios",
"//ios/chrome/browser/ui/coordinators",
]
allow_circular_includes_from = [ ":overlays_internal" ]
configs += [ "//build/config/compiler:enable_arc" ]
}
source_set("overlays_internal") {
sources = [
"browser_overlay_queue.h",
"browser_overlay_queue.mm",
"overlay_coordinator+internal.h",
"overlay_coordinator.mm",
"overlay_queue.h",
"overlay_queue.mm",
"overlay_queue_manager.h",
"overlay_queue_manager.mm",
"overlay_queue_manager_observer.h",
"overlay_queue_observer.h",
"overlay_scheduler.h",
"overlay_scheduler.mm",
"overlay_scheduler_observer.h",
"overlay_service_factory.mm",
"overlay_service_impl.h",
"overlay_service_impl.mm",
"web_state_overlay_queue.h",
"web_state_overlay_queue.mm",
]
deps = [
"//base",
"//components/keyed_service/core",
"//components/keyed_service/ios",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators",
"//ios/chrome/browser/web_state_list",
"//ios/web",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
source_set("unit_tests") {
testonly = true
sources = [
"overlay_queue_manager_unittest.mm",
"overlay_queue_unittest.mm",
"overlay_scheduler_unittest.mm",
]
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
":overlays",
":overlays_internal",
"//base",
"//base/test:test_support",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/coordinators",
"//ios/chrome/browser/ui/coordinators:test_support",
"//ios/chrome/browser/ui/overlays/test",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/test/base",
"//ios/web",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//testing/gtest",
]
}
// Copyright 2017 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_BROWSER_OVERLAY_QUEUE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_BROWSER_OVERLAY_QUEUE_H_
#import <Foundation/Foundation.h>
#import "ios/chrome/browser/ui/browser_list/browser_user_data.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
@class BrowserCoordinator;
// Class used to queue overlays to display over the browser content area
// regardless of which WebState's content is currently visible.
class BrowserOverlayQueue : public BrowserUserData<BrowserOverlayQueue>,
public OverlayQueue {
public:
~BrowserOverlayQueue() override;
// OverlayQueue:
void StartNextOverlay() override;
void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator) override;
void OverlayWasStopped(OverlayCoordinator* overlay_coordinator) override;
// Adds |overlay_coordinator| to the queue. |overlay_parent| will be used as
// the parent coordinator when StartNextOverlay() is called.
void AddBrowserOverlay(OverlayCoordinator* overlay_coordinator,
BrowserCoordinator* overlay_parent);
private:
friend class BrowserUserData<BrowserOverlayQueue>;
// Private constructor.
explicit BrowserOverlayQueue(Browser* browser);
// The parent coordinators added with each overlay.
NSMutableArray<BrowserCoordinator*>* overlay_parents_;
DISALLOW_COPY_AND_ASSIGN(BrowserOverlayQueue);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_BROWSER_OVERLAY_QUEUE_H_
// Copyright 2017 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/browser_overlay_queue.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
DEFINE_BROWSER_USER_DATA_KEY(BrowserOverlayQueue);
BrowserOverlayQueue::BrowserOverlayQueue(Browser* browser)
: overlay_parents_([[NSMutableArray alloc] init]) {}
BrowserOverlayQueue::~BrowserOverlayQueue() {}
void BrowserOverlayQueue::StartNextOverlay() {
DCHECK(HasQueuedOverlays());
DCHECK_EQ(GetCount(), [overlay_parents_ count]);
DCHECK(!IsShowingOverlay());
[GetFirstOverlay() startOverlayingCoordinator:[overlay_parents_ firstObject]];
OverlayWasStarted();
}
void BrowserOverlayQueue::ReplaceVisibleOverlay(
OverlayCoordinator* overlay_coordinator) {
DCHECK(IsShowingOverlay());
// Prepend the current overlay's parent to |overlay_parents_| so that the
// replacement overlay can also use that as its parents.
[overlay_parents_ addObject:[overlay_parents_ firstObject]];
OverlayQueue::ReplaceVisibleOverlay(overlay_coordinator);
}
void BrowserOverlayQueue::OverlayWasStopped(
OverlayCoordinator* overlay_coordinator) {
DCHECK_EQ(GetFirstOverlay(), overlay_coordinator);
[overlay_parents_ removeObjectAtIndex:0];
OverlayQueue::OverlayWasStopped(overlay_coordinator);
}
void BrowserOverlayQueue::AddBrowserOverlay(
OverlayCoordinator* overlay_coordinator,
BrowserCoordinator* overlay_parent) {
DCHECK(overlay_coordinator);
DCHECK(overlay_parent);
[overlay_parents_ addObject:overlay_parent];
OverlayQueue::AddOverlay(overlay_coordinator);
}
// Copyright 2017 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_OVERLAY_COORDINATOR_INTERNAL_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_INTERNAL_H_
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
class OverlayQueue;
// Internal interface for use by OverlayService implementation.
@interface OverlayCoordinator (OverlayCoordinatorInternal)
// Tells the OverlayCoordinator that it was added to |queue|. An
// OverlayCoordinator is expected to only be added to one OverlayQueue in its
// lifetime.
- (void)wasAddedToQueue:(OverlayQueue*)queue;
// Starts overlaying this coordinator over |overlayParent|. The receiver will
// be added as a child of |overlayParent|.
- (void)startOverlayingCoordinator:(BrowserCoordinator*)overlayParent;
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_INTERNAL_H_
// Copyright 2017 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_OVERLAY_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_H_
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
// A BrowserCoordinator that can be presented with OverlayService. This class
// is meant to be subclassed to display ephemeral UI with OverlayService that
// can easily be torn down in favor of other browser functions.
@interface OverlayCoordinator : BrowserCoordinator
// Performs cleanup tasks for an OverlayCoordinator whose presentation is
// cancelled via the OverlayService API. This allows for deterministic cleanup
// to occur for coordinators whose UI has not been started. Rather than relying
// on |-dealloc| to perform cleanup, |-cancelOverlay| can be used to perform
// cleanup tasks deterministically. The base class implementation does nothing.
- (void)cancelOverlay;
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_H_
// Copyright 2017 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/overlay_coordinator.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/overlay_service_factory.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface OverlayCoordinator ()
// The queue that presented this overlay.
@property(nonatomic, assign) OverlayQueue* queue;
@end
@implementation OverlayCoordinator
@synthesize queue = _queue;
#pragma mark - Public
- (void)cancelOverlay {
// Subclasses implement.
}
#pragma mark - BrowserCoordinator
- (void)start {
// OverlayCoordinators should only be presented via OverlayService, and are
// expected to be added to an OverlayQueue before being started.
DCHECK(self.queue);
DCHECK(self.parentCoordinator);
[super start];
}
- (void)stop {
DCHECK(self.queue);
[super stop];
[self.parentCoordinator removeChildCoordinator:self];
}
@end
@implementation OverlayCoordinator (Internal)
- (void)viewControllerWasDeactivated {
self.queue->OverlayWasStopped(self);
// Notify the queue that the overlay's UI has been stopped, allowing the
// next scheduled overlay to be displayed. OverlayCoordinators are owned by
// their queues and will be deallocated after OverlayWasStopped(), so do not
// add any more code after this call.
}
@end
@implementation OverlayCoordinator (OverlayCoordinatorInternal)
- (void)wasAddedToQueue:(OverlayQueue*)queue {
DCHECK(!self.queue);
DCHECK(queue);
self.queue = queue;
}
- (void)startOverlayingCoordinator:(BrowserCoordinator*)overlayParent {
DCHECK(overlayParent);
[overlayParent addChildCoordinator:self];
[self start];
}
@end
// Copyright 2017 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_OVERLAY_QUEUE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_H_
#import <Foundation/Foundation.h>
#include <vector>
#include "base/observer_list.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_observer.h"
@class OverlayCoordinator;
namespace web {
class WebState;
}
// Class used to enqueue OverlayCoordinators. It communicates changes in the
// queue to registered OverlayQueueObservers.
class OverlayQueue {
public:
virtual ~OverlayQueue();
// Adds and removes OverlayQueueObservers.
void AddObserver(OverlayQueueObserver* observer);
void RemoveObserver(OverlayQueueObserver* observer);
// Starts the next overlay in the queue. If GetWebState() returns non-null,
// it is expected that its content area is visible before this is called.
virtual void StartNextOverlay() = 0;
// Tells the OverlayQueue that |overlay_coordinator| was stopped.
virtual void OverlayWasStopped(OverlayCoordinator* overlay_coordinator);
// Removes the currently displayed overlay and adds |overlay_coordinator| to
// the front of the queue to be displayed immediately.
virtual void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator);
// Returns whether there are any queued overlays.
bool HasQueuedOverlays() const;
// Returns whether an overlay is curently started.
bool IsShowingOverlay() const;
// Cancels all queued overlays for this queue. If one is being displayed, it
// will also be stopped
void CancelOverlays();
// Some OverlayQueues require that a particular WebState's content area is
// visible before its queued BrowserCoordinators can be started. If this
// queue's overlays require showing a WebState, this function will return that
// WebState.
virtual web::WebState* GetWebState() const;
protected:
// Adds |overlay_coordinator| to the queue and schedules its presentation.
void AddOverlay(OverlayCoordinator* overlay_coordinator);
// Returns the number of overlays in the queue.
NSUInteger GetCount() const;
// Returns the first BrowserCoordinator in the queue.
OverlayCoordinator* GetFirstOverlay();
// Called when the first overlay in the queue is started.
void OverlayWasStarted();
// Default constructor.
OverlayQueue();
private:
// The observers for this queue.
base::ObserverList<OverlayQueueObserver>::Unchecked observers_;
// The queue of overlays that were added for this WebState.
__strong NSMutableArray<OverlayCoordinator*>* overlays_;
// Whether an overlay is currently started. If this is true, the first
// BrowserCoordinator in |overlays_| has been started.
bool showing_overlay_;
DISALLOW_COPY_AND_ASSIGN(OverlayQueue);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_H_
// Copyright 2017 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/overlay_queue.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator+internal.h"
#include "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
OverlayQueue::OverlayQueue()
: overlays_([[NSMutableArray<OverlayCoordinator*> alloc] init]),
showing_overlay_(false) {}
OverlayQueue::~OverlayQueue() {
CancelOverlays();
}
void OverlayQueue::AddObserver(OverlayQueueObserver* observer) {
observers_.AddObserver(observer);
}
void OverlayQueue::RemoveObserver(OverlayQueueObserver* observer) {
observers_.RemoveObserver(observer);
}
void OverlayQueue::OverlayWasStopped(OverlayCoordinator* overlay_coordinator) {
DCHECK(overlay_coordinator);
DCHECK_EQ(GetFirstOverlay(), overlay_coordinator);
DCHECK(IsShowingOverlay());
[overlays_ removeObjectAtIndex:0];
showing_overlay_ = false;
for (auto& observer : observers_) {
observer.OverlayQueueDidStopVisibleOverlay(this);
}
}
void OverlayQueue::ReplaceVisibleOverlay(
OverlayCoordinator* overlay_coordinator) {
DCHECK(overlay_coordinator);
DCHECK(IsShowingOverlay());
DCHECK_GE([overlays_ count], 1U);
// Add the overlay after the currently displayed overlay and notify observers
// before stopping the current overlay.
for (auto& observer : observers_) {
observer.OverlayQueueWillReplaceVisibleOverlay(this);
}
[overlays_ insertObject:overlay_coordinator atIndex:1];
[overlay_coordinator wasAddedToQueue:this];
OverlayCoordinator* visible_overlay = GetFirstOverlay();
[visible_overlay cancelOverlay];
[visible_overlay stop];
}
bool OverlayQueue::HasQueuedOverlays() const {
return GetCount() > 0U;
}
bool OverlayQueue::IsShowingOverlay() const {
return showing_overlay_;
}
void OverlayQueue::CancelOverlays() {
// Cancel all overlays in the queue.
for (OverlayCoordinator* overlay_coordinator in overlays_) {
[overlay_coordinator cancelOverlay];
}
for (auto& observer : observers_) {
observer.OverlayQueueDidCancelOverlays(this);
}
// Stop the visible overlay before emptying the queue.
if (IsShowingOverlay())
[GetFirstOverlay() stop];
[overlays_ removeAllObjects];
}
web::WebState* OverlayQueue::GetWebState() const {
return nullptr;
}
void OverlayQueue::AddOverlay(OverlayCoordinator* overlay_coordinator) {
// Add the overlay coordinator to the queue, then notify observers.
DCHECK(overlay_coordinator);
[overlays_ addObject:overlay_coordinator];
[overlay_coordinator wasAddedToQueue:this];
for (auto& observer : observers_) {
observer.OverlayQueueDidAddOverlay(this);
}
}
NSUInteger OverlayQueue::GetCount() const {
return [overlays_ count];
}
OverlayCoordinator* OverlayQueue::GetFirstOverlay() {
return [overlays_ firstObject];
}
void OverlayQueue::OverlayWasStarted() {
showing_overlay_ = true;
}
// Copyright 2017 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_OVERLAY_QUEUE_MANAGER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_MANAGER_H_
#include <Foundation/Foundation.h>
#include <set>
#include "base/macros.h"
#include "base/observer_list.h"
#import "ios/chrome/browser/ui/browser_list/browser_user_data.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
class OverlayQueue;
class OverlayQueueManagerObserver;
class WebStateList;
namespace web {
class WebState;
}
// Object that manages the creation of OverlayQueues for a Browser and all its
// associated WebStates.
class OverlayQueueManager : public BrowserUserData<OverlayQueueManager>,
public WebStateListObserver {
public:
~OverlayQueueManager() override;
// The WebStateList for which OverlayQueues are being managed.
WebStateList* web_state_list() { return web_state_list_; }
// The OverlayQueues managed by this object.
const std::set<OverlayQueue*>& queues() const { return queues_; }
// Adds and removes observers.
void AddObserver(OverlayQueueManagerObserver* observer);
void RemoveObserver(OverlayQueueManagerObserver* observer);
// Tells the OverlayQueueManager to disconnect itself as an observer before
// deallocation.
void Disconnect();
private:
friend class BrowserUserData<OverlayQueueManager>;
// Private constructor used by factory method.
explicit OverlayQueueManager(Browser* browser);
// WebStateListObserver:
void WebStateInsertedAt(WebStateList* web_state_list,
web::WebState* web_state,
int index,
bool activating) override;
void WebStateReplacedAt(WebStateList* web_state_list,
web::WebState* old_web_state,
web::WebState* new_web_state,
int index) override;
void WebStateDetachedAt(WebStateList* web_state_list,
web::WebState* web_state,
int index) override;
// Lazily creates an OverlayQueue for |web_state| and adds it to |queues_|.
void AddQueueForWebState(web::WebState* web_state);
// Removes the queue that was created in response to WebStateListObserver
// callbacks and notifies its observers.
void RemoveQueueForWebState(web::WebState* web_state);
// The observers for this manager.
base::ObserverList<OverlayQueueManagerObserver>::Unchecked observers_;
// The OverlayQueues created by this manager.
std::set<OverlayQueue*> queues_;
// The WebStateList for which queues are beign managed.
WebStateList* web_state_list_;
DISALLOW_COPY_AND_ASSIGN(OverlayQueueManager);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_MANAGER_H_
// Copyright 2017 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/overlay_queue_manager.h"
#import "ios/chrome/browser/ui/browser_list/browser_list.h"
#import "ios/chrome/browser/ui/overlays/browser_overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_manager_observer.h"
#import "ios/chrome/browser/ui/overlays/web_state_overlay_queue.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
DEFINE_BROWSER_USER_DATA_KEY(OverlayQueueManager);
OverlayQueueManager::OverlayQueueManager(Browser* browser)
: web_state_list_(&browser->web_state_list()) {
// Create the BrowserOverlayQueue and add it to |queues_|.
BrowserOverlayQueue::CreateForBrowser(browser);
queues_.insert(BrowserOverlayQueue::FromBrowser(browser));
// Add queues for each WebState in |web_state_list_|.
for (int i = 0; i < web_state_list_->count(); ++i) {
AddQueueForWebState(web_state_list_->GetWebStateAt(i));
}
// Add as an observer for |web_state_list_|. This allows the manager to
// create OverlayQueues for newly added WebStates.
web_state_list_->AddObserver(this);
}
OverlayQueueManager::~OverlayQueueManager() {
// Disconnect() removes the manager as an observer for |web_state_list_|, nils
// out |web_state_list_|, and removes the OverlayQueues from |queues_|. It is
// expected to be called before deallocation.
DCHECK(queues_.empty());
DCHECK(!web_state_list_);
}
#pragma mark - Public
void OverlayQueueManager::AddObserver(OverlayQueueManagerObserver* observer) {
observers_.AddObserver(observer);
}
void OverlayQueueManager::RemoveObserver(
OverlayQueueManagerObserver* observer) {
observers_.RemoveObserver(observer);
}
void OverlayQueueManager::Disconnect() {
for (auto& observer : observers_) {
for (OverlayQueue* queue : queues_) {
observer.OverlayQueueManagerWillRemoveQueue(this, queue);
}
}
queues_.clear();
web_state_list_->RemoveObserver(this);
web_state_list_ = nullptr;
}
#pragma mark - WebStateListObserver
void OverlayQueueManager::WebStateInsertedAt(WebStateList* web_state_list,
web::WebState* web_state,
int index,
bool activating) {
AddQueueForWebState(web_state);
}
void OverlayQueueManager::WebStateReplacedAt(WebStateList* web_state_list,
web::WebState* old_web_state,
web::WebState* new_web_state,
int index) {
RemoveQueueForWebState(old_web_state);
AddQueueForWebState(new_web_state);
}
void OverlayQueueManager::WebStateDetachedAt(WebStateList* web_state_list,
web::WebState* web_state,
int index) {
RemoveQueueForWebState(web_state);
}
#pragma mark -
void OverlayQueueManager::AddQueueForWebState(web::WebState* web_state) {
WebStateOverlayQueue::CreateForWebState(web_state);
OverlayQueue* queue = WebStateOverlayQueue::FromWebState(web_state);
if (queues_.insert(queue).second) {
for (auto& observer : observers_) {
observer.OverlayQueueManagerDidAddQueue(this, queue);
}
}
}
void OverlayQueueManager::RemoveQueueForWebState(web::WebState* web_state) {
OverlayQueue* queue = WebStateOverlayQueue::FromWebState(web_state);
auto queue_iter = queues_.find(queue);
DCHECK(queue_iter != queues_.end());
for (auto& observer : observers_) {
observer.OverlayQueueManagerWillRemoveQueue(this, queue);
}
queues_.erase(queue_iter);
}
// Copyright 2017 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_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
#include "base/macros.h"
class OverlayQueue;
class OverlayQueueManager;
// Observer class for OverlayQueueManager.
class OverlayQueueManagerObserver {
public:
OverlayQueueManagerObserver() = default;
virtual ~OverlayQueueManagerObserver() = default;
// Called when an OverlayQueueManager creates |queue|.
virtual void OverlayQueueManagerDidAddQueue(OverlayQueueManager* manager,
OverlayQueue* queue) {}
// Called when an OverlayQueueManager is about to remove |queue|.
virtual void OverlayQueueManagerWillRemoveQueue(OverlayQueueManager* manager,
OverlayQueue* queue) {}
private:
DISALLOW_COPY_AND_ASSIGN(OverlayQueueManagerObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
// Copyright 2017 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/overlay_queue_manager.h"
#include <memory>
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_coordinator.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_queue_manager_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#include "ios/web/public/test/fakes/test_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Returns the OverlayQueue in |queues| that retuns |web_state| for
// GetWebState().
OverlayQueue* GetQueueForWebState(const std::set<OverlayQueue*>& queues,
web::WebState* web_state) {
auto queue_iter = queues.begin();
while (queue_iter != queues.end()) {
if ((*queue_iter)->GetWebState() == web_state)
break;
++queue_iter;
}
return queue_iter == queues.end() ? nullptr : *queue_iter;
}
}
class OverlayQueueManagerTest : public BrowserCoordinatorTest {
public:
OverlayQueueManagerTest() {
OverlayQueueManager::CreateForBrowser(GetBrowser());
manager()->AddObserver(&observer_);
}
~OverlayQueueManagerTest() override {
manager()->RemoveObserver(&observer_);
manager()->Disconnect();
}
WebStateList* web_state_list() { return &(GetBrowser()->web_state_list()); }
OverlayQueueManager* manager() {
return OverlayQueueManager::FromBrowser(GetBrowser());
}
TestOverlayQueueManagerObserver* observer() { return &observer_; }
private:
TestOverlayQueueManagerObserver observer_;
DISALLOW_COPY_AND_ASSIGN(OverlayQueueManagerTest);
};
// Tests that an OverlayQueueManager for a Browser with no WebStates contains
// one Browser-specific OverlayQueue.
TEST_F(OverlayQueueManagerTest, NoWebStates) {
const std::set<OverlayQueue*>& queues = manager()->queues();
EXPECT_EQ(queues.size(), 1U);
ASSERT_NE(queues.begin(), queues.end());
EXPECT_FALSE((*queues.begin())->GetWebState());
}
// Tests that adding and removing a WebState successfully creates queues and
// notifies observers.
TEST_F(OverlayQueueManagerTest, AddAndRemoveWebState) {
// Create a WebState and add it to the WebStateList, verifying that the
// manager's queues are updated and that the observer callback is received.
std::unique_ptr<web::WebState> web_state =
std::make_unique<web::TestWebState>();
web_state_list()->InsertWebState(0, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
ASSERT_EQ(web_state_list()->count(), 1);
web::WebState* inserted_web_state = web_state_list()->GetWebStateAt(0);
const std::set<OverlayQueue*>& queues = manager()->queues();
EXPECT_EQ(queues.size(), 2U);
EXPECT_TRUE(GetQueueForWebState(queues, inserted_web_state));
EXPECT_TRUE(observer()->did_add_called());
// Remove the WebState from the WebStateList and verify that its queue is
// removed and that the observer callback is received.
web_state_list()->CloseWebStateAt(0, WebStateList::CLOSE_USER_ACTION);
EXPECT_EQ(queues.size(), 1U);
EXPECT_FALSE(GetQueueForWebState(queues, inserted_web_state));
EXPECT_TRUE(observer()->will_remove_called());
}
// Tests that adding and removing a WebState successfully creates queues and
// notifies observers.
TEST_F(OverlayQueueManagerTest, AddAndReplaceWebState) {
// Create a WebState and add it to the WebStateList, verifying that the
// manager's queues are updated and that the observer callback is received.
std::unique_ptr<web::WebState> web_state =
std::make_unique<web::TestWebState>();
web_state_list()->InsertWebState(0, std::move(web_state),
WebStateList::INSERT_FORCE_INDEX,
WebStateOpener());
ASSERT_EQ(web_state_list()->count(), 1);
web::WebState* inserted_web_state = web_state_list()->GetWebStateAt(0);
const std::set<OverlayQueue*>& queues = manager()->queues();
EXPECT_EQ(queues.size(), 2U);
EXPECT_TRUE(GetQueueForWebState(queues, inserted_web_state));
EXPECT_TRUE(observer()->did_add_called());
// Replace |web_state| and verify that the observer callbacks were called and
// that the queues were successfully added and removed.
observer()->reset();
std::unique_ptr<web::WebState> replacement =
std::make_unique<web::TestWebState>();
web_state_list()->ReplaceWebStateAt(0, std::move(replacement));
EXPECT_TRUE(observer()->will_remove_called());
EXPECT_TRUE(observer()->did_add_called());
EXPECT_EQ(queues.size(), 2U);
EXPECT_FALSE(GetQueueForWebState(queues, inserted_web_state));
inserted_web_state = web_state_list()->GetWebStateAt(0);
EXPECT_TRUE(GetQueueForWebState(queues, inserted_web_state));
}
// Copyright 2017 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_OVERLAY_QUEUE_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_OBSERVER_H_
#include "base/macros.h"
class OverlayQueue;
// Interface for listening to events occurring to OverlayQueues.
class OverlayQueueObserver {
public:
OverlayQueueObserver() = default;
virtual ~OverlayQueueObserver() = default;
// Tells the observer that an OverlayCoordinator was added to |queue|.
virtual void OverlayQueueDidAddOverlay(OverlayQueue* queue) {}
// Tells the observer that the overlay being presented by |queue| is about to
// be stopped so that a replacement overlay can be started.
virtual void OverlayQueueWillReplaceVisibleOverlay(OverlayQueue* queue) {}
// Tells the observer that the overlay being presented by |queue| was stopped.
virtual void OverlayQueueDidStopVisibleOverlay(OverlayQueue* queue) {}
// Tells the observer that the overlays in |queue| were cancelled.
virtual void OverlayQueueDidCancelOverlays(OverlayQueue* queue) {}
private:
DISALLOW_COPY_AND_ASSIGN(OverlayQueueObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_QUEUE_OBSERVER_H_
// Copyright 2017 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/overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_coordinator.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_queue_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
class OverlayQueueTest : public PlatformTest {
public:
OverlayQueueTest() : PlatformTest() { queue_.AddObserver(&observer_); }
TestOverlayQueue& queue() { return queue_; }
TestOverlayQueueObserver& observer() { return observer_; }
private:
TestOverlayQueue queue_;
TestOverlayQueueObserver observer_;
};
// Tests that adding an overlay to the queue updates state accordingly and
// notifies observers.
TEST_F(OverlayQueueTest, AddOverlay) {
OverlayCoordinator* overlay = [[TestOverlayCoordinator alloc] init];
queue().AddOverlay(overlay);
EXPECT_TRUE(queue().HasQueuedOverlays());
EXPECT_FALSE(queue().IsShowingOverlay());
EXPECT_TRUE(observer().did_add_called());
}
// Tests that OverlayWasStopped() updates state properly.
TEST_F(OverlayQueueTest, OverlayWasStopped) {
OverlayCoordinator* overlay = [[TestOverlayCoordinator alloc] init];
queue().AddOverlay(overlay);
queue().StartNextOverlay();
queue().OverlayWasStopped(overlay);
EXPECT_FALSE(queue().HasQueuedOverlays());
EXPECT_FALSE(queue().IsShowingOverlay());
EXPECT_TRUE(observer().stop_visible_called());
}
// Tests that the observer is notified when
TEST_F(OverlayQueueTest, ReplaceOverlay) {
OverlayCoordinator* overlay = [[TestOverlayCoordinator alloc] init];
queue().AddOverlay(overlay);
queue().StartNextOverlay();
OverlayCoordinator* replacement = [[TestOverlayCoordinator alloc] init];
queue().ReplaceVisibleOverlay(replacement);
EXPECT_TRUE(observer().will_replace_called());
EXPECT_TRUE(observer().stop_visible_called());
}
// Tests that CancelOverlays() cancels all queued overlays for a WebState.
TEST_F(OverlayQueueTest, CancelOverlays) {
TestOverlayCoordinator* overlay0 = [[TestOverlayCoordinator alloc] init];
TestOverlayCoordinator* overlay1 = [[TestOverlayCoordinator alloc] init];
queue().AddOverlay(overlay0);
queue().AddOverlay(overlay1);
queue().CancelOverlays();
EXPECT_FALSE(queue().HasQueuedOverlays());
EXPECT_FALSE(queue().IsShowingOverlay());
EXPECT_TRUE(observer().did_cancel_called());
EXPECT_TRUE(overlay0.cancelled);
EXPECT_TRUE(overlay1.cancelled);
}
// Copyright 2017 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_OVERLAY_SCHEDULER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SCHEDULER_H_
#include <Foundation/Foundation.h>
#include <list>
#include <memory>
#include "base/observer_list.h"
#import "ios/chrome/browser/ui/browser_list/browser_user_data.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_manager_observer.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_observer.h"
#include "ios/web/public/web_state/web_state_observer.h"
@class OverlayCoordinator;
class OverlaySchedulerObserver;
namespace web {
class WebState;
}
// An object that manages scheduling when overlays from various OverlayQueues
// can be started. If an OverlayQueue requires a WebState's content area to be
// visible, this class will update the WebStateLists's active WebState.
class OverlayScheduler : public BrowserUserData<OverlayScheduler>,
public OverlayQueueObserver,
public OverlayQueueManagerObserver,
public web::WebStateObserver {
public:
~OverlayScheduler() override;
// Adds and removes OverlaySchedulerObservers.
void AddObserver(OverlaySchedulerObserver* observer);
void RemoveObserver(OverlaySchedulerObserver* observer);
// Getter and setter for the OverlayQueueManager. Setting the manager to a
// new value will add the OverlayScheduler as an observer to the manager and
// all of its associated OverlayQueues.
OverlayQueueManager* queue_manager() { return queue_manager_; }
void SetQueueManager(OverlayQueueManager* queue_manager);
// Whether the scheduler is paused. When the scheduler is paused, no queued
// overlays will be started. When unpaused, it will attempt to start the next
// queued overlay.
void SetPaused(bool paused);
bool paused() { return paused_; }
// Whether a scheduled overlay is currently being shown.
bool IsShowingOverlay() const;
// Replaces the currently visible overlay with |overlay_coordinator|.
void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator);
// Cancels all scheduled overlays and empties overlay queues.
void CancelOverlays();
// Tells the OverlayScheduler to disconnect itself as an observer before
// deallocation.
void Disconnect();
private:
friend class BrowserUserData<OverlayScheduler>;
// Private constructor used by factory method.
explicit OverlayScheduler(Browser* browser);
// OverlayQueueManagerObserver:
void OverlayQueueManagerDidAddQueue(OverlayQueueManager* manager,
OverlayQueue* queue) override;
void OverlayQueueManagerWillRemoveQueue(OverlayQueueManager* manager,
OverlayQueue* queue) override;
// OverlayQueueObserver:
void OverlayQueueDidAddOverlay(OverlayQueue* queue) override;
void OverlayQueueWillReplaceVisibleOverlay(OverlayQueue* queue) override;
void OverlayQueueDidStopVisibleOverlay(OverlayQueue* queue) override;
void OverlayQueueDidCancelOverlays(OverlayQueue* queue) override;
// WebStateObserver:
void WasShown(web::WebState* web_state) override;
void WebStateDestroyed(web::WebState* web_state) override;
// Attempts to show the next queued overlay.
void TryToStartNextOverlay();
// Notifies the scheduler that |web_state|'s content area was shown.
void OnWebStateShown(web::WebState* web_state);
// Cancels outstanding overlays for |queue| and removes this as an observer.
void StopObservingQueue(OverlayQueue* queue);
// Stops observing |web_state|.
void StopObservingWebState(web::WebState* web_state);
// The WebStateList of the Browser whose overlays are being scheduled.
WebStateList* web_state_list_;
// The OverlaySchedulerObservers.
base::ObserverList<OverlaySchedulerObserver>::Unchecked observers_;
// The OverlayQueueManager responsible for creating queues for the Browser
// associated with this OverlayScheduler.
OverlayQueueManager* queue_manager_ = nullptr;
// The OverlayQueues that have queued overlays. After an overlay is stopped,
// the first queue is popped and the first ovelay in the next queue is
// started.
std::list<OverlayQueue*> overlay_queues_;
// Whether the scheduler is paused.
bool paused_ = false;
// Whether the |overlay_queues_|'s frontmost queue's WebState is being
// observed. When a WebState-specific overlay is scheduled to be shown, the
// scheduler will wait until its WebState's WasShown() is received before
// starting that overlay.
bool observing_front_web_state_ = false;
DISALLOW_COPY_AND_ASSIGN(OverlayScheduler);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SCHEDULER_H_
// Copyright 2017 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/overlay_scheduler.h"
#include <list>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_manager.h"
#import "ios/chrome/browser/ui/overlays/overlay_scheduler_observer.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
DEFINE_BROWSER_USER_DATA_KEY(OverlayScheduler);
OverlayScheduler::OverlayScheduler(Browser* browser)
: web_state_list_(&browser->web_state_list()) {
// Create the OverlayQueueManager and add the scheduler as an observer to the
// manager and all its queues.
OverlayQueueManager::CreateForBrowser(browser);
queue_manager_ = OverlayQueueManager::FromBrowser(browser);
queue_manager_->AddObserver(this);
for (OverlayQueue* queue : queue_manager_->queues()) {
queue->AddObserver(this);
}
}
OverlayScheduler::~OverlayScheduler() {
// Disconnect() removes the scheduler as an observer and nils out
// |queue_manager_|. It is expected to be called before deallocation.
DCHECK(!queue_manager_);
}
#pragma mark - Public
void OverlayScheduler::AddObserver(OverlaySchedulerObserver* observer) {
observers_.AddObserver(observer);
}
void OverlayScheduler::RemoveObserver(OverlaySchedulerObserver* observer) {
observers_.RemoveObserver(observer);
}
void OverlayScheduler::SetQueueManager(OverlayQueueManager* queue_manager) {
if (queue_manager_) {
queue_manager_->RemoveObserver(this);
for (OverlayQueue* queue : queue_manager_->queues()) {
StopObservingQueue(queue);
}
}
queue_manager_ = queue_manager;
if (queue_manager_) {
queue_manager_->AddObserver(this);
for (OverlayQueue* queue : queue_manager_->queues()) {
queue->AddObserver(this);
}
}
}
bool OverlayScheduler::IsShowingOverlay() const {
return !overlay_queues_.empty() &&
overlay_queues_.front()->IsShowingOverlay();
}
void OverlayScheduler::SetPaused(bool paused) {
if (paused_ == paused)
return;
paused_ = paused;
if (!paused_)
TryToStartNextOverlay();
}
void OverlayScheduler::ReplaceVisibleOverlay(
OverlayCoordinator* overlay_coordinator) {
DCHECK(overlay_coordinator);
DCHECK(IsShowingOverlay());
overlay_queues_.front()->ReplaceVisibleOverlay(overlay_coordinator);
}
void OverlayScheduler::CancelOverlays() {
// |overlay_queues_| will be updated in OverlayQueueDidCancelOverlays(), so a
// while loop is used to avoid using invalidated iterators.
while (!overlay_queues_.empty()) {
overlay_queues_.front()->CancelOverlays();
}
}
void OverlayScheduler::Disconnect() {
queue_manager_->RemoveObserver(this);
for (OverlayQueue* queue : queue_manager_->queues()) {
StopObservingQueue(queue);
}
queue_manager_->Disconnect();
queue_manager_ = nullptr;
}
#pragma mark - OverlayQueueManagerObserver
void OverlayScheduler::OverlayQueueManagerDidAddQueue(
OverlayQueueManager* manager,
OverlayQueue* queue) {
queue->AddObserver(this);
}
void OverlayScheduler::OverlayQueueManagerWillRemoveQueue(
OverlayQueueManager* manager,
OverlayQueue* queue) {
StopObservingQueue(queue);
}
#pragma mark - OverlayQueueObserver
void OverlayScheduler::OverlayQueueDidAddOverlay(OverlayQueue* queue) {
DCHECK(queue);
overlay_queues_.push_back(queue);
TryToStartNextOverlay();
}
void OverlayScheduler::OverlayQueueWillReplaceVisibleOverlay(
OverlayQueue* queue) {
DCHECK(queue);
DCHECK_EQ(overlay_queues_.front(), queue);
DCHECK(queue->IsShowingOverlay());
// An OverlayQueue's visible overlay can only be replaced if it's the first
// queue in the scheduler and is already showing an overlay. The queue is
// added here to schedule its replacement overlay can be displayed when its
// currently-visible overlay is stopped.
overlay_queues_.push_front(queue);
}
void OverlayScheduler::OverlayQueueDidStopVisibleOverlay(OverlayQueue* queue) {
DCHECK(!overlay_queues_.empty());
DCHECK_EQ(overlay_queues_.front(), queue);
// Only the first queue in the scheduler can start overlays, so it is expected
// that this function is only called for that queue.
overlay_queues_.pop_front();
TryToStartNextOverlay();
}
void OverlayScheduler::OverlayQueueDidCancelOverlays(OverlayQueue* queue) {
DCHECK(queue);
// Remove all scheduled instances of |queue| from the |overlay_queues_|.
auto i = overlay_queues_.begin();
while (i != overlay_queues_.end()) {
if (*i == queue)
overlay_queues_.erase(i);
}
// If |queue| is currently showing an overlay, prepend it to
// |overlay_queues_|. It will be removed when the cancelled overlay is
// stopped.
if (queue->IsShowingOverlay())
overlay_queues_.push_front(queue);
}
#pragma mark - WebStateObserver
void OverlayScheduler::WasShown(web::WebState* web_state) {
StopObservingWebState(web_state);
}
void OverlayScheduler::WebStateDestroyed(web::WebState* web_state) {
StopObservingWebState(web_state);
}
#pragma mark -
void OverlayScheduler::TryToStartNextOverlay() {
// Overlays cannot be started if:
// - the service is paused,
// - there are no overlays to display,
// - an overlay is already being displayed,
// - an overlay is already scheduled to be started once a specific WebState
// has been shown.
if (paused_ || overlay_queues_.empty() || IsShowingOverlay() ||
observing_front_web_state_) {
return;
}
OverlayQueue* queue = overlay_queues_.front();
web::WebState* web_state = queue->GetWebState();
// Create a WebStateVisibilityObserver if |web_state| needs to be activated.
if (web_state && (web_state_list_->GetActiveWebState() != web_state ||
!web_state->IsVisible())) {
web_state->AddObserver(this);
observing_front_web_state_ = true;
}
// Notify the observers that an overlay will be shown for |web_state|. If
// |web_state| isn't nil, this callback is expected to update the active
// WebState and show its content area.
for (auto& observer : observers_) {
observer.OverlaySchedulerWillShowOverlay(this, web_state);
}
// If |web_state| was nil or already activated, then start |queue|'s next
// overlay. Otherwise, it will be started in OnWebStateShown(). The check
// for IsShowingOverlay() is to prevent calling StartNextOverlay() twice in
// the event that WasShown() was called directly from the observer callbacks
// above.
if (!observing_front_web_state_ && !IsShowingOverlay()) {
queue->StartNextOverlay();
}
}
void OverlayScheduler::StopObservingQueue(OverlayQueue* queue) {
queue->RemoveObserver(this);
queue->CancelOverlays();
}
void OverlayScheduler::StopObservingWebState(web::WebState* web_state) {
DCHECK(observing_front_web_state_);
DCHECK(web_state);
DCHECK_EQ(overlay_queues_.front()->GetWebState(), web_state);
web_state->RemoveObserver(this);
observing_front_web_state_ = false;
TryToStartNextOverlay();
}
// Copyright 2017 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_OVERLAY_SCHEDULER_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SCHEDULER_OBSERVER_H_
#include "base/macros.h"
class OverlayScheduler;
namespace web {
class WebState;
}
// Interface for listening to OverlayService events.
class OverlaySchedulerObserver {
public:
OverlaySchedulerObserver() = default;
virtual ~OverlaySchedulerObserver() = default;
// Tells the observer that |scheduler| is about to display an overlay. If
// |web_state| is non-null, then this is a WebState-specific overlay, and the
// WebState's content view is expected to be visible after this callback.
virtual void OverlaySchedulerWillShowOverlay(OverlayScheduler* scheduler,
web::WebState* web_state) {}
private:
DISALLOW_COPY_AND_ASSIGN(OverlaySchedulerObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SCHEDULER_OBSERVER_H_
// Copyright 2017 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_OVERLAY_SERVICE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_H_
#include "base/macros.h"
#include "components/keyed_service/core/keyed_service.h"
namespace web {
class WebState;
}
class Browser;
@class BrowserCoordinator;
@class OverlayCoordinator;
class OverlayServiceObserver;
// OverlayService allows for the easy presentation and dismissal of overlay
// cordinators. Overlays are modal and displayed in the order in which this
// service receives them. If an overlay is added to this service while one is
// already presented, it will be queued until that current overlay is stopped.
// This serivce is run on the UI thread.
class OverlayService : public KeyedService {
public:
OverlayService() = default;
~OverlayService() override = default;
// Adds and removes observers to the OverlayService.
virtual void AddObserver(OverlayServiceObserver* observer) = 0;
virtual void RemoveObserver(OverlayServiceObserver* observer) = 0;
// The OverlayService can be paused for a particular Browser.
virtual void PauseServiceForBrowser(Browser* browser) = 0;
virtual void ResumeServiceForBrowser(Browser* browser) = 0;
virtual bool IsPausedForBrowser(Browser* browser) const = 0;
// Whether an overlay is currently displayed for |browser|. This will return
// true for both WebState-specific or Browser-level overlays.
virtual bool IsBrowserShowingOverlay(Browser* browser) const = 0;
// Replaces |browser|'s currently-visible overlay with |overlay_coordinator|.
// The replacement overlay will use the visible overlay's parent as its own.
// This will replace the current overlay regardless of if it's WebState-
// specific.
virtual void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator,
Browser* browser) = 0;
// Cancels all scheduled overlays added to this service. If an overlay is
// currently visible, it will be stopped.
virtual void CancelOverlays() = 0;
// Browser-level overlays:
// Shows |overlay_coordinator| over |parent_coordinator|'s UI in |browser|.
virtual void ShowOverlayForBrowser(OverlayCoordinator* overlay_coordinator,
BrowserCoordinator* parent_coordiantor,
Browser* browser) = 0;
// Cancells all scheduled overlays for |browser|. If an overlay is already
// being shown for |browser|, it will be stopped.
virtual void CancelAllOverlaysForBrowser(Browser* browser) = 0;
// WebState-specific overlays:
// Switches the active WebState to |web_state| and displays
// |overlay_coordinator|'s UI over it. If an overlay is already started,
// the active WebState will switch and |overlay_coordinator| will be started
// when that one is dismissed.
virtual void ShowOverlayForWebState(OverlayCoordinator* overlay_coordinator,
web::WebState* web_state) = 0;
// Cancels all scheduled overlays for |web_state|. If an overlay is already
// being shown for |web_state|, it will be stopped.
virtual void CancelAllOverlaysForWebState(web::WebState* web_state) = 0;
// Overlays added via ShowOverlayForWebState() can only be started when their
// associated WebState's content area is visible. When a coordinator showing
// a WebState's content is started, it can use this function to notify the
// OverlayService to use itself as the parent for that WebState's overlays.
virtual void SetWebStateParentCoordinator(
BrowserCoordinator* parent_coordinator,
web::WebState* web_state) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(OverlayService);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_H_
// Copyright 2017 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_OVERLAY_SERVICE_FACTORY_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_FACTORY_H_
#include "base/macros.h"
#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
}
namespace ios {
class ChromeBrowserState;
}
class OverlayService;
// OverlayServiceFactory attaches OverlayServices to ChromeBrowserStates.
class OverlayServiceFactory : public BrowserStateKeyedServiceFactory {
public:
// Convenience getter that typecasts the value returned to OverlayService.
static OverlayService* GetForBrowserState(
ios::ChromeBrowserState* browser_state);
// Getter for singleton instance.
static OverlayServiceFactory* GetInstance();
private:
friend struct base::DefaultSingletonTraits<OverlayServiceFactory>;
OverlayServiceFactory();
~OverlayServiceFactory() override;
// BrowserStateKeyedServiceFactory:
std::unique_ptr<KeyedService> BuildServiceInstanceFor(
web::BrowserState* context) const override;
web::BrowserState* GetBrowserStateToUse(
web::BrowserState* context) const override;
DISALLOW_COPY_AND_ASSIGN(OverlayServiceFactory);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_FACTORY_H_
// Copyright 2017 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/overlay_service_factory.h"
#include <memory>
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/ios/browser_state_dependency_manager.h"
#include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/ui/browser_list/browser_list.h"
#import "ios/chrome/browser/ui/browser_list/browser_list_factory.h"
#import "ios/chrome/browser/ui/overlays/overlay_service_impl.h"
#import "ios/web/public/certificate_policy_cache.h"
#import "ios/web/public/web_state/session_certificate_policy_cache.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// static
OverlayService* OverlayServiceFactory::GetForBrowserState(
ios::ChromeBrowserState* browser_state) {
return static_cast<OverlayService*>(
GetInstance()->GetServiceForBrowserState(browser_state, true));
}
// static
OverlayServiceFactory* OverlayServiceFactory::GetInstance() {
return base::Singleton<OverlayServiceFactory>::get();
}
OverlayServiceFactory::OverlayServiceFactory()
: BrowserStateKeyedServiceFactory(
"OverlayService",
BrowserStateDependencyManager::GetInstance()) {
DependsOn(BrowserListFactory::GetInstance());
}
OverlayServiceFactory::~OverlayServiceFactory() {}
std::unique_ptr<KeyedService> OverlayServiceFactory::BuildServiceInstanceFor(
web::BrowserState* context) const {
ios::ChromeBrowserState* browser_state =
ios::ChromeBrowserState::FromBrowserState(context);
return std::make_unique<OverlayServiceImpl>(
BrowserListFactory::GetForBrowserState(browser_state));
}
web::BrowserState* OverlayServiceFactory::GetBrowserStateToUse(
web::BrowserState* context) const {
return GetBrowserStateOwnInstanceInIncognito(context);
}
// Copyright 2017 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_OVERLAY_SERVICE_IMPL_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_IMPL_H_
#include "base/observer_list.h"
#import "ios/chrome/browser/ui/browser_list/browser_list_observer.h"
#import "ios/chrome/browser/ui/overlays/overlay_scheduler_observer.h"
#import "ios/chrome/browser/ui/overlays/overlay_service.h"
class BrowserList;
// Concrete subclass of OverlayService.
class OverlayServiceImpl : public BrowserListObserver,
public OverlaySchedulerObserver,
public OverlayService {
public:
// Constructor for an OverlayService that schedules overlays for the Browsers
// in |browser_list|.
OverlayServiceImpl(BrowserList* browser_list);
~OverlayServiceImpl() override;
private:
// The OverlayServiceObservers.
base::ObserverList<OverlayServiceObserver>::Unchecked observers_;
// The BrowserList passed on implementation.
BrowserList* browser_list_;
// BrowserListObserver:
void OnBrowserCreated(BrowserList* browser_list, Browser* browser) override;
void OnBrowserRemoved(BrowserList* browser_list, Browser* browser) override;
// KeyedService:
void Shutdown() override;
// OverlaySchedulerObserver:
void OverlaySchedulerWillShowOverlay(OverlayScheduler* scheduler,
web::WebState* web_state) override;
// OverlayService:
void AddObserver(OverlayServiceObserver* observer) override;
void RemoveObserver(OverlayServiceObserver* observer) override;
void PauseServiceForBrowser(Browser* browser) override;
void ResumeServiceForBrowser(Browser* browser) override;
bool IsPausedForBrowser(Browser* browser) const override;
bool IsBrowserShowingOverlay(Browser* browser) const override;
void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator,
Browser* browser) override;
void CancelOverlays() override;
void ShowOverlayForBrowser(OverlayCoordinator* overlay_coordinator,
BrowserCoordinator* parent_coordiantor,
Browser* browser) override;
void CancelAllOverlaysForBrowser(Browser* browser) override;
void ShowOverlayForWebState(OverlayCoordinator* overlay_coordinator,
web::WebState* web_state) override;
void SetWebStateParentCoordinator(BrowserCoordinator* parent_coordinator,
web::WebState* web_state) override;
void CancelAllOverlaysForWebState(web::WebState* web_state) override;
// Sets up or tears down the OverlayQueueManager and OverlayScheduler for
// |browser|.
void StartServiceForBrowser(Browser* browser);
void StopServiceForBrowser(Browser* browser);
DISALLOW_COPY_AND_ASSIGN(OverlayServiceImpl);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_IMPL_H_
// Copyright 2017 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/overlay_service_impl.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/browser_list/browser_list.h"
#import "ios/chrome/browser/ui/overlays/browser_overlay_queue.h"
#import "ios/chrome/browser/ui/overlays/overlay_queue_manager.h"
#import "ios/chrome/browser/ui/overlays/overlay_scheduler.h"
#import "ios/chrome/browser/ui/overlays/overlay_service_observer.h"
#import "ios/chrome/browser/ui/overlays/web_state_overlay_queue.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
OverlayServiceImpl::OverlayServiceImpl(BrowserList* browser_list)
: browser_list_(browser_list) {
DCHECK(browser_list_);
for (int index = 0; index < browser_list_->GetCount(); ++index) {
StartServiceForBrowser(browser_list_->GetBrowserAtIndex(index));
}
browser_list_->AddObserver(this);
}
OverlayServiceImpl::~OverlayServiceImpl() {}
#pragma mark - BrowserListObserver
void OverlayServiceImpl::OnBrowserCreated(BrowserList* browser_list,
Browser* browser) {
DCHECK_EQ(browser_list, browser_list_);
StartServiceForBrowser(browser);
}
void OverlayServiceImpl::OnBrowserRemoved(BrowserList* browser_list,
Browser* browser) {
DCHECK_EQ(browser_list, browser_list_);
StopServiceForBrowser(browser);
}
#pragma mark - KeyedService
void OverlayServiceImpl::Shutdown() {
for (int index = 0; index < browser_list_->GetCount(); ++index) {
StopServiceForBrowser(browser_list_->GetBrowserAtIndex(index));
}
browser_list_->RemoveObserver(this);
browser_list_ = nullptr;
}
#pragma mark - OverlaySchedulerObserver
void OverlayServiceImpl::OverlaySchedulerWillShowOverlay(
OverlayScheduler* scheduler,
web::WebState* web_state) {
DCHECK(scheduler);
Browser* scheduler_browser = nullptr;
for (int index = 0; index < browser_list_->GetCount(); ++index) {
Browser* browser = browser_list_->GetBrowserAtIndex(index);
if (OverlayScheduler::FromBrowser(browser) == scheduler) {
scheduler_browser = browser;
break;
}
}
DCHECK(scheduler_browser);
for (auto& observer : observers_) {
observer.OverlayServiceWillShowOverlay(this, web_state, scheduler_browser);
}
}
#pragma mark - OverlayService
void OverlayServiceImpl::AddObserver(OverlayServiceObserver* observer) {
observers_.AddObserver(observer);
}
void OverlayServiceImpl::RemoveObserver(OverlayServiceObserver* observer) {
observers_.RemoveObserver(observer);
}
void OverlayServiceImpl::PauseServiceForBrowser(Browser* browser) {
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
if (scheduler)
scheduler->SetPaused(true);
}
void OverlayServiceImpl::ResumeServiceForBrowser(Browser* browser) {
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
if (scheduler)
scheduler->SetPaused(false);
}
bool OverlayServiceImpl::IsPausedForBrowser(Browser* browser) const {
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
return scheduler && scheduler->paused();
}
bool OverlayServiceImpl::IsBrowserShowingOverlay(Browser* browser) const {
if (browser_list_->GetIndexOfBrowser(browser) == BrowserList::kInvalidIndex)
return false;
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
return scheduler && scheduler->IsShowingOverlay();
}
void OverlayServiceImpl::ReplaceVisibleOverlay(
OverlayCoordinator* overlay_coordinator,
Browser* browser) {
DCHECK(overlay_coordinator);
DCHECK(IsBrowserShowingOverlay(browser));
OverlayScheduler::FromBrowser(browser)->ReplaceVisibleOverlay(
overlay_coordinator);
}
void OverlayServiceImpl::CancelOverlays() {
for (int index = 0; index < browser_list_->GetCount(); ++index) {
OverlayScheduler::FromBrowser(browser_list_->GetBrowserAtIndex(index))
->CancelOverlays();
}
}
void OverlayServiceImpl::ShowOverlayForBrowser(
OverlayCoordinator* overlay_coordinator,
BrowserCoordinator* parent_coordiantor,
Browser* browser) {
BrowserOverlayQueue* queue = BrowserOverlayQueue::FromBrowser(browser);
if (queue)
queue->AddBrowserOverlay(overlay_coordinator, parent_coordiantor);
}
void OverlayServiceImpl::CancelAllOverlaysForBrowser(Browser* browser) {
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
if (scheduler)
scheduler->CancelOverlays();
}
void OverlayServiceImpl::ShowOverlayForWebState(
OverlayCoordinator* overlay_coordinator,
web::WebState* web_state) {
WebStateOverlayQueue* queue = WebStateOverlayQueue::FromWebState(web_state);
if (queue)
queue->AddWebStateOverlay(overlay_coordinator);
}
void OverlayServiceImpl::SetWebStateParentCoordinator(
BrowserCoordinator* parent_coordinator,
web::WebState* web_state) {
WebStateOverlayQueue* queue = WebStateOverlayQueue::FromWebState(web_state);
if (queue)
queue->SetWebStateParentCoordinator(parent_coordinator);
}
void OverlayServiceImpl::CancelAllOverlaysForWebState(
web::WebState* web_state) {
WebStateOverlayQueue* queue = WebStateOverlayQueue::FromWebState(web_state);
if (queue)
queue->CancelOverlays();
}
#pragma mark -
void OverlayServiceImpl::StartServiceForBrowser(Browser* browser) {
OverlayScheduler::CreateForBrowser(browser);
OverlayScheduler::FromBrowser(browser)->AddObserver(this);
}
void OverlayServiceImpl::StopServiceForBrowser(Browser* browser) {
OverlayScheduler* scheduler = OverlayScheduler::FromBrowser(browser);
scheduler->Disconnect();
scheduler->RemoveObserver(this);
}
// Copyright 2017 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_OVERLAY_SERVICE_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_OBSERVER_H_
#include "base/macros.h"
class Browser;
class OverlayService;
namespace web {
class WebState;
}
// Interface for listening to OverlayService events.
class OverlayServiceObserver {
public:
OverlayServiceObserver() = default;
virtual ~OverlayServiceObserver() = default;
// Tells the observer that |service| is about to display an overlay over
// |browser|. If |web_state| is non-null, then the overlay is meant to be
// displayed over its content area.
virtual void OverlayServiceWillShowOverlay(OverlayService* service,
web::WebState* web_state,
Browser* browser) {}
private:
DISALLOW_COPY_AND_ASSIGN(OverlayServiceObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_OBSERVER_H_
// Copyright 2017 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_OVERLAY_SERVICE_OBSERVER_BRIDGE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_OBSERVER_BRIDGE_H_
#include "ios/chrome/browser/ui/overlays/overlay_service_observer.h"
#import <Foundation/Foundation.h>
// Objective-C interface for observing an OverlayService. To use, wrap in an
// OverlayServiceObserverBridge.
@protocol OverlayServiceObserving<NSObject>
// Tells the observer that |service| is about to display an overlay over
// |browser|. If |web_state| is non-null, then the overlay is meant to be
// displayed over its content area.
- (void)overlayService:(OverlayService*)overlayService
willShowOverlayForWebState:(web::WebState*)webState
inBrowser:(Browser*)browser;
@end
// Observer that bridges OverlayService events to an Objective-C observer that
// implements the OverlayServiceObserving protocol (the observer is *not*
// owned).
class OverlayServiceObserverBridge final : public OverlayServiceObserver {
public:
// Constructor for a bridge that forwards events to |observer|.
explicit OverlayServiceObserverBridge(id<OverlayServiceObserving> observer);
~OverlayServiceObserverBridge() override;
private:
// OverlayServiceObserver:
void OverlayServiceWillShowOverlay(OverlayService* service,
web::WebState* web_state,
Browser* browser) override;
// The observer passed on initialization.
__weak id<OverlayServiceObserving> observer_;
DISALLOW_COPY_AND_ASSIGN(OverlayServiceObserverBridge);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_SERVICE_OBSERVER_BRIDGE_H_
// Copyright 2017 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/overlay_service_observer_bridge.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
OverlayServiceObserverBridge::OverlayServiceObserverBridge(
id<OverlayServiceObserving> observer)
: observer_(observer) {}
OverlayServiceObserverBridge::~OverlayServiceObserverBridge() {}
void OverlayServiceObserverBridge::OverlayServiceWillShowOverlay(
OverlayService* service,
web::WebState* web_state,
Browser* browser) {
[observer_ overlayService:service
willShowOverlayForWebState:web_state
inBrowser:browser];
}
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("test") {
testonly = true
sources = [
"overlay_coordinator_test.h",
"overlay_coordinator_test.mm",
"test_overlay_coordinator.h",
"test_overlay_coordinator.mm",
"test_overlay_parent_coordinator.h",
"test_overlay_parent_coordinator.mm",
"test_overlay_queue.h",
"test_overlay_queue.mm",
"test_overlay_queue_manager_observer.h",
"test_overlay_queue_manager_observer.mm",
"test_overlay_queue_observer.h",
"test_overlay_queue_observer.mm",
]
deps = [
"//base",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/ui/browser_list",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators",
"//ios/chrome/browser/ui/coordinators:test_support",
"//ios/chrome/browser/ui/overlays",
"//ios/chrome/browser/ui/overlays:overlays_internal",
"//ios/chrome/browser/web_state_list",
"//ios/web",
"//testing/gtest",
]
configs += [ "//build/config/compiler:enable_arc" ]
}
// Copyright 2017 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_TEST_HELPERS_OVERLAY_COORDINATOR_TEST_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_HELPERS_OVERLAY_COORDINATOR_TEST_H_
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_queue.h"
@class OverlayCoordinator;
// A test fixture for OverlayCoordinators.
class OverlayCoordinatorTest : public BrowserCoordinatorTest {
public:
OverlayCoordinatorTest();
~OverlayCoordinatorTest() override;
// Starts the OverlayCoordinator supplied by GetOverlay().
void StartOverlay();
protected:
// Returns the OverlayCoordinator being tested by this fixture.
virtual OverlayCoordinator* GetOverlay() = 0;
private:
// The queue to handle displying the overlay.
TestOverlayQueue queue_;
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_HELPERS_OVERLAY_COORDINATOR_TEST_H_
// Copyright 2017 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/test/overlay_coordinator_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
OverlayCoordinatorTest::OverlayCoordinatorTest() {
queue_.SetBrowser(GetBrowser());
}
OverlayCoordinatorTest::~OverlayCoordinatorTest() {
queue_.CancelOverlays();
}
void OverlayCoordinatorTest::StartOverlay() {
queue_.AddOverlay(GetOverlay());
queue_.StartNextOverlay();
}
// Copyright 2017 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_TEST_TEST_OVERLAY_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_COORDINATOR_H_
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
// Test OverlayCoordinator.
@interface TestOverlayCoordinator : OverlayCoordinator
// Whether |-cancel| has been called for this coordinator.
@property(nonatomic, readonly, getter=isCancelled) BOOL cancelled;
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_COORDINATOR_H_
// Copyright 2017 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/test/test_overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface TestOverlayCoordinator ()
// Dummy UIViewController that is presented when the coordinator is started.
@property(nonatomic, readonly) UIViewController* viewController;
@end
@implementation TestOverlayCoordinator
@synthesize cancelled = _cancelled;
@synthesize viewController = _viewController;
- (UIViewController*)viewController {
if (!_viewController)
_viewController = [[UIViewController alloc] init];
return _viewController;
}
#pragma mark - OverlayCoordinator
- (void)cancelOverlay {
_cancelled = YES;
}
@end
// Copyright 2017 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_TEST_HELPERS_TEST_OVERLAY_PARENT_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_HELPERS_TEST_OVERLAY_PARENT_COORDINATOR_H_
#import "ios/chrome/browser/ui/coordinators/browser_coordinator.h"
@class OverlayCoordinator;
// Test BrowserCoordinator subclass that can be used as the parent for overlays.
@interface TestOverlayParentCoordinator : BrowserCoordinator
// The overlay that is currently displayed over this parent.
@property(nonatomic, readonly) OverlayCoordinator* presentedOverlay;
@end
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_HELPERS_TEST_OVERLAY_PARENT_COORDINATOR_H_
// Copyright 2017 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/test/test_overlay_parent_coordinator.h"
#import <UIKit/UIKit.h>
#include "base/mac/foundation_util.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface TestOverlayParentCoordinator ()
// The parent view controller's window. Necessary for UIViewControllers to
// present properly.
@property(nonatomic, readonly, strong) UIWindow* window;
// The parent UIViewController.
@property(nonatomic, readonly, strong) UIViewController* viewController;
@end
@implementation TestOverlayParentCoordinator
@synthesize window = _window;
@synthesize viewController = _viewController;
- (instancetype)init {
if ((self = [super init])) {
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_viewController = [[UIViewController alloc] init];
_window.rootViewController = _viewController;
[_window makeKeyAndVisible];
}
return self;
}
- (void)dealloc {
[_window removeFromSuperview];
[_window resignKeyWindow];
}
#pragma mark - Public
- (OverlayCoordinator*)presentedOverlay {
NSUInteger childCount = self.children.count;
DCHECK_LE(childCount, 1U);
return childCount == 1U ? base::mac::ObjCCastStrict<OverlayCoordinator>(
[self.children anyObject])
: nil;
}
@end
@implementation TestOverlayParentCoordinator (Internal)
- (void)childCoordinatorDidStart:(BrowserCoordinator*)childCoordinator {
[self.viewController presentViewController:childCoordinator.viewController
animated:NO
completion:nil];
}
- (void)childCoordinatorWillStop:(BrowserCoordinator*)childCoordinator {
[self.viewController dismissViewControllerAnimated:NO completion:nil];
}
@end
// Copyright 2017 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_TEST_TEST_OVERLAY_QUEUE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_H_
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
class Browser;
@class BrowserCoordinator;
@class OverlayCoordinator;
// Test OverlayQueue implementation. This object constructs a dummy parent
// coordinator from which to start queued OverlayCoordinators.
class TestOverlayQueue : public OverlayQueue {
public:
TestOverlayQueue();
// Adds |overlay| to queue to be started over |parent_|.
void AddOverlay(OverlayCoordinator* overlay);
// Starts the first overlay in the queue using |parent_| as the parent
// coordinator. Waits until the overlay's view controller has finished being
// presented before returning.
void StartNextOverlay() override;
// Replaces the visible overlay with |overlay_coordinator|, waiting until the
// visible overlay's view controller has finished being dimissed before
// returning.
void ReplaceVisibleOverlay(OverlayCoordinator* overlay_coordinator) override;
// Seting the Browser also sets the Browser of |parent_|, which will be passed
// along to OverlayCoordinators presented by this queue when they are started.
Browser* browser() const { return browser_; }
void SetBrowser(Browser* browser);
private:
// The coordinator to use as the parent for overlays added via AddOverlay().
__strong BrowserCoordinator* parent_;
// The Browser to use, if any.
Browser* browser_;
DISALLOW_COPY_AND_ASSIGN(TestOverlayQueue);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_H_
// Copyright 2017 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/test/test_overlay_queue.h"
#import "ios/chrome/browser/ui/coordinators/browser_coordinator_test_util.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
#import "ios/chrome/browser/ui/overlays/test/test_overlay_parent_coordinator.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
TestOverlayQueue::TestOverlayQueue()
: OverlayQueue(), parent_([[TestOverlayParentCoordinator alloc] init]) {}
void TestOverlayQueue::AddOverlay(OverlayCoordinator* overlay) {
OverlayQueue::AddOverlay(overlay);
}
void TestOverlayQueue::StartNextOverlay() {
OverlayCoordinator* overlay = GetFirstOverlay();
EXPECT_TRUE(overlay);
[overlay startOverlayingCoordinator:parent_];
OverlayWasStarted();
WaitForBrowserCoordinatorActivation(overlay);
}
void TestOverlayQueue::ReplaceVisibleOverlay(
OverlayCoordinator* overlay_coordinator) {
OverlayCoordinator* overlay = GetFirstOverlay();
EXPECT_TRUE(overlay);
OverlayQueue::ReplaceVisibleOverlay(overlay_coordinator);
WaitForBrowserCoordinatorDeactivation(overlay);
}
void TestOverlayQueue::SetBrowser(Browser* browser) {
browser_ = browser;
parent_.browser = browser;
}
// Copyright 2017 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_TEST_TEST_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
#import "ios/chrome/browser/ui/overlays/overlay_queue_manager_observer.h"
#include <list>
class OverlayQueue;
class OverlayQueueManager;
// Observer class for OverlayQueueManager.
class TestOverlayQueueManagerObserver : public OverlayQueueManagerObserver {
public:
TestOverlayQueueManagerObserver();
~TestOverlayQueueManagerObserver() override;
// OverlayQueueManagerObserver:
void OverlayQueueManagerDidAddQueue(OverlayQueueManager* manager,
OverlayQueue* queue) override;
void OverlayQueueManagerWillRemoveQueue(OverlayQueueManager* manager,
OverlayQueue* queue) override;
// Flags recording whether the above callbacks have been received.
bool did_add_called() { return did_add_called_; }
bool will_remove_called() { return will_remove_called_; }
// Resets observer callback flags to false.
void reset() {
did_add_called_ = false;
will_remove_called_ = false;
}
// The added queues that were reported via OverlayQueueManagerObserver
// callbacks. The queues are present in the same order in which the callbacks
// were received.
const std::list<OverlayQueue*>& queues() { return queues_; }
private:
// Flags denoting which callbacks were called.
bool did_add_called_;
bool will_remove_called_;
std::list<OverlayQueue*> queues_;
DISALLOW_COPY_AND_ASSIGN(TestOverlayQueueManagerObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_MANAGER_OBSERVER_H_
// Copyright 2017 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/test/test_overlay_queue_manager_observer.h"
#include <algorithm>
#include <iterator>
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
TestOverlayQueueManagerObserver::TestOverlayQueueManagerObserver()
: did_add_called_(false), will_remove_called_(false) {}
TestOverlayQueueManagerObserver::~TestOverlayQueueManagerObserver() {}
void TestOverlayQueueManagerObserver::OverlayQueueManagerDidAddQueue(
OverlayQueueManager* manager,
OverlayQueue* queue) {
did_add_called_ = true;
queues_.push_back(queue);
}
void TestOverlayQueueManagerObserver::OverlayQueueManagerWillRemoveQueue(
OverlayQueueManager* manager,
OverlayQueue* queue) {
will_remove_called_ = true;
auto iter = std::find(std::begin(queues_), std::end(queues_), queue);
if (iter != queues_.end())
queues_.erase(iter);
}
// Copyright 2017 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_TEST_TEST_OVERLAY_QUEUE_OBSERVER_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_OBSERVER_H_
#import "ios/chrome/browser/ui/overlays/overlay_queue_observer.h"
// Test OverlayQueueObserver.
class TestOverlayQueueObserver : public OverlayQueueObserver {
public:
TestOverlayQueueObserver()
: did_add_called_(false),
will_replace_called_(false),
stop_visible_called_(false),
did_cancel_called_(false) {}
// OverlayQueueObserver:
void OverlayQueueDidAddOverlay(OverlayQueue* queue) override;
void OverlayQueueWillReplaceVisibleOverlay(OverlayQueue* queue) override;
void OverlayQueueDidStopVisibleOverlay(OverlayQueue* queue) override;
void OverlayQueueDidCancelOverlays(OverlayQueue* queue) override;
// Accessors for flags.
bool did_add_called() { return did_add_called_; }
bool will_replace_called() { return will_replace_called_; }
bool stop_visible_called() { return stop_visible_called_; }
bool did_cancel_called() { return did_cancel_called_; }
private:
// Flags denoting which observer callbacks have been called.
bool did_add_called_;
bool will_replace_called_;
bool stop_visible_called_;
bool did_cancel_called_;
DISALLOW_COPY_AND_ASSIGN(TestOverlayQueueObserver);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_TEST_OVERLAY_QUEUE_OBSERVER_H_
// Copyright 2017 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/test/test_overlay_queue_observer.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
void TestOverlayQueueObserver::OverlayQueueDidAddOverlay(OverlayQueue* queue) {
did_add_called_ = true;
}
void TestOverlayQueueObserver::OverlayQueueWillReplaceVisibleOverlay(
OverlayQueue* queue) {
will_replace_called_ = true;
}
void TestOverlayQueueObserver::OverlayQueueDidStopVisibleOverlay(
OverlayQueue* queue) {
stop_visible_called_ = true;
}
void TestOverlayQueueObserver::OverlayQueueDidCancelOverlays(
OverlayQueue* queue) {
did_cancel_called_ = true;
}
// Copyright 2017 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_WEB_STATE_OVERLAY_QUEUE_H_
#define IOS_CHROME_BROWSER_UI_OVERLAYS_WEB_STATE_OVERLAY_QUEUE_H_
#import "ios/chrome/browser/ui/overlays/overlay_queue.h"
#import "ios/web/public/web_state/web_state_user_data.h"
@class BrowserCoordinator;
// An implementation of OverlayQueue that stores BrowserCoordinators for a
// specific WebState.
class WebStateOverlayQueue
: public OverlayQueue,
public web::WebStateUserData<WebStateOverlayQueue> {
public:
// OverlayQueue:
web::WebState* GetWebState() const override;
void StartNextOverlay() override;
// Adds an overlay coordinator that will be displayed over GetWebState()'s
// content area.
void AddWebStateOverlay(OverlayCoordinator* overlay_coordinator);
// Sets the parent coordinator to use for queued BrowserCoordinators.
// |parent| is expected to be displaying GetWebState()'s content area before
// calling this function.
void SetWebStateParentCoordinator(BrowserCoordinator* parent_coordinator);
private:
friend class web::WebStateUserData<WebStateOverlayQueue>;
// Private constructor.
explicit WebStateOverlayQueue(web::WebState* web_state);
// The WebState with which this presenter is associated.
web::WebState* web_state_;
// The parent coordinator to use for overlays.
__weak BrowserCoordinator* parent_coordinator_;
DISALLOW_COPY_AND_ASSIGN(WebStateOverlayQueue);
};
#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_WEB_STATE_OVERLAY_QUEUE_H_
// Copyright 2017 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/web_state_overlay_queue.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator+internal.h"
#import "ios/chrome/browser/ui/overlays/overlay_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
DEFINE_WEB_STATE_USER_DATA_KEY(WebStateOverlayQueue);
WebStateOverlayQueue::WebStateOverlayQueue(web::WebState* web_state)
: web_state_(web_state), parent_coordinator_(nil) {
DCHECK(web_state);
}
web::WebState* WebStateOverlayQueue::GetWebState() const {
return web_state_;
}
void WebStateOverlayQueue::StartNextOverlay() {
DCHECK(parent_coordinator_);
DCHECK(HasQueuedOverlays());
DCHECK(!IsShowingOverlay());
[GetFirstOverlay() startOverlayingCoordinator:parent_coordinator_];
OverlayWasStarted();
}
void WebStateOverlayQueue::AddWebStateOverlay(
OverlayCoordinator* overlay_coordinator) {
AddOverlay(overlay_coordinator);
}
void WebStateOverlayQueue::SetWebStateParentCoordinator(
BrowserCoordinator* parent_coordinator) {
parent_coordinator_ = parent_coordinator;
}
......@@ -195,7 +195,6 @@ test("ios_chrome_unittests") {
"//ios/chrome/browser/ui/content_suggestions/cells:unit_tests",
"//ios/chrome/browser/ui/content_suggestions/identifier:unit_tests",
"//ios/chrome/browser/ui/context_menu:unit_tests",
"//ios/chrome/browser/ui/coordinators:unit_tests",
"//ios/chrome/browser/ui/dialogs:unit_tests",
"//ios/chrome/browser/ui/dialogs:unit_tests_internal",
"//ios/chrome/browser/ui/download:unit_tests",
......@@ -215,7 +214,6 @@ test("ios_chrome_unittests") {
"//ios/chrome/browser/ui/ntp:unit_tests",
"//ios/chrome/browser/ui/omnibox:unit_tests",
"//ios/chrome/browser/ui/omnibox/popup:unit_tests",
"//ios/chrome/browser/ui/overlays:unit_tests",
"//ios/chrome/browser/ui/payments:unit_tests",
"//ios/chrome/browser/ui/payments/cells:unit_tests",
"//ios/chrome/browser/ui/popup_menu:unit_tests",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment