chromium/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.mm

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.h"

#import "base/apple/foundation_util.h"
#import "base/metrics/histogram_macros.h"
#import "base/metrics/user_metrics.h"
#import "base/strings/sys_string_conversions.h"
#import "components/autofill/core/browser/filling_product.h"
#import "components/autofill/core/common/autofill_features.h"
#import "ios/chrome/browser/autofill/model/form_suggestion_client.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/autofill/ui_bundled/branding/branding_view_controller.h"
#import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller_delegate.h"
#import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_view.h"
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_accessory_view_controller.h"
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_accessory_view_controller_delegate.h"
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.h"
#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
#import "ios/chrome/common/ui/elements/form_input_accessory_view.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/device_form_factor.h"
#import "ui/base/l10n/l10n_util.h"

using autofill::FillingProduct;
using manual_fill::ManualFillDataType;

namespace {

// Logs the right metrics when the manual fallback menu is opened from the
// keyboard accessory's expand icon.
void LogManualFallbackEntryThroughExpandIcon(ManualFillDataType data_type,
                                             NSInteger suggestion_count) {
  switch (data_type) {
    case ManualFillDataType::kPassword:
      base::RecordAction(
          base::UserMetricsAction("ManualFallback_ExpandIcon_OpenPassword"));
      UMA_HISTOGRAM_COUNTS_100(
          "ManualFallback.VisibleSuggestions.ExpandIcon.OpenPasswords",
          suggestion_count);
      break;
    case ManualFillDataType::kPaymentMethod:
      base::RecordAction(base::UserMetricsAction(
          "ManualFallback_ExpandIcon_OpenPaymentMethod"));
      UMA_HISTOGRAM_COUNTS_100(
          "ManualFallback.VisibleSuggestions.ExpandIcon.OpenPaymentMethods",
          suggestion_count);
      break;
    case ManualFillDataType::kAddress:
      base::RecordAction(
          base::UserMetricsAction("ManualFallback_ExpandIcon_OpenAddress"));
      UMA_HISTOGRAM_COUNTS_100(
          "ManualFallback.VisibleSuggestions.ExpandIcon.OpenAddresses",
          suggestion_count);
      break;
    case manual_fill::ManualFillDataType::kOther:
      // The expand icon should only be available if the mapped `data_type` is
      // either associated with passwords, payment methods or addresses.
      NOTREACHED_NORETURN();
  }
}

}  // namespace

@interface FormInputAccessoryViewController () <
    FormSuggestionViewDelegate,
    ManualFillAccessoryViewControllerDelegate>

// The leading view that contains the branding and form suggestions.
@property(nonatomic, strong) UIStackView* leadingView;

// A BOOL value indicating whether any form accessory is visible. If YES, at
// lease one form accessory is visible.
@property(nonatomic, readonly, getter=isFormAccessoryVisible)
    BOOL formAccessoryVisible;

// The custom view that should be shown in the input accessory view.
@property(nonatomic, strong) FormInputAccessoryView* formInputAccessoryView;

// The view with the suggestions in FormInputAccessoryView.
@property(nonatomic, strong) FormSuggestionView* formSuggestionView;

// The manual fill accessory view controller to add at the end of the
// suggestions.
@property(nonatomic, strong, readonly)
    ManualFillAccessoryViewController* manualFillAccessoryViewController;

// Delegate to handle interactions with the manual fill buttons.
@property(nonatomic, readonly, weak)
    id<FormInputAccessoryViewControllerDelegate>
        formInputAccessoryViewControllerDelegate;

// The ID of the field that was last announced by VoiceOver.
@property(nonatomic, assign) autofill::FieldRendererId lastAnnouncedFieldId;

// Whether to show the scroll hint.
@property(nonatomic, assign) BOOL showScrollHint;

// UI tap recognizer used to dismiss bubble presenter.
@property(nonatomic, strong)
    UITapGestureRecognizer* formInputAccessoryTapRecognizer;

