OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #import "ios/clean/chrome/browser/ui/overlays/overlay_scheduler.h" | |
6 | |
7 #include <list> | |
8 | |
9 #include "base/logging.h" | |
10 #import "ios/chrome/browser/web_state_list/web_state_list.h" | |
11 #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h" | |
12 #import "ios/clean/chrome/browser/ui/overlays/browser_overlay_queue.h" | |
13 #import "ios/clean/chrome/browser/ui/overlays/overlay_queue.h" | |
14 #import "ios/clean/chrome/browser/ui/overlays/web_state_overlay_queue.h" | |
15 #import "ios/web/public/web_state/web_state.h" | |
16 | |
17 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
18 #error "This file requires ARC support." | |
19 #endif | |
20 | |
21 DEFINE_BROWSER_USER_DATA_KEY(OverlayScheduler); | |
22 | |
23 OverlayScheduler::OverlayScheduler(Browser* browser) | |
24 : browser_(browser), observing_(false) { | |
25 DCHECK(browser_); | |
26 StartObservingBrowser(); | |
27 } | |
28 | |
29 OverlayScheduler::~OverlayScheduler() {} | |
30 | |
31 #pragma mark - Public | |
32 | |
33 void OverlayScheduler::StartObservingBrowser() { | |
34 if (observing_) | |
35 return; | |
36 BrowserOverlayQueue::CreateForBrowser(browser_); | |
37 BrowserOverlayQueue::FromBrowser(browser_)->AddObserver(this); | |
38 StartObservingWebStateList(&browser_->web_state_list()); | |
39 observing_ = true; | |
40 } | |
41 | |
42 void OverlayScheduler::StopObservingBrowser() { | |
43 if (!observing_) | |
44 return; | |
45 BrowserOverlayQueue::FromBrowser(browser_)->RemoveObserver(this); | |
46 StopObservingWebStateList(&browser_->web_state_list()); | |
47 observing_ = false; | |
48 } | |
49 | |
50 bool OverlayScheduler::IsShowingOverlay() const { | |
51 return !overlay_queues_.empty() && | |
52 overlay_queues_.front()->IsShowingOverlay(); | |
53 } | |
54 | |
55 void OverlayScheduler::ReplaceVisibleOverlay( | |
56 BrowserCoordinator* overlay_coordinator) { | |
57 DCHECK(overlay_coordinator); | |
58 DCHECK(IsShowingOverlay()); | |
59 overlay_queues_.front()->ReplaceVisibleOverlay(overlay_coordinator); | |
60 } | |
61 | |
62 void OverlayScheduler::CancelOverlays() { | |
63 // |overlay_queues_| will be updated in OverlayQueueDidCancelOverlays(), so a | |
64 // while loop is used to avoid using invalidated iterators. | |
65 while (!overlay_queues_.empty()) { | |
66 overlay_queues_.front()->CancelOverlays(); | |
67 } | |
68 } | |
69 | |
70 #pragma mark - OverlayQueueObserver | |
71 | |
72 void OverlayScheduler::OverlayQueueDidAddOverlay(OverlayQueue* queue) { | |
73 DCHECK(queue); | |
74 overlay_queues_.push_back(queue); | |
75 TryToStartNextOverlay(); | |
76 } | |
77 | |
78 void OverlayScheduler::OverlayQueueWillReplaceVisibleOverlay( | |
79 OverlayQueue* queue) { | |
80 DCHECK(queue); | |
81 DCHECK_EQ(overlay_queues_.front(), queue); | |
82 DCHECK(queue->IsShowingOverlay()); | |
83 // An OverlayQueue's visible overlay can only be replaced if it's the first | |
84 // queue in the scheduler and is already showing an overlay. The queue is | |
85 // added here so that its replacement overlay can be displayed when its | |
86 // currently-visible overlay is stopped. | |
87 overlay_queues_.push_front(queue); | |
88 } | |
89 | |
90 void OverlayScheduler::OverlayQueueDidStopVisibleOverlay(OverlayQueue* queue) { | |
91 DCHECK(!overlay_queues_.empty()); | |
92 DCHECK_EQ(overlay_queues_.front(), queue); | |
93 // Only the first queue in the scheduler can start overlays, so it is expected | |
94 // that this function is only called for that queue. | |
95 overlay_queues_.pop_front(); | |
96 TryToStartNextOverlay(); | |
97 } | |
98 | |
99 void OverlayScheduler::OverlayQueueDidCancelOverlays(OverlayQueue* queue) { | |
100 DCHECK(queue); | |
101 // Remove all scheduled instances of |queue| from the |overlay_queues_|. | |
102 auto i = overlay_queues_.begin(); | |
103 while (i != overlay_queues_.end()) { | |
104 if (*i == queue) | |
105 overlay_queues_.erase(i); | |
106 } | |
107 // If |queue| is currently showing an overlay, prepend it to | |
108 // |overlay_queues_|. It will be removed when the cancelled overlay is | |
109 // stopped. | |
110 if (queue->IsShowingOverlay()) | |
111 overlay_queues_.push_front(queue); | |
112 } | |
113 | |
114 #pragma mark - WebStateListObserver | |
115 | |
116 void OverlayScheduler::WebStateInsertedAt(WebStateList* web_state_list, | |
117 web::WebState* web_state, | |
118 int index) { | |
119 StartObservingQueueForWebState(web_state); | |
120 } | |
121 | |
122 void OverlayScheduler::WebStateDetachedAt(WebStateList* web_state_list, | |
123 web::WebState* web_state, | |
124 int index) { | |
125 StopObservingQueueForWebState(web_state); | |
126 } | |
127 | |
128 #pragma mark - | |
129 | |
130 void OverlayScheduler::TryToStartNextOverlay() { | |
131 // Early return if an overlay is already started or if there are no queued | |
132 // overlays to show. | |
133 if (overlay_queues_.empty() || IsShowingOverlay()) | |
134 return; | |
135 // If the next queue requires a WebState's content area to be shown, switch | |
136 // the active WebState before starting the next overlay. | |
137 OverlayQueue* queue = overlay_queues_.front(); | |
138 web::WebState* web_state = queue->GetWebState(); | |
139 if (web_state) { | |
140 WebStateList& web_state_list = browser_->web_state_list(); | |
marq (ping after 24h)
2017/06/21 09:41:54
Rather than passing the whole browser into the sch
kkhorimoto
2017/06/23 06:11:16
This object is a BrowserUserData, so I don't think
marq (ping after 24h)
2017/06/23 10:42:01
Dispatcher is moving out of browser once I have ti
| |
141 int new_active_index = web_state_list.GetIndexOfWebState(web_state); | |
142 DCHECK_NE(new_active_index, WebStateList::kInvalidIndex); | |
143 web_state_list.ActivateWebStateAt(new_active_index); | |
marq (ping after 24h)
2017/06/21 09:41:53
We should arrive at some consensus about how activ
kkhorimoto
2017/06/23 06:11:16
As I mentioned in the meeting this morning, I thin
marq (ping after 24h)
2017/06/23 10:42:01
OK. I think I would like to start with pure model-
| |
144 id<TabGridCommands> grid_dispatcher = | |
145 static_cast<id<TabGridCommands>>(browser_->dispatcher()); | |
146 [grid_dispatcher showTabGridTabAtIndex:new_active_index]; | |
147 } | |
148 // Start the next overlay in the first queue. | |
149 queue->StartNextOverlay(); | |
150 } | |
151 | |
152 void OverlayScheduler::StartObservingWebStateList( | |
153 WebStateList* web_state_list) { | |
154 DCHECK(web_state_list); | |
155 web_state_list->AddObserver(this); | |
156 for (int index = 0; index < web_state_list->count(); ++index) { | |
157 StartObservingQueueForWebState(web_state_list->GetWebStateAt(index)); | |
158 } | |
159 } | |
160 | |
161 void OverlayScheduler::StopObservingWebStateList(WebStateList* web_state_list) { | |
162 DCHECK(web_state_list); | |
163 web_state_list->RemoveObserver(this); | |
164 for (int index = 0; index < web_state_list->count(); ++index) { | |
165 StopObservingQueueForWebState(web_state_list->GetWebStateAt(index)); | |
166 } | |
167 } | |
168 | |
169 void OverlayScheduler::StartObservingQueueForWebState( | |
170 web::WebState* web_state) { | |
171 DCHECK(web_state); | |
172 WebStateOverlayQueue::CreateForWebState(web_state); | |
173 WebStateOverlayQueue::FromWebState(web_state)->AddObserver(this); | |
174 } | |
175 | |
176 void OverlayScheduler::StopObservingQueueForWebState(web::WebState* web_state) { | |
177 DCHECK(web_state); | |
178 WebStateOverlayQueue::FromWebState(web_state)->CancelOverlays(); | |
marq (ping after 24h)
2017/06/21 09:41:53
If WSOQ::FromWebState(foo) returns nullptr, this w
kkhorimoto
2017/06/23 06:11:16
There is no codepath where that can occur.
| |
179 WebStateOverlayQueue::FromWebState(web_state)->RemoveObserver(this); | |
180 } | |
OLD | NEW |