| Index: chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
 | 
| diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
 | 
| index 89925cee23efa839e82e4105a6ff2f6b6bc68806..ad9bd1d676f707874ef91c809544bfbe8ca8efab 100644
 | 
| --- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
 | 
| +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
 | 
| @@ -4,10 +4,14 @@
 | 
|  
 | 
|  #include "chrome/browser/ui/views/autofill/autofill_popup_view_views.h"
 | 
|  
 | 
| +#include "base/optional.h"
 | 
|  #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
 | 
|  #include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
 | 
| +#include "chrome/grit/generated_resources.h"
 | 
|  #include "components/autofill/core/browser/popup_item_ids.h"
 | 
|  #include "components/autofill/core/browser/suggestion.h"
 | 
| +#include "ui/accessibility/ax_node_data.h"
 | 
| +#include "ui/base/l10n/l10n_util.h"
 | 
|  #include "ui/events/keycodes/keyboard_codes.h"
 | 
|  #include "ui/gfx/canvas.h"
 | 
|  #include "ui/gfx/geometry/point.h"
 | 
| @@ -16,30 +20,67 @@
 | 
|  #include "ui/gfx/native_widget_types.h"
 | 
|  #include "ui/gfx/text_utils.h"
 | 
|  #include "ui/views/border.h"
 | 
| +#include "ui/views/view.h"
 | 
|  #include "ui/views/widget/widget.h"
 | 
|  
 | 
|  namespace autofill {
 | 
|  
 | 
| +namespace {
 | 
| +
 | 
| +// Child view only for triggering accessibility events. Rendering is handled
 | 
| +// by |AutofillPopupViewViews|.
 | 
| +class AutofillPopupChildView : public views::View {
 | 
| + public:
 | 
| +  explicit AutofillPopupChildView(const Suggestion& suggestion)
 | 
| +      : suggestion_(suggestion) {
 | 
| +    SetFocusBehavior(FocusBehavior::ALWAYS);
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  ~AutofillPopupChildView() override {}
 | 
| +
 | 
| +  // views::Views implementation
 | 
| +  void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
 | 
| +    node_data->role = ui::AX_ROLE_MENU_ITEM;
 | 
| +    node_data->SetName(suggestion_.value);
 | 
| +  }
 | 
| +
 | 
| +  const Suggestion& suggestion_;
 | 
| +
 | 
| +  DISALLOW_COPY_AND_ASSIGN(AutofillPopupChildView);
 | 
| +};
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
|  AutofillPopupViewViews::AutofillPopupViewViews(
 | 
|      AutofillPopupController* controller,
 | 
|      views::Widget* parent_widget)
 | 
|      : AutofillPopupBaseView(controller, parent_widget),
 | 
| -      controller_(controller) {}
 | 
| +      controller_(controller) {
 | 
| +  CreateChildViews();
 | 
| +  SetFocusBehavior(FocusBehavior::ALWAYS);
 | 
| +}
 | 
|  
 | 
|  AutofillPopupViewViews::~AutofillPopupViewViews() {}
 | 
|  
 | 
|  void AutofillPopupViewViews::Show() {
 | 
|    DoShow();
 | 
| +  NotifyAccessibilityEvent(ui::AX_EVENT_MENU_START, true);
 | 
|  }
 | 
|  
 | 
|  void AutofillPopupViewViews::Hide() {
 | 
|    // The controller is no longer valid after it hides us.
 | 
|    controller_ = NULL;
 | 
| -
 | 
|    DoHide();
 | 
| +  NotifyAccessibilityEvent(ui::AX_EVENT_MENU_END, true);
 | 
|  }
 | 
|  
 | 
| -void AutofillPopupViewViews::UpdateBoundsAndRedrawPopup() {
 | 
| +void AutofillPopupViewViews::OnSuggestionsChanged() {
 | 
| +  // We recreate the child views so we can be sure the |controller_|'s
 | 
| +  // |GetLineCount()| will match the number of child views. Otherwise,
 | 
| +  // the number of suggestions i.e. |GetLineCount()| may not match 1x1 with the
 | 
| +  // child views. See crbug.com/697466.
 | 
| +  CreateChildViews();
 | 
|    DoUpdateBoundsAndRedrawPopup();
 | 
|  }
 | 
|  
 | 
| @@ -51,7 +92,8 @@ void AutofillPopupViewViews::OnPaint(gfx::Canvas* canvas) {
 | 
|        ui::NativeTheme::kColorId_ResultsTableNormalBackground));
 | 
|    OnPaintBorder(canvas);
 | 
|  
 | 
| -  for (size_t i = 0; i < controller_->GetLineCount(); ++i) {
 | 
| +  DCHECK_EQ(controller_->GetLineCount(), child_count());
 | 
| +  for (int i = 0; i < controller_->GetLineCount(); ++i) {
 | 
|      gfx::Rect line_rect = controller_->layout_model().GetRowBounds(i);
 | 
|  
 | 
|      if (controller_->GetSuggestionAt(i).frontend_id ==
 | 
| @@ -66,8 +108,16 @@ void AutofillPopupViewViews::OnPaint(gfx::Canvas* canvas) {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -void AutofillPopupViewViews::InvalidateRow(size_t row) {
 | 
| -  SchedulePaintInRect(controller_->layout_model().GetRowBounds(row));
 | 
| +void AutofillPopupViewViews::OnSelectedRowChanged(
 | 
| +    base::Optional<int> previous_row_selection,
 | 
| +    base::Optional<int> current_row_selection) {
 | 
| +  SchedulePaint();
 | 
| +
 | 
| +  if (current_row_selection) {
 | 
| +    DCHECK_LT(*current_row_selection, child_count());
 | 
| +    child_at(*current_row_selection)
 | 
| +        ->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  /**
 | 
| @@ -189,6 +239,20 @@ void AutofillPopupViewViews::DrawAutofillEntry(gfx::Canvas* canvas,
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +void AutofillPopupViewViews::GetAccessibleNodeData(ui::AXNodeData* node_data) {
 | 
| +  node_data->role = ui::AX_ROLE_MENU;
 | 
| +  node_data->SetName(
 | 
| +      l10n_util::GetStringUTF16(IDS_AUTOFILL_POPUP_ACCESSIBLE_NODE_DATA));
 | 
| +}
 | 
| +
 | 
| +void AutofillPopupViewViews::CreateChildViews() {
 | 
| +  RemoveAllChildViews(true /* delete_children */);
 | 
| +
 | 
| +  for (int i = 0; i < controller_->GetLineCount(); ++i) {
 | 
| +    AddChildView(new AutofillPopupChildView(controller_->GetSuggestionAt(i)));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  AutofillPopupView* AutofillPopupView::Create(
 | 
|      AutofillPopupController* controller) {
 | 
|    views::Widget* observing_widget =
 | 
| 
 |