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

Unified Diff: ios/chrome/browser/tabs/tab_model.mm

Issue 2683393003: Refactor TabModel to use WebStateList to store WebStates. (Closed)
Patch Set: Rebase to get dependent CL fix of "gn check". 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
« no previous file with comments | « ios/chrome/browser/tabs/BUILD.gn ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/chrome/browser/tabs/tab_model.mm
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 7a5c68f84f4c48e2a8e148d0691eaf8d1d6f06d1..2a344082d667b86259ade56e52b5ad9f66d541aa 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -28,12 +28,16 @@
#import "ios/chrome/browser/sessions/session_window.h"
#import "ios/chrome/browser/snapshots/snapshot_cache.h"
#include "ios/chrome/browser/tab_parenting_global_observer.h"
+#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
#import "ios/chrome/browser/tabs/tab.h"
#import "ios/chrome/browser/tabs/tab_model_list.h"
#import "ios/chrome/browser/tabs/tab_model_observers.h"
#import "ios/chrome/browser/tabs/tab_model_order_controller.h"
#import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
#import "ios/chrome/browser/xcallback_parameters.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
#import "ios/web/navigation/crw_session_certificate_policy_manager.h"
#import "ios/web/navigation/crw_session_controller.h"
#include "ios/web/public/browser_state.h"
@@ -79,38 +83,51 @@ void UpdateCertificatePolicyCacheFromWebState(
updateCertificatePolicyCache:policy_cache];
}
-// Populates the certificate policy cache based on the WebStates of |tab_model|.
+// Populates the certificate policy cache based on the WebStates of
+// |web_state_list|.
void RestoreCertificatePolicyCacheFromModel(
const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
- TabModel* tab_model) {
+ WebStateList* web_state_list) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
- for (Tab* tab in tab_model)
- UpdateCertificatePolicyCacheFromWebState(policy_cache, tab.webState);
+ for (size_t index = 0; index < web_state_list->count(); ++index) {
+ UpdateCertificatePolicyCacheFromWebState(
+ policy_cache, web_state_list->GetWebStateAt(index));
+ }
}
// Scrubs the certificate policy cache of all certificates policies except
-// those for the current entries in |tab_model|.
+// those for the current entries in |web_state_list|.
void CleanCertificatePolicyCache(
base::CancelableTaskTracker* task_tracker,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
- TabModel* tab_model) {
- DCHECK(tab_model);
+ WebStateList* web_state_list) {
DCHECK(policy_cache);
+ DCHECK(web_state_list);
DCHECK_CURRENTLY_ON(web::WebThread::UI);
task_tracker->PostTaskAndReply(
task_runner.get(), FROM_HERE,
base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies,
policy_cache),
base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache,
- base::Unretained(tab_model)));
+ base::Unretained(web_state_list)));
}
} // anonymous namespace
-@interface TabModel ()<TabUsageRecorderDelegate> {
- // Array of |Tab| objects.
- base::scoped_nsobject<NSMutableArray> _tabs;
+@interface TabModel ()<TabUsageRecorderDelegate, WebStateProxyFactory> {
+ // Underlying shared model implementation.
+ WebStateList _webStateList;
+
+ // Helper providing NSFastEnumeration implementation over the WebStateList.
+ base::scoped_nsobject<WebStateListFastEnumerationHelper>
+ _fastEnumerationHelper;
+
+ // Used to keep the Tabs alive while the corresponding WebStates are stored
+ // in the WebStateList (as Tabs currently owns their WebState). Remove once
rohitrao (ping after 24h) 2017/02/14 14:37:12 "own"
sdefresne 2017/02/14 16:45:46 Done.
+ // WebState owns the associated Tab.
+ base::scoped_nsobject<NSMutableSet<Tab*>> _tabs;
rohitrao (ping after 24h) 2017/02/14 14:37:12 Another naming option is to call this something li
sdefresne 2017/02/14 16:45:46 Done.
+
// Maintains policy for where new tabs go and the selection when a tab
// is removed.
base::scoped_nsobject<TabModelOrderController> _orderController;
@@ -214,7 +231,7 @@ void CleanCertificatePolicyCache(
}
- (void)setCurrentTab:(Tab*)newTab {
- DCHECK([_tabs containsObject:newTab]);
+ DCHECK_NE([self indexOfTab:newTab], static_cast<NSUInteger>(NSNotFound));
if (_currentTab != newTab) {
base::RecordAction(base::UserMetricsAction("MobileTabSwitched"));
[self updateSnapshotCache:newTab];
@@ -238,19 +255,23 @@ void CleanCertificatePolicyCache(
}
- (BOOL)isEmpty {
- return self.count == 0;
+ return _webStateList.empty();
}
- (NSUInteger)count {
- return [_tabs count];
+ return _webStateList.count();
}
- (instancetype)initWithSessionWindow:(SessionWindowIOS*)window
sessionService:(SessionServiceIOS*)service
browserState:(ios::ChromeBrowserState*)browserState {
if ((self = [super init])) {
- _observers.reset([[TabModelObservers
- observersWithProtocol:@protocol(TabModelObserver)] retain]);
+ _tabs.reset([[NSMutableSet alloc] init]);
+ _observers.reset([[TabModelObservers observers] retain]);
+
+ _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc]
+ initWithWebStateList:&_webStateList
+ proxyFactory:self]);
_browserState = browserState;
DCHECK(_browserState);
@@ -268,7 +289,6 @@ void CleanCertificatePolicyCache(
}
_syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self));
- _tabs.reset([[NSMutableArray alloc] init]);
if (window) {
DCHECK([_observers empty]);
// Restore the session and reset the session metrics (as the event have
@@ -317,7 +337,7 @@ void CleanCertificatePolicyCache(
- (void)saveSessionImmediately:(BOOL)immediately {
// Do nothing if there are tabs in the model but no selected tab. This is
// a transitional state.
- if ((!_currentTab && [_tabs count]) || !_browserState)
+ if ((!_currentTab && _webStateList.count()) || !_browserState)
return;
[_sessionService saveWindow:self.windowForSavingSession
forBrowserState:_browserState
@@ -325,17 +345,19 @@ void CleanCertificatePolicyCache(
}
- (Tab*)tabAtIndex:(NSUInteger)index {
- return [_tabs objectAtIndex:index];
+ web::WebState* webState = _webStateList.GetWebStateAt(index);
+ return LegacyTabHelper::GetTabForWebState(webState);
}
- (NSUInteger)indexOfTab:(Tab*)tab {
- return [_tabs indexOfObject:tab];
+ size_t index = _webStateList.GetIndexOfWebState(tab.webState);
+ return index == WebStateList::kInvalidIndex ? NSNotFound : index;
}
- (Tab*)tabWithWindowName:(NSString*)windowName {
if (!windowName)
return nil;
- for (Tab* tab in _tabs.get()) {
+ for (Tab* tab in self) {
if ([windowName isEqualToString:tab.windowName]) {
return tab;
}
@@ -354,8 +376,8 @@ void CleanCertificatePolicyCache(
if (startIndex == NSNotFound)
return nil;
NSString* parentID = tab.tabId;
- for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) {
- Tab* current = [_tabs objectAtIndex:i];
+ for (NSUInteger i = startIndex + 1; i < _webStateList.count(); ++i) {
+ Tab* current = [self tabAtIndex:i];
DCHECK([current navigationManager]);
CRWSessionController* sessionController =
[current navigationManager]->GetSessionController();
@@ -380,7 +402,7 @@ void CleanCertificatePolicyCache(
DCHECK([tab navigationManager]);
NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex();
for (NSUInteger i = 0; i < stopIndex; ++i) {
- Tab* tabToCheck = [_tabs objectAtIndex:i];
+ Tab* tabToCheck = [self tabAtIndex:i];
DCHECK([tabToCheck navigationManager]);
CRWSessionController* sessionController =
[tabToCheck navigationManager]->GetSessionController();
@@ -407,8 +429,8 @@ void CleanCertificatePolicyCache(
// tabs whose opener's id and opener's navigation index match. The navigation
// index is used in addition to the session id to detect navigations changes
// within the same session.
- for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) {
- Tab* tabToCheck = [_tabs objectAtIndex:i];
+ for (NSUInteger i = startIndex + 1; i < _webStateList.count(); ++i) {
+ Tab* tabToCheck = [self tabAtIndex:i];
DCHECK([tabToCheck navigationManager]);
CRWSessionController* sessionController =
[tabToCheck navigationManager]->GetSessionController();
@@ -428,7 +450,7 @@ void CleanCertificatePolicyCache(
NSString* openerId = [tab navigationManager]->GetSessionController().openerId;
if (!openerId.length) // Short-circuit if opener is empty.
return nil;
- for (Tab* iteratedTab in _tabs.get()) {
+ for (Tab* iteratedTab in self) {
if ([iteratedTab.tabId isEqualToString:openerId])
return iteratedTab;
}
@@ -521,10 +543,11 @@ void CleanCertificatePolicyCache(
- (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index {
DCHECK(tab);
- DCHECK(index <= [_tabs count]);
+ DCHECK(![_tabs containsObject:tab]);
[tab fetchFavicon];
- [_tabs insertObject:tab atIndex:index];
+ [_tabs addObject:tab];
+ _webStateList.InsertWebState(index, tab.webState);
TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState);
[_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO];
[_observers tabModelDidChangeTabCount:self];
@@ -535,34 +558,29 @@ void CleanCertificatePolicyCache(
// state properly. If it does eventually become active, another save will
// be triggered to properly capture the end result.
[self saveSessionImmediately:NO];
+
++_newTabCount;
}
- (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
rohitrao (ping after 24h) 2017/02/14 14:37:12 DCHECK([_tabs containsObject:tab]);
- NSUInteger fromIndex = [self indexOfTab:tab];
- DCHECK_NE(NSNotFound, static_cast<NSInteger>(fromIndex));
- DCHECK_LT(toIndex, self.count);
- if (fromIndex == NSNotFound || toIndex >= self.count ||
- fromIndex == toIndex) {
- return;
- }
-
- base::scoped_nsobject<Tab> tabSaver([tab retain]);
- [_tabs removeObject:tab];
- [_tabs insertObject:tab atIndex:toIndex];
-
+ size_t fromIndex = _webStateList.GetIndexOfWebState(tab.webState);
+ _webStateList.MoveWebStateAt(fromIndex, toIndex);
[_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex];
}
- (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab {
NSUInteger index = [self indexOfTab:oldTab];
DCHECK_NE(NSNotFound, static_cast<NSInteger>(index));
+ DCHECK([_tabs containsObject:oldTab]);
+ DCHECK(![_tabs containsObject:newTab]);
base::scoped_nsobject<Tab> tabSaver([oldTab retain]);
[newTab fetchFavicon];
- [_tabs replaceObjectAtIndex:index withObject:newTab];
+ [_tabs removeObject:oldTab];
+ [_tabs addObject:newTab];
[newTab setParentTabModel:self];
+ _webStateList.ReplaceWebStateAt(index, newTab.webState);
TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState);
[_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index];
@@ -578,8 +596,8 @@ void CleanCertificatePolicyCache(
}
- (void)closeTabAtIndex:(NSUInteger)index {
- DCHECK(index < [_tabs count]);
- [self closeTab:[_tabs objectAtIndex:index]];
+ DCHECK(index < _webStateList.count());
+ [self closeTab:[self tabAtIndex:index]];
}
- (void)closeTab:(Tab*)tab {
@@ -599,7 +617,7 @@ void CleanCertificatePolicyCache(
}
- (void)haltAllTabs {
- for (Tab* tab in _tabs.get()) {
+ for (Tab* tab in self) {
[tab terminateNetworkActivity];
}
}
@@ -636,7 +654,7 @@ void CleanCertificatePolicyCache(
}
- (void)resetAllWebViews {
- for (Tab* tab in _tabs.get()) {
+ for (Tab* tab in self) {
[tab.webController reinitializeWebViewAndReload:(tab == _currentTab)];
}
}
@@ -645,7 +663,7 @@ void CleanCertificatePolicyCache(
if (webUsageEnabled_ == webUsageEnabled)
return;
webUsageEnabled_ = webUsageEnabled;
- for (Tab* tab in _tabs.get()) {
+ for (Tab* tab in self) {
tab.webUsageEnabled = webUsageEnabled;
}
}
@@ -660,7 +678,7 @@ void CleanCertificatePolicyCache(
if (!_browserState)
return referencedFiles;
// Check the currently open tabs for external files.
- for (Tab* tab in _tabs.get()) {
+ for (Tab* tab in self) {
if (UrlIsExternalFileReference(tab.url)) {
NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName());
[referencedFiles addObject:fileName];
@@ -697,7 +715,7 @@ void CleanCertificatePolicyCache(
// Called when a tab is closing, but before its CRWWebController is destroyed.
// Equivalent to DetachTabContentsAt() in Chrome's TabStripModel.
- (void)didCloseTab:(Tab*)closedTab {
- NSUInteger closedTabIndex = [_tabs indexOfObject:closedTab];
+ NSUInteger closedTabIndex = [self indexOfTab:closedTab];
DCHECK(closedTab);
DCHECK(closedTabIndex != NSNotFound);
// Let the sessions::TabRestoreService know about that new tab.
@@ -716,8 +734,8 @@ void CleanCertificatePolicyCache(
// This needs to be called before the tab is removed from the list.
Tab* newSelection =
[_orderController determineNewSelectedTabFromRemovedTab:closedTab];
+
base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]);
- [_tabs removeObject:closedTab];
// If closing the current tab, clear |_currentTab| before sending any
// notification. This avoids various parts of the code getting confused
@@ -726,6 +744,10 @@ void CleanCertificatePolicyCache(
if (closedTab == _currentTab)
_currentTab.reset(nil);
+ DCHECK([_tabs containsObject:closedTab]);
+ [_tabs removeObject:closedTab];
+
+ _webStateList.RemoveWebStateAt(closedTabIndex);
[_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex];
[_observers tabModelDidChangeTabCount:self];
@@ -773,21 +795,28 @@ void CleanCertificatePolicyCache(
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
objects:(id*)objects
count:(NSUInteger)count {
- return [_tabs countByEnumeratingWithState:state objects:objects count:count];
+ return [_fastEnumerationHelper countByEnumeratingWithState:state
+ objects:objects
+ count:count];
}
#pragma mark - TabUsageRecorderDelegate
- (NSUInteger)liveTabsCount {
NSUInteger count = 0;
- NSArray* tabs = _tabs.get();
- for (Tab* tab in tabs) {
+ for (Tab* tab in self) {
if ([tab.webController isViewAlive])
count++;
}
return count;
}
+#pragma mark - WebStateProxyFactory
+
+- (id)proxyForWebState:(web::WebState*)webState {
rohitrao (ping after 24h) 2017/02/14 14:37:12 What is this for?
+ return LegacyTabHelper::GetTabForWebState(webState);
+}
+
#pragma mark - Private methods
- (SessionWindowIOS*)windowForSavingSession {
@@ -952,7 +981,7 @@ void CleanCertificatePolicyCache(
if (!sessions.count)
return NO;
- size_t oldCount = [_tabs count];
+ size_t oldCount = _webStateList.count();
web::WebState::CreateParams params(_browserState);
scoped_refptr<web::CertificatePolicyCache> policyCache =
web::BrowserState::GetCertificatePolicyCache(_browserState);
@@ -961,20 +990,20 @@ void CleanCertificatePolicyCache(
std::unique_ptr<web::WebState> webState =
web::WebState::Create(params, session);
DCHECK_EQ(webState->GetBrowserState(), _browserState);
- Tab* tab =
- [self insertTabWithWebState:std::move(webState) atIndex:[_tabs count]];
+ Tab* tab = [self insertTabWithWebState:std::move(webState)
+ atIndex:_webStateList.count()];
tab.webController.usePlaceholderOverlay = YES;
// Restore the CertificatePolicyCache (note that webState is invalid after
// passing it via move semantic to -insertTabWithWebState:atIndex:).
UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState);
}
- DCHECK_GT([_tabs count], oldCount);
+ DCHECK_GT(_webStateList.count(), oldCount);
// Update the selected tab if there was a selected Tab in the saved session.
if (window.selectedIndex != NSNotFound) {
NSUInteger selectedIndex = window.selectedIndex + oldCount;
- DCHECK_LT(selectedIndex, [_tabs count]);
+ DCHECK_LT(selectedIndex, _webStateList.count());
DCHECK([self tabAtIndex:selectedIndex]);
[self changeSelectedTabFrom:_currentTab
to:[self tabAtIndex:selectedIndex]
@@ -984,7 +1013,7 @@ void CleanCertificatePolicyCache(
// If there was only one tab and it was the new tab page, clobber it.
BOOL closedNTPTab = NO;
if (oldCount == 1) {
- Tab* tab = [_tabs objectAtIndex:0];
+ Tab* tab = [self tabAtIndex:0];
if (tab.url == GURL(kChromeUINewTabURL)) {
[self closeTab:tab];
closedNTPTab = YES;
@@ -992,10 +1021,12 @@ void CleanCertificatePolicyCache(
}
}
if (_tabUsageRecorder) {
- _tabUsageRecorder->InitialRestoredTabs(
- _currentTab,
- [_tabs
- subarrayWithRange:NSMakeRange(oldCount, [_tabs count] - oldCount)]);
+ NSMutableArray<Tab*>* restoredTabs =
+ [NSMutableArray arrayWithCapacity:_webStateList.count() - oldCount];
+ for (size_t index = oldCount; index < _webStateList.count(); ++index) {
+ [restoredTabs addObject:[self tabAtIndex:index]];
+ }
+ _tabUsageRecorder->InitialRestoredTabs(_currentTab, restoredTabs);
}
return closedNTPTab;
}
@@ -1020,7 +1051,8 @@ void CleanCertificatePolicyCache(
CleanCertificatePolicyCache(
&_clearPoliciesTaskTracker,
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
- web::BrowserState::GetCertificatePolicyCache(_browserState), self);
+ web::BrowserState::GetCertificatePolicyCache(_browserState),
+ &_webStateList);
if (_tabUsageRecorder)
_tabUsageRecorder->AppDidEnterBackground();
« no previous file with comments | « ios/chrome/browser/tabs/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698