Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: ios/chrome/browser/web_state_list/web_state_list.mm

Issue 2812623002: Revert of [ios] Move WebStateList to ios/chrome/browser/web_state_list. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/chrome/browser/web_state_list/web_state_list.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #import "ios/chrome/browser/web_state_list/web_state_list_delegate.h"
13 #import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
14 #import "ios/chrome/browser/web_state_list/web_state_list_order_controller.h"
15 #import "ios/chrome/browser/web_state_list/web_state_opener.h"
16 #import "ios/web/public/navigation_manager.h"
17 #import "ios/web/public/web_state/web_state.h"
18
19 #if !defined(__has_feature) || !__has_feature(objc_arc)
20 #error "This file requires ARC support."
21 #endif
22
23 // Wrapper around a WebState stored in a WebStateList.
24 class WebStateList::WebStateWrapper {
25 public:
26 explicit WebStateWrapper(std::unique_ptr<web::WebState> web_state);
27 ~WebStateWrapper();
28
29 web::WebState* web_state() const { return web_state_.get(); }
30
31 // Replaces the wrapped WebState (and clear associated state) and returns the
32 // old WebState after forfeiting ownership.
33 std::unique_ptr<web::WebState> ReplaceWebState(
34 std::unique_ptr<web::WebState> web_state);
35
36 // Gets and sets information about this WebState opener. The navigation index
37 // is used to detect navigation changes during the same session.
38 WebStateOpener opener() const { return opener_; }
39 void set_opener(WebStateOpener opener) { opener_ = opener; }
40
41 // Returns whether |opener| spawned the wrapped WebState. If |use_group| is
42 // true, also use the opener navigation index to detect navigation changes
43 // during the same session.
44 bool WasOpenedBy(const web::WebState* opener,
45 int opener_navigation_index,
46 bool use_group) const;
47
48 private:
49 std::unique_ptr<web::WebState> web_state_;
50 WebStateOpener opener_;
51
52 DISALLOW_COPY_AND_ASSIGN(WebStateWrapper);
53 };
54
55 WebStateList::WebStateWrapper::WebStateWrapper(
56 std::unique_ptr<web::WebState> web_state)
57 : web_state_(std::move(web_state)), opener_(nullptr) {
58 DCHECK(web_state_);
59 }
60
61 WebStateList::WebStateWrapper::~WebStateWrapper() = default;
62
63 std::unique_ptr<web::WebState> WebStateList::WebStateWrapper::ReplaceWebState(
64 std::unique_ptr<web::WebState> web_state) {
65 DCHECK_NE(web_state.get(), web_state_.get());
66 std::swap(web_state, web_state_);
67 opener_ = WebStateOpener(nullptr);
68 return web_state;
69 }
70
71 bool WebStateList::WebStateWrapper::WasOpenedBy(const web::WebState* opener,
72 int opener_navigation_index,
73 bool use_group) const {
74 DCHECK(opener);
75 if (opener_.opener != opener)
76 return false;
77
78 if (!use_group)
79 return true;
80
81 return opener_.navigation_index == opener_navigation_index;
82 }
83
84 WebStateList::WebStateList(WebStateListDelegate* delegate)
85 : delegate_(delegate),
86 order_controller_(base::MakeUnique<WebStateListOrderController>(this)) {
87 DCHECK(delegate_);
88 }
89
90 WebStateList::~WebStateList() {
91 CloseAllWebStates();
92 }
93
94 bool WebStateList::ContainsIndex(int index) const {
95 return 0 <= index && index < count();
96 }
97
98 web::WebState* WebStateList::GetActiveWebState() const {
99 if (active_index_ != kInvalidIndex)
100 return GetWebStateAt(active_index_);
101 return nullptr;
102 }
103
104 web::WebState* WebStateList::GetWebStateAt(int index) const {
105 DCHECK(ContainsIndex(index));
106 return web_state_wrappers_[index]->web_state();
107 }
108
109 int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const {
110 for (int index = 0; index < count(); ++index) {
111 if (web_state_wrappers_[index]->web_state() == web_state)
112 return index;
113 }
114 return kInvalidIndex;
115 }
116
117 WebStateOpener WebStateList::GetOpenerOfWebStateAt(int index) const {
118 DCHECK(ContainsIndex(index));
119 return web_state_wrappers_[index]->opener();
120 }
121
122 void WebStateList::SetOpenerOfWebStateAt(int index, WebStateOpener opener) {
123 DCHECK(ContainsIndex(index));
124 DCHECK(ContainsIndex(GetIndexOfWebState(opener.opener)));
125 web_state_wrappers_[index]->set_opener(opener);
126 }
127
128 int WebStateList::GetIndexOfNextWebStateOpenedBy(const web::WebState* opener,
129 int start_index,
130 bool use_group) const {
131 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, 1);
132 }
133
134 int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener,
135 int start_index,
136 bool use_group) const {
137 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX);
138 }
139
140 void WebStateList::InsertWebState(int index,
141 std::unique_ptr<web::WebState> web_state) {
142 DCHECK(ContainsIndex(index) || index == count());
143 delegate_->WillAddWebState(web_state.get());
144
145 web::WebState* web_state_ptr = web_state.get();
146 web_state_wrappers_.insert(
147 web_state_wrappers_.begin() + index,
148 base::MakeUnique<WebStateWrapper>(std::move(web_state)));
149
150 if (active_index_ >= index)
151 ++active_index_;
152
153 for (auto& observer : observers_)
154 observer.WebStateInsertedAt(this, web_state_ptr, index);
155 }
156
157 void WebStateList::AppendWebState(ui::PageTransition transition,
158 std::unique_ptr<web::WebState> web_state,
159 WebStateOpener opener) {
160 int index =
161 order_controller_->DetermineInsertionIndex(transition, opener.opener);
162 if (index < 0 || count() < index)
163 index = count();
164
165 InsertWebState(index, std::move(web_state));
166
167 if (opener.opener)
168 SetOpenerOfWebStateAt(index, opener);
169 }
170
171 void WebStateList::MoveWebStateAt(int from_index, int to_index) {
172 DCHECK(ContainsIndex(from_index));
173 DCHECK(ContainsIndex(to_index));
174 if (from_index == to_index)
175 return;
176
177 std::unique_ptr<WebStateWrapper> web_state_wrapper =
178 std::move(web_state_wrappers_[from_index]);
179 web::WebState* web_state = web_state_wrapper->web_state();
180 web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index);
181 web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index,
182 std::move(web_state_wrapper));
183
184 if (active_index_ == from_index) {
185 active_index_ = to_index;
186 } else {
187 int min = std::min(from_index, to_index);
188 int max = std::max(from_index, to_index);
189 int delta = from_index < to_index ? -1 : +1;
190 if (min <= active_index_ && active_index_ <= max)
191 active_index_ += delta;
192 }
193
194 for (auto& observer : observers_)
195 observer.WebStateMoved(this, web_state, from_index, to_index);
196 }
197
198 std::unique_ptr<web::WebState> WebStateList::ReplaceWebStateAt(
199 int index,
200 std::unique_ptr<web::WebState> web_state) {
201 DCHECK(ContainsIndex(index));
202 delegate_->WillAddWebState(web_state.get());
203
204 ClearOpenersReferencing(index);
205
206 web::WebState* web_state_ptr = web_state.get();
207 std::unique_ptr<web::WebState> old_web_state =
208 web_state_wrappers_[index]->ReplaceWebState(std::move(web_state));
209
210 for (auto& observer : observers_)
211 observer.WebStateReplacedAt(this, old_web_state.get(), web_state_ptr,
212 index);
213
214 delegate_->WebStateDetached(old_web_state.get());
215 return old_web_state;
216 }
217
218 std::unique_ptr<web::WebState> WebStateList::DetachWebStateAt(int index) {
219 DCHECK(ContainsIndex(index));
220 int new_active_index = order_controller_->DetermineNewActiveIndex(index);
221
222 web::WebState* web_state = web_state_wrappers_[index]->web_state();
223 for (auto& observer : observers_)
224 observer.WillDetachWebStateAt(this, web_state, index);
225
226 ClearOpenersReferencing(index);
227 std::unique_ptr<web::WebState> detached_web_state =
228 web_state_wrappers_[index]->ReplaceWebState(nullptr);
229 web_state_wrappers_.erase(web_state_wrappers_.begin() + index);
230
231 // Update the active index to prevent observer from seeing an invalid WebState
232 // as the active one but only send the WebStateActivatedAt notification after
233 // the WebStateDetachedAt one.
234 bool active_web_state_was_closed = (index == active_index_);
235 if (active_index_ > index)
236 --active_index_;
237 else if (active_index_ == index)
238 active_index_ = new_active_index;
239
240 for (auto& observer : observers_)
241 observer.WebStateDetachedAt(this, web_state, index);
242
243 if (active_web_state_was_closed)
244 NotifyIfActiveWebStateChanged(web_state, false);
245
246 delegate_->WebStateDetached(web_state);
247 return detached_web_state;
248 }
249
250 void WebStateList::CloseWebStateAt(int index) {
251 auto detached_web_state = DetachWebStateAt(index);
252
253 for (auto& observer : observers_)
254 observer.WillCloseWebStateAt(this, detached_web_state.get(), index);
255
256 detached_web_state.reset();
257 }
258
259 void WebStateList::CloseAllWebStates() {
260 while (!empty())
261 CloseWebStateAt(count() - 1);
262 }
263
264 void WebStateList::ActivateWebStateAt(int index) {
265 DCHECK(ContainsIndex(index));
266 web::WebState* old_web_state = GetActiveWebState();
267 active_index_ = index;
268 NotifyIfActiveWebStateChanged(old_web_state, true);
269 }
270
271 void WebStateList::AddObserver(WebStateListObserver* observer) {
272 observers_.AddObserver(observer);
273 }
274
275 void WebStateList::RemoveObserver(WebStateListObserver* observer) {
276 observers_.RemoveObserver(observer);
277 }
278
279 void WebStateList::ClearOpenersReferencing(int index) {
280 web::WebState* old_web_state = web_state_wrappers_[index]->web_state();
281 for (auto& web_state_wrapper : web_state_wrappers_) {
282 if (web_state_wrapper->opener().opener == old_web_state)
283 web_state_wrapper->set_opener(WebStateOpener(nullptr));
284 }
285 }
286
287 void WebStateList::NotifyIfActiveWebStateChanged(web::WebState* old_web_state,
288 bool user_action) {
289 web::WebState* new_web_state = GetActiveWebState();
290 if (old_web_state == new_web_state)
291 return;
292
293 for (auto& observer : observers_) {
294 observer.WebStateActivatedAt(this, old_web_state, new_web_state,
295 active_index_, user_action);
296 }
297 }
298
299 int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener,
300 int start_index,
301 bool use_group,
302 int n) const {
303 DCHECK_GT(n, 0);
304 if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX)
305 return kInvalidIndex;
306
307 const int opener_navigation_index =
308 use_group ? opener->GetNavigationManager()->GetLastCommittedItemIndex()
309 : -1;
310
311 int found_index = kInvalidIndex;
312 for (int index = start_index + 1; index < count() && n; ++index) {
313 if (web_state_wrappers_[index]->WasOpenedBy(opener, opener_navigation_index,
314 use_group)) {
315 found_index = index;
316 --n;
317 } else if (found_index != kInvalidIndex) {
318 return found_index;
319 }
320 }
321
322 return found_index;
323 }
324
325 // static
326 const int WebStateList::kInvalidIndex;
OLDNEW
« no previous file with comments | « ios/chrome/browser/web_state_list/web_state_list.h ('k') | ios/chrome/browser/web_state_list/web_state_list_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698