OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/shared/chrome/browser/tabs/web_state_list.h" | 5 #import "ios/shared/chrome/browser/tabs/web_state_list.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
11 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" | 12 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
12 #import "ios/shared/chrome/browser/tabs/web_state_list_order_controller.h" | 13 #import "ios/shared/chrome/browser/tabs/web_state_list_order_controller.h" |
13 #import "ios/web/public/navigation_manager.h" | 14 #import "ios/web/public/navigation_manager.h" |
14 #import "ios/web/public/web_state/web_state.h" | 15 #import "ios/web/public/web_state/web_state.h" |
15 | 16 |
16 #if !defined(__has_feature) || !__has_feature(objc_arc) | 17 #if !defined(__has_feature) || !__has_feature(objc_arc) |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 web::WebState* web_state = web_state_wrapper->web_state(); | 100 web::WebState* web_state = web_state_wrapper->web_state(); |
100 delete web_state; | 101 delete web_state; |
101 } | 102 } |
102 } | 103 } |
103 } | 104 } |
104 | 105 |
105 bool WebStateList::ContainsIndex(int index) const { | 106 bool WebStateList::ContainsIndex(int index) const { |
106 return 0 <= index && index < count(); | 107 return 0 <= index && index < count(); |
107 } | 108 } |
108 | 109 |
| 110 web::WebState* WebStateList::GetActiveWebState() const { |
| 111 if (active_index_ != kInvalidIndex) |
| 112 return GetWebStateAt(active_index_); |
| 113 return nullptr; |
| 114 } |
| 115 |
109 web::WebState* WebStateList::GetWebStateAt(int index) const { | 116 web::WebState* WebStateList::GetWebStateAt(int index) const { |
110 DCHECK(ContainsIndex(index)); | 117 DCHECK(ContainsIndex(index)); |
111 return web_state_wrappers_[index]->web_state(); | 118 return web_state_wrappers_[index]->web_state(); |
112 } | 119 } |
113 | 120 |
114 int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const { | 121 int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const { |
115 for (int index = 0; index < count(); ++index) { | 122 for (int index = 0; index < count(); ++index) { |
116 if (web_state_wrappers_[index]->web_state() == web_state) | 123 if (web_state_wrappers_[index]->web_state() == web_state) |
117 return index; | 124 return index; |
118 } | 125 } |
(...skipping 23 matching lines...) Expand all Loading... |
142 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX); | 149 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX); |
143 } | 150 } |
144 | 151 |
145 void WebStateList::InsertWebState(int index, | 152 void WebStateList::InsertWebState(int index, |
146 web::WebState* web_state, | 153 web::WebState* web_state, |
147 web::WebState* opener) { | 154 web::WebState* opener) { |
148 DCHECK(ContainsIndex(index) || index == count()); | 155 DCHECK(ContainsIndex(index) || index == count()); |
149 web_state_wrappers_.insert(web_state_wrappers_.begin() + index, | 156 web_state_wrappers_.insert(web_state_wrappers_.begin() + index, |
150 base::MakeUnique<WebStateWrapper>(web_state)); | 157 base::MakeUnique<WebStateWrapper>(web_state)); |
151 | 158 |
| 159 if (active_index_ >= index) |
| 160 ++active_index_; |
| 161 |
152 if (opener) | 162 if (opener) |
153 SetOpenerOfWebStateAt(index, opener); | 163 SetOpenerOfWebStateAt(index, opener); |
154 | 164 |
155 for (auto& observer : observers_) | 165 for (auto& observer : observers_) |
156 observer.WebStateInsertedAt(this, web_state, index); | 166 observer.WebStateInsertedAt(this, web_state, index); |
157 } | 167 } |
158 | 168 |
159 void WebStateList::AppendWebState(ui::PageTransition transition, | 169 void WebStateList::AppendWebState(ui::PageTransition transition, |
160 web::WebState* web_state, | 170 web::WebState* web_state, |
161 web::WebState* opener) { | 171 web::WebState* opener) { |
(...skipping 10 matching lines...) Expand all Loading... |
172 if (from_index == to_index) | 182 if (from_index == to_index) |
173 return; | 183 return; |
174 | 184 |
175 std::unique_ptr<WebStateWrapper> web_state_wrapper = | 185 std::unique_ptr<WebStateWrapper> web_state_wrapper = |
176 std::move(web_state_wrappers_[from_index]); | 186 std::move(web_state_wrappers_[from_index]); |
177 web::WebState* web_state = web_state_wrapper->web_state(); | 187 web::WebState* web_state = web_state_wrapper->web_state(); |
178 web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index); | 188 web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index); |
179 web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index, | 189 web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index, |
180 std::move(web_state_wrapper)); | 190 std::move(web_state_wrapper)); |
181 | 191 |
| 192 if (active_index_ == from_index) { |
| 193 active_index_ = to_index; |
| 194 } else { |
| 195 int min = std::min(from_index, to_index); |
| 196 int max = std::max(from_index, to_index); |
| 197 int delta = from_index < to_index ? -1 : +1; |
| 198 if (min <= active_index_ && active_index_ <= max) |
| 199 active_index_ += delta; |
| 200 } |
| 201 |
182 for (auto& observer : observers_) | 202 for (auto& observer : observers_) |
183 observer.WebStateMoved(this, web_state, from_index, to_index); | 203 observer.WebStateMoved(this, web_state, from_index, to_index); |
184 } | 204 } |
185 | 205 |
186 web::WebState* WebStateList::ReplaceWebStateAt(int index, | 206 web::WebState* WebStateList::ReplaceWebStateAt(int index, |
187 web::WebState* web_state, | 207 web::WebState* web_state, |
188 web::WebState* opener) { | 208 web::WebState* opener) { |
189 DCHECK(ContainsIndex(index)); | 209 DCHECK(ContainsIndex(index)); |
190 ClearOpenersReferencing(index); | 210 ClearOpenersReferencing(index); |
191 | 211 |
192 auto& web_state_wrapper = web_state_wrappers_[index]; | 212 auto& web_state_wrapper = web_state_wrappers_[index]; |
193 web::WebState* old_web_state = web_state_wrapper->ReplaceWebState(web_state); | 213 web::WebState* old_web_state = web_state_wrapper->ReplaceWebState(web_state); |
194 | 214 |
195 if (opener && opener != old_web_state) | 215 if (opener && opener != old_web_state) |
196 SetOpenerOfWebStateAt(index, opener); | 216 SetOpenerOfWebStateAt(index, opener); |
197 | 217 |
198 for (auto& observer : observers_) | 218 for (auto& observer : observers_) |
199 observer.WebStateReplacedAt(this, old_web_state, web_state, index); | 219 observer.WebStateReplacedAt(this, old_web_state, web_state, index); |
200 | 220 |
201 return old_web_state; | 221 return old_web_state; |
202 } | 222 } |
203 | 223 |
204 web::WebState* WebStateList::DetachWebStateAt(int index) { | 224 web::WebState* WebStateList::DetachWebStateAt(int index) { |
205 DCHECK(ContainsIndex(index)); | 225 DCHECK(ContainsIndex(index)); |
206 ClearOpenersReferencing(index); | 226 ClearOpenersReferencing(index); |
207 | 227 |
| 228 int new_active_index = order_controller_->DetermineNewActiveIndex(index); |
| 229 |
208 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); | 230 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); |
209 web_state_wrappers_.erase(web_state_wrappers_.begin() + index); | 231 web_state_wrappers_.erase(web_state_wrappers_.begin() + index); |
210 | 232 |
| 233 // Update the active index to prevent observer from seeing an invalid WebState |
| 234 // as the active one but only send the WebStateActivatedAt notification after |
| 235 // the WebStateDetachedAt one. |
| 236 bool active_web_state_was_closed = (index == active_index_); |
| 237 if (active_index_ > index) |
| 238 --active_index_; |
| 239 else if (active_index_ == index) |
| 240 active_index_ = new_active_index; |
| 241 |
211 for (auto& observer : observers_) | 242 for (auto& observer : observers_) |
212 observer.WebStateDetachedAt(this, old_web_state, index); | 243 observer.WebStateDetachedAt(this, old_web_state, index); |
213 | 244 |
| 245 if (active_web_state_was_closed) |
| 246 NotifyIfActiveWebStateChanged(old_web_state, false); |
| 247 |
214 return old_web_state; | 248 return old_web_state; |
215 } | 249 } |
216 | 250 |
| 251 void WebStateList::ActivateWebStateAt(int index) { |
| 252 DCHECK(ContainsIndex(index)); |
| 253 web::WebState* old_web_state = GetActiveWebState(); |
| 254 active_index_ = index; |
| 255 NotifyIfActiveWebStateChanged(old_web_state, true); |
| 256 } |
| 257 |
217 void WebStateList::AddObserver(WebStateListObserver* observer) { | 258 void WebStateList::AddObserver(WebStateListObserver* observer) { |
218 observers_.AddObserver(observer); | 259 observers_.AddObserver(observer); |
219 } | 260 } |
220 | 261 |
221 void WebStateList::RemoveObserver(WebStateListObserver* observer) { | 262 void WebStateList::RemoveObserver(WebStateListObserver* observer) { |
222 observers_.RemoveObserver(observer); | 263 observers_.RemoveObserver(observer); |
223 } | 264 } |
224 | 265 |
225 void WebStateList::ClearOpenersReferencing(int index) { | 266 void WebStateList::ClearOpenersReferencing(int index) { |
226 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); | 267 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); |
227 for (auto& web_state_wrapper : web_state_wrappers_) { | 268 for (auto& web_state_wrapper : web_state_wrappers_) { |
228 if (web_state_wrapper->opener() == old_web_state) | 269 if (web_state_wrapper->opener() == old_web_state) |
229 web_state_wrapper->SetOpener(nullptr); | 270 web_state_wrapper->SetOpener(nullptr); |
230 } | 271 } |
231 } | 272 } |
232 | 273 |
| 274 void WebStateList::NotifyIfActiveWebStateChanged(web::WebState* old_web_state, |
| 275 bool user_action) { |
| 276 web::WebState* new_web_state = GetActiveWebState(); |
| 277 if (old_web_state == new_web_state) |
| 278 return; |
| 279 |
| 280 for (auto& observer : observers_) { |
| 281 observer.WebStateActivatedAt(this, old_web_state, new_web_state, |
| 282 active_index_, user_action); |
| 283 } |
| 284 } |
| 285 |
233 int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener, | 286 int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener, |
234 int start_index, | 287 int start_index, |
235 bool use_group, | 288 bool use_group, |
236 int n) const { | 289 int n) const { |
237 DCHECK_GT(n, 0); | 290 DCHECK_GT(n, 0); |
238 if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX) | 291 if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX) |
239 return kInvalidIndex; | 292 return kInvalidIndex; |
240 | 293 |
241 const int opener_navigation_index = | 294 const int opener_navigation_index = |
242 use_group ? opener->GetNavigationManager()->GetCurrentItemIndex() : -1; | 295 use_group ? opener->GetNavigationManager()->GetCurrentItemIndex() : -1; |
243 | 296 |
244 int found_index = kInvalidIndex; | 297 int found_index = kInvalidIndex; |
245 for (int index = start_index + 1; index < count() && n; ++index) { | 298 for (int index = start_index + 1; index < count() && n; ++index) { |
246 if (web_state_wrappers_[index]->WasOpenedBy(opener, opener_navigation_index, | 299 if (web_state_wrappers_[index]->WasOpenedBy(opener, opener_navigation_index, |
247 use_group)) { | 300 use_group)) { |
248 found_index = index; | 301 found_index = index; |
249 --n; | 302 --n; |
250 } else if (found_index != kInvalidIndex) { | 303 } else if (found_index != kInvalidIndex) { |
251 return found_index; | 304 return found_index; |
252 } | 305 } |
253 } | 306 } |
254 | 307 |
255 return found_index; | 308 return found_index; |
256 } | 309 } |
257 | 310 |
258 // static | 311 // static |
259 const int WebStateList::kInvalidIndex; | 312 const int WebStateList::kInvalidIndex; |
OLD | NEW |