Reland "Omnibox UI Refresh: Implement popup open and close opacity animations."

This is a reland of 5cab33d1317a67d2512b8677a91611b5b5d18d91

In Patchset 2, it also makes the widget insensitive to mouse events
while animating closed.

This fixes the crash triggered when the user clicks on the results list
while the popup is animating closed. It also makes the popup no longer
change its highlighted match in response to mouseover events.

We also are insensitive to gesture events while closing, but we do not capture
them.

Original change's description:
> Omnibox UI Refresh: Implement popup open and close opacity animations.
>
> This eases in and out the Omnibox popup opacity over 82ms as it opens
> and closes. This matches the animation spec provided by UX.
>
> Bug: 823535
> Change-Id: Ic2add1f57f63ae6d043812f2bd5a766f84d302c9
> Reviewed-on: https://chromium-review.googlesource.com/1081198
> Commit-Queue: Tommy Li <tommycli@chromium.org>
> Reviewed-by: Peter Kasting <pkasting@chromium.org>
> Reviewed-by: Ali Juma <ajuma@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#564295}

TBR=ajuma@chromium.org

Bug: 823535, 857486
Change-Id: Ie497eefd007ae30a9098be30f55f63dc51adecc3
Reviewed-on: https://chromium-review.googlesource.com/1138514
Commit-Queue: Tommy Li <tommycli@chromium.org>
Reviewed-by: Justin Donnelly <jdonnelly@chromium.org>
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575706}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 98ee886..4c60d9b 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -29,7 +29,9 @@
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/theme_provider.h"
 #include "ui/compositor/clip_recorder.h"
+#include "ui/compositor/closure_animation_observer.h"
 #include "ui/compositor/paint_recorder.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
@@ -194,9 +196,92 @@
       SetBounds(bounds);
   }
 
+  void ShowAnimated() {
+    if (!LocationBarView::IsRounded()) {
+      ShowInactive();
+      return;
+    }
+
+    // Set the initial opacity to 0 and ease into fully opaque.
+    GetLayer()->SetOpacity(0.0);
+    ShowInactive();
+
+    auto scoped_settings = GetScopedAnimationSettings();
+    GetLayer()->SetOpacity(1.0);
+  }
+
+  void CloseAnimated() {
+    if (!LocationBarView::IsRounded()) {
+      // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack
+      // triggered by the popup receiving a message (e.g. LBUTTONUP), and
+      // destroying the popup would cause us to read garbage when we unwind back
+      // to that level.
+      Close();
+      return;
+    }
+
+    // If the opening or shrinking animations still running, abort them, as the
+    // popup is closing. This is an edge case for superhumanly fast users.
+    GetLayer()->GetAnimator()->AbortAllAnimations();
+
+    auto scoped_settings = GetScopedAnimationSettings();
+    GetLayer()->SetOpacity(0.0);
+    is_animating_closed_ = true;
+
+    // Destroy the popup when done. The observer deletes itself on completion.
+    scoped_settings->AddObserver(new ui::ClosureAnimationObserver(
+        base::BindOnce(&AutocompletePopupWidget::Close, AsWeakPtr())));
+  }
+
+  void OnNativeWidgetDestroying() override {
+    // End all our animations immediately, as our closing animation may trigger
+    // a Close call which will be invalid once the native widget is gone.
+    GetLayer()->GetAnimator()->AbortAllAnimations();
+
+    ThemeCopyingWidget::OnNativeWidgetDestroying();
+  }
+
+  void OnMouseEvent(ui::MouseEvent* event) override {
+    // Ignore mouse events if the popup is closed or animating closed.
+    if (IsClosed() || is_animating_closed_) {
+      if (event->cancelable())
+        event->SetHandled();
+      return;
+    }
+
+    ThemeCopyingWidget::OnMouseEvent(event);
+  }
+
+  void OnGestureEvent(ui::GestureEvent* event) override {
+    // Ignore gesture events if the popup is closed or animating closed.
+    // However, just like the base class, we do not capture the event, so
+    // multiple widgets may get tap events at the same time.
+    if (IsClosed() || is_animating_closed_)
+      return;
+
+    ThemeCopyingWidget::OnGestureEvent(event);
+  }
+
  private:
+  std::unique_ptr<ui::ScopedLayerAnimationSettings>
+  GetScopedAnimationSettings() {
+    auto settings = std::make_unique<ui::ScopedLayerAnimationSettings>(
+        GetLayer()->GetAnimator());
+
+    settings->SetTweenType(gfx::Tween::Type::FAST_OUT_SLOW_IN);
+
+    constexpr base::TimeDelta kPopupOpacityAnimationDuration =
+        base::TimeDelta::FromMilliseconds(82);
+    settings->SetTransitionDuration(kPopupOpacityAnimationDuration);
+
+    return settings;
+  }
+
   std::unique_ptr<WidgetShrinkAnimation> animator_;
 
+  // True if the popup is in the process of closing via animation.
+  bool is_animating_closed_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget);
 };
 
@@ -302,11 +387,7 @@
     // the omnibox popup window.  Close any existing popup.
     if (popup_) {
       NotifyAccessibilityEvent(ax::mojom::Event::kExpandedChanged, true);
-      // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack
-      // triggered by the popup receiving a message (e.g. LBUTTONUP), and
-      // destroying the popup would cause us to read garbage when we unwind back
-      // to that level.
-      popup_->Close();  // This will eventually delete the popup.
+      popup_->CloseAnimated();  // This will eventually delete the popup.
       popup_.reset();
     }
     return;
@@ -362,7 +443,7 @@
   if (!popup_)
     return;
 
-  popup_->ShowInactive();
+  popup_->ShowAnimated();
 
   // Popup is now expanded and first item will be selected.
   NotifyAccessibilityEvent(ax::mojom::Event::kExpandedChanged, true);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
index ac4982e..96bab85 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
@@ -29,6 +29,7 @@
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "content/public/test/test_utils.h"
 #include "ui/base/ui_base_switches.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
@@ -413,6 +414,9 @@
 
   generator.ClickLeftButton();
   ASSERT_TRUE(GetPopupWidget());
+
+  // Instantly finish all queued animations.
+  GetPopupWidget()->GetLayer()->GetAnimator()->StopAnimating();
   EXPECT_TRUE(GetPopupWidget()->IsClosed());
 }
 
diff --git a/ui/compositor/closure_animation_observer.cc b/ui/compositor/closure_animation_observer.cc
index 2ac7f91c..77abfba 100644
--- a/ui/compositor/closure_animation_observer.cc
+++ b/ui/compositor/closure_animation_observer.cc
@@ -6,8 +6,8 @@
 
 namespace ui {
 
-ClosureAnimationObserver::ClosureAnimationObserver(const base::Closure& closure)
-    : closure_(closure) {
+ClosureAnimationObserver::ClosureAnimationObserver(base::OnceClosure closure)
+    : closure_(std::move(closure)) {
   DCHECK(!closure_.is_null());
 }
 
@@ -15,7 +15,7 @@
 }
 
 void ClosureAnimationObserver::OnImplicitAnimationsCompleted() {
-  closure_.Run();
+  std::move(closure_).Run();
   delete this;
 }
 
diff --git a/ui/compositor/closure_animation_observer.h b/ui/compositor/closure_animation_observer.h
index 1fd1cdf..60b1341 100644
--- a/ui/compositor/closure_animation_observer.h
+++ b/ui/compositor/closure_animation_observer.h
@@ -17,7 +17,7 @@
 class COMPOSITOR_EXPORT ClosureAnimationObserver
     : public ImplicitAnimationObserver {
  public:
-  explicit ClosureAnimationObserver(const base::Closure& closure);
+  explicit ClosureAnimationObserver(base::OnceClosure closure);
 
  private:
   ~ClosureAnimationObserver() override;
@@ -25,7 +25,7 @@
   // ImplicitAnimationObserver:
   void OnImplicitAnimationsCompleted() override;
 
-  const base::Closure closure_;
+  base::OnceClosure closure_;
 
   DISALLOW_COPY_AND_ASSIGN(ClosureAnimationObserver);
 };