Commit a6d3efbd authored by Mohammad Refaat's avatar Mohammad Refaat Committed by Commit Bot

Refactor TabStripLegacyCoordinator and TabStripController

This CL:
1- Updates the tabStripLegacyCoordinator to use Browser
   instead of TabModel.
2- Update TabStripController to use Browser instead of tabModel:
  - Change methods & variables to be more suitable to the usage of
    webStateList.
  - Change the type of indices related to the WebStateList to int.
  - Get the dispatchers from the browser instead of getting them
    from the initializer.
  - Remove initializeTabArrayWithNoModel, as there was no way to
    provide the controller no TabModel earlier, which means that
    was a dead code.
  - Updates the test to use TestBrowser instead of the fake tabModel.

Bug: 1049918, 1048683
Change-Id: I4183ce90df9dafd0182c4fa9f03834f21f507cf6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2043077
Commit-Queue: Mohammad Refaat <mrefaat@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742894}
parent cafbb262
...@@ -2021,11 +2021,9 @@ NSString* const kBrowserViewControllerSnackbarCategory = ...@@ -2021,11 +2021,9 @@ NSString* const kBrowserViewControllerSnackbarCategory =
static_cast<id<LoadQueryCommands>>(self.commandDispatcher)); static_cast<id<LoadQueryCommands>>(self.commandDispatcher));
if (IsIPadIdiom()) { if (IsIPadIdiom()) {
self.tabStripCoordinator = self.tabStripCoordinator = [[TabStripLegacyCoordinator alloc]
[[TabStripLegacyCoordinator alloc] initWithBaseViewController:self]; initWithBaseViewController:self
self.tabStripCoordinator.browserState = self.browserState; browser:self.browser];
self.tabStripCoordinator.dispatcher = self.commandDispatcher;
self.tabStripCoordinator.tabModel = self.tabModel;
self.tabStripCoordinator.presentationProvider = self; self.tabStripCoordinator.presentationProvider = self;
self.tabStripCoordinator.animationWaitDuration = self.tabStripCoordinator.animationWaitDuration =
kLegacyFullscreenControllerToolbarAnimationDuration; kLegacyFullscreenControllerToolbarAnimationDuration;
......
...@@ -41,6 +41,7 @@ source_set("tabs") { ...@@ -41,6 +41,7 @@ source_set("tabs") {
"//ios/chrome/browser", "//ios/chrome/browser",
"//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state",
"//ios/chrome/browser/drag_and_drop", "//ios/chrome/browser/drag_and_drop",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/snapshots", "//ios/chrome/browser/snapshots",
"//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/bubble", "//ios/chrome/browser/ui/bubble",
...@@ -80,6 +81,7 @@ source_set("coordinator") { ...@@ -80,6 +81,7 @@ source_set("coordinator") {
":tabs", ":tabs",
"//ios/chrome/browser", "//ios/chrome/browser",
"//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/ui/bubble", "//ios/chrome/browser/ui/bubble",
"//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
...@@ -95,8 +97,11 @@ source_set("unit_tests") { ...@@ -95,8 +97,11 @@ source_set("unit_tests") {
":tabs", ":tabs",
"//base", "//base",
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/main:test_support",
"//ios/chrome/browser/sessions:test_support", "//ios/chrome/browser/sessions:test_support",
"//ios/chrome/browser/tabs", "//ios/chrome/browser/tabs",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util",
"//ios/chrome/browser/web_state_list", "//ios/chrome/browser/web_state_list",
"//ios/chrome/browser/web_state_list:test_support", "//ios/chrome/browser/web_state_list:test_support",
......
...@@ -9,11 +9,9 @@ ...@@ -9,11 +9,9 @@
#import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h" #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h"
@protocol ApplicationCommands;
@protocol BrowserCommands;
@protocol PopupMenuLongPressDelegate; @protocol PopupMenuLongPressDelegate;
@class TabModel;
@protocol TabStripPresentation; @protocol TabStripPresentation;
class Browser;
// Controller class for the tabstrip. Manages displaying tabs and keeping the // Controller class for the tabstrip. Manages displaying tabs and keeping the
// display in sync with the TabModel. This controller is only instantiated on // display in sync with the TabModel. This controller is only instantiated on
...@@ -24,8 +22,6 @@ ...@@ -24,8 +22,6 @@
@property(nonatomic, assign) BOOL highlightsSelectedTab; @property(nonatomic, assign) BOOL highlightsSelectedTab;
@property(nonatomic, readonly, retain) UIView* view; @property(nonatomic, readonly, retain) UIView* view;
@property(nonatomic, readonly, weak) id<BrowserCommands, ApplicationCommands>
dispatcher;
// Delegate for the long press gesture recognizer triggering popup menu. // Delegate for the long press gesture recognizer triggering popup menu.
@property(nonatomic, weak) id<PopupMenuLongPressDelegate> longPressDelegate; @property(nonatomic, weak) id<PopupMenuLongPressDelegate> longPressDelegate;
...@@ -37,11 +33,8 @@ ...@@ -37,11 +33,8 @@
@property(nonatomic, assign) id<TabStripPresentation> presentationProvider; @property(nonatomic, assign) id<TabStripPresentation> presentationProvider;
// Designated initializer, |dispatcher| is not retained. // Designated initializer, |dispatcher| is not retained.
- (instancetype)initWithTabModel:(TabModel*)tabModel - (instancetype)initWithBrowser:(Browser*)browser
style:(TabStripStyle)style style:(TabStripStyle)style NS_DESIGNATED_INITIALIZER;
dispatcher:
(id<ApplicationCommands, BrowserCommands>)dispatcher
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
......
...@@ -19,15 +19,16 @@ ...@@ -19,15 +19,16 @@
#include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h" #include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h"
#import "ios/chrome/browser/drag_and_drop/drop_and_navigate_delegate.h" #import "ios/chrome/browser/drag_and_drop/drop_and_navigate_delegate.h"
#import "ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction.h" #import "ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction.h"
#include "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
#include "ios/chrome/browser/system_flags.h" #include "ios/chrome/browser/system_flags.h"
#import "ios/chrome/browser/tabs/tab_model.h"
#import "ios/chrome/browser/tabs/tab_title_util.h" #import "ios/chrome/browser/tabs/tab_title_util.h"
#import "ios/chrome/browser/ui/bubble/bubble_util.h" #import "ios/chrome/browser/ui/bubble/bubble_util.h"
#import "ios/chrome/browser/ui/bubble/bubble_view.h" #import "ios/chrome/browser/ui/bubble/bubble_view.h"
#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/commands/popup_menu_commands.h"
#include "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" #include "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
#include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" #include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h"
#import "ios/chrome/browser/ui/ntp/ntp_util.h" #import "ios/chrome/browser/ui/ntp/ntp_util.h"
...@@ -87,8 +88,8 @@ const CGFloat kMinTabWidthStacked = 200.0; ...@@ -87,8 +88,8 @@ const CGFloat kMinTabWidthStacked = 200.0;
const CGFloat kMinTabWidthUnstacked = 160.0; const CGFloat kMinTabWidthUnstacked = 160.0;
const CGFloat kCollapsedTabOverlap = 5.0; const CGFloat kCollapsedTabOverlap = 5.0;
const NSUInteger kMaxNumCollapsedTabsStacked = 3; const int kMaxNumCollapsedTabsStacked = 3;
const NSUInteger kMaxNumCollapsedTabsUnstacked = 0; const int kMaxNumCollapsedTabsUnstacked = 0;
// Tabs with a visible width smaller than this draw as collapsed tabs.. // Tabs with a visible width smaller than this draw as collapsed tabs..
const CGFloat kCollapsedTabWidthThreshold = 40.0; const CGFloat kCollapsedTabWidthThreshold = 40.0;
...@@ -157,7 +158,8 @@ UIColor* BackgroundColor() { ...@@ -157,7 +158,8 @@ UIColor* BackgroundColor() {
WebStateFaviconDriverObserver, WebStateFaviconDriverObserver,
UIGestureRecognizerDelegate, UIGestureRecognizerDelegate,
UIScrollViewDelegate> { UIScrollViewDelegate> {
TabModel* _tabModel; Browser* _browser;
WebStateList* _webStateList;
UIView* _view; UIView* _view;
TabStripView* _tabStripView; TabStripView* _tabStripView;
UIButton* _buttonNewTab; UIButton* _buttonNewTab;
...@@ -170,12 +172,12 @@ UIColor* BackgroundColor() { ...@@ -170,12 +172,12 @@ UIColor* BackgroundColor() {
TabStripStyle _style; TabStripStyle _style;
// Array of TabViews. There is a one-to-one correspondence between this array // Array of TabViews. There is a one-to-one correspondence between this array
// and the set of Tabs in the TabModel. // and the set of Tabs in the WebStateList.
NSMutableArray* _tabArray; NSMutableArray* _tabArray;
// Set of TabViews that are currently closing. These TabViews are also in // Set of TabViews that are currently closing. These TabViews are also in
// |_tabArray|. Used to translate between |_tabArray| indexes and TabModel // |_tabArray|. Used to translate between |_tabArray| indexes and
// indexes. // WebStateList indexes.
NSMutableSet* _closingTabs; NSMutableSet* _closingTabs;
// Tracks target frames for TabViews. // Tracks target frames for TabViews.
...@@ -218,11 +220,11 @@ UIColor* BackgroundColor() { ...@@ -218,11 +220,11 @@ UIColor* BackgroundColor() {
// tabstrip will scroll to the left; if positive, to the right. // tabstrip will scroll to the left; if positive, to the right.
CGFloat _autoscrollDistance; CGFloat _autoscrollDistance;
// The model index of the placeholder gap, if one exists. This value is used // The WebStateList index of the placeholder gap, if one exists. This value is
// as the new model index of the dragged tab when it is dropped. // used as the new WebStateList index of the dragged tab when it is dropped.
NSUInteger _placeholderGapModelIndex; int _placeholderGapWebStateListIndex;
// YES if this tab strip is representing an incognito TabModel. // YES if this tab strip is representing an incognito browser.
BOOL _isIncognito; BOOL _isIncognito;
// The disabler that prevents the toolbar from being scrolled offscreen during // The disabler that prevents the toolbar from being scrolled offscreen during
...@@ -261,14 +263,10 @@ UIColor* BackgroundColor() { ...@@ -261,14 +263,10 @@ UIColor* BackgroundColor() {
// redraw and relayout. Defaults to |YES|. // redraw and relayout. Defaults to |YES|.
@property(nonatomic, assign) BOOL useTabStacking; @property(nonatomic, assign) BOOL useTabStacking;
// Initializes the tab array based on the the entries in the TabModel. Creates // Initializes the tab array based on the the entries in the |_webStateList|'s.
// one TabView per Tab and adds it to the tabstrip. A later call to // Creates one TabView per Tab and adds it to the tabstrip. A later call to
// |-layoutTabs| is needed to properly place the tabs in the correct positions. // |-layoutTabs| is needed to properly place the tabs in the correct positions.
- (void)initializeTabArrayFromTabModel; - (void)initializeTabArray;
// Initializes the tab array to have only one empty tab, for the case (used
// during startup) when there is not a tab model available.
- (void)initializeTabArrayWithNoModel;
// Returns an autoreleased TabView object with no content. // Returns an autoreleased TabView object with no content.
- (TabView*)emptyTabView; - (TabView*)emptyTabView;
...@@ -288,11 +286,11 @@ UIColor* BackgroundColor() { ...@@ -288,11 +286,11 @@ UIColor* BackgroundColor() {
- (void)removeDimmingViewWithAnimation:(BOOL)animate; - (void)removeDimmingViewWithAnimation:(BOOL)animate;
// Converts between model indexes and |_tabArray| indexes. The conversion is // Converts between model indexes and |_tabArray| indexes. The conversion is
// necessary because |_tabArray| contains closing tabs whereas the TabModel does // necessary because |_tabArray| contains closing tabs whereas the WebStateList
// not. // does not.
- (NSUInteger)indexForModelIndex:(NSUInteger)modelIndex; - (NSUInteger)indexForWebStateListIndex:(int)modelIndex;
- (NSUInteger)modelIndexForIndex:(NSUInteger)index; - (int)webStateListIndexForIndex:(NSUInteger)index;
- (NSUInteger)modelIndexForTabView:(TabView*)view; - (int)webStateListIndexForTabView:(TabView*)view;
// Helper methods to handle each stage of a drag. // Helper methods to handle each stage of a drag.
- (void)beginDrag:(UILongPressGestureRecognizer*)gesture; - (void)beginDrag:(UILongPressGestureRecognizer*)gesture;
...@@ -358,7 +356,7 @@ UIColor* BackgroundColor() { ...@@ -358,7 +356,7 @@ UIColor* BackgroundColor() {
// Returns the maximum number of collapsed tabs depending on the current layout // Returns the maximum number of collapsed tabs depending on the current layout
// mode. // mode.
- (NSUInteger)maxNumCollapsedTabs; - (int)maxNumCollapsedTabs;
// Returns the tab overlap width depending on the current layout mode. // Returns the tab overlap width depending on the current layout mode.
- (CGFloat)tabOverlap; - (CGFloat)tabOverlap;
...@@ -371,7 +369,7 @@ UIColor* BackgroundColor() { ...@@ -371,7 +369,7 @@ UIColor* BackgroundColor() {
// Automatically scroll the tab strip view to keep the given tab view visible. // Automatically scroll the tab strip view to keep the given tab view visible.
// This method must be called with a valid |tabIndex|. // This method must be called with a valid |tabIndex|.
- (void)scrollTabToVisible:(NSUInteger)tabIndex; - (void)scrollTabToVisible:(int)tabIndex;
// Updates the content offset of the tab strip view in order to keep the // Updates the content offset of the tab strip view in order to keep the
// selected tab view visible. // selected tab view visible.
...@@ -403,32 +401,29 @@ UIColor* BackgroundColor() { ...@@ -403,32 +401,29 @@ UIColor* BackgroundColor() {
@synthesize highlightsSelectedTab = _highlightsSelectedTab; @synthesize highlightsSelectedTab = _highlightsSelectedTab;
@synthesize tabStripView = _tabStripView; @synthesize tabStripView = _tabStripView;
@synthesize view = _view; @synthesize view = _view;
@synthesize dispatcher = _dispatcher;
@synthesize longPressDelegate = _longPressDelegate; @synthesize longPressDelegate = _longPressDelegate;
@synthesize presentationProvider = _presentationProvider; @synthesize presentationProvider = _presentationProvider;
@synthesize animationWaitDuration = _animationWaitDuration; @synthesize animationWaitDuration = _animationWaitDuration;
- (instancetype)initWithTabModel:(TabModel*)tabModel - (instancetype)initWithBrowser:(Browser*)browser style:(TabStripStyle)style {
style:(TabStripStyle)style
dispatcher:
(id<ApplicationCommands, BrowserCommands>)dispatcher {
if ((self = [super init])) { if ((self = [super init])) {
_tabArray = [[NSMutableArray alloc] initWithCapacity:10]; _tabArray = [[NSMutableArray alloc] initWithCapacity:10];
_closingTabs = [[NSMutableSet alloc] initWithCapacity:5]; _closingTabs = [[NSMutableSet alloc] initWithCapacity:5];
DCHECK(browser);
_tabModel = tabModel; _browser = browser;
_webStateList = _browser->GetWebStateList();
_webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
_tabModel.webStateList->AddObserver(_webStateListObserver.get()); _webStateList->AddObserver(_webStateListObserver.get());
_webStateListFaviconObserver = _webStateListFaviconObserver =
std::make_unique<WebStateListFaviconDriverObserver>( std::make_unique<WebStateListFaviconDriverObserver>(_webStateList,
_tabModel.webStateList, self); self);
_webStateObserver = std::make_unique<web::WebStateObserverBridge>(self); _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
// Observe all webStates of this |_tabModel.webStateList|. // Observe all webStates of this |_webStateList|.
_allWebStateObservationForwarder = _allWebStateObservationForwarder =
std::make_unique<AllWebStateObservationForwarder>( std::make_unique<AllWebStateObservationForwarder>(
_tabModel.webStateList, _webStateObserver.get()); _webStateList, _webStateObserver.get());
_style = style; _style = style;
_dispatcher = dispatcher;
// |self.view| setup. // |self.view| setup.
_useTabStacking = [self shouldUseTabStacking]; _useTabStacking = [self shouldUseTabStacking];
...@@ -455,7 +450,7 @@ UIColor* BackgroundColor() { ...@@ -455,7 +450,7 @@ UIColor* BackgroundColor() {
CGRect buttonNewTabFrame = tabStripFrame; CGRect buttonNewTabFrame = tabStripFrame;
buttonNewTabFrame.size.width = kNewTabButtonWidth; buttonNewTabFrame.size.width = kNewTabButtonWidth;
_buttonNewTab = [[UIButton alloc] initWithFrame:buttonNewTabFrame]; _buttonNewTab = [[UIButton alloc] initWithFrame:buttonNewTabFrame];
_isIncognito = tabModel && tabModel.browserState->IsOffTheRecord(); _isIncognito = _browser->GetBrowserState()->IsOffTheRecord();
// TODO(crbug.com/600829): Rewrite layout code and convert these masks to // TODO(crbug.com/600829): Rewrite layout code and convert these masks to
// to trailing and leading margins rather than right and bottom. // to trailing and leading margins rather than right and bottom.
_buttonNewTab.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | _buttonNewTab.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin |
...@@ -495,10 +490,7 @@ UIColor* BackgroundColor() { ...@@ -495,10 +490,7 @@ UIColor* BackgroundColor() {
[self installTabSwitcherButton]; [self installTabSwitcherButton];
// Add tab buttons to tab strip. // Add tab buttons to tab strip.
if (_tabModel) [self initializeTabArray];
[self initializeTabArrayFromTabModel];
else
[self initializeTabArrayWithNoModel];
// Update the layout of the tab buttons. // Update the layout of the tab buttons.
[self updateContentSizeAndRepositionViews]; [self updateContentSizeAndRepositionViews];
...@@ -528,7 +520,7 @@ UIColor* BackgroundColor() { ...@@ -528,7 +520,7 @@ UIColor* BackgroundColor() {
[_tabStripView setLayoutDelegate:nil]; [_tabStripView setLayoutDelegate:nil];
_allWebStateObservationForwarder.reset(); _allWebStateObservationForwarder.reset();
_webStateListFaviconObserver.reset(); _webStateListFaviconObserver.reset();
_tabModel.webStateList->RemoveObserver(_webStateListObserver.get()); _webStateList->RemoveObserver(_webStateListObserver.get());
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
self.disconnected = YES; self.disconnected = YES;
} }
...@@ -540,12 +532,10 @@ UIColor* BackgroundColor() { ...@@ -540,12 +532,10 @@ UIColor* BackgroundColor() {
#pragma mark - Private #pragma mark - Private
- (void)initializeTabArrayFromTabModel { - (void)initializeTabArray {
DCHECK(_tabModel); for (int index = 0; index < _webStateList->count(); ++index) {
WebStateList* webStateList = _tabModel.webStateList; web::WebState* webState = _webStateList->GetWebStateAt(index);
for (int index = 0; index < webStateList->count(); ++index) { BOOL isSelected = index == _webStateList->active_index();
web::WebState* webState = webStateList->GetWebStateAt(index);
BOOL isSelected = index == webStateList->active_index();
TabView* view = [self createTabViewForWebState:webState TabView* view = [self createTabViewForWebState:webState
isSelected:isSelected]; isSelected:isSelected];
[_tabArray addObject:view]; [_tabArray addObject:view];
...@@ -553,15 +543,6 @@ UIColor* BackgroundColor() { ...@@ -553,15 +543,6 @@ UIColor* BackgroundColor() {
} }
} }
- (void)initializeTabArrayWithNoModel {
DCHECK(!_tabModel);
TabView* view = [self emptyTabView];
[_tabArray addObject:view];
[_tabStripView addSubview:view];
[view setSelected:YES];
return;
}
- (TabView*)emptyTabView { - (TabView*)emptyTabView {
TabView* view = [[TabView alloc] initWithEmptyView:YES selected:YES]; TabView* view = [[TabView alloc] initWithEmptyView:YES selected:YES];
[view setIncognitoStyle:(_style == INCOGNITO)]; [view setIncognitoStyle:(_style == INCOGNITO)];
...@@ -676,7 +657,7 @@ UIColor* BackgroundColor() { ...@@ -676,7 +657,7 @@ UIColor* BackgroundColor() {
toView:_buttonNewTab.window]; toView:_buttonNewTab.window];
OpenNewTabCommand* command = OpenNewTabCommand* command =
[OpenNewTabCommand commandWithIncognito:_isIncognito originPoint:center]; [OpenNewTabCommand commandWithIncognito:_isIncognito originPoint:center];
[self.dispatcher openURLInNewTab:command]; [[self applicationCommandsHandler] openURLInNewTab:command];
} }
- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture { - (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
...@@ -707,7 +688,7 @@ UIColor* BackgroundColor() { ...@@ -707,7 +688,7 @@ UIColor* BackgroundColor() {
} }
} }
- (NSUInteger)indexForModelIndex:(NSUInteger)modelIndex { - (NSUInteger)indexForWebStateListIndex:(int)modelIndex {
NSUInteger index = modelIndex; NSUInteger index = modelIndex;
NSUInteger i = 0; NSUInteger i = 0;
for (TabView* tab in _tabArray) { for (TabView* tab in _tabArray) {
...@@ -719,31 +700,31 @@ UIColor* BackgroundColor() { ...@@ -719,31 +700,31 @@ UIColor* BackgroundColor() {
++i; ++i;
} }
DCHECK_GE(index, modelIndex); DCHECK_GE(index, static_cast<NSUInteger>(modelIndex));
return index; return index;
} }
- (NSUInteger)modelIndexForIndex:(NSUInteger)index { - (int)webStateListIndexForIndex:(NSUInteger)index {
NSUInteger modelIndex = 0; int listIndex = 0;
NSUInteger arrayIndex = 0; NSUInteger arrayIndex = 0;
for (TabView* tab in _tabArray) { for (TabView* tab in _tabArray) {
if (arrayIndex == index) { if (arrayIndex == index) {
if ([_closingTabs containsObject:tab]) if ([_closingTabs containsObject:tab])
return NSNotFound; return WebStateList::kInvalidIndex;
return modelIndex; return listIndex;
} }
if (![_closingTabs containsObject:tab]) if (![_closingTabs containsObject:tab])
++modelIndex; ++listIndex;
++arrayIndex; ++arrayIndex;
} }
return NSNotFound; return WebStateList::kInvalidIndex;
} }
- (NSUInteger)modelIndexForTabView:(TabView*)view { - (int)webStateListIndexForTabView:(TabView*)view {
return [self modelIndexForIndex:[_tabArray indexOfObject:view]]; return [self webStateListIndexForIndex:[_tabArray indexOfObject:view]];
} }
// The |tabSwitcherGuide| cannot use constrainedView in the tab strip because // The |tabSwitcherGuide| cannot use constrainedView in the tab strip because
...@@ -778,6 +759,18 @@ UIColor* BackgroundColor() { ...@@ -778,6 +759,18 @@ UIColor* BackgroundColor() {
[_tabStripView setNeedsLayout]; [_tabStripView setNeedsLayout];
} }
// Gets PopupMenuCommands handler from |_browser|'s command dispatcher.
- (id<PopupMenuCommands>)popupMenuCommandsHandler {
return HandlerForProtocol(_browser->GetCommandDispatcher(),
PopupMenuCommands);
}
// Gets ApplicationCommands handler from |_browser|'s command dispatcher.
- (id<ApplicationCommands>)applicationCommandsHandler {
return HandlerForProtocol(_browser->GetCommandDispatcher(),
ApplicationCommands);
}
#pragma mark - #pragma mark -
#pragma mark Tab Drag and Drop methods #pragma mark Tab Drag and Drop methods
...@@ -786,22 +779,23 @@ UIColor* BackgroundColor() { ...@@ -786,22 +779,23 @@ UIColor* BackgroundColor() {
TabView* view = (TabView*)[gesture view]; TabView* view = (TabView*)[gesture view];
// Sanity checks. // Sanity checks.
NSUInteger index = [self modelIndexForTabView:view]; int index = [self webStateListIndexForTabView:view];
DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); DCHECK_NE(WebStateList::kInvalidIndex, index);
if (index == NSNotFound) if (index == WebStateList::kInvalidIndex)
return; return;
// Install the dimming view, hide the new tab button, and select the tab so it // Install the dimming view, hide the new tab button, and select the tab so it
// appears highlighted. // appears highlighted.
self.highlightsSelectedTab = YES; self.highlightsSelectedTab = YES;
_buttonNewTab.hidden = YES; _buttonNewTab.hidden = YES;
_tabModel.webStateList->ActivateWebStateAt(index); _webStateList->ActivateWebStateAt(index);
// Set up initial drag state. // Set up initial drag state.
_lastDragLocation = [gesture locationInView:[_tabStripView superview]]; _lastDragLocation = [gesture locationInView:[_tabStripView superview]];
_isReordering = YES; _isReordering = YES;
_draggedTab = view; _draggedTab = view;
_placeholderGapModelIndex = [self modelIndexForTabView:_draggedTab]; _placeholderGapWebStateListIndex =
[self webStateListIndexForTabView:_draggedTab];
// Update the autoscroll distance and timer. // Update the autoscroll distance and timer.
[self computeAutoscrollDistanceForTabView:_draggedTab]; [self computeAutoscrollDistanceForTabView:_draggedTab];
...@@ -812,7 +806,7 @@ UIColor* BackgroundColor() { ...@@ -812,7 +806,7 @@ UIColor* BackgroundColor() {
// Disable fullscreen during drags. // Disable fullscreen during drags.
_fullscreenDisabler = std::make_unique<ScopedFullscreenDisabler>( _fullscreenDisabler = std::make_unique<ScopedFullscreenDisabler>(
FullscreenController::FromBrowserState(_tabModel.browserState)); FullscreenController::FromBrowserState(_browser->GetBrowserState()));
} }
- (void)continueDrag:(UILongPressGestureRecognizer*)gesture { - (void)continueDrag:(UILongPressGestureRecognizer*)gesture {
...@@ -843,25 +837,25 @@ UIColor* BackgroundColor() { ...@@ -843,25 +837,25 @@ UIColor* BackgroundColor() {
// Stop disabling fullscreen. // Stop disabling fullscreen.
_fullscreenDisabler = nullptr; _fullscreenDisabler = nullptr;
NSUInteger fromIndex = [self modelIndexForTabView:_draggedTab]; int fromIndex = [self webStateListIndexForTabView:_draggedTab];
// TODO(rohitrao): We're seeing crashes where fromIndex is NSNotFound, // TODO(crbug.com/1049882): We're seeing crashes where fromIndex is
// indicating that the dragged tab is no longer in the TabModel. This could // kInvalidIndex, indicating that the dragged tab is no longer in the
// happen if a tab closed itself during a drag. Investigate this further, but // WebStateList. This could happen if a tab closed itself during a drag.
// for now, simply test |fromIndex| before proceeding. // Investigate this further, but for now, simply test |fromIndex| before
if (fromIndex == NSNotFound) { // proceeding.
if (fromIndex == WebStateList::kInvalidIndex) {
[self resetDragState]; [self resetDragState];
[self setNeedsLayoutWithAnimation]; [self setNeedsLayoutWithAnimation];
return; return;
} }
NSUInteger toIndex = _placeholderGapModelIndex; int toIndex = _placeholderGapWebStateListIndex;
DCHECK_NE(NSNotFound, static_cast<NSInteger>(toIndex)); DCHECK_NE(WebStateList::kInvalidIndex, toIndex);
DCHECK_LT(toIndex, [_tabModel count]); DCHECK_LT(toIndex, _webStateList->count());
// Reset drag state variables before notifying the model that the tab moved. // Reset drag state variables before notifying the model that the tab moved.
[self resetDragState]; [self resetDragState];
_tabModel.webStateList->MoveWebStateAt(static_cast<int>(fromIndex), _webStateList->MoveWebStateAt(fromIndex, toIndex);
static_cast<int>(toIndex));
[self setNeedsLayoutWithAnimation]; [self setNeedsLayoutWithAnimation];
} }
...@@ -883,7 +877,7 @@ UIColor* BackgroundColor() { ...@@ -883,7 +877,7 @@ UIColor* BackgroundColor() {
[self removeAutoscrollTimer]; [self removeAutoscrollTimer];
_isReordering = NO; _isReordering = NO;
_placeholderGapModelIndex = NSNotFound; _placeholderGapWebStateListIndex = WebStateList::kInvalidIndex;
_draggedTab = nil; _draggedTab = nil;
} }
...@@ -995,7 +989,8 @@ UIColor* BackgroundColor() { ...@@ -995,7 +989,8 @@ UIColor* BackgroundColor() {
- (void)webStateDidStartLoading:(web::WebState*)webState { - (void)webStateDidStartLoading:(web::WebState*)webState {
// webState can start loading before didInsertWebState is called, in that // webState can start loading before didInsertWebState is called, in that
// case early return as there is no view to update yet. // case early return as there is no view to update yet.
if (_tabModel.count > _tabArray.count - _closingTabs.count) if (static_cast<NSUInteger>(_webStateList->count()) >
_tabArray.count - _closingTabs.count)
return; return;
if (IsVisibleURLNewTabPage(webState)) if (IsVisibleURLNewTabPage(webState))
...@@ -1053,7 +1048,7 @@ UIColor* BackgroundColor() { ...@@ -1053,7 +1048,7 @@ UIColor* BackgroundColor() {
[view setSelected:NO]; [view setSelected:NO];
} }
NSUInteger index = [self indexForModelIndex:atIndex]; NSUInteger index = [self indexForWebStateListIndex:atIndex];
TabView* activeView = [_tabArray objectAtIndex:index]; TabView* activeView = [_tabArray objectAtIndex:index];
[activeView setSelected:YES]; [activeView setSelected:YES];
...@@ -1071,7 +1066,7 @@ UIColor* BackgroundColor() { ...@@ -1071,7 +1066,7 @@ UIColor* BackgroundColor() {
DCHECK(!_isReordering); DCHECK(!_isReordering);
// Reorder the objects in _tabArray to keep in sync with the model ordering. // Reorder the objects in _tabArray to keep in sync with the model ordering.
NSUInteger arrayIndex = [self indexForModelIndex:fromIndex]; NSUInteger arrayIndex = [self indexForWebStateListIndex:fromIndex];
TabView* view = [_tabArray objectAtIndex:arrayIndex]; TabView* view = [_tabArray objectAtIndex:arrayIndex];
[_tabArray removeObject:view]; [_tabArray removeObject:view];
[_tabArray insertObject:view atIndex:toIndex]; [_tabArray insertObject:view atIndex:toIndex];
...@@ -1084,7 +1079,7 @@ UIColor* BackgroundColor() { ...@@ -1084,7 +1079,7 @@ UIColor* BackgroundColor() {
atIndex:(int)atIndex { atIndex:(int)atIndex {
// Keep the actual view around while it is animating out. Once the animation // Keep the actual view around while it is animating out. Once the animation
// is done, remove the view. // is done, remove the view.
NSUInteger index = [self indexForModelIndex:atIndex]; NSUInteger index = [self indexForWebStateListIndex:atIndex];
TabView* view = [_tabArray objectAtIndex:index]; TabView* view = [_tabArray objectAtIndex:index];
[_closingTabs addObject:view]; [_closingTabs addObject:view];
_targetFrames.RemoveFrame(view); _targetFrames.RemoveFrame(view);
...@@ -1124,7 +1119,7 @@ UIColor* BackgroundColor() { ...@@ -1124,7 +1119,7 @@ UIColor* BackgroundColor() {
activating:(BOOL)activating { activating:(BOOL)activating {
TabView* view = [self createTabViewForWebState:webState TabView* view = [self createTabViewForWebState:webState
isSelected:activating]; isSelected:activating];
[_tabArray insertObject:view atIndex:[self indexForModelIndex:index]]; [_tabArray insertObject:view atIndex:[self indexForWebStateListIndex:index]];
[[self tabStripView] addSubview:view]; [[self tabStripView] addSubview:view];
[self updateContentSizeAndRepositionViews]; [self updateContentSizeAndRepositionViews];
...@@ -1152,14 +1147,14 @@ UIColor* BackgroundColor() { ...@@ -1152,14 +1147,14 @@ UIColor* BackgroundColor() {
if (!driver) if (!driver)
return; return;
int modelIndex = _tabModel.webStateList->GetIndexOfWebState(webState); int listIndex = _webStateList->GetIndexOfWebState(webState);
if (modelIndex == WebStateList::kInvalidIndex) { if (listIndex == WebStateList::kInvalidIndex) {
DCHECK(false) << "Received FavIcon update notification for webState that is" DCHECK(false) << "Received FavIcon update notification for webState that is"
" not in the WebStateList"; " not in the WebStateList";
return; return;
} }
NSUInteger index = [self indexForModelIndex:modelIndex]; NSUInteger index = [self indexForWebStateListIndex:listIndex];
TabView* view = [_tabArray objectAtIndex:index]; TabView* view = [_tabArray objectAtIndex:index];
[view setFavicon:nil]; [view setFavicon:nil];
...@@ -1174,10 +1169,10 @@ UIColor* BackgroundColor() { ...@@ -1174,10 +1169,10 @@ UIColor* BackgroundColor() {
#pragma mark Views and Layout #pragma mark Views and Layout
- (TabView*)tabViewForWebState:(web::WebState*)webState { - (TabView*)tabViewForWebState:(web::WebState*)webState {
int modelIndex = _tabModel.webStateList->GetIndexOfWebState(webState); int listIndex = _webStateList->GetIndexOfWebState(webState);
if (modelIndex == WebStateList::kInvalidIndex) if (listIndex == WebStateList::kInvalidIndex)
return nil; return nil;
NSUInteger index = [self indexForModelIndex:modelIndex]; NSUInteger index = [self indexForWebStateListIndex:listIndex];
return [_tabArray objectAtIndex:index]; return [_tabArray objectAtIndex:index];
} }
...@@ -1221,10 +1216,10 @@ UIColor* BackgroundColor() { ...@@ -1221,10 +1216,10 @@ UIColor* BackgroundColor() {
forState:UIControlStateNormal]; forState:UIControlStateNormal];
[_tabSwitcherButton setImage:tabSwitcherButtonIconPressed [_tabSwitcherButton setImage:tabSwitcherButtonIconPressed
forState:UIControlStateHighlighted]; forState:UIControlStateHighlighted];
[_tabSwitcherButton addTarget:self.dispatcher [_tabSwitcherButton addTarget:[self applicationCommandsHandler]
action:@selector(prepareTabSwitcher) action:@selector(prepareTabSwitcher)
forControlEvents:UIControlEventTouchDown]; forControlEvents:UIControlEventTouchDown];
[_tabSwitcherButton addTarget:self.dispatcher [_tabSwitcherButton addTarget:[self applicationCommandsHandler]
action:@selector(displayTabSwitcher) action:@selector(displayTabSwitcher)
forControlEvents:UIControlEventTouchUpInside]; forControlEvents:UIControlEventTouchUpInside];
[_tabSwitcherButton addTarget:self [_tabSwitcherButton addTarget:self
...@@ -1253,7 +1248,7 @@ UIColor* BackgroundColor() { ...@@ -1253,7 +1248,7 @@ UIColor* BackgroundColor() {
// Handles the long press on the |_tabSwitcherButton|. // Handles the long press on the |_tabSwitcherButton|.
- (void)handleTabSwitcherLongPress:(UILongPressGestureRecognizer*)gesture { - (void)handleTabSwitcherLongPress:(UILongPressGestureRecognizer*)gesture {
if (gesture.state == UIGestureRecognizerStateBegan) { if (gesture.state == UIGestureRecognizerStateBegan) {
[self.dispatcher showTabStripTabGridButtonPopup]; [[self popupMenuCommandsHandler] showTabStripTabGridButtonPopup];
TriggerHapticFeedbackForImpact(UIImpactFeedbackStyleMedium); TriggerHapticFeedbackForImpact(UIImpactFeedbackStyleMedium);
} else if (gesture.state == UIGestureRecognizerStateEnded) { } else if (gesture.state == UIGestureRecognizerStateEnded) {
[self.longPressDelegate [self.longPressDelegate
...@@ -1309,7 +1304,7 @@ UIColor* BackgroundColor() { ...@@ -1309,7 +1304,7 @@ UIColor* BackgroundColor() {
} }
- (CGRect)scrollViewFrameForTab:(TabView*)view { - (CGRect)scrollViewFrameForTab:(TabView*)view {
NSUInteger index = [self modelIndexForTabView:view]; int index = [self webStateListIndexForTabView:view];
CGRect frame = [view frame]; CGRect frame = [view frame];
frame.origin.x = frame.origin.x =
...@@ -1335,7 +1330,7 @@ UIColor* BackgroundColor() { ...@@ -1335,7 +1330,7 @@ UIColor* BackgroundColor() {
#pragma mark - #pragma mark -
#pragma mark - Unstacked layout #pragma mark - Unstacked layout
- (NSUInteger)maxNumCollapsedTabs { - (int)maxNumCollapsedTabs {
return self.useTabStacking ? kMaxNumCollapsedTabsStacked return self.useTabStacking ? kMaxNumCollapsedTabsStacked
: kMaxNumCollapsedTabsUnstacked; : kMaxNumCollapsedTabsUnstacked;
} }
...@@ -1352,8 +1347,8 @@ UIColor* BackgroundColor() { ...@@ -1352,8 +1347,8 @@ UIColor* BackgroundColor() {
return self.useTabStacking ? kMinTabWidthStacked : kMinTabWidthUnstacked; return self.useTabStacking ? kMinTabWidthStacked : kMinTabWidthUnstacked;
} }
- (void)scrollTabToVisible:(NSUInteger)tabIndex { - (void)scrollTabToVisible:(int)tabIndex {
DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); DCHECK_NE(WebStateList::kInvalidIndex, tabIndex);
// The following code calculates the amount of scroll needed to make // The following code calculates the amount of scroll needed to make
// |tabIndex| visible in the "virtual" coordinate system, where root is x=0 // |tabIndex| visible in the "virtual" coordinate system, where root is x=0
...@@ -1361,7 +1356,7 @@ UIColor* BackgroundColor() { ...@@ -1361,7 +1356,7 @@ UIColor* BackgroundColor() {
// long. The amount of scroll is calculated as a desired length that it is // long. The amount of scroll is calculated as a desired length that it is
// just large enough to contain all the tabs to the left of |tabIndex|, with // just large enough to contain all the tabs to the left of |tabIndex|, with
// the standard overlap. // the standard overlap.
if (tabIndex == [_tabArray count] - 1) { if (tabIndex == static_cast<int>([_tabArray count]) - 1) {
const CGFloat tabStripAvailableSpace = const CGFloat tabStripAvailableSpace =
_tabStripView.frame.size.width - _tabStripView.contentInset.right; _tabStripView.frame.size.width - _tabStripView.contentInset.right;
CGPoint oldOffset = [_tabStripView contentOffset]; CGPoint oldOffset = [_tabStripView contentOffset];
...@@ -1378,7 +1373,7 @@ UIColor* BackgroundColor() { ...@@ -1378,7 +1373,7 @@ UIColor* BackgroundColor() {
} }
NSUInteger numNonClosingTabsToLeft = 0; NSUInteger numNonClosingTabsToLeft = 0;
NSUInteger i = 0; int i = 0;
for (TabView* tab in _tabArray) { for (TabView* tab in _tabArray) {
if ([_closingTabs containsObject:tab]) if ([_closingTabs containsObject:tab])
++i; ++i;
...@@ -1462,20 +1457,21 @@ UIColor* BackgroundColor() { ...@@ -1462,20 +1457,21 @@ UIColor* BackgroundColor() {
} }
- (void)updateTabCount { - (void)updateTabCount {
[_tabSwitcherButton setTitle:TextForTabCount(_tabModel.count) [_tabSwitcherButton setTitle:TextForTabCount(_webStateList->count())
forState:UIControlStateNormal]; forState:UIControlStateNormal];
[_tabSwitcherButton [_tabSwitcherButton
setAccessibilityValue:[NSString setAccessibilityValue:[NSString stringWithFormat:@"%d",
stringWithFormat:@"%zd", _tabModel.count]]; _webStateList->count()]];
} }
#pragma mark - TabStripViewLayoutDelegate #pragma mark - TabStripViewLayoutDelegate
// Creates TabViews for each Tab in the TabModel and positions them in the // Creates TabViews for each Tab in the WebStateList and positions them in the
// correct location onscreen. // correct location onscreen.
- (void)layoutTabStripSubviews { - (void)layoutTabStripSubviews {
[self updateTabSwitcherGuide]; [self updateTabSwitcherGuide];
const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; const int tabCount =
static_cast<int>([_tabArray count] - [_closingTabs count]);
if (!tabCount) if (!tabCount)
return; return;
BOOL animate = _animateLayout; BOOL animate = _animateLayout;
...@@ -1494,9 +1490,9 @@ UIColor* BackgroundColor() { ...@@ -1494,9 +1490,9 @@ UIColor* BackgroundColor() {
: _tabStripView.contentSize.width; : _tabStripView.contentSize.width;
// The array and model indexes of the selected tab. // The array and model indexes of the selected tab.
NSUInteger selectedModelIndex = int selectedListIndex = _webStateList->active_index();
static_cast<NSUInteger>(_tabModel.webStateList->active_index()); NSUInteger selectedArrayIndex =
NSUInteger selectedArrayIndex = [self indexForModelIndex:selectedModelIndex]; [self indexForWebStateListIndex:selectedListIndex];
// This method lays out tabs in two coordinate systems. The first, the // This method lays out tabs in two coordinate systems. The first, the
// "virtual" coordinate system, is a system rooted at x=0 that contains all // "virtual" coordinate system, is a system rooted at x=0 that contains all
...@@ -1570,8 +1566,8 @@ UIColor* BackgroundColor() { ...@@ -1570,8 +1566,8 @@ UIColor* BackgroundColor() {
} }
// Ignore closing tabs when repositioning. // Ignore closing tabs when repositioning.
NSUInteger currentModelIndex = [self modelIndexForIndex:arrayIndex]; int currentListIndex = [self webStateListIndexForIndex:arrayIndex];
if (currentModelIndex == NSNotFound) if (currentListIndex == WebStateList::kInvalidIndex)
continue; continue;
// Ignore the tab that is currently being dragged. // Ignore the tab that is currently being dragged.
...@@ -1587,28 +1583,28 @@ UIColor* BackgroundColor() { ...@@ -1587,28 +1583,28 @@ UIColor* BackgroundColor() {
// selected // selected
// tab, and the same number to the right of the selected tab. // tab, and the same number to the right of the selected tab.
NSUInteger numPossibleCollapsedTabsToLeft = NSUInteger numPossibleCollapsedTabsToLeft =
std::min(currentModelIndex, [self maxNumCollapsedTabs]); std::min(currentListIndex, [self maxNumCollapsedTabs]);
if (currentModelIndex > selectedModelIndex) { if (currentListIndex > selectedListIndex) {
// If this tab is to the right of the selected tab, also include the // If this tab is to the right of the selected tab, also include the
// number of collapsed tabs on the right of the selected tab. // number of collapsed tabs on the right of the selected tab.
numPossibleCollapsedTabsToLeft = numPossibleCollapsedTabsToLeft =
std::min(selectedModelIndex, [self maxNumCollapsedTabs]) + std::min(selectedListIndex, [self maxNumCollapsedTabs]) +
std::min(currentModelIndex - selectedModelIndex, std::min(currentListIndex - selectedListIndex,
[self maxNumCollapsedTabs]); [self maxNumCollapsedTabs]);
} }
CGFloat realMinX = CGFloat realMinX =
offset + (numPossibleCollapsedTabsToLeft * kCollapsedTabOverlap); offset + (numPossibleCollapsedTabsToLeft * kCollapsedTabOverlap);
// |realMaxX| is the furthest right the tab can be, in real coordinates. // |realMaxX| is the furthest right the tab can be, in real coordinates.
NSUInteger numPossibleCollapsedTabsToRight = int numPossibleCollapsedTabsToRight =
std::min(tabCount - currentModelIndex - 1, [self maxNumCollapsedTabs]); std::min(tabCount - currentListIndex - 1, [self maxNumCollapsedTabs]);
if (currentModelIndex < selectedModelIndex) { if (currentListIndex < selectedListIndex) {
// If this tab is to the left of the selected tab, also include the // If this tab is to the left of the selected tab, also include the
// number of collapsed tabs on the left of the selected tab. // number of collapsed tabs on the left of the selected tab.
numPossibleCollapsedTabsToRight = numPossibleCollapsedTabsToRight =
std::min(tabCount - selectedModelIndex - 1, std::min(tabCount - selectedListIndex - 1,
[self maxNumCollapsedTabs]) + [self maxNumCollapsedTabs]) +
std::min(selectedModelIndex - currentModelIndex, std::min(selectedListIndex - currentListIndex,
[self maxNumCollapsedTabs]); [self maxNumCollapsedTabs]);
} }
CGFloat realMaxX = offset + availableSpace - CGFloat realMaxX = offset + availableSpace -
...@@ -1629,9 +1625,9 @@ UIColor* BackgroundColor() { ...@@ -1629,9 +1625,9 @@ UIColor* BackgroundColor() {
// the shifted tab, adjusted for the presence of the dragged tab. This // the shifted tab, adjusted for the presence of the dragged tab. This
// value will be used as the new model index for the dragged tab when it // value will be used as the new model index for the dragged tab when it
// is dropped. // is dropped.
_placeholderGapModelIndex = currentModelIndex; _placeholderGapWebStateListIndex = currentListIndex;
if ([self modelIndexForTabView:_draggedTab] < currentModelIndex) if ([self webStateListIndexForTabView:_draggedTab] < currentListIndex)
_placeholderGapModelIndex--; _placeholderGapWebStateListIndex--;
} }
// |tabX| stores where we are placing the tab, in real coordinates. Start // |tabX| stores where we are placing the tab, in real coordinates. Start
...@@ -1711,9 +1707,9 @@ UIColor* BackgroundColor() { ...@@ -1711,9 +1707,9 @@ UIColor* BackgroundColor() {
// If in reordering mode and there was no placeholder gap, then the dragged // If in reordering mode and there was no placeholder gap, then the dragged
// tab must be all the way to the right of the other tabs. Set the // tab must be all the way to the right of the other tabs. Set the
// _placeholderGapModelIndex accordingly. // _placeholderGapWebStateListIndex accordingly.
if (!hasPlaceholderGap && _isReordering) if (!hasPlaceholderGap && _isReordering)
_placeholderGapModelIndex = [_tabModel count] - 1; _placeholderGapWebStateListIndex = _webStateList->count() - 1;
// Do not move the new tab button if it is hidden. This will lead to better // Do not move the new tab button if it is hidden. This will lead to better
// animations when exiting drag and drop mode, as the new tab button will not // animations when exiting drag and drop mode, as the new tab button will not
...@@ -1768,7 +1764,7 @@ UIColor* BackgroundColor() { ...@@ -1768,7 +1764,7 @@ UIColor* BackgroundColor() {
inIncognito:_isIncognito inIncognito:_isIncognito
inBackground:NO inBackground:NO
appendTo:kLastTab]; appendTo:kLastTab];
[self.dispatcher openURLInNewTab:command]; [[self applicationCommandsHandler] openURLInNewTab:command];
} }
#pragma mark - TabViewDelegate #pragma mark - TabViewDelegate
...@@ -1779,17 +1775,17 @@ UIColor* BackgroundColor() { ...@@ -1779,17 +1775,17 @@ UIColor* BackgroundColor() {
if ([self isReorderingTabs]) if ([self isReorderingTabs])
return; return;
NSUInteger index = [self modelIndexForTabView:tabView]; int index = [self webStateListIndexForTabView:tabView];
DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); DCHECK_NE(WebStateList::kInvalidIndex, index);
if (index == NSNotFound) if (index == WebStateList::kInvalidIndex)
return; return;
if (IsIPadIdiom() && if (IsIPadIdiom() &&
(_tabModel.webStateList->active_index() != static_cast<int>(index))) { (_webStateList->active_index() != static_cast<int>(index))) {
SnapshotTabHelper::FromWebState(_tabModel.webStateList->GetActiveWebState()) SnapshotTabHelper::FromWebState(_webStateList->GetActiveWebState())
->UpdateSnapshotWithCallback(nil); ->UpdateSnapshotWithCallback(nil);
} }
_tabModel.webStateList->ActivateWebStateAt(static_cast<int>(index)); _webStateList->ActivateWebStateAt(static_cast<int>(index));
[self updateContentOffsetForWebStateIndex:index isNewWebState:NO]; [self updateContentOffsetForWebStateIndex:index isNewWebState:NO];
} }
...@@ -1801,17 +1797,18 @@ UIColor* BackgroundColor() { ...@@ -1801,17 +1797,18 @@ UIColor* BackgroundColor() {
return; return;
base::RecordAction(UserMetricsAction("MobileTabStripCloseTab")); base::RecordAction(UserMetricsAction("MobileTabStripCloseTab"));
NSUInteger modelIndex = [self modelIndexForTabView:tabView]; int webStateListIndex = [self webStateListIndexForTabView:tabView];
if (modelIndex != NSNotFound) if (webStateListIndex != WebStateList::kInvalidIndex)
[_tabModel closeTabAtIndex:modelIndex]; _webStateList->CloseWebStateAt(webStateListIndex,
WebStateList::CLOSE_USER_ACTION);
} }
- (void)tabView:(TabView*)tabView receivedDroppedURL:(GURL)url { - (void)tabView:(TabView*)tabView receivedDroppedURL:(GURL)url {
NSUInteger index = [self modelIndexForTabView:tabView]; int index = [self webStateListIndexForTabView:tabView];
DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); DCHECK_NE(WebStateList::kInvalidIndex, index);
if (index == NSNotFound) if (index == WebStateList::kInvalidIndex)
return; return;
web::WebState* webState = _tabModel.webStateList->GetWebStateAt(index); web::WebState* webState = _webStateList->GetWebStateAt(index);
web::NavigationManager::WebLoadParams params(url); web::NavigationManager::WebLoadParams params(url);
params.transition_type = ui::PAGE_TRANSITION_GENERATED; params.transition_type = ui::PAGE_TRANSITION_GENERATED;
...@@ -1840,7 +1837,7 @@ UIColor* BackgroundColor() { ...@@ -1840,7 +1837,7 @@ UIColor* BackgroundColor() {
_useTabStacking = useTabStacking; _useTabStacking = useTabStacking;
[self updateScrollViewFrameForTabSwitcherButton]; [self updateScrollViewFrameForTabSwitcherButton];
[self updateContentSizeAndRepositionViews]; [self updateContentSizeAndRepositionViews];
int selectedModelIndex = _tabModel.webStateList->active_index(); int selectedModelIndex = _webStateList->active_index();
if (selectedModelIndex != WebStateList::kInvalidIndex) { if (selectedModelIndex != WebStateList::kInvalidIndex) {
[self updateContentOffsetForWebStateIndex:selectedModelIndex [self updateContentOffsetForWebStateIndex:selectedModelIndex
isNewWebState:NO]; isNewWebState:NO];
......
...@@ -6,15 +6,16 @@ ...@@ -6,15 +6,16 @@
#include <memory> #include <memory>
#include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/main/test_browser.h"
#import "ios/chrome/browser/sessions/test_session_service.h" #import "ios/chrome/browser/sessions/test_session_service.h"
#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/popup_menu_commands.h"
#import "ios/chrome/browser/ui/tabs/tab_strip_controller.h" #import "ios/chrome/browser/ui/tabs/tab_strip_controller.h"
#import "ios/chrome/browser/ui/tabs/tab_strip_view.h" #import "ios/chrome/browser/ui/tabs/tab_strip_view.h"
#import "ios/chrome/browser/ui/tabs/tab_view.h" #import "ios/chrome/browser/ui/tabs/tab_view.h"
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/navigation/navigation_item.h"
...@@ -31,65 +32,6 @@ ...@@ -31,65 +32,6 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
@interface TabStripControllerTestTabModel : NSObject
@property(nonatomic, assign) ChromeBrowserState* browserState;
@end
@implementation TabStripControllerTestTabModel {
FakeWebStateListDelegate _webStateListDelegate;
std::unique_ptr<WebStateList> _webStateList;
std::unique_ptr<web::NavigationItem> _visibleNavigationItem;
}
@synthesize browserState = _browserState;
- (instancetype)init {
if ((self = [super init])) {
_webStateList = std::make_unique<WebStateList>(&_webStateListDelegate);
_visibleNavigationItem = web::NavigationItem::Create();
}
return self;
}
- (void)browserStateDestroyed {
_webStateList->CloseAllWebStates(WebStateList::CLOSE_NO_FLAGS);
_browserState = nullptr;
}
- (void)addWebStateForTestingWithTitle:(NSString*)title {
auto testWebState = std::make_unique<web::TestWebState>();
testWebState->SetTitle(base::SysNSStringToUTF16(title));
auto testNavigationManager = std::make_unique<web::TestNavigationManager>();
testNavigationManager->SetVisibleItem(_visibleNavigationItem.get());
testWebState->SetNavigationManager(std::move(testNavigationManager));
_webStateList->InsertWebState(0, std::move(testWebState),
WebStateList::INSERT_NO_FLAGS,
WebStateOpener());
}
- (BOOL)isEmpty {
return _webStateList->empty();
}
- (NSUInteger)count {
return static_cast<NSUInteger>(_webStateList->count());
}
- (void)closeTabAtIndex:(NSUInteger)index {
DCHECK(index < static_cast<NSUInteger>(INT_MAX));
DCHECK(static_cast<int>(index) < _webStateList->count());
_webStateList->CloseWebStateAt(static_cast<int>(index),
WebStateList::CLOSE_NO_FLAGS);
}
- (WebStateList*)webStateList {
return _webStateList.get();
}
@end
namespace { namespace {
class TabStripControllerTest : public PlatformTest { class TabStripControllerTest : public PlatformTest {
...@@ -98,40 +40,52 @@ class TabStripControllerTest : public PlatformTest { ...@@ -98,40 +40,52 @@ class TabStripControllerTest : public PlatformTest {
if (!IsIPadIdiom()) if (!IsIPadIdiom())
return; return;
// Need a ChromeBrowserState for the tab model. visible_navigation_item_ = web::NavigationItem::Create();
TestChromeBrowserState::Builder test_cbs_builder; mock_application_commands_handler_ =
chrome_browser_state_ = test_cbs_builder.Build(); OCMStrictProtocolMock(@protocol(ApplicationCommands));
mock_popup_menu_commands_handler_ =
// Setup mock TabModel. OCMStrictProtocolMock(@protocol(PopupMenuCommands));
tab_model_ = [[TabStripControllerTestTabModel alloc] init]; mock_application_settings_commands_handler_ =
tab_model_.browserState = chrome_browser_state_.get(); OCMStrictProtocolMock(@protocol(ApplicationSettingsCommands));
// Populate the TabModel. [browser_.GetCommandDispatcher()
[tab_model_ addWebStateForTestingWithTitle:@"Tab Title 1"]; startDispatchingToTarget:mock_application_commands_handler_
[tab_model_ addWebStateForTestingWithTitle:@"Tab Title 2"]; forProtocol:@protocol(ApplicationCommands)];
[browser_.GetCommandDispatcher()
controller_ = [[TabStripController alloc] startDispatchingToTarget:mock_application_settings_commands_handler_
initWithTabModel:static_cast<TabModel*>(tab_model_) forProtocol:@protocol(ApplicationSettingsCommands)];
style:NORMAL [browser_.GetCommandDispatcher()
dispatcher:nil]; startDispatchingToTarget:mock_popup_menu_commands_handler_
forProtocol:@protocol(PopupMenuCommands)];
// Force the view to load.
UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectZero]; controller_ = [[TabStripController alloc] initWithBrowser:&browser_
[window addSubview:[controller_ view]]; style:NORMAL];
window_ = window;
} }
void TearDown() override { void TearDown() override {
if (!IsIPadIdiom()) if (!IsIPadIdiom())
return; return;
[tab_model_ browserStateDestroyed];
[controller_ disconnect]; [controller_ disconnect];
} }
void AddWebStateForTesting(std::string title) {
auto test_web_state = std::make_unique<web::TestWebState>();
test_web_state->SetTitle(base::UTF8ToUTF16(title));
auto test_navigation_manager =
std::make_unique<web::TestNavigationManager>();
test_navigation_manager->SetVisibleItem(visible_navigation_item_.get());
test_web_state->SetNavigationManager(std::move(test_navigation_manager));
browser_.GetWebStateList()->InsertWebState(
/*index=*/0, std::move(test_web_state), WebStateList::INSERT_NO_FLAGS,
WebStateOpener());
}
web::WebTaskEnvironment task_environment_; web::WebTaskEnvironment task_environment_;
std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<web::NavigationItem> visible_navigation_item_;
TabStripControllerTestTabModel* tab_model_; TestBrowser browser_;
id mock_application_commands_handler_;
id mock_popup_menu_commands_handler_;
id mock_application_settings_commands_handler_;
TabStripController* controller_; TabStripController* controller_;
UIWindow* window_; UIWindow* window_;
}; };
...@@ -139,6 +93,12 @@ class TabStripControllerTest : public PlatformTest { ...@@ -139,6 +93,12 @@ class TabStripControllerTest : public PlatformTest {
TEST_F(TabStripControllerTest, LoadAndDisplay) { TEST_F(TabStripControllerTest, LoadAndDisplay) {
if (!IsIPadIdiom()) if (!IsIPadIdiom())
return; return;
AddWebStateForTesting("Tab Title 1");
AddWebStateForTesting("Tab Title 2");
// Force the view to load.
UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectZero];
[window addSubview:[controller_ view]];
window_ = window;
// There should be two TabViews and one new tab button nested within the // There should be two TabViews and one new tab button nested within the
// parent view (which contains exactly one scroll view). // parent view (which contains exactly one scroll view).
......
...@@ -10,29 +10,25 @@ ...@@ -10,29 +10,25 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
#import "ios/chrome/browser/ui/tabs/requirements/tab_strip_highlighting.h" #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_highlighting.h"
@protocol ApplicationCommands;
@protocol BrowserCommands;
class ChromeBrowserState;
@protocol PopupMenuLongPressDelegate; @protocol PopupMenuLongPressDelegate;
@class TabModel;
@protocol TabStripPresentation; @protocol TabStripPresentation;
// A legacy coordinator that presents the public interface for the tablet tab // A legacy coordinator that presents the public interface for the tablet tab
// strip feature. // strip feature.
@interface TabStripLegacyCoordinator : ChromeCoordinator<TabStripHighlighting> @interface TabStripLegacyCoordinator : ChromeCoordinator<TabStripHighlighting>
// BrowserState for this coordinator. // Use Browser based init. -initWithBaseViewController:browser:
@property(nonatomic, assign) ChromeBrowserState* browserState; - (instancetype)initWithBaseViewController:(UIViewController*)viewController
NS_UNAVAILABLE;
// Dispatcher for sending commands. // Use Browser based init. -initWithBaseViewController:browser:
@property(nonatomic, weak) id dispatcher; - (instancetype)initWithBaseViewController:(UIViewController*)viewController
browserState:(ChromeBrowserState*)browserState
NS_UNAVAILABLE;
// Delegate for the long press gesture recognizer triggering popup menu. // Delegate for the long press gesture recognizer triggering popup menu.
@property(nonatomic, weak) id<PopupMenuLongPressDelegate> longPressDelegate; @property(nonatomic, weak) id<PopupMenuLongPressDelegate> longPressDelegate;
// Model layer for the tab strip.
@property(nonatomic, weak) TabModel* tabModel;
// Provides methods for presenting the tab strip and checking the visibility // Provides methods for presenting the tab strip and checking the visibility
// of the tab strip in the containing object. // of the tab strip in the containing object.
@property(nonatomic, assign) id<TabStripPresentation> presentationProvider; @property(nonatomic, assign) id<TabStripPresentation> presentationProvider;
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
#import "ios/chrome/browser/ui/tabs/tab_strip_legacy_coordinator.h" #import "ios/chrome/browser/ui/tabs/tab_strip_legacy_coordinator.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/ui/tabs/requirements/tab_strip_presentation.h" #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_presentation.h"
#import "ios/chrome/browser/ui/tabs/tab_strip_controller.h" #import "ios/chrome/browser/ui/tabs/tab_strip_controller.h"
...@@ -18,25 +18,12 @@ ...@@ -18,25 +18,12 @@
@end @end
@implementation TabStripLegacyCoordinator @implementation TabStripLegacyCoordinator
@synthesize browserState = _browserState;
@synthesize dispatcher = _dispatcher;
@synthesize longPressDelegate = _longPressDelegate; @synthesize longPressDelegate = _longPressDelegate;
@synthesize tabModel = _tabModel;
@synthesize presentationProvider = _presentationProvider; @synthesize presentationProvider = _presentationProvider;
@synthesize started = _started; @synthesize started = _started;
@synthesize tabStripController = _tabStripController; @synthesize tabStripController = _tabStripController;
@synthesize animationWaitDuration = _animationWaitDuration; @synthesize animationWaitDuration = _animationWaitDuration;
- (void)setDispatcher:(id<BrowserCommands, ApplicationCommands>)dispatcher {
DCHECK(!self.started);
_dispatcher = dispatcher;
}
- (void)setTabModel:(TabModel*)tabModel {
DCHECK(!self.started);
_tabModel = tabModel;
}
- (void)setLongPressDelegate:(id<PopupMenuLongPressDelegate>)longPressDelegate { - (void)setLongPressDelegate:(id<PopupMenuLongPressDelegate>)longPressDelegate {
_longPressDelegate = longPressDelegate; _longPressDelegate = longPressDelegate;
self.tabStripController.longPressDelegate = longPressDelegate; self.tabStripController.longPressDelegate = longPressDelegate;
...@@ -69,16 +56,12 @@ ...@@ -69,16 +56,12 @@
#pragma mark - ChromeCoordinator #pragma mark - ChromeCoordinator
- (void)start { - (void)start {
DCHECK(self.browserState); DCHECK(self.browser);
DCHECK(self.tabModel);
DCHECK(self.dispatcher);
DCHECK(self.presentationProvider); DCHECK(self.presentationProvider);
TabStripStyle style = TabStripStyle style =
self.browserState->IsOffTheRecord() ? INCOGNITO : NORMAL; self.browser->GetBrowserState()->IsOffTheRecord() ? INCOGNITO : NORMAL;
self.tabStripController = self.tabStripController =
[[TabStripController alloc] initWithTabModel:self.tabModel [[TabStripController alloc] initWithBrowser:self.browser style:style];
style:style
dispatcher:self.dispatcher];
self.tabStripController.presentationProvider = self.presentationProvider; self.tabStripController.presentationProvider = self.presentationProvider;
self.tabStripController.animationWaitDuration = self.animationWaitDuration; self.tabStripController.animationWaitDuration = self.animationWaitDuration;
self.tabStripController.longPressDelegate = self.longPressDelegate; self.tabStripController.longPressDelegate = self.longPressDelegate;
...@@ -90,8 +73,6 @@ ...@@ -90,8 +73,6 @@
self.started = NO; self.started = NO;
[self.tabStripController disconnect]; [self.tabStripController disconnect];
self.tabStripController = nil; self.tabStripController = nil;
self.dispatcher = nil;
self.tabModel = nil;
self.presentationProvider = nil; self.presentationProvider = nil;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment