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

Unified Diff: ios/chrome/browser/ui/history/tab_history_view_controller.mm

Issue 2693013005: Updated tab history classes to use NavigationItemLists. (Closed)
Patch Set: update DEPS, include url_formatter in BUILD.gn 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/chrome/browser/ui/history/tab_history_view_controller.mm
diff --git a/ios/chrome/browser/ui/history/tab_history_view_controller.mm b/ios/chrome/browser/ui/history/tab_history_view_controller.mm
index 954ea175ae541159381e16051280b8637e80e1e0..5f84835e3722f9a9a0541c0884779ea516126c50 100644
--- a/ios/chrome/browser/ui/history/tab_history_view_controller.mm
+++ b/ios/chrome/browser/ui/history/tab_history_view_controller.mm
@@ -12,7 +12,6 @@
#import "ios/chrome/browser/ui/history/tab_history_cell.h"
#include "ios/chrome/browser/ui/rtl_geometry.h"
#import "ios/third_party/material_components_ios/src/components/Ink/src/MaterialInk.h"
-#import "ios/web/navigation/crw_session_entry.h"
#include "ios/web/public/favicon_status.h"
#include "ios/web/public/navigation_item.h"
#include "ui/gfx/image/image.h"
@@ -27,9 +26,11 @@
// Tools menu is scrollable.
const CGFloat kLastRowVisiblePercentage = 0.6;
// Reuse identifier for cells.
-NSString* cellIdentifier = @"TabHistoryCell";
-NSString* footerIdentifier = @"Footer";
-NSString* headerIdentifier = @"Header";
+NSString* const kCellIdentifier = @"TabHistoryCell";
+NSString* const kFooterIdentifier = @"Footer";
+NSString* const kHeaderIdentifier = @"Header";
+// The collection view's a11y label.
+NSString* const kCollectionViewLabel = @"Tab History";
// Height of rows.
const CGFloat kCellHeight = 48.0;
// Fraction height for partially visible row.
@@ -71,6 +72,36 @@ NS_INLINE CGFloat FooterHeight() {
return 1.0 / [[UIScreen mainScreen] scale];
}
+// Returns a vector of of NavigationItemLists where the NavigationItems in
+// |items| are separated by host.
+NS_INLINE std::vector<web::NavigationItemList> PartitionItemsByHost(
+ const web::NavigationItemList& items) {
+ std::vector<web::NavigationItemList> partitionedItems;
+ // Used to store the previous host when partitioning NavigationItems.
+ std::string previousHost;
+ // The NavigationItemList containing NavigationItems with the same host.
+ web::NavigationItemList itemsWithSameHostname;
+ // Separate the items in |items| by host.
+ for (web::NavigationItem* item : items) {
+ std::string currentHost = item->GetURL().host();
+ if (previousHost.empty())
+ previousHost = currentHost;
+ // TODO: This should use some sort of Top Level Domain matching instead of
+ // explicit host match so that images.googe.com matches shopping.google.com.
+ if (previousHost == currentHost) {
+ itemsWithSameHostname.push_back(item);
+ } else {
+ partitionedItems.push_back(itemsWithSameHostname);
+ itemsWithSameHostname = web::NavigationItemList(1, item);
+ previousHost = currentHost;
+ }
+ }
+ // Add the last list contiaining the same host.
+ if (!itemsWithSameHostname.empty())
+ partitionedItems.push_back(itemsWithSameHostname);
+ return partitionedItems;
+}
+
} // namespace
@interface TabHistoryViewControllerLayout : UICollectionViewLayout
@@ -219,15 +250,50 @@ - (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:
@interface TabHistoryViewController ()<MDCInkTouchControllerDelegate> {
MDCInkTouchController* _inkTouchController;
- NSArray* _partitionedEntries;
- NSArray* _sessionEntries;
+ // A vector of NavigationItemLists where the NavigationItems are separated
+ // by hostname.
+ std::vector<web::NavigationItemList> _partitionedItems;
}
+
+// Returns the NavigationItem corresponding with |indexPath|.
+- (const web::NavigationItem*)itemAtIndexPath:(NSIndexPath*)indexPath;
+
+// Removes all NavigationItem pointers from this class. Tapping a cell that
+// triggers a navigation may delete NavigationItems, so NavigationItem
+// references should be reset to avoid use-after-free errors.
+- (void)clearNavigationItems;
+
@end
@implementation TabHistoryViewController
-- (NSArray*)sessionEntries {
- return _sessionEntries;
+- (instancetype)initWithItems:(const web::NavigationItemList&)items {
+ TabHistoryViewControllerLayout* layout =
+ [[TabHistoryViewControllerLayout alloc] init];
+ if ((self = [super initWithCollectionViewLayout:layout])) {
+ // Populate |_partitionedItems|.
+ _partitionedItems = PartitionItemsByHost(items);
+
+ // Set up the UICollectionView.
+ UICollectionView* collectionView = [self collectionView];
+ collectionView.accessibilityLabel = kCollectionViewLabel;
+ collectionView.backgroundColor = [UIColor whiteColor];
+ [collectionView registerClass:[TabHistoryCell class]
+ forCellWithReuseIdentifier:kCellIdentifier];
+ [collectionView registerClass:[TabHistorySectionHeader class]
+ forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
+ withReuseIdentifier:kHeaderIdentifier];
+ [collectionView registerClass:[TabHistorySectionFooter class]
+ forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
+ withReuseIdentifier:kFooterIdentifier];
+
+ // Set up the ink controller.
+ _inkTouchController =
+ [[MDCInkTouchController alloc] initWithView:collectionView];
+ [_inkTouchController setDelegate:self];
+ [_inkTouchController addInkView];
+ }
+ return self;
}
#pragma mark Public Methods
@@ -236,9 +302,8 @@ - (CGFloat)optimalHeight:(CGFloat)suggestedHeight {
DCHECK(suggestedHeight >= kCellHeight);
CGFloat optimalHeight = 0;
- for (NSArray* sectionArray in _partitionedEntries) {
- NSUInteger sectionItemCount = [sectionArray count];
- for (NSUInteger i = 0; i < sectionItemCount; ++i) {
+ for (web::NavigationItemList& itemsWithSameHost : _partitionedItems) {
+ for (size_t count = 0; count < itemsWithSameHost.size(); ++count) {
CGFloat proposedHeight = optimalHeight + kCellHeight;
if (proposedHeight > suggestedHeight) {
@@ -263,153 +328,67 @@ - (CGFloat)optimalHeight:(CGFloat)suggestedHeight {
return optimalHeight;
}
-- (instancetype)init {
- TabHistoryViewControllerLayout* layout =
- [[TabHistoryViewControllerLayout alloc] init];
-
- return [self initWithCollectionViewLayout:layout];
-}
-
-- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout*)layout {
- self = [super initWithCollectionViewLayout:layout];
- if (self) {
- UICollectionView* collectionView = [self collectionView];
- [collectionView setBackgroundColor:[UIColor whiteColor]];
-
- [collectionView registerClass:[TabHistoryCell class]
- forCellWithReuseIdentifier:cellIdentifier];
-
- [collectionView registerClass:[TabHistorySectionHeader class]
- forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
- withReuseIdentifier:headerIdentifier];
-
- [collectionView registerClass:[TabHistorySectionFooter class]
- forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
- withReuseIdentifier:footerIdentifier];
-
- _inkTouchController =
- [[MDCInkTouchController alloc] initWithView:collectionView];
- [_inkTouchController setDelegate:self];
- [_inkTouchController addInkView];
- }
-
- return self;
-}
-
#pragma mark UICollectionViewDelegate
- (void)collectionView:(UICollectionView*)collectionView
didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
- UICollectionViewCell* cell =
- [collectionView cellForItemAtIndexPath:indexPath];
+ TabHistoryCell* cell = base::mac::ObjCCastStrict<TabHistoryCell>(
+ [collectionView cellForItemAtIndexPath:indexPath]);
[collectionView chromeExecuteCommand:cell];
+ [self clearNavigationItems];
}
#pragma mark UICollectionViewDataSource
-- (CRWSessionEntry*)entryForIndexPath:(NSIndexPath*)indexPath {
- NSInteger section = [indexPath section];
- NSInteger item = [indexPath item];
-
- DCHECK(section < (NSInteger)[_partitionedEntries count]);
- DCHECK(item < (NSInteger)[[_partitionedEntries objectAtIndex:section] count]);
- NSArray* sectionedArray = [_partitionedEntries objectAtIndex:section];
-
- return [sectionedArray objectAtIndex:item];
-}
-
- (NSInteger)collectionView:(UICollectionView*)collectionView
numberOfItemsInSection:(NSInteger)section {
- DCHECK(section < (NSInteger)[_partitionedEntries count]);
- return [[_partitionedEntries objectAtIndex:section] count];
+ size_t sectionIdx = static_cast<size_t>(section);
+ DCHECK_LT(sectionIdx, _partitionedItems.size());
+ return _partitionedItems[sectionIdx].size();
}
- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
cellForItemAtIndexPath:(NSIndexPath*)indexPath {
TabHistoryCell* cell =
- [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier
+ [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier
forIndexPath:indexPath];
-
- [cell setEntry:[self entryForIndexPath:indexPath]];
- [cell setTag:IDC_BACK_FORWARD_IN_TAB_HISTORY];
-
+ cell.item = [self itemAtIndexPath:indexPath];
+ cell.tag = IDC_BACK_FORWARD_IN_TAB_HISTORY;
return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)view {
- return [_partitionedEntries count];
+ return _partitionedItems.size();
}
- (UICollectionReusableView*)collectionView:(UICollectionView*)view
viewForSupplementaryElementOfKind:(NSString*)kind
atIndexPath:(NSIndexPath*)indexPath {
+ // Return a footer cell if requested.
if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
return [view dequeueReusableSupplementaryViewOfKind:kind
- withReuseIdentifier:footerIdentifier
+ withReuseIdentifier:kFooterIdentifier
forIndexPath:indexPath];
}
-
DCHECK([kind isEqualToString:UICollectionElementKindSectionHeader]);
- CRWSessionEntry* sessionEntry = [self entryForIndexPath:indexPath];
- web::NavigationItem* navigationItem = [sessionEntry navigationItem];
+ // Dequeue a header cell and populate its favicon image.
TabHistorySectionHeader* header =
[view dequeueReusableSupplementaryViewOfKind:kind
- withReuseIdentifier:headerIdentifier
+ withReuseIdentifier:kHeaderIdentifier
forIndexPath:indexPath];
-
UIImage* iconImage = nil;
- const gfx::Image& image = navigationItem->GetFavicon().image;
+ const gfx::Image& image =
+ [self itemAtIndexPath:indexPath]->GetFavicon().image;
if (!image.IsEmpty())
iconImage = image.ToUIImage();
else
iconImage = [UIImage imageNamed:@"default_favicon"];
-
[[header iconView] setImage:iconImage];
return header;
}
-- (void)setSessionEntries:(NSArray*)sessionEntries {
- _sessionEntries = sessionEntries;
-
- std::string previousHost;
-
- NSMutableArray* sectionArray = [NSMutableArray array];
- NSMutableArray* partitionedEntries = [NSMutableArray array];
-
- NSInteger numberOfEntries = [_sessionEntries count];
- for (NSInteger index = 0; index < numberOfEntries; ++index) {
- CRWSessionEntry* sessionEntry = [_sessionEntries objectAtIndex:index];
- web::NavigationItem* navigationItem = [sessionEntry navigationItem];
-
- std::string currentHost;
- if (navigationItem)
- currentHost = navigationItem->GetURL().host();
-
- if (previousHost.empty())
- previousHost = currentHost;
-
- // TODO: This should use some sort of Top Level Domain matching instead of
- // explicit host match so that images.googe.com matches shopping.google.com.
- if (previousHost == currentHost) {
- [sectionArray addObject:sessionEntry];
- } else {
- [partitionedEntries addObject:sectionArray];
- sectionArray = [NSMutableArray arrayWithObject:sessionEntry];
- previousHost = currentHost;
- }
- }
-
- if ([sectionArray count])
- [partitionedEntries addObject:sectionArray];
-
- if (![partitionedEntries count])
- partitionedEntries = nil;
-
- _partitionedEntries = partitionedEntries;
-}
-
#pragma mark MDCInkTouchControllerDelegate
- (BOOL)inkTouchController:(MDCInkTouchController*)inkTouchController
@@ -431,4 +410,22 @@ - (BOOL)inkTouchController:(MDCInkTouchController*)inkTouchController
return YES;
}
+#pragma mark -
+
+- (const web::NavigationItem*)itemAtIndexPath:(NSIndexPath*)indexPath {
+ size_t section = static_cast<size_t>([indexPath section]);
+ size_t item = static_cast<size_t>([indexPath item]);
+ DCHECK_LT(section, _partitionedItems.size());
+ DCHECK_LT(item, _partitionedItems[section].size());
+ return _partitionedItems[section][item];
+}
+
+- (void)clearNavigationItems {
+ _partitionedItems.clear();
+ for (UICollectionViewCell* cell in self.collectionView.visibleCells) {
+ TabHistoryCell* historyCell = base::mac::ObjCCast<TabHistoryCell>(cell);
+ historyCell.item = nullptr;
+ }
+}
+
@end
« no previous file with comments | « ios/chrome/browser/ui/history/tab_history_view_controller.h ('k') | ios/chrome/browser/ui/toolbar/web_toolbar_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698