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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: ios/shared/chrome/browser/tabs/web_state_list.mm
diff --git a/ios/shared/chrome/browser/tabs/web_state_list.mm b/ios/shared/chrome/browser/tabs/web_state_list.mm
index cb85ed433ee72233257fc0c3181adf4e9dfaca74..09d4539a504cac82030c843e29af024f475a295c 100644
--- a/ios/shared/chrome/browser/tabs/web_state_list.mm
+++ b/ios/shared/chrome/browser/tabs/web_state_list.mm
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
+#import "ios/web/public/navigation_manager.h"
#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -22,10 +23,26 @@ class WebStateList::WebStateWrapper {
~WebStateWrapper();
web::WebState* web_state() const { return web_state_; }
- void set_web_state(web::WebState* web_state) { web_state_ = web_state; }
+ web::WebState* opener() const { return opener_; }
+
+ // Resets the wrapped WebState (and clear associated state).
+ void SetWebState(web::WebState* web_state);
+
+ // Sets the opener for the wrapped WebState and record the opener navigation
+ // index to allow detecting navigation changes during the same session.
+ void SetOpener(web::WebState* opener);
+
+ // 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.
+ // true, also use the opener navigation index to detect navigation changes
+ // during the same session.
+ 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.
+ int opener_navigation_index,
+ bool use_group) const;
private:
web::WebState* web_state_;
+ web::WebState* opener_ = nullptr;
+ int opener_last_committed_index_;
const bool has_web_state_ownership_;
DISALLOW_COPY_AND_ASSIGN(WebStateWrapper);
@@ -33,13 +50,42 @@ class WebStateList::WebStateWrapper {
WebStateList::WebStateWrapper::WebStateWrapper(web::WebState* web_state,
bool assume_ownership)
- : web_state_(web_state), has_web_state_ownership_(assume_ownership) {}
+ : web_state_(web_state), has_web_state_ownership_(assume_ownership) {
+ DCHECK(web_state_);
+}
WebStateList::WebStateWrapper::~WebStateWrapper() {
if (has_web_state_ownership_)
delete web_state_;
}
+void WebStateList::WebStateWrapper::SetWebState(web::WebState* web_state) {
+ DCHECK(web_state);
+ web_state_ = web_state;
+ opener_ = nullptr;
+}
+
+void WebStateList::WebStateWrapper::SetOpener(web::WebState* opener) {
+ opener_ = opener;
+ if (opener_) {
+ opener_last_committed_index_ =
+ opener_->GetNavigationManager()->GetLastCommittedItemIndex();
+ }
+}
+
+bool WebStateList::WebStateWrapper::WasOpenBy(const web::WebState* opener,
+ int opener_navigation_index,
+ bool use_group) const {
+ DCHECK(opener);
+ if (opener_ != opener)
+ return false;
+
+ if (!use_group)
+ return true;
+
+ return opener_last_committed_index_ == opener_navigation_index;
+}
+
WebStateList::WebStateList(WebStateOwnership ownership)
: web_state_ownership_(ownership) {}
@@ -62,13 +108,35 @@ int WebStateList::GetIndexOfWebState(const web::WebState* web_state) const {
return kInvalidIndex;
}
-void WebStateList::InsertWebState(int index, web::WebState* web_state) {
+web::WebState* WebStateList::GetOpenerOfWebStateAt(int index) const {
+ DCHECK(ContainsIndex(index));
+ return web_state_wrappers_[index]->opener();
+}
+
+int WebStateList::GetIndexOfNextWebStateOpenedBy(const web::WebState* opener,
+ int start_index,
+ bool use_group) const {
+ return GetIndexOfNthWebStateOpenedBy(opener, start_index, 1, use_group);
+}
+
+int WebStateList::GetIndexOfLastWebStateOpenedBy(const web::WebState* opener,
+ int start_index,
+ bool use_group) const {
+ return GetIndexOfNthWebStateOpenedBy(opener, start_index, INT_MAX, use_group);
+}
+
+void WebStateList::InsertWebState(int index,
+ web::WebState* web_state,
+ web::WebState* opener) {
DCHECK(ContainsIndex(index) || index == count());
web_state_wrappers_.insert(
web_state_wrappers_.begin() + index,
base::MakeUnique<WebStateWrapper>(web_state,
web_state_ownership_ == WebStateOwned));
+ if (opener)
+ SetOpenerOfWebStateAt(index, opener);
+
for (auto& observer : observers_)
observer.WebStateInsertedAt(this, web_state, index);
}
@@ -91,10 +159,17 @@ void WebStateList::MoveWebStateAt(int from_index, int to_index) {
}
web::WebState* WebStateList::ReplaceWebStateAt(int index,
- web::WebState* web_state) {
+ web::WebState* web_state,
+ web::WebState* opener) {
DCHECK(ContainsIndex(index));
- web::WebState* old_web_state = web_state_wrappers_[index]->web_state();
- web_state_wrappers_[index]->set_web_state(web_state);
+ FixOpenersReferencing(index);
+
+ auto& web_state_wrapper = web_state_wrappers_[index];
+ web::WebState* old_web_state = web_state_wrapper->web_state();
+ web_state_wrapper->SetWebState(web_state);
+
+ if (opener && opener != old_web_state)
+ SetOpenerOfWebStateAt(index, opener);
for (auto& observer : observers_)
observer.WebStateReplacedAt(this, old_web_state, web_state, index);
@@ -104,6 +179,8 @@ web::WebState* WebStateList::ReplaceWebStateAt(int index,
void WebStateList::DetachWebStateAt(int index) {
DCHECK(ContainsIndex(index));
+ FixOpenersReferencing(index);
+
web::WebState* web_state = web_state_wrappers_[index]->web_state();
web_state_wrappers_.erase(web_state_wrappers_.begin() + index);
@@ -119,5 +196,44 @@ void WebStateList::RemoveObserver(WebStateListObserver* observer) {
observers_.RemoveObserver(observer);
}
+void WebStateList::SetOpenerOfWebStateAt(int index, web::WebState* opener) {
+ DCHECK(ContainsIndex(index));
+ DCHECK(ContainsIndex(GetIndexOfWebState(opener)));
+ web_state_wrappers_[index]->SetOpener(opener);
+}
+
+void WebStateList::FixOpenersReferencing(int index) {
+ web::WebState* old_web_state = web_state_wrappers_[index]->web_state();
+ for (auto& web_state_wrapper : web_state_wrappers_) {
+ if (web_state_wrapper->opener() == old_web_state)
+ web_state_wrapper->SetOpener(nullptr);
+ }
+}
+
+int WebStateList::GetIndexOfNthWebStateOpenedBy(const web::WebState* opener,
+ int start_index,
+ int skip_up_to,
+ bool use_group) const {
+ 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.
+ if (!opener || !ContainsIndex(start_index) || start_index == INT_MAX)
+ return kInvalidIndex;
+
+ const int opener_navigation_index =
+ use_group ? opener->GetNavigationManager()->GetCurrentItemIndex() : -1;
+
+ int found_index = kInvalidIndex;
+ for (int index = start_index + 1; index < count() && skip_up_to; ++index) {
+ if (web_state_wrappers_[index]->WasOpenBy(opener, opener_navigation_index,
+ use_group)) {
+ found_index = index;
+ --skip_up_to;
+ } else if (found_index != kInvalidIndex) {
+ return found_index;
+ }
+ }
+
+ return found_index;
+}
+
// static
const int WebStateList::kInvalidIndex;

Powered by Google App Engine
This is Rietveld 408576698