@end

@implementation FormInputAccessoryViewController {
  // Is the preferred omnibox position at the bottom.
  BOOL _isBottomOmnibox;

  // Whether the keyboard was closed before the keyboard accessory appeared.
  BOOL _keyboardWasClosed;
}

@synthesize addressButtonHidden = _addressButtonHidden;
@synthesize creditCardButtonHidden = _creditCardButtonHidden;
@synthesize formInputNextButtonEnabled = _formInputNextButtonEnabled;
@synthesize formInputPreviousButtonEnabled = _formInputPreviousButtonEnabled;
@synthesize navigationDelegate = _navigationDelegate;
@synthesize passwordButtonHidden = _passwordButtonHidden;
@synthesize mainFillingProduct = _mainFillingProduct;
@synthesize currentFieldId = _currentFieldId;

#pragma mark - Life Cycle

- (instancetype)initWithFormInputAccessoryViewControllerDelegate:
    (id<FormInputAccessoryViewControllerDelegate>)
        formInputAccessoryViewControllerDelegate {
  self = [super init];
  if (self) {
    _formInputAccessoryViewControllerDelegate =
        formInputAccessoryViewControllerDelegate;
    _manualFillAccessoryViewController =
        [[ManualFillAccessoryViewController alloc] initWithDelegate:self];
    [self addChildViewController:_manualFillAccessoryViewController];
    // TODO(crbug.com/326398845): Completely remove the
    // `_manualFillAccessoryViewController` property (and its class) once the
    // Keyboard Accessory Upgrade feature has launched both on iPhone and iPad.
    _manualFillAccessoryViewController.view.hidden =
        IsKeyboardAccessoryUpgradeEnabled();
    _keyboardWasClosed = YES;
  }
  return self;
}

- (void)loadView {
  [self createFormInputAccessoryViewIfNeeded];

  self.view = self.formInputAccessoryView;

  if (IsBottomOmniboxAvailable()) {
    [self updateOmniboxTypingShieldVisibility];
  }
}

- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
  [super traitCollectionDidChange:previousTraitCollection];
  if (IsBottomOmniboxAvailable()) {
    [self updateOmniboxTypingShieldVisibility];
  }
}

#pragma mark - UIViewController

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];

  // `showScrollHint` will be set to YES only when `viewDidAppear` is called
  // from a state where the keyboard was previously closed, otherwise it will be
  // set to NO. `viewDidAppear` is called when they keyboard accessory remains
  // open after a user switches between fields on a form, but `viewDidDisappear`
  // is not, so `showScrollHint` will not be set to YES in that scenario.
  self.showScrollHint = _keyboardWasClosed;
  _keyboardWasClosed = NO;
}

- (void)viewDidDisappear:(BOOL)animated {
  [super viewDidDisappear:animated];

  // Exit the manual fill view, so that the next time the keyboard opens, it is
  // showing the keyboard and not the manual fill view.
  if (IsKeyboardAccessoryUpgradeEnabled()) {
    // Reset the delegate.
    [self.formInputAccessoryViewControllerDelegate
        formInputAccessoryViewControllerReset:self];
  }

  // Whether the keyboard was closed the next time the keyboard accessory opens.
  _keyboardWasClosed = YES;
}

#pragma mark - Public

- (void)lockManualFallbackView {
  [self.formSuggestionView lockTrailingView];
}

- (void)reset {
  [self resetAnimated:YES];
}

#pragma mark - FormInputAccessoryConsumer

