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

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

Powered by Google App Engine
This is Rietveld 408576698