Commit 14263a93 authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Move OverlayService to ios/chrome.

Although this is only used by the new architecture, it is model code
built on top of BrowserCoordinator, which also lives in ios/chrome.

This CL also renames the test_helpers/ directory to test/ to match other
cases in ios/chrome.

Bug: none
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I9b731c0805b36feb9cbced4688cb9899ac129ca8
Reviewed-on: https://chromium-review.googlesource.com/648076
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarKurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521593}
parent e700ab58
...@@ -110,6 +110,7 @@ source_set("browser_state_impl") { ...@@ -110,6 +110,7 @@ source_set("browser_state_impl") {
"//ios/chrome/browser/ui/browser_list:browser_list_impl", "//ios/chrome/browser/ui/browser_list:browser_list_impl",
"//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen",
"//ios/chrome/browser/ui/fullscreen:new_fullscreen", "//ios/chrome/browser/ui/fullscreen:new_fullscreen",
"//ios/chrome/browser/ui/overlays",
"//ios/chrome/browser/undo", "//ios/chrome/browser/undo",
"//ios/net", "//ios/net",
"//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser",
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include "ios/chrome/browser/ui/browser_list/browser_list_session_service_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" #include "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
#include "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #include "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
#import "ios/chrome/browser/ui/overlays/overlay_service_factory.h"
#include "ios/chrome/browser/undo/bookmark_undo_service_factory.h" #include "ios/chrome/browser/undo/bookmark_undo_service_factory.h"
#include "ios/chrome/browser/web_data_service_factory.h" #include "ios/chrome/browser/web_data_service_factory.h"
...@@ -125,4 +126,5 @@ void EnsureBrowserStateKeyedServiceFactoriesBuilt() { ...@@ -125,4 +126,5 @@ void EnsureBrowserStateKeyedServiceFactoriesBuilt() {
if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) { if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
FullscreenControllerFactory::GetInstance(); FullscreenControllerFactory::GetInstance();
} }
OverlayServiceFactory::GetInstance();
} }
# 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> 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> 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 "base/memory/ptr_util.h"
#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 =
base::MakeUnique<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 =
base::MakeUnique<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 =
base::MakeUnique<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> 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_
This diff is collapsed.
// 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/ptr_util.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 base::MakeUnique<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> 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