[ios] Adds custom accessibility actions to HistoryEntryItem

- Migrates the code from LegacyHistoryCollectionVC and LegacyHistoryEntryItem into
HistoryTableVC and HistoryEntryItem to add support for custom accessibility actions.

Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I73d9a35a31822e98fb09d5828f7eee37211d06d5
Reviewed-on: https://chromium-review.googlesource.com/1125328
Reviewed-by: edchin <edchin@chromium.org>
Commit-Queue: Sergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576174}
diff --git a/ios/chrome/browser/ui/history/history_entry_item.h b/ios/chrome/browser/ui/history/history_entry_item.h
index 3cef1f0f..131b021 100644
--- a/ios/chrome/browser/ui/history/history_entry_item.h
+++ b/ios/chrome/browser/ui/history/history_entry_item.h
@@ -8,10 +8,19 @@
 #import "ios/chrome/browser/ui/history/history_entry_item_interface.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
 
+@protocol HistoryEntryItemDelegate;
+
 // Item that display a History entry. A history entry contains the title of the
 // website, the URL and a timestamp of a previously visited website.
 @interface HistoryEntryItem : TableViewItem<HistoryEntryItemInterface>
 
+// The |delegate| is used to perform accessibility actions, it might be nil and
+// it will not be retained.
+- (instancetype)initWithType:(NSInteger)type
+       accessibilityDelegate:(id<HistoryEntryItemDelegate>)delegate
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithType:(NSInteger)type NS_UNAVAILABLE;
+
 // Identifier to match a URLItem with its URLCell. Uses URL.host() as "unique"
 // identifier. Ensures that cell still is displaying item's contents before
 // setting favicon in async callback. Even if there is a case of cells with the
diff --git a/ios/chrome/browser/ui/history/history_entry_item.mm b/ios/chrome/browser/ui/history/history_entry_item.mm
index 4357bf5a..866d847 100644
--- a/ios/chrome/browser/ui/history/history_entry_item.mm
+++ b/ios/chrome/browser/ui/history/history_entry_item.mm
@@ -7,8 +7,12 @@
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/history/core/browser/browsing_history_service.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/history/history_entry_item_delegate.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -16,17 +20,28 @@
 
 #pragma mark - HistoryEntryItem
 
+@interface HistoryEntryItem ()
+// Delegate to perform custom accessibility actions.
+@property(nonatomic, weak) id<HistoryEntryItemDelegate> accessibilityDelegate;
+
+// Custom accessibility actions for the history entry cell.
+- (NSArray*)accessibilityActions;
+@end
+
 @implementation HistoryEntryItem
+@synthesize accessibilityDelegate = _accessibilityDelegate;
 @synthesize text = _text;
 @synthesize detailText = _detailText;
 @synthesize timeText = _timeText;
 @synthesize URL = _URL;
 @synthesize timestamp = _timestamp;
 
-- (instancetype)initWithType:(NSInteger)type {
+- (instancetype)initWithType:(NSInteger)type
+       accessibilityDelegate:(id<HistoryEntryItemDelegate>)delegate {
   self = [super initWithType:type];
   if (self) {
     self.cellClass = [TableViewURLCell class];
+    _accessibilityDelegate = delegate;
   }
   return self;
 }
@@ -46,13 +61,63 @@
   cell.titleLabel.backgroundColor = styler.tableViewBackgroundColor;
   cell.URLLabel.backgroundColor = styler.tableViewBackgroundColor;
   cell.metadataLabel.backgroundColor = styler.tableViewBackgroundColor;
+  cell.isAccessibilityElement = YES;
+  cell.accessibilityCustomActions = self.accessibilityActions;
 }
 
 - (NSString*)uniqueIdentifier {
   return base::SysUTF8ToNSString(self.URL.host());
 }
 