- (void)showAccessorySuggestions:(NSArray<FormSuggestion*>*)suggestions {
  BOOL hasSingleManualFillButton =
      suggestions.count > 0 &&
      (_mainFillingProduct != FillingProduct::kAutocomplete);
  self.formInputAccessoryView.manualFillButton.hidden =
      !hasSingleManualFillButton;
  self.formInputAccessoryView.passwordManualFillButton.hidden =
      hasSingleManualFillButton;
  self.formInputAccessoryView.creditCardManualFillButton.hidden =
      hasSingleManualFillButton;
  self.formInputAccessoryView.addressManualFillButton.hidden =
      hasSingleManualFillButton;

  [self createFormSuggestionViewIfNeeded];
  __weak __typeof(self) weakSelf = self;
  auto completion = ^(BOOL finished) {
    // Disable the scroll hint once it's been shown once.
    if (finished) {
      weakSelf.showScrollHint = NO;
    }
  };
  [self.formInputAccessoryView layoutIfNeeded];
  [self.formSuggestionView
          updateSuggestions:suggestions
             showScrollHint:self.showScrollHint
      accessoryTrailingView:self.formInputAccessoryView.trailingView
                 completion:completion];
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;
  [self announceVoiceOverMessageIfNeeded:[suggestions count]];
}

- (void)manualFillButtonPressed:(UIButton*)button {
  ManualFillDataType dataType =
      [ManualFillUtil manualFillDataTypeFromFillingProduct:_mainFillingProduct];
  LogManualFallbackEntryThroughExpandIcon(
      dataType, self.formSuggestionView.suggestions.count);
  [self manualFillButtonPressed:button forDataType:dataType];
}

- (void)passwordManualFillButtonPressed:(UIButton*)button {
  base::RecordAction(base::UserMetricsAction("ManualFallback_OpenPassword"));
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenPasswords",
                           self.formSuggestionView.suggestions.count);
  [self manualFillButtonPressed:button
                    forDataType:ManualFillDataType::kPassword];
}

- (void)creditCardManualFillButtonPressed:(UIButton*)button {
  base::RecordAction(base::UserMetricsAction("ManualFallback_OpenCreditCard"));
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenCreditCards",
                           self.formSuggestionView.suggestions.count);
  [self manualFillButtonPressed:button
                    forDataType:ManualFillDataType::kPaymentMethod];
}

- (void)addressManualFillButtonPressed:(UIButton*)button {
  base::RecordAction(base::UserMetricsAction("ManualFallback_OpenProfile"));
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenProfiles",
                           self.formSuggestionView.suggestions.count);
  [self manualFillButtonPressed:button
                    forDataType:ManualFillDataType::kAddress];
}

- (void)newOmniboxPositionIsBottom:(BOOL)isBottomOmnibox {
  _isBottomOmnibox = isBottomOmnibox;
  [self updateOmniboxTypingShieldVisibility];
}

- (void)keyboardHeightChanged:(CGFloat)newHeight oldHeight:(CGFloat)oldHeight {
  if (newHeight < oldHeight) {
    // Add a quick animation to move the keyboard accessory view, which will
    // prevent it from moving if this is a quick flicker of the keyboard.
    [self verticalOffset:newHeight - oldHeight];
    [UIView animateWithDuration:0.1
                          delay:0.1
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                       [self verticalOffset:0];
                     }
                     completion:nil];
  } else if (newHeight > oldHeight) {
    // If the height is increasing, whether or not this was a flicker, we can
    // cancel the animations and offset to immediately return to the default
    // state.
    [self.formInputAccessoryView.layer removeAllAnimations];
    [self verticalOffset:0];
  }
}

#pragma mark - Getter

- (BOOL)isFormAccessoryVisible {
  return !(self.manualFillAccessoryViewController.allButtonsHidden &&
           self.formSuggestionView.suggestions.count == 0);
}

#pragma mark - Setters

- (void)setPasswordButtonHidden:(BOOL)passwordButtonHidden {
  _passwordButtonHidden = passwordButtonHidden;
  self.manualFillAccessoryViewController.passwordButtonHidden =
      passwordButtonHidden;
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;
}

- (void)setAddressButtonHidden:(BOOL)addressButtonHidden {
  _addressButtonHidden = addressButtonHidden;
  self.manualFillAccessoryViewController.addressButtonHidden =
      addressButtonHidden;
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;
}

- (void)setCreditCardButtonHidden:(BOOL)creditCardButtonHidden {
  _creditCardButtonHidden = creditCardButtonHidden;
  self.manualFillAccessoryViewController.creditCardButtonHidden =
      creditCardButtonHidden;
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;
}

- (void)setFormInputNextButtonEnabled:(BOOL)formInputNextButtonEnabled {
  if (formInputNextButtonEnabled == _formInputNextButtonEnabled) {
    return;
  }
  _formInputNextButtonEnabled = formInputNextButtonEnabled;
  self.formInputAccessoryView.nextButton.enabled = _formInputNextButtonEnabled;
}

- (void)setFormInputPreviousButtonEnabled:(BOOL)formInputPreviousButtonEnabled {
  if (formInputPreviousButtonEnabled == _formInputPreviousButtonEnabled) {
    return;
  }
  _formInputPreviousButtonEnabled = formInputPreviousButtonEnabled;
  self.formInputAccessoryView.previousButton.enabled =
      _formInputPreviousButtonEnabled;
}

#pragma mark - Actions

- (void)tapInsideRecognized:(id)sender {
  [self.formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
          didTapFormInputAccessoryView:self.formInputAccessoryView];
}

#pragma mark - Private

// Invoked after the user taps any of the `manual fill` buttons.
- (void)manualFillButtonPressed:(UIButton*)button
                    forDataType:(manual_fill::ManualFillDataType)dataType {
  DCHECK(IsKeyboardAccessoryUpgradeEnabled());

  self.formInputAccessoryView.hidden = YES;

  [_formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
              didPressManualFillButton:button
                           forDataType:dataType];
}

// Resets this view to its original state. Can be animated.
- (void)resetAnimated:(BOOL)animated {
  self.formInputAccessoryView.hidden = NO;

  [self.formSuggestionView resetContentInsetAndDelegateAnimated:animated];
  [self.manualFillAccessoryViewController resetAnimated:animated];
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;
}

// Creates formInputAccessoryView if not done yet.
- (void)createFormInputAccessoryViewIfNeeded {
  if (self.formInputAccessoryView) {
    return;
  }

  [self createFormSuggestionViewIfNeeded];

  FormInputAccessoryView* formInputAccessoryView =
      [[FormInputAccessoryView alloc] init];

  // Sets up leading view.
  self.leadingView = [[UIStackView alloc] init];
  self.leadingView.axis = UILayoutConstraintAxisHorizontal;

  [self addChildViewController:self.brandingViewController];
  [self.leadingView addArrangedSubview:self.brandingViewController.view];
  [self.brandingViewController didMoveToParentViewController:self];

  [self.leadingView addArrangedSubview:self.formSuggestionView];

  if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) {
    [formInputAccessoryView
        setUpWithLeadingView:self.leadingView
          customTrailingView:self.manualFillAccessoryViewController.view];
  } else {
    formInputAccessoryView.accessibilityViewIsModal = YES;
    if (IsKeyboardAccessoryUpgradeEnabled()) {
      [formInputAccessoryView
                setUpWithLeadingView:self.leadingView
                  navigationDelegate:self.navigationDelegate
                    manualFillSymbol:DefaultSymbolWithPointSize(
                                         kExpandSymbol, kSymbolActionPointSize)
            passwordManualFillSymbol:CustomSymbolWithPointSize(
                                         kPasswordSymbol,
                                         kSymbolActionPointSize)
          creditCardManualFillSymbol:DefaultSymbolWithPointSize(
                                         kCreditCardSymbol,
                                         kSymbolActionPointSize)
             addressManualFillSymbol:CustomSymbolWithPointSize(
                                         kLocationSymbol,
                                         kSymbolActionPointSize)
                   closeButtonSymbol:DefaultSymbolWithPointSize(
                                         kKeyboardDownSymbol,
                                         kSymbolActionPointSize)];
    } else {
      self.formSuggestionView.trailingView =
          self.manualFillAccessoryViewController.view;
      [formInputAccessoryView setUpWithLeadingView:self.leadingView
                                navigationDelegate:self.navigationDelegate];
    }
    formInputAccessoryView.nextButton.enabled = self.formInputNextButtonEnabled;
    formInputAccessoryView.previousButton.enabled =
        self.formInputPreviousButtonEnabled;
  }

  // Update branding view keyboard accessory visibility after
  // `self.manualFillAccessoryViewController` loaded its view, as
  // `self.formAccessoryVisible` depends on the visible state of its view.
  self.brandingViewController.keyboardAccessoryVisible =
      self.formAccessoryVisible;

  // Adds tap recognizer.
  self.formInputAccessoryTapRecognizer = [[UITapGestureRecognizer alloc]
      initWithTarget:self
              action:@selector(tapInsideRecognized:)];
  self.formInputAccessoryTapRecognizer.cancelsTouchesInView = NO;
  [formInputAccessoryView
      addGestureRecognizer:self.formInputAccessoryTapRecognizer];

  self.formInputAccessoryView = formInputAccessoryView;
}

