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

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

Issue 2775623002: [ios] WebStateList owns all WebState it manages. (Closed)
Patch Set: Fix gn check 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
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 <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #import "ios/shared/chrome/browser/tabs/web_state_list_delegate.h" 12 #import "ios/shared/chrome/browser/tabs/web_state_list_delegate.h"
13 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" 13 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
14 #import "ios/shared/chrome/browser/tabs/web_state_list_order_controller.h" 14 #import "ios/shared/chrome/browser/tabs/web_state_list_order_controller.h"
15 #import "ios/shared/chrome/browser/tabs/web_state_opener.h" 15 #import "ios/shared/chrome/browser/tabs/web_state_opener.h"
16 #import "ios/web/public/navigation_manager.h" 16 #import "ios/web/public/navigation_manager.h"
17 #import "ios/web/public/web_state/web_state.h" 17 #import "ios/web/public/web_state/web_state.h"
18 18
19 #if !defined(__has_feature) || !__has_feature(objc_arc) 19 #if !defined(__has_feature) || !__has_feature(objc_arc)
20 #error "This file requires ARC support." 20 #error "This file requires ARC support."
21 #endif 21 #endif
22 22
23 // Wrapper around a WebState stored in a WebStateList. 23 // Wrapper around a WebState stored in a WebStateList.
24 class WebStateList::WebStateWrapper { 24 class WebStateList::WebStateWrapper {
25 public: 25 public:
26 explicit WebStateWrapper(web::WebState* web_state); 26 explicit WebStateWrapper(std::unique_ptr<web::WebState> web_state);
27 ~WebStateWrapper(); 27 ~WebStateWrapper();
28 28
29 web::WebState* web_state() const { return web_state_; } 29 web::WebState* web_state() const { return web_state_.get(); }
30 30
31 // Replaces the wrapped WebState (and clear associated state) and returns the 31 // Replaces the wrapped WebState (and clear associated state) and returns the
32 // old WebState after forfeiting ownership. 32 // old WebState after forfeiting ownership.
33 web::WebState* ReplaceWebState(web::WebState* web_state); 33 std::unique_ptr<web::WebState> ReplaceWebState(
34 std::unique_ptr<web::WebState> web_state);
34 35
35 // Gets and sets information about this WebState opener. The navigation index 36 // Gets and sets information about this WebState opener. The navigation index
36 // is used to detect navigation changes during the same session. 37 // is used to detect navigation changes during the same session.
37 WebStateOpener opener() const { return opener_; } 38 WebStateOpener opener() const { return opener_; }
38 void set_opener(WebStateOpener opener) { opener_ = opener; } 39 void set_opener(WebStateOpener opener) { opener_ = opener; }
39 40
40 // Returns whether |opener| spawned the wrapped WebState. If |use_group| is 41 // Returns whether |opener| spawned the wrapped WebState. If |use_group| is
41 // true, also use the opener navigation index to detect navigation changes 42 // true, also use the opener navigation index to detect navigation changes
42 // during the same session. 43 // during the same session.
43 bool WasOpenedBy(const web::WebState* opener, 44 bool WasOpenedBy(const web::WebState* opener,
44 int opener_navigation_index, 45 int opener_navigation_index,
45 bool use_group) const; 46 bool use_group) const;
46 47
47 private: 48 private:
48 web::WebState* web_state_; 49 std::unique_ptr<web::WebState> web_state_;
49 WebStateOpener opener_; 50 WebStateOpener opener_;
50 51
51 DISALLOW_COPY_AND_ASSIGN(WebStateWrapper); 52 DISALLOW_COPY_AND_ASSIGN(WebStateWrapper);
52 }; 53 };
53 54
54 WebStateList::WebStateWrapper::WebStateWrapper(web::WebState* web_state) 55 WebStateList::WebStateWrapper::WebStateWrapper(
55 : web_state_(web_state), opener_(nullptr) { 56 std::unique_ptr<web::WebState> web_state)
57 : web_state_(std::move(web_state)), opener_(nullptr) {
56 DCHECK(web_state_); 58 DCHECK(web_state_);
57 } 59 }
58 60
59 WebStateList::WebStateWrapper::~WebStateWrapper() = default; 61 WebStateList::WebStateWrapper::~WebStateWrapper() = default;
60 62
61 web::WebState* WebStateList::WebStateWrapper::ReplaceWebState( 63 std::unique_ptr<web::WebState> WebStateList::WebStateWrapper::ReplaceWebState(
62 web::WebState* web_state) { 64 std::unique_ptr<web::WebState> web_state) {
63 DCHECK(web_state); 65 DCHECK_NE(web_state.get(), web_state_.get());
64 DCHECK_NE(web_state, web_state_);
65 std::swap(web_state, web_state_); 66 std::swap(web_state, web_state_);
66 opener_ = WebStateOpener(nullptr); 67 opener_ = WebStateOpener(nullptr);
67 return web_state; 68 return web_state;
68 } 69 }
69 70
70 bool WebStateList::WebStateWrapper::WasOpenedBy(const web::WebState* opener, 71 bool WebStateList::WebStateWrapper::WasOpenedBy(const web::WebState* opener,
71 int opener_navigation_index, 72 int opener_navigation_index,
72 bool use_group) const { 73 bool use_group) const {
73 DCHECK(opener); 74 DCHECK(opener);
74 if (opener_.opener != opener) 75 if (opener_.opener != opener)
75 return false; 76 return false;
76 77
77 if (!use_group) 78 if (!use_group)
78 return true; 79 return true;
79 80
80 return opener_.navigation_index == opener_navigation_index; 81 return opener_.navigation_index == opener_navigation_index;
81 } 82 }
82 83
83 WebStateList::WebStateList(WebStateListDelegate* delegate, 84 WebStateList::WebStateList(WebStateListDelegate* delegate)
84 WebStateOwnership ownership)
85 : delegate_(delegate), 85 : delegate_(delegate),
86 web_state_ownership_(ownership),
87 order_controller_(base::MakeUnique<WebStateListOrderController>(this)) { 86 order_controller_(base::MakeUnique<WebStateListOrderController>(this)) {
88 DCHECK(delegate_); 87 DCHECK(delegate_);
89 } 88 }
90 89
91 WebStateList::~WebStateList() { 90 WebStateList::~WebStateList() {
92 // Once WebStateList owns the WebState and has a CloseWebStateAt() method, 91 CloseAllWebStates();
93 // then change this to close all the WebState. See http://crbug.com/546222
94 // for progress.
95 if (web_state_ownership_ == WebStateOwned) {
96 for (auto& web_state_wrapper : web_state_wrappers_) {
97 web::WebState* web_state = web_state_wrapper->web_state();
98 delete web_state;
99 }
100 }
101 } 92 }
102 93
103 bool WebStateList::ContainsIndex(int index) const { 94 bool WebStateList::ContainsIndex(int index) const {
104 return 0 <= index && index < count(); 95 return 0 <= index && index < count();
105 } 96 }
106 97
107 web::WebState* WebStateList::GetActiveWebState() const { 98 web::WebState* WebStateList::GetActiveWebState() const {
108 if (active_index_ != kInvalidIndex) 99 if (active_index_ != kInvalidIndex)
109 return GetWebStateAt(active_index_); 100 return GetWebStateAt(active_index_);
110 return nullptr; 101 return nullptr;
(...skipping 28 matching lines...) Expand all
139 bool use_group) const { 130 bool use_group) const {
140 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, 1); 131 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, 1);
141 } 132 }
142 133
143 int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener, 134 int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener,
144 int start_index, 135 int start_index,
145 bool use_group) const { 136 bool use_group) const {
146 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX); 137 return GetIndexOfNthWebStateOpenedBy(opener, start_index, use_group, INT_MAX);
147 } 138 }
148 139
149 void WebStateList::InsertWebState(int index, web::WebState* web_state) { 140 void WebStateList::InsertWebState(int index,
141 std::unique_ptr<web::WebState> web_state) {
150 DCHECK(ContainsIndex(index) || index == count()); 142 DCHECK(ContainsIndex(index) || index == count());
151 delegate_->WillAddWebState(web_state); 143 delegate_->WillAddWebState(web_state.get());
152 144
153 web_state_wrappers_.insert(web_state_wrappers_.begin() + index, 145 web::WebState* web_state_ptr = web_state.get();
154 base::MakeUnique<WebStateWrapper>(web_state)); 146 web_state_wrappers_.insert(
147 web_state_wrappers_.begin() + index,
148 base::MakeUnique<WebStateWrapper>(std::move(web_state)));
155 149
156 if (active_index_ >= index) 150 if (active_index_ >= index)
157 ++active_index_; 151 ++active_index_;
158 152
159 for (auto& observer : observers_) 153 for (auto& observer : observers_)
160 observer.WebStateInsertedAt(this, web_state, index); 154 observer.WebStateInsertedAt(this, web_state_ptr, index);
161 } 155 }
162 156
163 void WebStateList::AppendWebState(ui::PageTransition transition, 157 void WebStateList::AppendWebState(ui::PageTransition transition,
164 web::WebState* web_state, 158 std::unique_ptr<web::WebState> web_state,
165 WebStateOpener opener) { 159 WebStateOpener opener) {
166 int index = 160 int index =
167 order_controller_->DetermineInsertionIndex(transition, opener.opener); 161 order_controller_->DetermineInsertionIndex(transition, opener.opener);
168 if (index < 0 || count() < index) 162 if (index < 0 || count() < index)
169 index = count(); 163 index = count();
170 164
171 InsertWebState(index, web_state); 165 InsertWebState(index, std::move(web_state));
172 166
173 if (opener.opener) 167 if (opener.opener)
174 SetOpenerOfWebStateAt(index, opener); 168 SetOpenerOfWebStateAt(index, opener);
175 } 169 }
176 170
177 void WebStateList::MoveWebStateAt(int from_index, int to_index) { 171 void WebStateList::MoveWebStateAt(int from_index, int to_index) {
178 DCHECK(ContainsIndex(from_index)); 172 DCHECK(ContainsIndex(from_index));
179 DCHECK(ContainsIndex(to_index)); 173 DCHECK(ContainsIndex(to_index));
180 if (from_index == to_index) 174 if (from_index == to_index)
181 return; 175 return;
(...skipping 12 matching lines...) Expand all
194 int max = std::max(from_index, to_index); 188 int max = std::max(from_index, to_index);
195 int delta = from_index < to_index ? -1 : +1; 189 int delta = from_index < to_index ? -1 : +1;
196 if (min <= active_index_ && active_index_ <= max) 190 if (min <= active_index_ && active_index_ <= max)
197 active_index_ += delta; 191 active_index_ += delta;
198 } 192 }
199 193
200 for (auto& observer : observers_) 194 for (auto& observer : observers_)
201 observer.WebStateMoved(this, web_state, from_index, to_index); 195 observer.WebStateMoved(this, web_state, from_index, to_index);
202 } 196 }
203 197
204 web::WebState* WebStateList::ReplaceWebStateAt(int index, 198 std::unique_ptr<web::WebState> WebStateList::ReplaceWebStateAt(
205 web::WebState* web_state) { 199 int index,
200 std::unique_ptr<web::WebState> web_state) {
206 DCHECK(ContainsIndex(index)); 201 DCHECK(ContainsIndex(index));
207 delegate_->WillAddWebState(web_state); 202 delegate_->WillAddWebState(web_state.get());
208 203
209 ClearOpenersReferencing(index); 204 ClearOpenersReferencing(index);
210 205
211 auto& web_state_wrapper = web_state_wrappers_[index]; 206 web::WebState* web_state_ptr = web_state.get();
212 web::WebState* old_web_state = web_state_wrapper->ReplaceWebState(web_state); 207 std::unique_ptr<web::WebState> old_web_state =
208 web_state_wrappers_[index]->ReplaceWebState(std::move(web_state));
213 209
214 for (auto& observer : observers_) 210 for (auto& observer : observers_)
215 observer.WebStateReplacedAt(this, old_web_state, web_state, index); 211 observer.WebStateReplacedAt(this, old_web_state.get(), web_state_ptr,
212 index);
216 213
217 delegate_->WebStateDetached(old_web_state); 214 delegate_->WebStateDetached(old_web_state.get());
218 return old_web_state; 215 return old_web_state;
219 } 216 }
220 217
221 web::WebState* WebStateList::DetachWebStateAt(int index) { 218 std::unique_ptr<web::WebState> WebStateList::DetachWebStateAt(int index) {
222 DCHECK(ContainsIndex(index)); 219 DCHECK(ContainsIndex(index));
223 int new_active_index = order_controller_->DetermineNewActiveIndex(index); 220 int new_active_index = order_controller_->DetermineNewActiveIndex(index);
224 221
225 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); 222 web::WebState* web_state = web_state_wrappers_[index]->web_state();
226 for (auto& observer : observers_) 223 for (auto& observer : observers_)
227 observer.WillDetachWebStateAt(this, old_web_state, index); 224 observer.WillDetachWebStateAt(this, web_state, index);
228 225
229 ClearOpenersReferencing(index); 226 ClearOpenersReferencing(index);
227 std::unique_ptr<web::WebState> detached_web_state =
228 web_state_wrappers_[index]->ReplaceWebState(nullptr);
230 web_state_wrappers_.erase(web_state_wrappers_.begin() + index); 229 web_state_wrappers_.erase(web_state_wrappers_.begin() + index);
231 230
232 // Update the active index to prevent observer from seeing an invalid WebState 231 // Update the active index to prevent observer from seeing an invalid WebState
233 // as the active one but only send the WebStateActivatedAt notification after 232 // as the active one but only send the WebStateActivatedAt notification after
234 // the WebStateDetachedAt one. 233 // the WebStateDetachedAt one.
235 bool active_web_state_was_closed = (index == active_index_); 234 bool active_web_state_was_closed = (index == active_index_);
236 if (active_index_ > index) 235 if (active_index_ > index)
237 --active_index_; 236 --active_index_;
238 else if (active_index_ == index) 237 else if (active_index_ == index)
239 active_index_ = new_active_index; 238 active_index_ = new_active_index;
240 239
241 for (auto& observer : observers_) 240 for (auto& observer : observers_)
242 observer.WebStateDetachedAt(this, old_web_state, index); 241 observer.WebStateDetachedAt(this, web_state, index);
243 242
244 if (active_web_state_was_closed) 243 if (active_web_state_was_closed)
245 NotifyIfActiveWebStateChanged(old_web_state, false); 244 NotifyIfActiveWebStateChanged(web_state, false);
246 245
247 delegate_->WebStateDetached(old_web_state); 246 delegate_->WebStateDetached(web_state);
248 return old_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);
249 } 262 }
250 263
251 void WebStateList::ActivateWebStateAt(int index) { 264 void WebStateList::ActivateWebStateAt(int index) {
252 DCHECK(ContainsIndex(index)); 265 DCHECK(ContainsIndex(index));
253 web::WebState* old_web_state = GetActiveWebState(); 266 web::WebState* old_web_state = GetActiveWebState();
254 active_index_ = index; 267 active_index_ = index;
255 NotifyIfActiveWebStateChanged(old_web_state, true); 268 NotifyIfActiveWebStateChanged(old_web_state, true);
256 } 269 }
257 270
258 void WebStateList::AddObserver(WebStateListObserver* observer) { 271 void WebStateList::AddObserver(WebStateListObserver* observer) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 } else if (found_index != kInvalidIndex) { 317 } else if (found_index != kInvalidIndex) {
305 return found_index; 318 return found_index;
306 } 319 }
307 } 320 }
308 321
309 return found_index; 322 return found_index;
310 } 323 }
311 324
312 // static 325 // static
313 const int WebStateList::kInvalidIndex; 326 const int WebStateList::kInvalidIndex;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698