-#pragma mark NSObject
+#pragma mark - Accessibility
+
+- (NSArray*)accessibilityActions {
+  UIAccessibilityCustomAction* deleteAction =
+      [[UIAccessibilityCustomAction alloc]
+          initWithName:l10n_util::GetNSString(
+                           IDS_HISTORY_ENTRY_ACCESSIBILITY_DELETE)
+                target:self
+              selector:@selector(deleteHistoryEntry)];
+  UIAccessibilityCustomAction* openInNewTabAction =
+      [[UIAccessibilityCustomAction alloc]
+          initWithName:l10n_util::GetNSString(
+                           IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)
+                target:self
+              selector:@selector(openInNewTab)];
+  UIAccessibilityCustomAction* openInNewIncognitoTabAction =
+      [[UIAccessibilityCustomAction alloc]
+          initWithName:l10n_util::GetNSString(
+                           IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)
+                target:self
+              selector:@selector(openInNewIncognitoTab)];
+  UIAccessibilityCustomAction* copyURLAction =
+      [[UIAccessibilityCustomAction alloc]
+          initWithName:l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY)
+                target:self
+              selector:@selector(copyURL)];
+  return @[
+    deleteAction, openInNewTabAction, openInNewIncognitoTabAction, copyURLAction
+  ];
+}
+
+- (void)deleteHistoryEntry {
+  [self.accessibilityDelegate historyEntryItemDidRequestDelete:self];
+}
+
+- (void)openInNewTab {
+  [self.accessibilityDelegate historyEntryItemDidRequestOpenInNewTab:self];
+}
+
+- (void)openInNewIncognitoTab {
+  [self.accessibilityDelegate
+      historyEntryItemDidRequestOpenInNewIncognitoTab:self];
+}
+
+- (void)copyURL {
+  [self.accessibilityDelegate historyEntryItemDidRequestCopy:self];
+}
+
+#pragma mark - NSObject
 
 - (BOOL)isEqualToHistoryEntryItem:(HistoryEntryItem*)item {
   return item && item.URL == _URL && item.timestamp == _timestamp;
diff --git a/ios/chrome/browser/ui/history/history_entry_item_delegate.h b/ios/chrome/browser/ui/history/history_entry_item_delegate.h
index 31774bd..38f274a 100644
--- a/ios/chrome/browser/ui/history/history_entry_item_delegate.h
+++ b/ios/chrome/browser/ui/history/history_entry_item_delegate.h
@@ -5,24 +5,29 @@
 #ifndef IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_ENTRY_ITEM_DELEGATE_H_
 #define IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_ENTRY_ITEM_DELEGATE_H_
 
-@class LegacyHistoryEntryItem;
+@class ListItem;
+@protocol HistoryEntryItemInterface;
 
 // Delegate for HistoryEntryItem. Handles actions invoked as custom
 // accessibility actions.
 @protocol HistoryEntryItemDelegate
 // Called when custom accessibility action to delete the entry is invoked.
-- (void)historyEntryItemDidRequestDelete:(LegacyHistoryEntryItem*)item;
+- (void)historyEntryItemDidRequestDelete:
+    (ListItem<HistoryEntryItemInterface>*)item;
 // Called when custom accessibility action to open the entry in a new tab is
 // invoked.
-- (void)historyEntryItemDidRequestOpenInNewTab:(LegacyHistoryEntryItem*)item;
+- (void)historyEntryItemDidRequestOpenInNewTab:
+    (ListItem<HistoryEntryItemInterface>*)item;
 // Called when custom accessibility action to open the entry in a new incognito
 // tab is invoked.
 - (void)historyEntryItemDidRequestOpenInNewIncognitoTab:
-    (LegacyHistoryEntryItem*)item;
+    (ListItem<HistoryEntryItemInterface>*)item;
 // Called when custom accessibility action to copy the entry's URL is invoked.
-- (void)historyEntryItemDidRequestCopy:(LegacyHistoryEntryItem*)item;
+- (void)historyEntryItemDidRequestCopy:
+    (ListItem<HistoryEntryItemInterface>*)item;
 // Called when the view associated with the HistoryEntryItem should be updated.
-- (void)historyEntryItemShouldUpdateView:(LegacyHistoryEntryItem*)item;
+- (void)historyEntryItemShouldUpdateView:
+    (ListItem<HistoryEntryItemInterface>*)item;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_ENTRY_ITEM_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm
index 54a0cb3..e7f0f78 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -21,6 +21,7 @@
 #import "ios/chrome/browser/ui/history/history_entries_status_item_delegate.h"
 #include "ios/chrome/browser/ui/history/history_entry_inserter.h"
 #import "ios/chrome/browser/ui/history/history_entry_item.h"
+#import "ios/chrome/browser/ui/history/history_entry_item_delegate.h"
 #import "ios/chrome/browser/ui/history/history_image_data_source.h"
 #include "ios/chrome/browser/ui/history/history_local_commands.h"
 #import "ios/chrome/browser/ui/history/history_ui_constants.h"
@@ -65,6 +66,7 @@
 
 @interface HistoryTableViewController ()<HistoryEntriesStatusItemDelegate,
                                          HistoryEntryInserterDelegate,
+                                         HistoryEntryItemDelegate,
                                          TableViewTextLinkCellDelegate,
                                          UISearchResultsUpdating,
                                          UISearchBarDelegate> {
@@ -272,7 +274,8 @@
     DCHECK([[self tableViewModel] numberOfSections]);
     for (const BrowsingHistoryService::HistoryEntry& entry : results) {
       HistoryEntryItem* item =
-          [[HistoryEntryItem alloc] initWithType:ItemTypeHistoryEntry];
+          [[HistoryEntryItem alloc] initWithType:ItemTypeHistoryEntry
+                           accessibilityDelegate:self];
       item.text = [history::FormattedTitle(entry.title, entry.url) copy];
       item.detailText =
           [base::SysUTF8ToNSString(entry.url.GetOrigin().spec()) copy];
@@ -364,8 +367,48 @@
 }
 
 #pragma mark HistoryEntryItemDelegate
-// TODO(crbug.com/805190): Migrate once we decide how to handle favicons and the
-// a11y callback on HistoryEntryItem.
+
+- (void)historyEntryItemDidRequestOpen:(HistoryEntryItem*)item {
+  [self openURL:item.URL];
+}
+
+- (void)historyEntryItemDidRequestDelete:(HistoryEntryItem*)item {
+  NSInteger sectionIdentifier =
+      [self.entryInserter sectionIdentifierForTimestamp:item.timestamp];
+  if ([self.tableViewModel hasSectionForSectionIdentifier:sectionIdentifier] &&
+      [self.tableViewModel hasItem:item
+           inSectionWithIdentifier:sectionIdentifier]) {
+    NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
+    [self.tableView selectRowAtIndexPath:indexPath
+                                animated:NO
+                          scrollPosition:UITableViewScrollPositionNone];
+    [self deleteSelectedItemsFromHistory];
+  }
+}
+
+- (void)historyEntryItemDidRequestCopy:(HistoryEntryItem*)item {
+  StoreURLInPasteboard(item.URL);
+}
+
+- (void)historyEntryItemDidRequestOpenInNewTab:(HistoryEntryItem*)item {
+  [self openURLInNewTab:item.URL];
+}
+
+- (void)historyEntryItemDidRequestOpenInNewIncognitoTab:
+    (HistoryEntryItem*)item {
+  [self openURLInNewIncognitoTab:item.URL];
+}
+
+- (void)historyEntryItemShouldUpdateView:(HistoryEntryItem*)item {
+  NSInteger sectionIdentifier =
+      [self.entryInserter sectionIdentifierForTimestamp:item.timestamp];
+  // If the item is still in the model, reconfigure it.
+  if ([self.tableViewModel hasSectionForSectionIdentifier:sectionIdentifier] &&
+      [self.tableViewModel hasItem:item
+           inSectionWithIdentifier:sectionIdentifier]) {
+    [self reconfigureCellsForItems:@[ item ]];
+  }
+}
 
 #pragma mark TableViewTextLinkCellDelegate