// Creates formSuggestionView if not done yet.
- (void)createFormSuggestionViewIfNeeded {
  if (!self.formSuggestionView) {
    self.formSuggestionView = [[FormSuggestionView alloc] init];
    self.formSuggestionView.formSuggestionViewDelegate = self;
    self.formSuggestionView.layoutGuideCenter = self.layoutGuideCenter;
    self.formSuggestionView.translatesAutoresizingMaskIntoConstraints = NO;
  }
}

// Sets up and posts the VoiceOver message that announces the presence of
// suggestions above the keyboard. The message should be announced when a new
// field enters edit mode and has suggestions available.
- (void)announceVoiceOverMessageIfNeeded:(int)suggestionCount {
  if (UIAccessibilityIsVoiceOverRunning() && suggestionCount > 0 &&
      self.lastAnnouncedFieldId != _currentFieldId) {
    std::u16string mainFillingProductString;
    switch (_mainFillingProduct) {
      case FillingProduct::kAddress:
      case FillingProduct::kPlusAddresses:
        mainFillingProductString = l10n_util::GetPluralStringFUTF16(
            IDS_IOS_AUTOFILL_ADDRESS_SUGGESTIONS_AVAILABLE_ACCESSIBILITY_ANNOUNCEMENT,
            suggestionCount);
        break;
      case FillingProduct::kPassword:
        mainFillingProductString = l10n_util::GetPluralStringFUTF16(
            IDS_IOS_AUTOFILL_PASSWORD_SUGGESTIONS_AVAILABLE_ACCESSIBILITY_ANNOUNCEMENT,
            suggestionCount);
        break;
      case FillingProduct::kCreditCard:
      case FillingProduct::kIban:
      case FillingProduct::kStandaloneCvc:
        mainFillingProductString = l10n_util::GetPluralStringFUTF16(
            IDS_IOS_AUTOFILL_PAYMENT_METHOD_SUGGESTIONS_AVAILABLE_ACCESSIBILITY_ANNOUNCEMENT,
            suggestionCount);
        break;
      case FillingProduct::kAutocomplete:
        mainFillingProductString = l10n_util::GetPluralStringFUTF16(
            IDS_IOS_AUTOFILL_AUTOCOMPLETE_SUGGESTIONS_AVAILABLE_ACCESSIBILITY_ANNOUNCEMENT,
            suggestionCount);
        break;
      case FillingProduct::kMerchantPromoCode:
      case FillingProduct::kCompose:
      case FillingProduct::kPredictionImprovements:
      case FillingProduct::kNone:
        // `kMerchantPromoCode` and `kCompose` cases are currently not available
        // on iOS. Also, there shouldn't be suggestions of type `kNone`.
        NOTREACHED();
    }

    // VoiceOver message setup with
    // UIAccessibilitySpeechAttributeQueueAnnouncement attribute so it doesn't
    // interrupt another message.
    NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
    [attributes setObject:@YES
                   forKey:UIAccessibilitySpeechAttributeQueueAnnouncement];
    NSMutableAttributedString* suggestionsVoiceOverMessage =
        [[NSMutableAttributedString alloc]
            initWithString:base::SysUTF16ToNSString(mainFillingProductString)
                attributes:attributes];

    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
                                    suggestionsVoiceOverMessage);
  }
  self.lastAnnouncedFieldId = _currentFieldId;
}

