Index: ios/clean/chrome/browser/ui/overlays/overlay_queue.mm |
diff --git a/ios/clean/chrome/browser/ui/overlays/overlay_queue.mm b/ios/clean/chrome/browser/ui/overlays/overlay_queue.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c22b96fb3dfa2bafec0948761b92ab360461bdbe |
--- /dev/null |
+++ b/ios/clean/chrome/browser/ui/overlays/overlay_queue.mm |
@@ -0,0 +1,102 @@ |
+// 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/clean/chrome/browser/ui/overlays/overlay_queue.h" |
+ |
+#include "base/logging.h" |
+#import "ios/clean/chrome/browser/ui/commands/overlay_commands.h" |
+#import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator.h" |
+ |
+#if !defined(__has_feature) || !__has_feature(objc_arc) |
+#error "This file requires ARC support." |
+#endif |
+ |
+DEFINE_WEB_STATE_USER_DATA_KEY(OverlayQueue); |
+ |
+// static |
+void OverlayQueue::CreateForWebState(web::WebState* web_state, |
+ id<OverlaySchedulerCommands> dispatcher) { |
+ DCHECK(web_state); |
+ DCHECK(dispatcher); |
+ if (!FromWebState(web_state)) { |
+ std::unique_ptr<OverlayQueue> queue = |
+ base::WrapUnique(new OverlayQueue(web_state, dispatcher)); |
+ web_state->SetUserData(UserDataKey(), std::move(queue)); |
+ } |
+} |
+ |
+OverlayQueue::OverlayQueue(web::WebState* web_state, |
+ id<OverlaySchedulerCommands> dispatcher) |
+ : web_state_(web_state), |
+ dispatcher_(dispatcher), |
+ overlays_([[NSMutableArray alloc] init]), |
+ showing_overlay_(false) { |
+ DCHECK(web_state); |
+ DCHECK(dispatcher); |
+} |
+ |
+OverlayQueue::~OverlayQueue() { |
+ [dispatcher_ cancelOverlaysForWebState:web_state_]; |
+} |
+ |
+void OverlayQueue::AddOverlay(OverlayCoordinator* overlay_coordinator) { |
+ // Add the overlay coordinator to the queue, then notify the scheduler. |
+ DCHECK(overlay_coordinator); |
+ [overlays_ addObject:overlay_coordinator]; |
+ [dispatcher_ scheduleOverlayForWebState:web_state_]; |
+} |
+ |
+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 the |
+ // scheduler that the overlay was replaced. Stopping the front overlay below |
+ // will cause |overlay_cordinator| to start. |
+ [overlays_ insertObject:overlay_coordinator atIndex:1]; |
+ [dispatcher_ visibleOverlayWasReplacedForWebState:web_state_]; |
+ OverlayCoordinator* visible_overlay = [overlays_ firstObject]; |
+ [visible_overlay cancelOverlay]; |
+ [visible_overlay stop]; |
+} |
+ |
+bool OverlayQueue::HasQueuedOverlays() const { |
+ return [overlays_ count] > 0U; |
+} |
+ |
+void OverlayQueue::StartNextOverlay(BrowserCoordinator* web_coordinator) { |
+ DCHECK(web_coordinator); |
+ DCHECK(HasQueuedOverlays()); |
+ DCHECK(!IsShowingOverlay()); |
+ [[overlays_ firstObject] startOverlayingCoordinator:web_coordinator]; |
+ showing_overlay_ = true; |
+} |
+ |
+bool OverlayQueue::IsShowingOverlay() const { |
+ return showing_overlay_; |
+} |
+ |
+void OverlayQueue::OverlayWasStopped(OverlayCoordinator* overlay_coordinator) { |
+ DCHECK(overlay_coordinator); |
+ DCHECK_EQ([overlays_ firstObject], overlay_coordinator); |
+ DCHECK(showing_overlay_); |
+ [overlays_ removeObjectAtIndex:0]; |
+ showing_overlay_ = false; |
+ [dispatcher_ overlayWasStoppedForWebState:web_state_]; |
+} |
+ |
+void OverlayQueue::CancelOverlays() { |
+ // Call the WebKit completion blocks for all queued overlays. |
+ for (OverlayCoordinator* overlay_coordinator in overlays_) { |
+ [overlay_coordinator cancelOverlay]; |
+ } |
+ // Remove the queued overlays and stop the visible overlay if one is |
+ // presented. Stopping the visible overlay will trigger the next scheduled |
+ // overlay, so the queue should be emptied before calling |-stop|. |
+ OverlayCoordinator* visible_overlay = |
+ showing_overlay_ ? [overlays_ firstObject] : nil; |
+ [overlays_ removeAllObjects]; |
+ [visible_overlay stop]; |
+} |