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

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

Issue 2697193004: Add opener-opened relationship between WebState in WebStateList. (Closed)
Patch Set: Created 3 years, 10 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 "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" 9 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
10 #import "ios/web/public/navigation_manager.h"
10 #import "ios/web/public/web_state/web_state.h" 11 #import "ios/web/public/web_state/web_state.h"
11 12
12 #if !defined(__has_feature) || !__has_feature(objc_arc) 13 #if !defined(__has_feature) || !__has_feature(objc_arc)
13 #error "This file requires ARC support." 14 #error "This file requires ARC support."
14 #endif 15 #endif
15 16
16 // Wrapper around a WebState stored in a WebStateList. May own the WebState 17 // Wrapper around a WebState stored in a WebStateList. May own the WebState
17 // dependending on the WebStateList ownership setting (should always be true 18 // dependending on the WebStateList ownership setting (should always be true
18 // once ownership of Tab is sane, see http://crbug.com/546222 for progress). 19 // once ownership of Tab is sane, see http://crbug.com/546222 for progress).
19 class WebStateList::WebStateWrapper { 20 class WebStateList::WebStateWrapper {
20 public: 21 public:
21 WebStateWrapper(web::WebState* web_state, bool assume_ownership); 22 WebStateWrapper(web::WebState* web_state, bool assume_ownership);
22 ~WebStateWrapper(); 23 ~WebStateWrapper();
23 24
24 web::WebState* web_state() const { return web_state_; } 25 web::WebState* web_state() const { return web_state_; }
25 void set_web_state(web::WebState* web_state) { web_state_ = web_state; } 26 web::WebState* opener() const { return opener_; }
27
28 // Resets the wrapped WebState (and clear associated state).
29 void SetWebState(web::WebState* web_state);
30
31 // Sets the opener for the wrapped WebState and record the opener navigation
32 // index to allow detecting navigation changes during the same session.
33 void SetOpener(web::WebState* opener);
34
35 // Returns whether opener spawned the wrapped WebState. If |use_group| is
marq (ping after 24h) 2017/02/16 15:19:17 |opener|
sdefresne 2017/02/16 15:42:01 Done.
36 // true, also use the opener navigation index to detect navigation changes
37 // during the same session.
38 bool WasOpenBy(const web::WebState* opener,
marq (ping after 24h) 2017/02/16 15:19:17 WasOpenedBy(). yay, English!
sdefresne 2017/02/16 15:42:01 Done.
39 int opener_navigation_index,
40 bool use_group) const;
26 41
27 private: 42 private:
28 web::WebState* web_state_; 43 web::WebState* web_state_;
44 web::WebState* opener_ = nullptr;
45 int opener_last_committed_index_;
29 const bool has_web_state_ownership_; 46 const bool has_web_state_ownership_;
30 47
31 DISALLOW_COPY_AND_ASSIGN(WebStateWrapper); 48 DISALLOW_COPY_AND_ASSIGN(WebStateWrapper);
32 }; 49 };
33 50
34 WebStateList::WebStateWrapper::WebStateWrapper(web::WebState* web_state, 51 WebStateList::WebStateWrapper::WebStateWrapper(web::WebState* web_state,
35 bool assume_ownership) 52 bool assume_ownership)
36 : web_state_(web_state), has_web_state_ownership_(assume_ownership) {} 53 : web_state_(web_state), has_web_state_ownership_(assume_ownership) {
54 DCHECK(web_state_);
55 }
37 56
38 WebStateList::WebStateWrapper::~WebStateWrapper() { 57 WebStateList::WebStateWrapper::~WebStateWrapper() {
39 if (has_web_state_ownership_) 58 if (has_web_state_ownership_)
40 delete web_state_; 59 delete web_state_;
41 } 60 }
42 61
62 void WebStateList::WebStateWrapper::SetWebState(web::WebState* web_state) {
63 DCHECK(web_state);
64 web_state_ = web_state;
65 opener_ = nullptr;
66 }
67
68 void WebStateList::WebStateWrapper::SetOpener(web::WebState* opener) {
69 opener_ = opener;
70 if (opener_) {
71 opener_last_committed_index_ =
72 opener_->GetNavigationManager()->GetLastCommittedItemIndex();
73 }
74 }
75
76 bool WebStateList::WebStateWrapper::WasOpenBy(const web::WebState* opener,
77 int opener_navigation_index,
78 bool use_group) const {
79 DCHECK(opener);
80 if (opener_ != opener)
81 return false;
82
83 if (!use_group)
84 return true;
85
86 return opener_last_committed_index_ == opener_navigation_index;
87 }
88
43 WebStateList::WebStateList(WebStateOwnership ownership) 89 WebStateList::WebStateList(WebStateOwnership ownership)
44 : web_state_ownership_(ownership) {} 90 : web_state_ownership_(ownership) {}
45 91
46 WebStateList::~WebStateList() = default; 92 WebStateList::~WebStateList() = default;
47 93
48 bool WebStateList::ContainsIndex(int index) const { 94 bool WebStateList::ContainsIndex(int index) const {
49 return 0 <= index && index < count(); 95 return 0 <= index && index < count();
50 } 96 }
51 97
52 web::WebState* WebStateList::GetWebStateAt(int index) const { 98 web::WebState* WebStateList::GetWebStateAt(int index) const {
53 DCHECK(ContainsIndex(index)); 99 DCHECK(ContainsIndex(index));
54 return web_state_wrappers_[index]->web_state(); 100 return web_state_wrappers_[index]->web_state();
55 } 101 }
56 102
57 int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const { 103 int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const {
58 for (int index = 0; index < count(); ++index) { 104 for (int index = 0; index < count(); ++index) {
59 if (web_state_wrappers_[index]->web_state() == web_state) 105 if (web_state_wrappers_[index]->web_state() == web_state)
60 return index; 106 return index;
61 } 107 }
62 return kInvalidIndex; 108 return kInvalidIndex;
63 } 109 }
64 110
65 void WebStateList::InsertWebState(int index, web::WebState* web_state) { 111 web::WebState* WebStateList::GetOpenerOfWebStateAt(int index) const {
112 DCHECK(ContainsIndex(index));
113 return web_state_wrappers_[index]->opener();
114 }
115
116 int WebStateList::GetIndexOfNextWebStateOpenedBy(const web::WebState* opener,
117 int start_index,
118 bool use_group) const {
119 return GetIndexOfNthWebStateOpenedBy(opener, start_index, 1, use_group);
120 }
121
122 int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener,
123 int start_index,
124 bool use_group) const {
125 return GetIndexOfNthWebStateOpenedBy(opener, start_index, INT_MAX, use_group);
126 }
127
128 void WebStateList::InsertWebState(int index,
129 web::WebState* web_state,
130 web::WebState* opener) {
66 DCHECK(ContainsIndex(index) || index == count()); 131 DCHECK(ContainsIndex(index) || index == count());
67 web_state_wrappers_.insert( 132 web_state_wrappers_.insert(
68 web_state_wrappers_.begin() + index, 133 web_state_wrappers_.begin() + index,
69 base::MakeUnique<WebStateWrapper>(web_state, 134 base::MakeUnique<WebStateWrapper>(web_state,
70 web_state_ownership_ == WebStateOwned)); 135 web_state_ownership_ == WebStateOwned));
71 136
137 if (opener)
138 SetOpenerOfWebStateAt(index, opener);
139
72 for (auto& observer : observers_) 140 for (auto& observer : observers_)
73 observer.WebStateInsertedAt(this, web_state, index); 141 observer.WebStateInsertedAt(this, web_state, index);
74 } 142 }
75 143
76 void WebStateList::MoveWebStateAt(int from_index, int to_index) { 144 void WebStateList::MoveWebStateAt(int from_index, int to_index) {
77 DCHECK(ContainsIndex(from_index)); 145 DCHECK(ContainsIndex(from_index));
78 DCHECK(ContainsIndex(to_index)); 146 DCHECK(ContainsIndex(to_index));
79 if (from_index == to_index) 147 if (from_index == to_index)
80 return; 148 return;
81 149
82 std::unique_ptr<WebStateWrapper> web_state_wrapper = 150 std::unique_ptr<WebStateWrapper> web_state_wrapper =
83 std::move(web_state_wrappers_[from_index]); 151 std::move(web_state_wrappers_[from_index]);
84 web::WebState* web_state = web_state_wrapper->web_state(); 152 web::WebState* web_state = web_state_wrapper->web_state();
85 web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index); 153 web_state_wrappers_.erase(web_state_wrappers_.begin() + from_index);
86 web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index, 154 web_state_wrappers_.insert(web_state_wrappers_.begin() + to_index,
87 std::move(web_state_wrapper)); 155 std::move(web_state_wrapper));
88 156
89 for (auto& observer : observers_) 157 for (auto& observer : observers_)
90 observer.WebStateMoved(this, web_state, from_index, to_index); 158 observer.WebStateMoved(this, web_state, from_index, to_index);
91 } 159 }
92 160
93 web::WebState* WebStateList::ReplaceWebStateAt(int index, 161 web::WebState* WebStateList::ReplaceWebStateAt(int index,
94 web::WebState* web_state) { 162 web::WebState* web_state,
163 web::WebState* opener) {
95 DCHECK(ContainsIndex(index)); 164 DCHECK(ContainsIndex(index));
96 web::WebState* old_web_state = web_state_wrappers_[index]->web_state(); 165 FixOpenersReferencing(index);
97 web_state_wrappers_[index]->set_web_state(web_state); 166
167 auto& web_state_wrapper = web_state_wrappers_[index];
168 web::WebState* old_web_state = web_state_wrapper->web_state();
169 web_state_wrapper->SetWebState(web_state);
170
171 if (opener && opener != old_web_state)
172 SetOpenerOfWebStateAt(index, opener);
98 173
99 for (auto& observer : observers_) 174 for (auto& observer : observers_)
100 observer.WebStateReplacedAt(this, old_web_state, web_state, index); 175 observer.WebStateReplacedAt(this, old_web_state, web_state, index);
101 176
102 return old_web_state; 177 return old_web_state;
103 } 178 }
104 179
105 void WebStateList::DetachWebStateAt(int index) { 180 void WebStateList::DetachWebStateAt(int index) {
106 DCHECK(ContainsIndex(index)); 181 DCHECK(ContainsIndex(index));
182 FixOpenersReferencing(index);
183
107 web::WebState* web_state = web_state_wrappers_[index]->web_state(); 184 web::WebState* web_state = web_state_wrappers_[index]->web_state();
108 web_state_wrappers_.erase(web_state_wrappers_.begin() + index); 185 web_state_wrappers_.erase(web_state_wrappers_.begin() + index);
109 186
110 for (auto& observer : observers_) 187 for (auto& observer : observers_)
111 observer.WebStateDetachedAt(this, web_state, index); 188 observer.WebStateDetachedAt(this, web_state, index);
112 } 189 }
113 190
114 void WebStateList::AddObserver(WebStateListObserver* observer) { 191 void WebStateList::AddObserver(WebStateListObserver* observer) {
115 observers_.AddObserver(observer); 192 observers_.AddObserver(observer);
116 } 193 }
117 194
118 void WebStateList::RemoveObserver(WebStateListObserver* observer) { 195 void WebStateList::RemoveObserver(WebStateListObserver* observer) {
119 observers_.RemoveObserver(observer); 196 observers_.RemoveObserver(observer);
120 } 197 }
121 198
199 void WebStateList::SetOpenerOfWebStateAt(int index, web::WebState* opener) {
200 DCHECK(ContainsIndex(index));
201 DCHECK(ContainsIndex(GetIndexOfWebState(opener)));
202 web_state_wrappers_[index]->SetOpener(opener);
203 }
204
205 void WebStateList::FixOpenersReferencing(int index) {
206 web::WebState* old_web_state = web_state_wrappers_[index]->web_state();
207 for (auto& web_state_wrapper : web_state_wrappers_) {
208 if (web_state_wrapper->opener() == old_web_state)
209 web_state_wrapper->SetOpener(nullptr);
210 }
211 }
212
213 int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener,
214 int start_index,
215 int skip_up_to,
216 bool use_group) const {
217 DCHECK_GT(skip_up_to, 0);
marq (ping after 24h) 2017/02/16 15:19:17 Document this precondition in the header comments.
sdefresne 2017/02/16 15:42:01 Done.
218 if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX)
219 return kInvalidIndex;
220
221 const int opener_navigation_index =
222 use_group ? opener->GetNavigationManager()->GetCurrentItemIndex() : -1;
223
224 int found_index = kInvalidIndex;
225 for (int index = start_index + 1; index < count() && skip_up_to; ++index) {
226 if (web_state_wrappers_[index]->WasOpenBy(opener, opener_navigation_index,
227 use_group)) {
228 found_index = index;
229 --skip_up_to;
230 } else if (found_index != kInvalidIndex) {
231 return found_index;
232 }
233 }
234
235 return found_index;
236 }
237
122 // static 238 // static
123 const int WebStateList::kInvalidIndex; 239 const int WebStateList::kInvalidIndex;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698