- (void)updateOmniboxTypingShieldVisibility {
  if (!self.formInputAccessoryView) {
    return;
  }
  const BOOL shouldShowTypingShield =
      _isBottomOmnibox && IsSplitToolbarMode(self.traitCollection);
  const CGFloat typingShieldHeight =
      shouldShowTypingShield
          ? ToolbarCollapsedHeight(
                self.traitCollection.preferredContentSizeCategory)
          : 0.0;
  [self.formInputAccessoryView setOmniboxTypingShieldHeight:typingShieldHeight];
}

// Moves the main view down by a certain offset (negative offsets move the view
// up).
- (void)verticalOffset:(CGFloat)offset {
  self.formInputAccessoryView.transform =
      CGAffineTransformMakeTranslation(0, offset);
}

#pragma mark - ManualFillAccessoryViewControllerDelegate

- (void)manualFillAccessoryViewController:(ManualFillAccessoryViewController*)
                                              manualFillAccessoryViewController
                   didPressKeyboardButton:(UIButton*)keyboardButton {
  CHECK(!IsKeyboardAccessoryUpgradeEnabled());
  [self.formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
                didPressKeyboardButton:keyboardButton];
}

- (void)manualFillAccessoryViewController:(ManualFillAccessoryViewController*)
                                              manualFillAccessoryViewController
                    didPressAccountButton:(UIButton*)accountButton {
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenProfiles",
                           self.formSuggestionView.suggestions.count);
  [self.formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
                 didPressAccountButton:accountButton];
}

- (void)manualFillAccessoryViewController:(ManualFillAccessoryViewController*)
                                              manualFillAccessoryViewController
                 didPressCreditCardButton:(UIButton*)creditCardButton {
  CHECK(!IsKeyboardAccessoryUpgradeEnabled());
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenCreditCards",
                           self.formSuggestionView.suggestions.count);
  [self.formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
              didPressCreditCardButton:creditCardButton];
}

- (void)manualFillAccessoryViewController:(ManualFillAccessoryViewController*)
                                              manualFillAccessoryViewController
                   didPressPasswordButton:(UIButton*)passwordButton {
  CHECK(!IsKeyboardAccessoryUpgradeEnabled());
  UMA_HISTOGRAM_COUNTS_100("ManualFallback.VisibleSuggestions.OpenPasswords",
                           self.formSuggestionView.suggestions.count);
  [self.formInputAccessoryViewControllerDelegate
      formInputAccessoryViewController:self
                didPressPasswordButton:passwordButton];
}

#pragma mark - FormSuggestionViewDelegate

- (void)formSuggestionView:(FormSuggestionView*)formSuggestionView
       didAcceptSuggestion:(FormSuggestion*)suggestion
                   atIndex:(NSInteger)index {
  [self.formSuggestionClient didSelectSuggestion:suggestion atIndex:index];
}

- (void)formSuggestionViewShouldResetFromPull:
    (FormSuggestionView*)formSuggestionView {
  DCHECK(!IsKeyboardAccessoryUpgradeEnabled());

  base::RecordAction(base::UserMetricsAction("ManualFallback_ClosePull"));
  // The pull gesture has the same effect as when the keyboard button is
  // pressed.
  [self manualFillAccessoryViewController:self.manualFillAccessoryViewController
                   didPressKeyboardButton:nil];
  [self.manualFillAccessoryViewController resetAnimated:YES];
}

@end