[go: nahoru, domu]

CrOS shelf: refactor some code between the various shelf button classes

Change the hierarchy a bit:

                ShelfButton
                 /      \
                /        \
      ShelfAppButton    ShelfControlButton
        (new class)         \
                       {AppList,Back,Overflow}Button

This allows us to gather some logic common to all shelf buttons into
the ShelfButton class and avoid a bit of duplication in all subclasses.

The ShelfAppButton class is very close to the former ShelfButton class.
The new ShelfButton class is a lot shorter.

Also remove the ink drop listener constructor argument, since there
were no occurrences where that listener was different from the shelf
view (so we only need the shelf view as a constructor argument).

Yay deletions!

Bug: 714781
Change-Id: I5d39e9f58a457513a475c1c499dee60baa8d8b5a
Reviewed-on: https://chromium-review.googlesource.com/c/1396319
Commit-Queue: Manu Cornet <manucornet@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#622346}
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index eb0bff9b..a8b5a25 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -603,6 +603,8 @@
     "shelf/overflow_button.cc",
     "shelf/overflow_button.h",
     "shelf/shelf.cc",
+    "shelf/shelf_app_button.cc",
+    "shelf/shelf_app_button.h",
     "shelf/shelf_application_menu_model.cc",
     "shelf/shelf_application_menu_model.h",
     "shelf/shelf_background_animator.cc",
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc
index 9ccac053..da4bf46 100644
--- a/ash/shelf/app_list_button.cc
+++ b/ash/shelf/app_list_button.cc
@@ -58,15 +58,8 @@
 
 }  // namespace
 
-AppListButton::AppListButton(InkDropButtonListener* listener,
-                             ShelfView* shelf_view,
-                             Shelf* shelf)
-    : ShelfControlButton(),
-      listener_(listener),
-      shelf_view_(shelf_view),
-      shelf_(shelf) {
-  DCHECK(listener_);
-  DCHECK(shelf_view_);
+AppListButton::AppListButton(ShelfView* shelf_view, Shelf* shelf)
+    : ShelfControlButton(shelf_view), shelf_(shelf) {
   DCHECK(shelf_);
   Shell::Get()->AddShellObserver(this);
   Shell::Get()->session_controller()->AddObserver(this);
@@ -177,33 +170,6 @@
   }
 }
 
-bool AppListButton::OnMousePressed(const ui::MouseEvent& event) {
-  Button::OnMousePressed(event);
-  shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event);
-  return true;
-}
-
-void AppListButton::OnMouseReleased(const ui::MouseEvent& event) {
-  Button::OnMouseReleased(event);
-  shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false);
-}
-
-void AppListButton::OnMouseCaptureLost() {
-  shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, true);
-  Button::OnMouseCaptureLost();
-}
-
-bool AppListButton::OnMouseDragged(const ui::MouseEvent& event) {
-  Button::OnMouseDragged(event);
-  shelf_view_->PointerDraggedOnButton(this, ShelfView::MOUSE, event);
-  return true;
-}
-
-void AppListButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kButton;
-  node_data->SetName(shelf_view_->GetTitleForView(this));
-}
-
 std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple()
     const {
   const int app_list_button_radius = ShelfConstants::control_border_radius();
@@ -217,30 +183,6 @@
       ink_drop_visible_opacity());
 }
 
-void AppListButton::NotifyClick(const ui::Event& event) {
-  Button::NotifyClick(event);
-  if (listener_)
-    listener_->ButtonPressed(this, event, GetInkDrop());
-}
-
-bool AppListButton::ShouldEnterPushedState(const ui::Event& event) {
-  if (!shelf_view_->ShouldEventActivateButton(this, event))
-    return false;
-  return views::Button::ShouldEnterPushedState(event);
-}
-
-std::unique_ptr<views::InkDrop> AppListButton::CreateInkDrop() {
-  std::unique_ptr<views::InkDropImpl> ink_drop =
-      Button::CreateDefaultInkDropImpl();
-  ink_drop->SetShowHighlightOnHover(false);
-  return std::move(ink_drop);
-}
-
-std::unique_ptr<views::InkDropMask> AppListButton::CreateInkDropMask() const {
-  return std::make_unique<views::CircleInkDropMask>(
-      size(), GetCenterPoint(), ShelfConstants::control_border_radius());
-}
-
 void AppListButton::PaintButtonContents(gfx::Canvas* canvas) {
   gfx::PointF circle_center(GetCenterPoint());
 
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h
index 8d50849..c5f4e7c 100644
--- a/ash/shelf/app_list_button.h
+++ b/ash/shelf/app_list_button.h
@@ -23,7 +23,6 @@
 namespace ash {
 
 class AssistantOverlay;
-class InkDropButtonListener;
 class Shelf;
 class ShelfView;
 
@@ -33,9 +32,7 @@
                                  public SessionObserver,
                                  public DefaultVoiceInteractionObserver {
  public:
-  AppListButton(InkDropButtonListener* listener,
-                ShelfView* shelf_view,
-                Shelf* shelf);
+  AppListButton(ShelfView* shelf_view, Shelf* shelf);
   ~AppListButton() override;
 
   void OnAppListShown();
@@ -43,21 +40,12 @@
 
   bool is_showing_app_list() const { return is_showing_app_list_; }
 
-  // views::ImageButton:
+  // views::Button:
   void OnGestureEvent(ui::GestureEvent* event) override;
 
  protected:
-  // views::ImageButton:
-  bool OnMousePressed(const ui::MouseEvent& event) override;
-  void OnMouseReleased(const ui::MouseEvent& event) override;
-  void OnMouseCaptureLost() override;
-  bool OnMouseDragged(const ui::MouseEvent& event) override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+  // views::Button:
   std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
-  void NotifyClick(const ui::Event& event) override;
-  bool ShouldEnterPushedState(const ui::Event& event) override;
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
-  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
  private:
@@ -86,8 +74,6 @@
   // This is useful because other app_list_visible functions aren't per-display.
   bool is_showing_app_list_ = false;
 
-  InkDropButtonListener* listener_;
-  ShelfView* shelf_view_;
   Shelf* shelf_;
 
   // Owned by the view hierarchy. Null if the voice interaction is not enabled.
diff --git a/ash/shelf/back_button.cc b/ash/shelf/back_button.cc
index 50b1c46..31e6522 100644
--- a/ash/shelf/back_button.cc
+++ b/ash/shelf/back_button.cc
@@ -27,14 +27,14 @@
 
 namespace ash {
 
-BackButton::BackButton() : ShelfControlButton() {
+BackButton::BackButton(ShelfView* shelf_view) : ShelfControlButton(shelf_view) {
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_BACK_BUTTON_TITLE));
 }
 
 BackButton::~BackButton() = default;
 
 void BackButton::OnGestureEvent(ui::GestureEvent* event) {
-  Button::OnGestureEvent(event);
+  ShelfButton::OnGestureEvent(event);
   if (event->type() == ui::ET_GESTURE_TAP ||
       event->type() == ui::ET_GESTURE_TAP_DOWN) {
     GenerateAndSendBackEvent(event->type());
@@ -42,13 +42,13 @@
 }
 
 bool BackButton::OnMousePressed(const ui::MouseEvent& event) {
-  Button::OnMousePressed(event);
+  ShelfButton::OnMousePressed(event);
   GenerateAndSendBackEvent(event.type());
   return true;
 }
 
 void BackButton::OnMouseReleased(const ui::MouseEvent& event) {
-  Button::OnMouseReleased(event);
+  ShelfButton::OnMouseReleased(event);
   GenerateAndSendBackEvent(event.type());
 }
 
diff --git a/ash/shelf/back_button.h b/ash/shelf/back_button.h
index 09acc47..c07f2b0 100644
--- a/ash/shelf/back_button.h
+++ b/ash/shelf/back_button.h
@@ -18,7 +18,7 @@
 // in/out of the icon matches the movement of ShelfView's items.
 class ASH_EXPORT BackButton : public ShelfControlButton {
  public:
-  BackButton();
+  explicit BackButton(ShelfView* shelf_view);
   ~BackButton() override;
 
  protected:
diff --git a/ash/shelf/overflow_button.cc b/ash/shelf/overflow_button.cc
index 7f127ab..306b41c 100644
--- a/ash/shelf/overflow_button.cc
+++ b/ash/shelf/overflow_button.cc
@@ -23,12 +23,7 @@
 namespace ash {
 
 OverflowButton::OverflowButton(ShelfView* shelf_view, Shelf* shelf)
-    : ShelfControlButton(), shelf_view_(shelf_view), shelf_(shelf) {
-  DCHECK(shelf_view_);
-
-  set_hide_ink_drop_when_showing_context_menu(false);
-
-  SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
+    : ShelfControlButton(shelf_view) {
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
 
   horizontal_dots_image_view_ = new views::ImageView();
@@ -41,32 +36,16 @@
 OverflowButton::~OverflowButton() = default;
 
 bool OverflowButton::ShouldEnterPushedState(const ui::Event& event) {
-  if (shelf_view_->IsShowingOverflowBubble())
+  if (shelf_view()->IsShowingOverflowBubble())
     return false;
 
+  // We bypass out direct superclass on purpose here.
   return Button::ShouldEnterPushedState(event);
 }
 
 void OverflowButton::NotifyClick(const ui::Event& event) {
-  shelf_view_->ButtonPressed(this, event, nullptr);
-}
-
-void OverflowButton::PaintButtonContents(gfx::Canvas* canvas) {
-  gfx::Rect bounds = CalculateButtonBounds();
-  PaintBackground(canvas, bounds);
-}
-
-gfx::Rect OverflowButton::CalculateButtonBounds() const {
-  ShelfAlignment alignment = shelf_->alignment();
-  gfx::Rect content_bounds = GetContentsBounds();
-  // Align the button to the top of a bottom-aligned shelf, to the right edge
-  // a left-aligned shelf, and to the left edge of a right-aligned shelf.
-  const int inset = (ShelfConstants::shelf_size() - kShelfControlSize) / 2;
-  const int x = alignment == SHELF_ALIGNMENT_LEFT
-                    ? content_bounds.right() - inset - kShelfControlSize
-                    : content_bounds.x() + inset;
-  return gfx::Rect(x, content_bounds.y() + inset, kShelfControlSize,
-                   kShelfControlSize);
+  // For this button, do not call the superclass's handler.
+  shelf_view()->ButtonPressed(this, event, nullptr);
 }
 
 }  // namespace ash
diff --git a/ash/shelf/overflow_button.h b/ash/shelf/overflow_button.h
index cc19b678..f3624345 100644
--- a/ash/shelf/overflow_button.h
+++ b/ash/shelf/overflow_button.h
@@ -34,17 +34,10 @@
   // views::Button:
   bool ShouldEnterPushedState(const ui::Event& event) override;
   void NotifyClick(const ui::Event& event) override;
-  void PaintButtonContents(gfx::Canvas* canvas) override;
-
-  // Calculates the bounds of the control button based on the shelf alignment.
-  gfx::Rect CalculateButtonBounds() const;
 
   const gfx::ImageSkia horizontal_dots_image_;
   views::ImageView* horizontal_dots_image_view_;
 
-  ShelfView* shelf_view_;
-  Shelf* shelf_;
-
   DISALLOW_COPY_AND_ASSIGN(OverflowButton);
 };
 
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
new file mode 100644
index 0000000..7cddc95
--- /dev/null
+++ b/ash/shelf/shelf_app_button.cc
@@ -0,0 +1,743 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/shelf/shelf_app_button.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "ash/public/cpp/ash_constants.h"
+#include "ash/public/cpp/shelf_model.h"
+#include "ash/shelf/shelf.h"
+#include "ash/shelf/shelf_constants.h"
+#include "ash/shelf/shelf_view.h"
+#include "ash/system/tray/tray_popup_utils.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "skia/ext/image_operations.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/scoped_canvas.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "ui/gfx/transform_util.h"
+#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/animation/square_ink_drop_ripple.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/painter.h"
+
+namespace {
+
+constexpr int kStatusIndicatorAttentionThrobDurationMS = 800;
+constexpr int kStatusIndicatorMaxAnimationSeconds = 10;
+constexpr int kStatusIndicatorRadiusDip = 2;
+constexpr int kStatusIndicatorMaxSize = 10;
+constexpr int kStatusIndicatorActiveSize = 8;
+constexpr int kStatusIndicatorRunningSize = 4;
+constexpr int kStatusIndicatorThickness = 2;
+constexpr int kNotificationIndicatorRadiusDip = 7;
+constexpr SkColor kIndicatorColor = SK_ColorWHITE;
+
+// Slightly different colors and alpha in the new UI.
+constexpr SkColor kIndicatorColorActive = kIndicatorColor;
+constexpr SkColor kIndicatorColorRunning = SkColorSetA(SK_ColorWHITE, 0x7F);
+
+// Shelf item ripple size.
+constexpr int kInkDropLargeSize = 60;
+
+// The time threshold before an item can be dragged.
+constexpr int kDragTimeThresholdMs = 300;
+
+// The time threshold before the ink drop should activate on a long press.
+constexpr int kInkDropRippleActivationTimeMs = 650;
+
+// The drag and drop app icon should get scaled by this factor.
+constexpr float kAppIconScale = 1.2f;
+
+// The drag and drop app icon scaling up or down animation transition duration.
+constexpr int kDragDropAppIconScaleTransitionMs = 200;
+
+// Simple AnimationDelegate that owns a single ThrobAnimation instance to
+// keep all Draw Attention animations in sync.
+class ShelfAppButtonAnimation : public gfx::AnimationDelegate {
+ public:
+  class Observer {
+   public:
+    virtual void AnimationProgressed() = 0;
+
+   protected:
+    virtual ~Observer() = default;
+  };
+
+  static ShelfAppButtonAnimation* GetInstance() {
+    static ShelfAppButtonAnimation* s_instance = new ShelfAppButtonAnimation();
+    return s_instance;
+  }
+
+  void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
+
+  void RemoveObserver(Observer* observer) {
+    observers_.RemoveObserver(observer);
+    if (!observers_.might_have_observers())
+      animation_.Stop();
+  }
+
+  bool HasObserver(Observer* observer) const {
+    return observers_.HasObserver(observer);
+  }
+
+  SkAlpha GetAlpha() {
+    return GetThrobAnimation().CurrentValueBetween(SK_AlphaTRANSPARENT,
+                                                   SK_AlphaOPAQUE);
+  }
+
+  double GetAnimation() { return GetThrobAnimation().GetCurrentValue(); }
+
+ private:
+  ShelfAppButtonAnimation() : animation_(this) {
+    animation_.SetThrobDuration(kStatusIndicatorAttentionThrobDurationMS);
+    animation_.SetTweenType(gfx::Tween::SMOOTH_IN_OUT);
+  }
+
+  ~ShelfAppButtonAnimation() override = default;
+
+  gfx::ThrobAnimation& GetThrobAnimation() {
+    if (!animation_.is_animating()) {
+      animation_.Reset();
+      animation_.StartThrobbing(-1 /*throb indefinitely*/);
+    }
+    return animation_;
+  }
+
+  // gfx::AnimationDelegate
+  void AnimationProgressed(const gfx::Animation* animation) override {
+    if (animation != &animation_)
+      return;
+    if (!animation_.is_animating())
+      return;
+    for (auto& observer : observers_)
+      observer.AnimationProgressed();
+  }
+
+  gfx::ThrobAnimation animation_;
+  base::ObserverList<Observer>::Unchecked observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShelfAppButtonAnimation);
+};
+
+}  // namespace
+
+namespace ash {
+
+////////////////////////////////////////////////////////////////////////////////
+// ShelfAppButton::AppNotificationIndicatorView
+
+// The indicator which is activated when the app corresponding with this
+// ShelfAppButton receives a notification.
+class ShelfAppButton::AppNotificationIndicatorView : public views::View {
+ public:
+  explicit AppNotificationIndicatorView(SkColor indicator_color)
+      : indicator_color_(indicator_color) {}
+
+  ~AppNotificationIndicatorView() override {}
+
+  void OnPaint(gfx::Canvas* canvas) override {
+    gfx::ScopedCanvas scoped(canvas);
+
+    canvas->SaveLayerAlpha(SK_AlphaOPAQUE);
+
+    DCHECK_EQ(width(), height());
+    DCHECK_EQ(kNotificationIndicatorRadiusDip, width() / 2);
+    const float dsf = canvas->UndoDeviceScaleFactor();
+    const int kStrokeWidthPx = 1;
+    gfx::PointF center = gfx::RectF(GetLocalBounds()).CenterPoint();
+    center.Scale(dsf);
+
+    // Fill the center.
+    cc::PaintFlags flags;
+    flags.setColor(indicator_color_);
+    flags.setAntiAlias(true);
+    canvas->DrawCircle(
+        center, dsf * kNotificationIndicatorRadiusDip - kStrokeWidthPx, flags);
+
+    // Stroke the border.
+    flags.setColor(SkColorSetA(SK_ColorBLACK, 0x4D));
+    flags.setStyle(cc::PaintFlags::kStroke_Style);
+    canvas->DrawCircle(
+        center, dsf * kNotificationIndicatorRadiusDip - kStrokeWidthPx / 2.0f,
+        flags);
+  }
+
+ private:
+  const SkColor indicator_color_;
+
+  DISALLOW_COPY_AND_ASSIGN(AppNotificationIndicatorView);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// ShelfAppButton::AppStatusIndicatorView
+
+class ShelfAppButton::AppStatusIndicatorView
+    : public views::View,
+      public ShelfAppButtonAnimation::Observer {
+ public:
+  AppStatusIndicatorView() : show_attention_(false), active_(false) {
+    // Make sure the events reach the parent view for handling.
+    set_can_process_events_within_subtree(false);
+  }
+
+  ~AppStatusIndicatorView() override {
+    ShelfAppButtonAnimation::GetInstance()->RemoveObserver(this);
+  }
+
+  // views::View:
+  void OnPaint(gfx::Canvas* canvas) override {
+    gfx::ScopedCanvas scoped(canvas);
+    if (show_attention_) {
+      const SkAlpha alpha =
+          ShelfAppButtonAnimation::GetInstance()->HasObserver(this)
+              ? ShelfAppButtonAnimation::GetInstance()->GetAlpha()
+              : SK_AlphaOPAQUE;
+      canvas->SaveLayerAlpha(alpha);
+    }
+
+    const float dsf = canvas->UndoDeviceScaleFactor();
+    gfx::PointF center = gfx::RectF(GetLocalBounds()).CenterPoint();
+    cc::PaintFlags flags;
+    // Active and running indicators look a little different in the new UI.
+    flags.setColor(active_ ? kIndicatorColorActive : kIndicatorColorRunning);
+    flags.setAntiAlias(true);
+    flags.setStrokeCap(cc::PaintFlags::Cap::kRound_Cap);
+    flags.setStrokeJoin(cc::PaintFlags::Join::kRound_Join);
+    flags.setStrokeWidth(kStatusIndicatorThickness);
+    flags.setStyle(cc::PaintFlags::kStroke_Style);
+    float stroke_length =
+        active_ ? kStatusIndicatorActiveSize : kStatusIndicatorRunningSize;
+    gfx::PointF start;
+    gfx::PointF end;
+    if (horizontal_shelf_) {
+      start = gfx::PointF(center.x() - stroke_length / 2, center.y());
+      end = start;
+      end.Offset(stroke_length, 0);
+    } else {
+      start = gfx::PointF(center.x(), center.y() - stroke_length / 2);
+      end = start;
+      end.Offset(0, stroke_length);
+    }
+    SkPath path;
+    path.moveTo(start.x() * dsf, start.y() * dsf);
+    path.lineTo(end.x() * dsf, end.y() * dsf);
+    canvas->DrawPath(path, flags);
+  }
+
+  // ShelfAppButtonAnimation::Observer
+  void AnimationProgressed() override {
+    UpdateAnimating();
+    SchedulePaint();
+  }
+
+  void ShowAttention(bool show) {
+    if (show_attention_ == show)
+      return;
+
+    show_attention_ = show;
+    if (show_attention_) {
+      animation_end_time_ =
+          base::TimeTicks::Now() +
+          base::TimeDelta::FromSeconds(kStatusIndicatorMaxAnimationSeconds);
+      ShelfAppButtonAnimation::GetInstance()->AddObserver(this);
+    } else {
+      ShelfAppButtonAnimation::GetInstance()->RemoveObserver(this);
+    }
+  }
+
+  void ShowActiveStatus(bool active) {
+    if (active_ == active)
+      return;
+    active_ = active;
+    SchedulePaint();
+  }
+
+  void SetHorizontalShelf(bool horizontal_shelf) {
+    if (horizontal_shelf_ == horizontal_shelf)
+      return;
+    horizontal_shelf_ = horizontal_shelf;
+    SchedulePaint();
+  }
+
+ private:
+  void UpdateAnimating() {
+    if (base::TimeTicks::Now() > animation_end_time_)
+      ShelfAppButtonAnimation::GetInstance()->RemoveObserver(this);
+  }
+
+  bool show_attention_ = false;
+  bool active_ = false;
+  bool horizontal_shelf_ = true;
+  base::TimeTicks animation_end_time_;  // For attention throbbing underline.
+
+  DISALLOW_COPY_AND_ASSIGN(AppStatusIndicatorView);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// ShelfAppButton
+
+// static
+const char ShelfAppButton::kViewClassName[] = "ash/ShelfAppButton";
+
+ShelfAppButton::ShelfAppButton(ShelfView* shelf_view)
+    : ShelfButton(shelf_view),
+      icon_view_(new views::ImageView()),
+      indicator_(new AppStatusIndicatorView()),
+      notification_indicator_(nullptr),
+      state_(STATE_NORMAL),
+      destroyed_flag_(nullptr),
+      is_notification_indicator_enabled_(
+          features::IsNotificationIndicatorEnabled()) {
+  const gfx::ShadowValue kShadows[] = {
+      gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)),
+      gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)),
+      gfx::ShadowValue(gfx::Vector2d(0, 0), 1, SkColorSetARGB(0x54, 0, 0, 0)),
+  };
+  icon_shadows_.assign(kShadows, kShadows + base::size(kShadows));
+
+  // TODO: refactor the layers so each button doesn't require 3.
+  // |icon_view_| needs its own layer so it can be scaled up independently of
+  // the ink drop ripple.
+  icon_view_->SetPaintToLayer();
+  icon_view_->layer()->SetFillsBoundsOpaquely(false);
+  icon_view_->SetHorizontalAlignment(views::ImageView::CENTER);
+  icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
+  // Do not make this interactive, so that events are sent to ShelfView.
+  icon_view_->set_can_process_events_within_subtree(false);
+
+  AddChildView(indicator_);
+  AddChildView(icon_view_);
+  if (is_notification_indicator_enabled_) {
+    notification_indicator_ = new AppNotificationIndicatorView(kIndicatorColor);
+    notification_indicator_->SetPaintToLayer();
+    notification_indicator_->layer()->SetFillsBoundsOpaquely(false);
+    notification_indicator_->SetVisible(false);
+    AddChildView(notification_indicator_);
+  }
+
+  SetFocusPainter(TrayPopupUtils::CreateFocusPainter());
+}
+
+ShelfAppButton::~ShelfAppButton() {
+  if (destroyed_flag_)
+    *destroyed_flag_ = true;
+}
+
+void ShelfAppButton::SetShadowedImage(const gfx::ImageSkia& image) {
+  icon_view_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow(
+      image, icon_shadows_));
+}
+
+void ShelfAppButton::SetImage(const gfx::ImageSkia& image) {
+  if (image.isNull()) {
+    // TODO: need an empty image.
+    icon_view_->SetImage(image);
+    return;
+  }
+
+  const int icon_size = ShelfConstants::button_icon_size();
+
+  // Resize the image maintaining our aspect ratio.
+  float aspect_ratio =
+      static_cast<float>(image.width()) / static_cast<float>(image.height());
+  int height = icon_size;
+  int width = static_cast<int>(aspect_ratio * height);
+  if (width > icon_size) {
+    width = icon_size;
+    height = static_cast<int>(width / aspect_ratio);
+  }
+
+  if (width == image.width() && height == image.height()) {
+    SetShadowedImage(image);
+    return;
+  }
+
+  SetShadowedImage(gfx::ImageSkiaOperations::CreateResizedImage(
+      image, skia::ImageOperations::RESIZE_BEST, gfx::Size(width, height)));
+}
+
+const gfx::ImageSkia& ShelfAppButton::GetImage() const {
+  return icon_view_->GetImage();
+}
+
+void ShelfAppButton::AddState(State state) {
+  if (!(state_ & state)) {
+    state_ |= state;
+    Layout();
+    if (state & STATE_ATTENTION)
+      indicator_->ShowAttention(true);
+
+    if (state & STATE_ACTIVE)
+      indicator_->ShowActiveStatus(true);
+
+    if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION))
+      notification_indicator_->SetVisible(true);
+
+    if (state & STATE_DRAGGING)
+      ScaleAppIcon(true);
+  }
+}
+
+void ShelfAppButton::ClearState(State state) {
+  if (state_ & state) {
+    state_ &= ~state;
+    Layout();
+    if (state & STATE_ATTENTION)
+      indicator_->ShowAttention(false);
+    if (state & STATE_ACTIVE)
+      indicator_->ShowActiveStatus(false);
+
+    if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION))
+      notification_indicator_->SetVisible(false);
+
+    if (state & STATE_DRAGGING)
+      ScaleAppIcon(false);
+  }
+}
+
+gfx::Rect ShelfAppButton::GetIconBounds() const {
+  return icon_view_->bounds();
+}
+
+views::InkDrop* ShelfAppButton::GetInkDropForTesting() {
+  return GetInkDrop();
+}
+
+void ShelfAppButton::OnDragStarted(const ui::LocatedEvent* event) {
+  AnimateInkDrop(views::InkDropState::HIDDEN, event);
+}
+
+void ShelfAppButton::OnMenuClosed() {
+  DCHECK_EQ(views::InkDropState::ACTIVATED,
+            GetInkDrop()->GetTargetInkDropState());
+  GetInkDrop()->AnimateToState(views::InkDropState::DEACTIVATED);
+}
+
+void ShelfAppButton::ShowContextMenu(const gfx::Point& p,
+                                     ui::MenuSourceType source_type) {
+  if (!context_menu_controller())
+    return;
+
+  bool destroyed = false;
+  destroyed_flag_ = &destroyed;
+
+  if (source_type == ui::MenuSourceType::MENU_SOURCE_MOUSE ||
+      source_type == ui::MenuSourceType::MENU_SOURCE_KEYBOARD) {
+    GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
+  }
+
+  ShelfButton::ShowContextMenu(p, source_type);
+
+  if (!destroyed) {
+    destroyed_flag_ = nullptr;
+    // The menu will not propagate mouse events while it's shown. To address,
+    // the hover state gets cleared once the menu was shown (and this was not
+    // destroyed). In case context menu is shown target view does not receive
+    // OnMouseReleased events and we need to cancel capture manually.
+    if (shelf_view()->drag_view() == this)
+      OnMouseCaptureLost();
+    else
+      ClearState(STATE_HOVERED);
+  }
+}
+
+void ShelfAppButton::ReflectItemStatus(const ShelfItem& item) {
+  ShelfID active_id = shelf_view()->model()->active_shelf_id();
+  if (!active_id.IsNull() && item.id == active_id) {
+    // The active status trumps all other statuses.
+    AddState(ShelfAppButton::STATE_ACTIVE);
+    ClearState(ShelfAppButton::STATE_RUNNING);
+    ClearState(ShelfAppButton::STATE_ATTENTION);
+    return;
+  }
+
+  ClearState(ShelfAppButton::STATE_ACTIVE);
+
+  switch (item.status) {
+    case STATUS_CLOSED:
+      ClearState(ShelfAppButton::STATE_RUNNING);
+      ClearState(ShelfAppButton::STATE_ATTENTION);
+      break;
+    case STATUS_RUNNING:
+      AddState(ShelfAppButton::STATE_RUNNING);
+      ClearState(ShelfAppButton::STATE_ATTENTION);
+      break;
+    case STATUS_ATTENTION:
+      ClearState(ShelfAppButton::STATE_RUNNING);
+      AddState(ShelfAppButton::STATE_ATTENTION);
+      break;
+  }
+
+  if (features::IsNotificationIndicatorEnabled()) {
+    if (item.has_notification)
+      AddState(ShelfAppButton::STATE_NOTIFICATION);
+    else
+      ClearState(ShelfAppButton::STATE_NOTIFICATION);
+  }
+}
+
+const char* ShelfAppButton::GetClassName() const {
+  return kViewClassName;
+}
+
+bool ShelfAppButton::OnMousePressed(const ui::MouseEvent& event) {
+  // TODO: This call should probably live somewhere else (such as inside
+  // |ShelfView.PointerPressedOnButton|.
+  // No need to scale up the app for mouse right click since the app can't be
+  // dragged through right button.
+  if (!(event.flags() & ui::EF_LEFT_MOUSE_BUTTON)) {
+    Button::OnMousePressed(event);
+    return true;
+  }
+
+  ShelfButton::OnMousePressed(event);
+
+  if (shelf_view()->IsDraggedView(this)) {
+    drag_timer_.Start(
+        FROM_HERE, base::TimeDelta::FromMilliseconds(kDragTimeThresholdMs),
+        base::Bind(&ShelfAppButton::OnTouchDragTimer, base::Unretained(this)));
+  }
+  return true;
+}
+
+void ShelfAppButton::OnMouseReleased(const ui::MouseEvent& event) {
+  drag_timer_.Stop();
+  ClearState(STATE_DRAGGING);
+  ShelfButton::OnMouseReleased(event);
+  // WARNING: we may have been deleted.
+}
+
+void ShelfAppButton::OnMouseCaptureLost() {
+  ClearState(STATE_HOVERED);
+  ShelfButton::OnMouseCaptureLost();
+}
+
+void ShelfAppButton::Layout() {
+  // TODO: Find out why there is an extra pixel of padding between each item
+  // and the inner side of the shelf.
+  int icon_padding =
+      (ShelfConstants::shelf_size() - ShelfConstants::button_icon_size()) / 2 -
+      1;
+  const int icon_size = ShelfConstants::button_icon_size();
+  const int status_indicator_offet_from_shelf_edge =
+      ShelfConstants::status_indicator_offset_from_edge();
+
+  const gfx::Rect button_bounds(GetContentsBounds());
+  Shelf* shelf = shelf_view()->shelf();
+  const bool is_horizontal_shelf = shelf->IsHorizontalAlignment();
+  int x_offset = is_horizontal_shelf ? 0 : icon_padding;
+  int y_offset = is_horizontal_shelf ? icon_padding : 0;
+
+  int icon_width = std::min(icon_size, button_bounds.width() - x_offset);
+  int icon_height = std::min(icon_size, button_bounds.height() - y_offset);
+
+  // If on the left or top 'invert' the inset so the constant gap is on
+  // the interior (towards the center of display) edge of the shelf.
+  if (SHELF_ALIGNMENT_LEFT == shelf->alignment())
+    x_offset = button_bounds.width() - (icon_size + icon_padding);
+
+  // Center icon with respect to the secondary axis.
+  if (is_horizontal_shelf)
+    x_offset = std::max(0, button_bounds.width() - icon_width) / 2;
+  else
+    y_offset = std::max(0, button_bounds.height() - icon_height) / 2;
+
+  // Expand bounds to include shadows.
+  gfx::Insets insets_shadows = gfx::ShadowValue::GetMargin(icon_shadows_);
+  // Adjust offsets to center icon, not icon + shadow.
+  x_offset += (insets_shadows.left() - insets_shadows.right()) / 2;
+  y_offset += (insets_shadows.top() - insets_shadows.bottom()) / 2;
+  gfx::Rect icon_view_bounds =
+      gfx::Rect(button_bounds.x() + x_offset, button_bounds.y() + y_offset,
+                icon_width, icon_height);
+
+  // The indicators should be aligned with the icon, not the icon + shadow.
+  gfx::Point indicator_midpoint = icon_view_bounds.CenterPoint();
+  if (is_notification_indicator_enabled_) {
+    notification_indicator_->SetBoundsRect(
+        gfx::Rect(icon_view_bounds.right() - kNotificationIndicatorRadiusDip,
+                  icon_view_bounds.y(), kNotificationIndicatorRadiusDip * 2,
+                  kNotificationIndicatorRadiusDip * 2));
+  }
+
+  icon_view_bounds.Inset(insets_shadows);
+  icon_view_bounds.AdjustToFit(gfx::Rect(size()));
+  icon_view_->SetBoundsRect(icon_view_bounds);
+
+  // Icon size has been incorrect when running
+  // PanelLayoutManagerTest.PanelAlignmentSecondDisplay on valgrind bot, see
+  // http://crbug.com/234854.
+  DCHECK_LE(icon_width, icon_size);
+  DCHECK_LE(icon_height, icon_size);
+
+  switch (shelf->alignment()) {
+    case SHELF_ALIGNMENT_BOTTOM:
+    case SHELF_ALIGNMENT_BOTTOM_LOCKED:
+      indicator_midpoint.set_y(button_bounds.bottom() -
+                               kStatusIndicatorRadiusDip -
+                               status_indicator_offet_from_shelf_edge);
+      break;
+    case SHELF_ALIGNMENT_LEFT:
+      indicator_midpoint.set_x(button_bounds.x() + kStatusIndicatorRadiusDip +
+                               status_indicator_offet_from_shelf_edge);
+      break;
+    case SHELF_ALIGNMENT_RIGHT:
+      indicator_midpoint.set_x(button_bounds.right() -
+                               kStatusIndicatorRadiusDip -
+                               status_indicator_offet_from_shelf_edge);
+      break;
+  }
+
+  gfx::Rect indicator_bounds(indicator_midpoint, gfx::Size());
+  indicator_bounds.Inset(gfx::Insets(-kStatusIndicatorMaxSize));
+  indicator_->SetBoundsRect(indicator_bounds);
+
+  UpdateState();
+}
+
+void ShelfAppButton::ChildPreferredSizeChanged(views::View* child) {
+  Layout();
+}
+
+void ShelfAppButton::OnGestureEvent(ui::GestureEvent* event) {
+  switch (event->type()) {
+    case ui::ET_GESTURE_TAP_DOWN:
+      if (shelf_view()->shelf()->IsVisible()) {
+        AddState(STATE_HOVERED);
+        drag_timer_.Start(
+            FROM_HERE, base::TimeDelta::FromMilliseconds(kDragTimeThresholdMs),
+            base::BindRepeating(&ShelfAppButton::OnTouchDragTimer,
+                                base::Unretained(this)));
+        ripple_activation_timer_.Start(
+            FROM_HERE,
+            base::TimeDelta::FromMilliseconds(kInkDropRippleActivationTimeMs),
+            base::BindRepeating(&ShelfAppButton::OnRippleTimer,
+                                base::Unretained(this)));
+        GetInkDrop()->AnimateToState(views::InkDropState::ACTION_PENDING);
+        event->SetHandled();
+      }
+      break;
+    case ui::ET_GESTURE_END:
+      drag_timer_.Stop();
+      // If the button is being dragged, or there is an active context menu,
+      // for this ShelfAppButton, don't deactivate the ink drop.
+      if (!(state_ & STATE_DRAGGING) &&
+          !shelf_view()->IsShowingMenuForView(this) &&
+          (GetInkDrop()->GetTargetInkDropState() ==
+           views::InkDropState::ACTIVATED)) {
+        GetInkDrop()->AnimateToState(views::InkDropState::DEACTIVATED);
+      }
+      ClearState(STATE_HOVERED);
+      ClearState(STATE_DRAGGING);
+      break;
+    case ui::ET_GESTURE_SCROLL_BEGIN:
+      if (state_ & STATE_DRAGGING) {
+        shelf_view()->PointerPressedOnButton(this, ShelfView::TOUCH, *event);
+        event->SetHandled();
+      } else {
+        // The drag went to the bezel and is about to be passed to
+        // ShelfLayoutManager.
+        drag_timer_.Stop();
+        GetInkDrop()->AnimateToState(views::InkDropState::HIDDEN);
+      }
+      break;
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      if ((state_ & STATE_DRAGGING) && shelf_view()->IsDraggedView(this)) {
+        shelf_view()->PointerDraggedOnButton(this, ShelfView::TOUCH, *event);
+        event->SetHandled();
+      }
+      break;
+    case ui::ET_GESTURE_SCROLL_END:
+    case ui::ET_SCROLL_FLING_START:
+      if (state_ & STATE_DRAGGING) {
+        ClearState(STATE_DRAGGING);
+        shelf_view()->PointerReleasedOnButton(this, ShelfView::TOUCH, false);
+        event->SetHandled();
+      }
+      break;
+    case ui::ET_GESTURE_LONG_TAP:
+      GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
+      // Handle LONG_TAP to avoid opening the context menu twice.
+      event->SetHandled();
+      break;
+    case ui::ET_GESTURE_TWO_FINGER_TAP:
+      GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
+      break;
+    default:
+      break;
+  }
+
+  if (!event->handled())
+    return Button::OnGestureEvent(event);
+}
+
+std::unique_ptr<views::InkDropRipple> ShelfAppButton::CreateInkDropRipple()
+    const {
+  const int ink_drop_small_size = ash::ShelfConstants::shelf_size();
+  return std::make_unique<views::SquareInkDropRipple>(
+      gfx::Size(kInkDropLargeSize, kInkDropLargeSize),
+      ink_drop_large_corner_radius(),
+      gfx::Size(ink_drop_small_size, ink_drop_small_size),
+      ink_drop_small_corner_radius(), GetLocalBounds().CenterPoint(),
+      GetInkDropBaseColor(), ink_drop_visible_opacity());
+}
+
+void ShelfAppButton::UpdateState() {
+  const bool is_horizontal_shelf =
+      shelf_view()->shelf()->IsHorizontalAlignment();
+
+  indicator_->SetVisible(!(state_ & STATE_HIDDEN) &&
+                         (state_ & STATE_ATTENTION || state_ & STATE_RUNNING ||
+                          state_ & STATE_ACTIVE));
+  indicator_->SetHorizontalShelf(is_horizontal_shelf);
+
+  icon_view_->SetHorizontalAlignment(is_horizontal_shelf
+                                         ? views::ImageView::CENTER
+                                         : views::ImageView::LEADING);
+  icon_view_->SetVerticalAlignment(is_horizontal_shelf
+                                       ? views::ImageView::LEADING
+                                       : views::ImageView::CENTER);
+  SchedulePaint();
+}
+
+void ShelfAppButton::OnTouchDragTimer() {
+  AddState(STATE_DRAGGING);
+}
+
+void ShelfAppButton::OnRippleTimer() {
+  if (GetInkDrop()->GetTargetInkDropState() !=
+      views::InkDropState::ACTION_PENDING) {
+    return;
+  }
+  GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
+}
+
+void ShelfAppButton::ScaleAppIcon(bool scale_up) {
+  ui::ScopedLayerAnimationSettings settings(icon_view_->layer()->GetAnimator());
+  settings.SetTransitionDuration(
+      base::TimeDelta::FromMilliseconds(kDragDropAppIconScaleTransitionMs));
+
+  if (scale_up) {
+    icon_view_->layer()->SetTransform(gfx::GetScaleTransform(
+        gfx::Rect(icon_view_->layer()->bounds().size()).CenterPoint(),
+        kAppIconScale));
+  } else {
+    icon_view_->layer()->SetTransform(gfx::Transform());
+  }
+}
+
+}  // namespace ash
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h
new file mode 100644
index 0000000..8ce352b
--- /dev/null
+++ b/ash/shelf/shelf_app_button.h
@@ -0,0 +1,152 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SHELF_SHELF_APP_BUTTON_H_
+#define ASH_SHELF_SHELF_APP_BUTTON_H_
+
+#include "ash/ash_export.h"
+#include "ash/shelf/shelf_button.h"
+#include "base/macros.h"
+#include "base/timer/timer.h"
+#include "ui/gfx/shadow_value.h"
+
+namespace views {
+class ImageView;
+}
+
+namespace ash {
+struct ShelfItem;
+class ShelfView;
+
+// Button used for app shortcuts on the shelf..
+class ASH_EXPORT ShelfAppButton : public ShelfButton {
+ public:
+  static const char kViewClassName[];
+
+  // Used to indicate the current state of the button.
+  enum State {
+    // Nothing special. Usually represents an app shortcut item with no running
+    // instance.
+    STATE_NORMAL = 0,
+    // Button has mouse hovering on it.
+    STATE_HOVERED = 1 << 0,
+    // Underlying ShelfItem has a running instance.
+    STATE_RUNNING = 1 << 1,
+    // Underlying ShelfItem needs user's attention.
+    STATE_ATTENTION = 1 << 2,
+    // Hide the status (temporarily for some animations).
+    STATE_HIDDEN = 1 << 3,
+    // Button is being dragged.
+    STATE_DRAGGING = 1 << 4,
+    // App has at least 1 notification.
+    STATE_NOTIFICATION = 1 << 5,
+    // Underlying ShelfItem owns the window that is currently active.
+    STATE_ACTIVE = 1 << 6,
+  };
+
+  ShelfAppButton(ShelfView* shelf_view);
+  ~ShelfAppButton() override;
+
+  // Sets the image to display for this entry.
+  void SetImage(const gfx::ImageSkia& image);
+
+  // Retrieve the image to show proxy operations.
+  const gfx::ImageSkia& GetImage() const;
+
+  // |state| is or'd into the current state.
+  void AddState(State state);
+  void ClearState(State state);
+  int state() const { return state_; }
+
+  // Returns the bounds of the icon.
+  gfx::Rect GetIconBounds() const;
+
+  views::InkDrop* GetInkDropForTesting();
+
+  // Called when user started dragging the shelf button.
+  void OnDragStarted(const ui::LocatedEvent* event);
+
+  // Callback used when a menu for this ShelfAppButton is closed.
+  void OnMenuClosed();
+
+  // Overrides to views::Button:
+  void ShowContextMenu(const gfx::Point& p,
+                       ui::MenuSourceType source_type) override;
+
+  // View override - needed by unit test.
+  void OnMouseCaptureLost() override;
+
+  // Update button state from ShelfItem.
+  void ReflectItemStatus(const ShelfItem& item);
+
+ protected:
+  // View overrides:
+  const char* GetClassName() const override;
+  bool OnMousePressed(const ui::MouseEvent& event) override;
+  void OnMouseReleased(const ui::MouseEvent& event) override;
+  void Layout() override;
+  void ChildPreferredSizeChanged(views::View* child) override;
+
+  // ui::EventHandler overrides:
+  void OnGestureEvent(ui::GestureEvent* event) override;
+
+  // views::Button overrides:
+  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
+
+  // Sets the icon image with a shadow.
+  void SetShadowedImage(const gfx::ImageSkia& bitmap);
+
+ private:
+  class AppNotificationIndicatorView;
+  class AppStatusIndicatorView;
+
+  // Updates the parts of the button to reflect the current |state_| and
+  // alignment. This may add or remove views, layout and paint.
+  void UpdateState();
+
+  // Invoked when |touch_drag_timer_| fires to show dragging UI.
+  void OnTouchDragTimer();
+
+  // Invoked when |ripple_activation_timer_| fires to activate the ink drop.
+  void OnRippleTimer();
+
+  // Scales up app icon if |scale_up| is true, otherwise scales it back to
+  // normal size.
+  void ScaleAppIcon(bool scale_up);
+
+  // The icon part of a button can be animated independently of the rest.
+  views::ImageView* icon_view_;
+
+  // Draws an indicator underneath the image to represent the state of the
+  // application.
+  AppStatusIndicatorView* indicator_;
+
+  // Draws an indicator in the top right corner of the image to represent an
+  // active notification.
+  AppNotificationIndicatorView* notification_indicator_;
+
+  // The current application state, a bitfield of State enum values.
+  int state_;
+
+  gfx::ShadowValues icon_shadows_;
+
+  // If non-null the destuctor sets this to true. This is set while the menu is
+  // showing and used to detect if the menu was deleted while running.
+  bool* destroyed_flag_;
+
+  // Whether the notification indicator is enabled.
+  const bool is_notification_indicator_enabled_;
+
+  // A timer to defer showing drag UI when the shelf button is pressed.
+  base::OneShotTimer drag_timer_;
+
+  // A timer to activate the ink drop ripple during a long press.
+  base::OneShotTimer ripple_activation_timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShelfAppButton);
+};
+
+}  // namespace ash
+
+#endif  // ASH_SHELF_SHELF_APP_BUTTON_H_
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc
index 46990d7..5d58a38 100644
--- a/ash/shelf/shelf_button.cc
+++ b/ash/shelf/shelf_button.cc
@@ -1,502 +1,47 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "ash/shelf/shelf_button.h"
 
-#include <algorithm>
-#include <memory>
-
-#include "ash/public/cpp/ash_constants.h"
 #include "ash/shelf/ink_drop_button_listener.h"
-#include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/shelf_view.h"
-#include "ash/system/tray/tray_popup_utils.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/time/time.h"
-#include "chromeos/constants/chromeos_switches.h"
-#include "skia/ext/image_operations.h"
 #include "ui/accessibility/ax_node_data.h"
-#include "ui/base/ui_base_features.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/animation/animation_delegate.h"
-#include "ui/gfx/animation/throb_animation.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/scoped_canvas.h"
-#include "ui/gfx/skbitmap_operations.h"
-#include "ui/gfx/transform_util.h"
 #include "ui/views/animation/ink_drop_impl.h"
-#include "ui/views/animation/square_ink_drop_ripple.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/painter.h"
-
-namespace {
-
-constexpr int kStatusIndicatorAttentionThrobDurationMS = 800;
-constexpr int kStatusIndicatorMaxAnimationSeconds = 10;
-constexpr int kStatusIndicatorRadiusDip = 2;
-constexpr int kStatusIndicatorMaxSize = 10;
-constexpr int kStatusIndicatorActiveSize = 8;
-constexpr int kStatusIndicatorRunningSize = 4;
-constexpr int kStatusIndicatorThickness = 2;
-constexpr int kNotificationIndicatorRadiusDip = 7;
-constexpr SkColor kIndicatorColor = SK_ColorWHITE;
-
-// Slightly different colors and alpha in the new UI.
-constexpr SkColor kIndicatorColorActive = kIndicatorColor;
-constexpr SkColor kIndicatorColorRunning = SkColorSetA(SK_ColorWHITE, 0x7F);
-
-// Shelf item ripple size.
-constexpr int kInkDropLargeSize = 60;
-
-// The time threshold before an item can be dragged.
-constexpr int kDragTimeThresholdMs = 300;
-
-// The time threshold before the ink drop should activate on a long press.
-constexpr int kInkDropRippleActivationTimeMs = 650;
-
-// The drag and drop app icon should get scaled by this factor.
-constexpr float kAppIconScale = 1.2f;
-
-// The drag and drop app icon scaling up or down animation transition duration.
-constexpr int kDragDropAppIconScaleTransitionMs = 200;
-
-// Simple AnimationDelegate that owns a single ThrobAnimation instance to
-// keep all Draw Attention animations in sync.
-class ShelfButtonAnimation : public gfx::AnimationDelegate {
- public:
-  class Observer {
-   public:
-    virtual void AnimationProgressed() = 0;
-
-   protected:
-    virtual ~Observer() = default;
-  };
-
-  static ShelfButtonAnimation* GetInstance() {
-    static ShelfButtonAnimation* s_instance = new ShelfButtonAnimation();
-    return s_instance;
-  }
-
-  void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
-
-  void RemoveObserver(Observer* observer) {
-    observers_.RemoveObserver(observer);
-    if (!observers_.might_have_observers())
-      animation_.Stop();
-  }
-
-  bool HasObserver(Observer* observer) const {
-    return observers_.HasObserver(observer);
-  }
-
-  SkAlpha GetAlpha() {
-    return GetThrobAnimation().CurrentValueBetween(SK_AlphaTRANSPARENT,
-                                                   SK_AlphaOPAQUE);
-  }
-
-  double GetAnimation() { return GetThrobAnimation().GetCurrentValue(); }
-
- private:
-  ShelfButtonAnimation() : animation_(this) {
-    animation_.SetThrobDuration(kStatusIndicatorAttentionThrobDurationMS);
-    animation_.SetTweenType(gfx::Tween::SMOOTH_IN_OUT);
-  }
-
-  ~ShelfButtonAnimation() override = default;
-
-  gfx::ThrobAnimation& GetThrobAnimation() {
-    if (!animation_.is_animating()) {
-      animation_.Reset();
-      animation_.StartThrobbing(-1 /*throb indefinitely*/);
-    }
-    return animation_;
-  }
-
-  // gfx::AnimationDelegate
-  void AnimationProgressed(const gfx::Animation* animation) override {
-    if (animation != &animation_)
-      return;
-    if (!animation_.is_animating())
-      return;
-    for (auto& observer : observers_)
-      observer.AnimationProgressed();
-  }
-
-  gfx::ThrobAnimation animation_;
-  base::ObserverList<Observer>::Unchecked observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfButtonAnimation);
-};
-
-}  // namespace
 
 namespace ash {
 
-////////////////////////////////////////////////////////////////////////////////
-// ShelfButton::AppNotificationIndicatorView
-
-// The indicator which is activated when the app corresponding with this
-// ShelfButton recieves a notification.
-class ShelfButton::AppNotificationIndicatorView : public views::View {
- public:
-  explicit AppNotificationIndicatorView(SkColor indicator_color)
-      : indicator_color_(indicator_color) {}
-
-  ~AppNotificationIndicatorView() override {}
-
-  void OnPaint(gfx::Canvas* canvas) override {
-    gfx::ScopedCanvas scoped(canvas);
-
-    canvas->SaveLayerAlpha(SK_AlphaOPAQUE);
-
-    DCHECK_EQ(width(), height());
-    DCHECK_EQ(kNotificationIndicatorRadiusDip, width() / 2);
-    const float dsf = canvas->UndoDeviceScaleFactor();
-    const int kStrokeWidthPx = 1;
-    gfx::PointF center = gfx::RectF(GetLocalBounds()).CenterPoint();
-    center.Scale(dsf);
-
-    // Fill the center.
-    cc::PaintFlags flags;
-    flags.setColor(indicator_color_);
-    flags.setAntiAlias(true);
-    canvas->DrawCircle(
-        center, dsf * kNotificationIndicatorRadiusDip - kStrokeWidthPx, flags);
-
-    // Stroke the border.
-    flags.setColor(SkColorSetA(SK_ColorBLACK, 0x4D));
-    flags.setStyle(cc::PaintFlags::kStroke_Style);
-    canvas->DrawCircle(
-        center, dsf * kNotificationIndicatorRadiusDip - kStrokeWidthPx / 2.0f,
-        flags);
-  }
-
- private:
-  const SkColor indicator_color_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppNotificationIndicatorView);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// ShelfButton::AppStatusIndicatorView
-
-class ShelfButton::AppStatusIndicatorView
-    : public views::View,
-      public ShelfButtonAnimation::Observer {
- public:
-  AppStatusIndicatorView() : show_attention_(false), active_(false) {
-    // Make sure the events reach the parent view for handling.
-    set_can_process_events_within_subtree(false);
-  }
-
-  ~AppStatusIndicatorView() override {
-    ShelfButtonAnimation::GetInstance()->RemoveObserver(this);
-  }
-
-  // views::View:
-  void OnPaint(gfx::Canvas* canvas) override {
-    gfx::ScopedCanvas scoped(canvas);
-    if (show_attention_) {
-      const SkAlpha alpha =
-          ShelfButtonAnimation::GetInstance()->HasObserver(this)
-              ? ShelfButtonAnimation::GetInstance()->GetAlpha()
-              : SK_AlphaOPAQUE;
-      canvas->SaveLayerAlpha(alpha);
-    }
-
-    const float dsf = canvas->UndoDeviceScaleFactor();
-    gfx::PointF center = gfx::RectF(GetLocalBounds()).CenterPoint();
-    cc::PaintFlags flags;
-    // Active and running indicators look a little different in the new UI.
-    flags.setColor(active_ ? kIndicatorColorActive : kIndicatorColorRunning);
-    flags.setAntiAlias(true);
-    flags.setStrokeCap(cc::PaintFlags::Cap::kRound_Cap);
-    flags.setStrokeJoin(cc::PaintFlags::Join::kRound_Join);
-    flags.setStrokeWidth(kStatusIndicatorThickness);
-    flags.setStyle(cc::PaintFlags::kStroke_Style);
-    float stroke_length =
-        active_ ? kStatusIndicatorActiveSize : kStatusIndicatorRunningSize;
-    gfx::PointF start;
-    gfx::PointF end;
-    if (horizontal_shelf_) {
-      start = gfx::PointF(center.x() - stroke_length / 2, center.y());
-      end = start;
-      end.Offset(stroke_length, 0);
-    } else {
-      start = gfx::PointF(center.x(), center.y() - stroke_length / 2);
-      end = start;
-      end.Offset(0, stroke_length);
-    }
-    SkPath path;
-    path.moveTo(start.x() * dsf, start.y() * dsf);
-    path.lineTo(end.x() * dsf, end.y() * dsf);
-    canvas->DrawPath(path, flags);
-  }
-
-  // ShelfButtonAnimation::Observer
-  void AnimationProgressed() override {
-    UpdateAnimating();
-    SchedulePaint();
-  }
-
-  void ShowAttention(bool show) {
-    if (show_attention_ == show)
-      return;
-
-    show_attention_ = show;
-    if (show_attention_) {
-      animation_end_time_ =
-          base::TimeTicks::Now() +
-          base::TimeDelta::FromSeconds(kStatusIndicatorMaxAnimationSeconds);
-      ShelfButtonAnimation::GetInstance()->AddObserver(this);
-    } else {
-      ShelfButtonAnimation::GetInstance()->RemoveObserver(this);
-    }
-  }
-
-  void ShowActiveStatus(bool active) {
-    if (active_ == active)
-      return;
-    active_ = active;
-    SchedulePaint();
-  }
-
-  void SetHorizontalShelf(bool horizontal_shelf) {
-    if (horizontal_shelf_ == horizontal_shelf)
-      return;
-    horizontal_shelf_ = horizontal_shelf;
-    SchedulePaint();
-  }
-
- private:
-  void UpdateAnimating() {
-    if (base::TimeTicks::Now() > animation_end_time_)
-      ShelfButtonAnimation::GetInstance()->RemoveObserver(this);
-  }
-
-  bool show_attention_ = false;
-  bool active_ = false;
-  bool horizontal_shelf_ = true;
-  base::TimeTicks animation_end_time_;  // For attention throbbing underline.
-
-  DISALLOW_COPY_AND_ASSIGN(AppStatusIndicatorView);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// ShelfButton
-
-// static
-const char ShelfButton::kViewClassName[] = "ash/ShelfButton";
-
-ShelfButton::ShelfButton(InkDropButtonListener* listener, ShelfView* shelf_view)
-    : Button(nullptr),
-      listener_(listener),
-      shelf_view_(shelf_view),
-      icon_view_(new views::ImageView()),
-      indicator_(new AppStatusIndicatorView()),
-      notification_indicator_(nullptr),
-      state_(STATE_NORMAL),
-      destroyed_flag_(nullptr),
-      is_notification_indicator_enabled_(
-          features::IsNotificationIndicatorEnabled()) {
-  SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
-  SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+ShelfButton::ShelfButton(ShelfView* shelf_view)
+    : Button(nullptr), shelf_view_(shelf_view), listener_(shelf_view) {
+  DCHECK(shelf_view_);
+  set_hide_ink_drop_when_showing_context_menu(false);
   set_ink_drop_base_color(kShelfInkDropBaseColor);
   set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity);
-  set_hide_ink_drop_when_showing_context_menu(false);
-  const gfx::ShadowValue kShadows[] = {
-      gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)),
-      gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)),
-      gfx::ShadowValue(gfx::Vector2d(0, 0), 1, SkColorSetARGB(0x54, 0, 0, 0)),
-  };
-  icon_shadows_.assign(kShadows, kShadows + base::size(kShadows));
-
-  // TODO: refactor the layers so each button doesn't require 3.
-  // |icon_view_| needs its own layer so it can be scaled up independently of
-  // the ink drop ripple.
-  icon_view_->SetPaintToLayer();
-  icon_view_->layer()->SetFillsBoundsOpaquely(false);
-  icon_view_->SetHorizontalAlignment(views::ImageView::CENTER);
-  icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
-  // Do not make this interactive, so that events are sent to ShelfView.
-  icon_view_->set_can_process_events_within_subtree(false);
-
-  AddChildView(indicator_);
-  AddChildView(icon_view_);
-  if (is_notification_indicator_enabled_) {
-    notification_indicator_ = new AppNotificationIndicatorView(kIndicatorColor);
-    notification_indicator_->SetPaintToLayer();
-    notification_indicator_->layer()->SetFillsBoundsOpaquely(false);
-    notification_indicator_->SetVisible(false);
-    AddChildView(notification_indicator_);
-  }
-
-  SetFocusPainter(TrayPopupUtils::CreateFocusPainter());
+  SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
+  SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
 }
 
-ShelfButton::~ShelfButton() {
-  if (destroyed_flag_)
-    *destroyed_flag_ = true;
-}
+ShelfButton::~ShelfButton() = default;
 
-void ShelfButton::SetShadowedImage(const gfx::ImageSkia& image) {
-  icon_view_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow(
-      image, icon_shadows_));
-}
-
-void ShelfButton::SetImage(const gfx::ImageSkia& image) {
-  if (image.isNull()) {
-    // TODO: need an empty image.
-    icon_view_->SetImage(image);
-    return;
-  }
-
-  const int icon_size = ShelfConstants::button_icon_size();
-
-  // Resize the image maintaining our aspect ratio.
-  float aspect_ratio =
-      static_cast<float>(image.width()) / static_cast<float>(image.height());
-  int height = icon_size;
-  int width = static_cast<int>(aspect_ratio * height);
-  if (width > icon_size) {
-    width = icon_size;
-    height = static_cast<int>(width / aspect_ratio);
-  }
-
-  if (width == image.width() && height == image.height()) {
-    SetShadowedImage(image);
-    return;
-  }
-
-  SetShadowedImage(gfx::ImageSkiaOperations::CreateResizedImage(
-      image, skia::ImageOperations::RESIZE_BEST, gfx::Size(width, height)));
-}
-
-const gfx::ImageSkia& ShelfButton::GetImage() const {
-  return icon_view_->GetImage();
-}
-
-void ShelfButton::AddState(State state) {
-  if (!(state_ & state)) {
-    state_ |= state;
-    Layout();
-    if (state & STATE_ATTENTION)
-      indicator_->ShowAttention(true);
-
-    if (state & STATE_ACTIVE)
-      indicator_->ShowActiveStatus(true);
-
-    if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION))
-      notification_indicator_->SetVisible(true);
-
-    if (state & STATE_DRAGGING)
-      ScaleAppIcon(true);
-  }
-}
-
-void ShelfButton::ClearState(State state) {
-  if (state_ & state) {
-    state_ &= ~state;
-    Layout();
-    if (state & STATE_ATTENTION)
-      indicator_->ShowAttention(false);
-    if (state & STATE_ACTIVE)
-      indicator_->ShowActiveStatus(false);
-
-    if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION))
-      notification_indicator_->SetVisible(false);
-
-    if (state & STATE_DRAGGING)
-      ScaleAppIcon(false);
-  }
-}
-
-gfx::Rect ShelfButton::GetIconBounds() const {
-  return icon_view_->bounds();
-}
-
-views::InkDrop* ShelfButton::GetInkDropForTesting() {
-  return GetInkDrop();
-}
-
-void ShelfButton::OnDragStarted(const ui::LocatedEvent* event) {
-  AnimateInkDrop(views::InkDropState::HIDDEN, event);
-}
-
-void ShelfButton::OnMenuClosed() {
-  DCHECK_EQ(views::InkDropState::ACTIVATED,
-            GetInkDrop()->GetTargetInkDropState());
-  GetInkDrop()->AnimateToState(views::InkDropState::DEACTIVATED);
-}
-
-void ShelfButton::ShowContextMenu(const gfx::Point& p,
-                                  ui::MenuSourceType source_type) {
-  if (!context_menu_controller())
-    return;
-
-  bool destroyed = false;
-  destroyed_flag_ = &destroyed;
-
-  if (source_type == ui::MenuSourceType::MENU_SOURCE_MOUSE ||
-      source_type == ui::MenuSourceType::MENU_SOURCE_KEYBOARD) {
-    GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
-  }
-
-  Button::ShowContextMenu(p, source_type);
-
-  if (!destroyed) {
-    destroyed_flag_ = nullptr;
-    // The menu will not propagate mouse events while its shown. To address,
-    // the hover state gets cleared once the menu was shown (and this was not
-    // destroyed). In case context menu is shown target view does not receive
-    // OnMouseReleased events and we need to cancel capture manually.
-    if (shelf_view_->drag_view() == this)
-      OnMouseCaptureLost();
-    else
-      ClearState(STATE_HOVERED);
-  }
-}
-
-const char* ShelfButton::GetClassName() const {
-  return kViewClassName;
-}
+////////////////////////////////////////////////////////////////////////////////
+// views::View
 
 bool ShelfButton::OnMousePressed(const ui::MouseEvent& event) {
   Button::OnMousePressed(event);
-
-  // No need to scale up the app for mouse right click since the app can't be
-  // dragged through right button.
-  if (!(event.flags() & ui::EF_LEFT_MOUSE_BUTTON))
-    return true;
-
   shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event);
-
-  if (shelf_view_->IsDraggedView(this)) {
-    drag_timer_.Start(
-        FROM_HERE, base::TimeDelta::FromMilliseconds(kDragTimeThresholdMs),
-        base::Bind(&ShelfButton::OnTouchDragTimer, base::Unretained(this)));
-  }
   return true;
 }
 
 void ShelfButton::OnMouseReleased(const ui::MouseEvent& event) {
   Button::OnMouseReleased(event);
-  drag_timer_.Stop();
-  ClearState(STATE_DRAGGING);
-  // PointerReleasedOnButton deletes the ShelfButton when user drags a pinned
+  // PointerReleasedOnButton deletes the ShelfAppButton when user drags a pinned
   // running app from shelf.
   shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false);
   // WARNING: we may have been deleted.
 }
 
 void ShelfButton::OnMouseCaptureLost() {
-  ClearState(STATE_HOVERED);
   shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, true);
   Button::OnMouseCaptureLost();
 }
@@ -509,176 +54,17 @@
 
 void ShelfButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kButton;
-  node_data->SetName(shelf_view_->GetTitleForView(this));
+  const base::string16 title = shelf_view_->GetTitleForView(this);
+  node_data->SetName(title.empty() ? GetAccessibleName() : title);
 }
 
-void ShelfButton::Layout() {
-  // TODO: Find out why there is an extra pixel of padding between each item
-  // and the inner side of the shelf.
-  int icon_padding =
-      (ShelfConstants::shelf_size() - ShelfConstants::button_icon_size()) / 2 -
-      1;
-  const int icon_size = ShelfConstants::button_icon_size();
-  const int status_indicator_offet_from_shelf_edge =
-      ShelfConstants::status_indicator_offset_from_edge();
+////////////////////////////////////////////////////////////////////////////////
+// views::Button
 
-  const gfx::Rect button_bounds(GetContentsBounds());
-  Shelf* shelf = shelf_view_->shelf();
-  const bool is_horizontal_shelf = shelf->IsHorizontalAlignment();
-  int x_offset = is_horizontal_shelf ? 0 : icon_padding;
-  int y_offset = is_horizontal_shelf ? icon_padding : 0;
-
-  int icon_width = std::min(icon_size, button_bounds.width() - x_offset);
-  int icon_height = std::min(icon_size, button_bounds.height() - y_offset);
-
-  // If on the left or top 'invert' the inset so the constant gap is on
-  // the interior (towards the center of display) edge of the shelf.
-  if (SHELF_ALIGNMENT_LEFT == shelf->alignment())
-    x_offset = button_bounds.width() - (icon_size + icon_padding);
-
-  // Center icon with respect to the secondary axis.
-  if (is_horizontal_shelf)
-    x_offset = std::max(0, button_bounds.width() - icon_width) / 2;
-  else
-    y_offset = std::max(0, button_bounds.height() - icon_height) / 2;
-
-  // Expand bounds to include shadows.
-  gfx::Insets insets_shadows = gfx::ShadowValue::GetMargin(icon_shadows_);
-  // Adjust offsets to center icon, not icon + shadow.
-  x_offset += (insets_shadows.left() - insets_shadows.right()) / 2;
-  y_offset += (insets_shadows.top() - insets_shadows.bottom()) / 2;
-  gfx::Rect icon_view_bounds =
-      gfx::Rect(button_bounds.x() + x_offset, button_bounds.y() + y_offset,
-                icon_width, icon_height);
-
-  // The indicators should be aligned with the icon, not the icon + shadow.
-  gfx::Point indicator_midpoint = icon_view_bounds.CenterPoint();
-  if (is_notification_indicator_enabled_) {
-    notification_indicator_->SetBoundsRect(
-        gfx::Rect(icon_view_bounds.right() - kNotificationIndicatorRadiusDip,
-                  icon_view_bounds.y(), kNotificationIndicatorRadiusDip * 2,
-                  kNotificationIndicatorRadiusDip * 2));
-  }
-
-  icon_view_bounds.Inset(insets_shadows);
-  icon_view_bounds.AdjustToFit(gfx::Rect(size()));
-  icon_view_->SetBoundsRect(icon_view_bounds);
-
-  // Icon size has been incorrect when running
-  // PanelLayoutManagerTest.PanelAlignmentSecondDisplay on valgrind bot, see
-  // http://crbug.com/234854.
-  DCHECK_LE(icon_width, icon_size);
-  DCHECK_LE(icon_height, icon_size);
-
-  switch (shelf->alignment()) {
-    case SHELF_ALIGNMENT_BOTTOM:
-    case SHELF_ALIGNMENT_BOTTOM_LOCKED:
-      indicator_midpoint.set_y(button_bounds.bottom() -
-                               kStatusIndicatorRadiusDip -
-                               status_indicator_offet_from_shelf_edge);
-      break;
-    case SHELF_ALIGNMENT_LEFT:
-      indicator_midpoint.set_x(button_bounds.x() + kStatusIndicatorRadiusDip +
-                               status_indicator_offet_from_shelf_edge);
-      break;
-    case SHELF_ALIGNMENT_RIGHT:
-      indicator_midpoint.set_x(button_bounds.right() -
-                               kStatusIndicatorRadiusDip -
-                               status_indicator_offet_from_shelf_edge);
-      break;
-  }
-
-  gfx::Rect indicator_bounds(indicator_midpoint, gfx::Size());
-  indicator_bounds.Inset(gfx::Insets(-kStatusIndicatorMaxSize));
-  indicator_->SetBoundsRect(indicator_bounds);
-
-  UpdateState();
-}
-
-void ShelfButton::ChildPreferredSizeChanged(views::View* child) {
-  Layout();
-}
-
-void ShelfButton::OnGestureEvent(ui::GestureEvent* event) {
-  switch (event->type()) {
-    case ui::ET_GESTURE_TAP_DOWN:
-      if (shelf_view_->shelf()->IsVisible()) {
-        AddState(STATE_HOVERED);
-        drag_timer_.Start(
-            FROM_HERE, base::TimeDelta::FromMilliseconds(kDragTimeThresholdMs),
-            base::BindRepeating(&ShelfButton::OnTouchDragTimer,
-                                base::Unretained(this)));
-        ripple_activation_timer_.Start(
-            FROM_HERE,
-            base::TimeDelta::FromMilliseconds(kInkDropRippleActivationTimeMs),
-            base::BindRepeating(&ShelfButton::OnRippleTimer,
-                                base::Unretained(this)));
-        GetInkDrop()->AnimateToState(views::InkDropState::ACTION_PENDING);
-        event->SetHandled();
-      }
-      break;
-    case ui::ET_GESTURE_END:
-      drag_timer_.Stop();
-      // If the button is being dragged, or there is an active context menu,
-      // for this ShelfButton, don't deactivate the ink drop.
-      if (!(state_ & STATE_DRAGGING) &&
-          !shelf_view_->IsShowingMenuForView(this) &&
-          (GetInkDrop()->GetTargetInkDropState() ==
-           views::InkDropState::ACTIVATED)) {
-        GetInkDrop()->AnimateToState(views::InkDropState::DEACTIVATED);
-      }
-      ClearState(STATE_HOVERED);
-      ClearState(STATE_DRAGGING);
-      break;
-    case ui::ET_GESTURE_SCROLL_BEGIN:
-      if (state_ & STATE_DRAGGING) {
-        shelf_view_->PointerPressedOnButton(this, ShelfView::TOUCH, *event);
-        event->SetHandled();
-      } else {
-        // The drag went to the bezel and is about to be passed to
-        // ShelfLayoutManager.
-        drag_timer_.Stop();
-        GetInkDrop()->AnimateToState(views::InkDropState::HIDDEN);
-      }
-      break;
-    case ui::ET_GESTURE_SCROLL_UPDATE:
-      if ((state_ & STATE_DRAGGING) && shelf_view_->IsDraggedView(this)) {
-        shelf_view_->PointerDraggedOnButton(this, ShelfView::TOUCH, *event);
-        event->SetHandled();
-      }
-      break;
-    case ui::ET_GESTURE_SCROLL_END:
-    case ui::ET_SCROLL_FLING_START:
-      if (state_ & STATE_DRAGGING) {
-        ClearState(STATE_DRAGGING);
-        shelf_view_->PointerReleasedOnButton(this, ShelfView::TOUCH, false);
-        event->SetHandled();
-      }
-      break;
-    case ui::ET_GESTURE_LONG_TAP:
-      GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
-      // Handle LONG_TAP to avoid opening the context menu twice.
-      event->SetHandled();
-      break;
-    case ui::ET_GESTURE_TWO_FINGER_TAP:
-      GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
-      break;
-    default:
-      break;
-  }
-
-  if (!event->handled())
-    return Button::OnGestureEvent(event);
-}
-
-std::unique_ptr<views::InkDropRipple> ShelfButton::CreateInkDropRipple() const {
-  const int ink_drop_small_size = ash::ShelfConstants::shelf_size();
-  return std::make_unique<views::SquareInkDropRipple>(
-      gfx::Size(kInkDropLargeSize, kInkDropLargeSize),
-      ink_drop_large_corner_radius(),
-      gfx::Size(ink_drop_small_size, ink_drop_small_size),
-      ink_drop_small_corner_radius(), GetLocalBounds().CenterPoint(),
-      GetInkDropBaseColor(), ink_drop_visible_opacity());
+void ShelfButton::NotifyClick(const ui::Event& event) {
+  Button::NotifyClick(event);
+  if (listener_)
+    listener_->ButtonPressed(this, event, GetInkDrop());
 }
 
 bool ShelfButton::ShouldEnterPushedState(const ui::Event& event) {
@@ -695,54 +81,4 @@
   return std::move(ink_drop);
 }
 
-void ShelfButton::NotifyClick(const ui::Event& event) {
-  Button::NotifyClick(event);
-  if (listener_)
-    listener_->ButtonPressed(this, event, GetInkDrop());
-}
-
-void ShelfButton::UpdateState() {
-  const bool is_horizontal_shelf =
-      shelf_view_->shelf()->IsHorizontalAlignment();
-
-  indicator_->SetVisible(!(state_ & STATE_HIDDEN) &&
-                         (state_ & STATE_ATTENTION || state_ & STATE_RUNNING ||
-                          state_ & STATE_ACTIVE));
-  indicator_->SetHorizontalShelf(is_horizontal_shelf);
-
-  icon_view_->SetHorizontalAlignment(is_horizontal_shelf
-                                         ? views::ImageView::CENTER
-                                         : views::ImageView::LEADING);
-  icon_view_->SetVerticalAlignment(is_horizontal_shelf
-                                       ? views::ImageView::LEADING
-                                       : views::ImageView::CENTER);
-  SchedulePaint();
-}
-
-void ShelfButton::OnTouchDragTimer() {
-  AddState(STATE_DRAGGING);
-}
-
-void ShelfButton::OnRippleTimer() {
-  if (GetInkDrop()->GetTargetInkDropState() !=
-      views::InkDropState::ACTION_PENDING) {
-    return;
-  }
-  GetInkDrop()->AnimateToState(views::InkDropState::ACTIVATED);
-}
-
-void ShelfButton::ScaleAppIcon(bool scale_up) {
-  ui::ScopedLayerAnimationSettings settings(icon_view_->layer()->GetAnimator());
-  settings.SetTransitionDuration(
-      base::TimeDelta::FromMilliseconds(kDragDropAppIconScaleTransitionMs));
-
-  if (scale_up) {
-    icon_view_->layer()->SetTransform(gfx::GetScaleTransform(
-        gfx::Rect(icon_view_->layer()->bounds().size()).CenterPoint(),
-        kAppIconScale));
-  } else {
-    icon_view_->layer()->SetTransform(gfx::Transform());
-  }
-}
-
 }  // namespace ash
diff --git a/ash/shelf/shelf_button.h b/ash/shelf/shelf_button.h
index a525729..89aa3f5 100644
--- a/ash/shelf/shelf_button.h
+++ b/ash/shelf/shelf_button.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,150 +6,38 @@
 #define ASH_SHELF_SHELF_BUTTON_H_
 
 #include "ash/ash_export.h"
-#include "base/macros.h"
-#include "base/timer/timer.h"
-#include "ui/gfx/shadow_value.h"
 #include "ui/views/controls/button/button.h"
 
-namespace views {
-class ImageView;
-}
-
 namespace ash {
 class InkDropButtonListener;
 class ShelfView;
 
-// Button used for items on the launcher, except for the AppList.
+// Button used for items on the shelf.
 class ASH_EXPORT ShelfButton : public views::Button {
  public:
-  static const char kViewClassName[];
-
-  // Used to indicate the current state of the button.
-  enum State {
-    // Nothing special. Usually represents an app shortcut item with no running
-    // instance.
-    STATE_NORMAL = 0,
-    // Button has mouse hovering on it.
-    STATE_HOVERED = 1 << 0,
-    // Underlying ShelfItem has a running instance.
-    STATE_RUNNING = 1 << 1,
-    // Underlying ShelfItem needs user's attention.
-    STATE_ATTENTION = 1 << 2,
-    // Hide the status (temporarily for some animations).
-    STATE_HIDDEN = 1 << 3,
-    // Button is being dragged.
-    STATE_DRAGGING = 1 << 4,
-    // App has at least 1 notification.
-    STATE_NOTIFICATION = 1 << 5,
-    // Underlying ShelfItem owns the window that is currently active.
-    STATE_ACTIVE = 1 << 6,
-  };
-
-  ShelfButton(InkDropButtonListener* listener, ShelfView* shelf_view);
+  explicit ShelfButton(ShelfView* shelf_view);
   ~ShelfButton() override;
 
-  // Sets the image to display for this entry.
-  void SetImage(const gfx::ImageSkia& image);
-
-  // Retrieve the image to show proxy operations.
-  const gfx::ImageSkia& GetImage() const;
-
-  // |state| is or'd into the current state.
-  void AddState(State state);
-  void ClearState(State state);
-  int state() const { return state_; }
-
-  // Returns the bounds of the icon.
-  gfx::Rect GetIconBounds() const;
-
-  views::InkDrop* GetInkDropForTesting();
-
-  // Called when user started dragging the shelf button.
-  void OnDragStarted(const ui::LocatedEvent* event);
-
-  // Callback used when a menu for this ShelfButton is closed.
-  void OnMenuClosed();
-
-  // Overrides to views::Button:
-  void ShowContextMenu(const gfx::Point& p,
-                       ui::MenuSourceType source_type) override;
-
-  // View override - needed by unit test.
-  void OnMouseCaptureLost() override;
-
  protected:
-  // View overrides:
-  const char* GetClassName() const override;
+  ShelfView* shelf_view() { return shelf_view_; }
+
+  // views::View
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
+  void OnMouseCaptureLost() override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  void Layout() override;
-  void ChildPreferredSizeChanged(views::View* child) override;
 
-  // ui::EventHandler overrides:
-  void OnGestureEvent(ui::GestureEvent* event) override;
-
-  // views::Button overrides:
-  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
+  // views::Button
+  void NotifyClick(const ui::Event& event) override;
   bool ShouldEnterPushedState(const ui::Event& event) override;
   std::unique_ptr<views::InkDrop> CreateInkDrop() override;
-  void NotifyClick(const ui::Event& event) override;
-
-  // Sets the icon image with a shadow.
-  void SetShadowedImage(const gfx::ImageSkia& bitmap);
 
  private:
-  class AppNotificationIndicatorView;
-  class AppStatusIndicatorView;
-
-  // Updates the parts of the button to reflect the current |state_| and
-  // alignment. This may add or remove views, layout and paint.
-  void UpdateState();
-
-  // Invoked when |touch_drag_timer_| fires to show dragging UI.
-  void OnTouchDragTimer();
-
-  // Invoked when |ripple_activation_timer_| fires to activate the ink drop.
-  void OnRippleTimer();
-
-  // Scales up app icon if |scale_up| is true, otherwise scales it back to
-  // normal size.
-  void ScaleAppIcon(bool scale_up);
-
-  InkDropButtonListener* listener_;
-
   // The shelf view hosting this button.
   ShelfView* shelf_view_;
 
-  // The icon part of a button can be animated independently of the rest.
-  views::ImageView* icon_view_;
-
-  // Draws an indicator underneath the image to represent the state of the
-  // application.
-  AppStatusIndicatorView* indicator_;
-
-  // Draws an indicator in the top right corner of the image to represent an
-  // active notification.
-  AppNotificationIndicatorView* notification_indicator_;
-
-  // The current application state, a bitfield of State enum values.
-  int state_;
-
-  gfx::ShadowValues icon_shadows_;
-
-  // If non-null the destuctor sets this to true. This is set while the menu is
-  // showing and used to detect if the menu was deleted while running.
-  bool* destroyed_flag_;
-
-  // Whether the notification indicator is enabled.
-  const bool is_notification_indicator_enabled_;
-
-  // A timer to defer showing drag UI when the shelf button is pressed.
-  base::OneShotTimer drag_timer_;
-
-  // A timer to activate the ink drop ripple during a long press.
-  base::OneShotTimer ripple_activation_timer_;
+  InkDropButtonListener* listener_;
 
   DISALLOW_COPY_AND_ASSIGN(ShelfButton);
 };
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc
index 36393e5..0597dfa 100644
--- a/ash/shelf/shelf_control_button.cc
+++ b/ash/shelf/shelf_control_button.cc
@@ -5,8 +5,10 @@
 #include "ash/shelf/shelf_control_button.h"
 
 #include "ash/resources/vector_icons/vector_icons.h"
+#include "ash/shelf/ink_drop_button_listener.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_constants.h"
+#include "ash/shelf/shelf_view.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -17,14 +19,10 @@
 
 namespace ash {
 
-ShelfControlButton::ShelfControlButton() : views::Button(nullptr) {
-  SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+ShelfControlButton::ShelfControlButton(ShelfView* shelf_view)
+    : ShelfButton(shelf_view), shelf_(shelf_view->shelf()) {
   set_has_ink_drop_action_on_click(true);
-  set_ink_drop_base_color(kShelfInkDropBaseColor);
-  set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity);
-
   SetSize(gfx::Size(kShelfControlSize, kShelfControlSize));
-  SetFocusPainter(TrayPopupUtils::CreateFocusPainter());
 }
 
 ShelfControlButton::~ShelfControlButton() = default;
@@ -43,19 +41,29 @@
       ink_drop_visible_opacity());
 }
 
-std::unique_ptr<views::InkDrop> ShelfControlButton::CreateInkDrop() {
-  std::unique_ptr<views::InkDropImpl> ink_drop =
-      Button::CreateDefaultInkDropImpl();
-  ink_drop->SetShowHighlightOnHover(false);
-  return std::move(ink_drop);
-}
-
 std::unique_ptr<views::InkDropMask> ShelfControlButton::CreateInkDropMask()
     const {
   return std::make_unique<views::CircleInkDropMask>(
       size(), GetCenterPoint(), ShelfConstants::control_border_radius());
 }
 
+gfx::Rect ShelfControlButton::CalculateButtonBounds() const {
+  ShelfAlignment alignment = shelf_->alignment();
+  gfx::Rect content_bounds = GetContentsBounds();
+  // Align the button to the top of a bottom-aligned shelf, to the right edge
+  // a left-aligned shelf, and to the left edge of a right-aligned shelf.
+  const int inset = (ShelfConstants::shelf_size() - kShelfControlSize) / 2;
+  const int x = alignment == SHELF_ALIGNMENT_LEFT
+                    ? content_bounds.right() - inset - kShelfControlSize
+                    : content_bounds.x() + inset;
+  return gfx::Rect(x, content_bounds.y() + inset, kShelfControlSize,
+                   kShelfControlSize);
+}
+
+void ShelfControlButton::PaintButtonContents(gfx::Canvas* canvas) {
+  PaintBackground(canvas, CalculateButtonBounds());
+}
+
 void ShelfControlButton::PaintBackground(gfx::Canvas* canvas,
                                          const gfx::Rect& bounds) {
   cc::PaintFlags flags;
diff --git a/ash/shelf/shelf_control_button.h b/ash/shelf/shelf_control_button.h
index 4fb3638..93c27cd 100644
--- a/ash/shelf/shelf_control_button.h
+++ b/ash/shelf/shelf_control_button.h
@@ -8,16 +8,19 @@
 #include <memory>
 
 #include "ash/ash_export.h"
+#include "ash/shelf/shelf_button.h"
 #include "base/macros.h"
 #include "ui/views/controls/button/button.h"
 
 namespace ash {
+class ShelfView;
+class Shelf;
 
 // Base class for controls shown on the shelf that are not app shortcuts, such
 // as the app list, back, and overflow buttons.
-class ASH_EXPORT ShelfControlButton : public views::Button {
+class ASH_EXPORT ShelfControlButton : public ShelfButton {
  public:
-  ShelfControlButton();
+  explicit ShelfControlButton(ShelfView* shelf_view);
   ~ShelfControlButton() override;
 
   // Get the center point of the button used to draw its background and ink
@@ -27,10 +30,16 @@
  protected:
   // views::Button:
   std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
   std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
 
   void PaintBackground(gfx::Canvas* canvas, const gfx::Rect& bounds);
+  void PaintButtonContents(gfx::Canvas* canvas) override;
+
+ private:
+  // Calculates the bounds of the control button based on the shelf alignment.
+  gfx::Rect CalculateButtonBounds() const;
+
+  Shelf* shelf_;
 
   DISALLOW_COPY_AND_ASSIGN(ShelfControlButton);
 };
diff --git a/ash/shelf/shelf_unittest.cc b/ash/shelf/shelf_unittest.cc
index 54065897..55116435 100644
--- a/ash/shelf/shelf_unittest.cc
+++ b/ash/shelf/shelf_unittest.cc
@@ -8,7 +8,7 @@
 #include "ash/root_window_controller.h"
 #include "ash/session/test_session_controller_client.h"
 #include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_button.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_controller.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shelf/shelf_view_test_api.h"
@@ -66,8 +66,8 @@
   item.status = STATUS_RUNNING;
   int index = shelf_model()->Add(item);
   ASSERT_EQ(++button_count, test_api()->GetButtonCount());
-  ShelfButton* button = test_api()->GetButton(index);
-  EXPECT_EQ(ShelfButton::STATE_RUNNING, button->state());
+  ShelfAppButton* button = test_api()->GetButton(index);
+  EXPECT_EQ(ShelfAppButton::STATE_RUNNING, button->state());
 
   // Remove it.
   shelf_model()->RemoveItemAt(index);
@@ -88,10 +88,10 @@
   int index = shelf_model()->Add(item);
 
   ASSERT_EQ(++button_count, test_api()->GetButtonCount());
-  ShelfButton* button = test_api()->GetButton(index);
-  button->AddState(ShelfButton::STATE_HOVERED);
+  ShelfAppButton* button = test_api()->GetButton(index);
+  button->AddState(ShelfAppButton::STATE_HOVERED);
   button->ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE);
-  EXPECT_FALSE(button->state() & ShelfButton::STATE_HOVERED);
+  EXPECT_FALSE(button->state() & ShelfAppButton::STATE_HOVERED);
 
   // Remove it.
   shelf_model()->RemoveItemAt(index);
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index a72ba8f27..0544754 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -21,6 +21,7 @@
 #include "ash/shelf/overflow_bubble_view.h"
 #include "ash/shelf/overflow_button.h"
 #include "ash/shelf/shelf.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_application_menu_model.h"
 #include "ash/shelf/shelf_button.h"
 #include "ash/shelf/shelf_constants.h"
@@ -228,56 +229,21 @@
   DISALLOW_COPY_AND_ASSIGN(FadeInAnimationDelegate);
 };
 
-void ReflectItemStatus(const ShelfItem& item, ShelfButton* button) {
-  ShelfID active_id = Shell::Get()->shelf_model()->active_shelf_id();
-  if (!active_id.IsNull() && item.id == active_id) {
-    // The active status trumps all other statuses.
-    button->AddState(ShelfButton::STATE_ACTIVE);
-    button->ClearState(ShelfButton::STATE_RUNNING);
-    button->ClearState(ShelfButton::STATE_ATTENTION);
-    return;
-  }
-
-  button->ClearState(ShelfButton::STATE_ACTIVE);
-
-  switch (item.status) {
-    case STATUS_CLOSED:
-      button->ClearState(ShelfButton::STATE_RUNNING);
-      button->ClearState(ShelfButton::STATE_ATTENTION);
-      break;
-    case STATUS_RUNNING:
-      button->AddState(ShelfButton::STATE_RUNNING);
-      button->ClearState(ShelfButton::STATE_ATTENTION);
-      break;
-    case STATUS_ATTENTION:
-      button->ClearState(ShelfButton::STATE_RUNNING);
-      button->AddState(ShelfButton::STATE_ATTENTION);
-      break;
-  }
-
-  if (features::IsNotificationIndicatorEnabled()) {
-    if (item.has_notification)
-      button->AddState(ShelfButton::STATE_NOTIFICATION);
-    else
-      button->ClearState(ShelfButton::STATE_NOTIFICATION);
-  }
-}
-
 // Returns the id of the display on which |view| is shown.
 int64_t GetDisplayIdForView(View* view) {
   aura::Window* window = view->GetWidget()->GetNativeWindow();
   return display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
 }
 
-// Whether |item_view| is a ShelfButton and its state is STATE_DRAGGING.
+// Whether |item_view| is a ShelfAppButton and its state is STATE_DRAGGING.
 bool ShelfButtonIsInDrag(const ShelfItemType item_type,
                          const views::View* item_view) {
   switch (item_type) {
     case TYPE_PINNED_APP:
     case TYPE_BROWSER_SHORTCUT:
     case TYPE_APP:
-      return static_cast<const ShelfButton*>(item_view)->state() &
-             ShelfButton::STATE_DRAGGING;
+      return static_cast<const ShelfAppButton*>(item_view)->state() &
+             ShelfAppButton::STATE_DRAGGING;
     case TYPE_DIALOG:
     case TYPE_BACK_BUTTON:
     case TYPE_APP_LIST:
@@ -430,12 +396,12 @@
 
   const gfx::Rect& ideal_bounds(view_model_->ideal_bounds(index));
   views::View* view = view_model_->view_at(index);
-  // The app list and back button are not ShelfButton subclass instances.
+  // The app list and back button are not ShelfAppButton subclass instances.
   if (view == GetAppListButton() || view == GetBackButton())
     return GetMirroredRect(ideal_bounds);
 
-  CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
-  ShelfButton* button = static_cast<ShelfButton*>(view);
+  CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName());
+  ShelfAppButton* button = static_cast<ShelfAppButton*>(view);
   gfx::Rect icon_bounds = button->GetIconBounds();
   return gfx::Rect(GetMirroredXWithWidthInView(
                        ideal_bounds.x() + icon_bounds.x(), icon_bounds.width()),
@@ -732,7 +698,7 @@
     drag_image_->SetScreenPosition(origin_in_screen_coordinates);
 }
 
-bool ShelfView::IsDraggedView(const ShelfButton* view) const {
+bool ShelfView::IsDraggedView(const ShelfAppButton* view) const {
   return drag_view_ == view;
 }
 
@@ -893,8 +859,8 @@
   is_repost_event_on_same_item_ =
       IsRepostEvent(event) && (last_pressed_index_ == index);
 
-  CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
-  drag_view_ = static_cast<ShelfButton*>(view);
+  CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName());
+  drag_view_ = static_cast<ShelfAppButton*>(view);
   drag_origin_ = gfx::Point(event.x(), event.y());
   UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
                             static_cast<ShelfAlignmentUmaEnumValue>(
@@ -1215,20 +1181,20 @@
     case TYPE_BROWSER_SHORTCUT:
     case TYPE_APP:
     case TYPE_DIALOG: {
-      ShelfButton* button = new ShelfButton(this, this);
+      ShelfAppButton* button = new ShelfAppButton(this);
       button->SetImage(item.image);
-      ReflectItemStatus(item, button);
+      button->ReflectItemStatus(item);
       view = button;
       break;
     }
 
     case TYPE_APP_LIST: {
-      view = new AppListButton(this, this, shelf_);
+      view = new AppListButton(this, shelf_);
       break;
     }
 
     case TYPE_BACK_BUTTON: {
-      view = new BackButton();
+      view = new BackButton(this);
       break;
     }
 
@@ -1544,7 +1510,7 @@
       // animation end the flag gets cleared if |snap_back_from_rip_off_view_|
       // is set.
       snap_back_from_rip_off_view_ = drag_view_;
-      drag_view_->AddState(ShelfButton::STATE_HIDDEN);
+      drag_view_->AddState(ShelfAppButton::STATE_HIDDEN);
       // When a canceling drag model is happening, the view model is diverged
       // from the menu model and movements / animations should not be done.
       model_->Move(current_index, start_drag_index_);
@@ -1958,9 +1924,9 @@
     case TYPE_BROWSER_SHORTCUT:
     case TYPE_APP:
     case TYPE_DIALOG: {
-      CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
-      ShelfButton* button = static_cast<ShelfButton*>(view);
-      ReflectItemStatus(item, button);
+      CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName());
+      ShelfAppButton* button = static_cast<ShelfAppButton*>(view);
+      button->ReflectItemStatus(item);
       button->SetImage(item.image);
       button->SchedulePaint();
       break;
@@ -1992,10 +1958,10 @@
 
   const ShelfItem item = model_->items()[index];
   views::View* view = view_model_->view_at(index);
-  CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
+  CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName());
   // TODO(manucornet): Add a helper to get the button.
-  ShelfButton* button = static_cast<ShelfButton*>(view);
-  ReflectItemStatus(item, button);
+  ShelfAppButton* button = static_cast<ShelfAppButton*>(view);
+  button->ReflectItemStatus(item);
   button->SchedulePaint();
 }
 
@@ -2129,7 +2095,7 @@
 
   const ShelfItem* item = ShelfItemForView(source);
   if (item && (item->type != TYPE_APP_LIST))
-    static_cast<ShelfButton*>(source)->OnMenuClosed();
+    static_cast<ShelfAppButton*>(source)->OnMenuClosed();
 
   shelf_menu_model_adapter_.reset();
 
@@ -2164,16 +2130,16 @@
 
   if (snap_back_from_rip_off_view_ && animator == bounds_animator_.get()) {
     if (!animator->IsAnimating(snap_back_from_rip_off_view_)) {
-      // Coming here the animation of the ShelfButton is finished and the
+      // Coming here the animation of the ShelfAppButton is finished and the
       // previously hidden status can be shown again. Since the button itself
       // might have gone away or changed locations we check that the button
       // is still in the shelf and show its status again.
       for (int index = 0; index < view_model_->view_size(); index++) {
         views::View* view = view_model_->view_at(index);
         if (view == snap_back_from_rip_off_view_) {
-          CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
-          ShelfButton* button = static_cast<ShelfButton*>(view);
-          button->ClearState(ShelfButton::STATE_HIDDEN);
+          CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName());
+          ShelfAppButton* button = static_cast<ShelfAppButton*>(view);
+          button->ClearState(ShelfAppButton::STATE_HIDDEN);
           break;
         }
       }
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index 355df80..c5998d3 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -48,7 +48,7 @@
 class OverflowButton;
 class ScopedRootWindowForNewWindows;
 class Shelf;
-class ShelfButton;
+class ShelfAppButton;
 class ShelfModel;
 struct ShelfItem;
 class ShelfMenuModelAdapter;
@@ -136,7 +136,7 @@
   bool IsShowingMenu() const;
 
   // Returns true if we're showing a menu for |view|. |view| could be a
-  // ShelfButton or the ShelfView.
+  // ShelfAppButton or the ShelfView.
   bool IsShowingMenuForView(const views::View* view) const;
 
   // Returns true if overflow bubble is shown.
@@ -251,7 +251,7 @@
   void OnTabletModeChanged();
 
   // True if the current |drag_view_| is the given |drag_view|.
-  bool IsDraggedView(const ShelfButton* drag_view) const;
+  bool IsDraggedView(const ShelfAppButton* drag_view) const;
 
   // Returns the list of open windows that correspond to the app represented by
   // this shelf view.
@@ -267,7 +267,7 @@
   // the overflow shelf.
   ShelfView* main_shelf() { return main_shelf_; }
 
-  const ShelfButton* drag_view() const { return drag_view_; }
+  const ShelfAppButton* drag_view() const { return drag_view_; }
 
   // Returns true when this ShelfView is used for Overflow Bubble.
   // In this mode, it does not show app list and overflow button.
@@ -508,10 +508,10 @@
 
   // The view being dragged. This is set immediately when the mouse is pressed.
   // |dragging_| is set only if the mouse is dragged far enough.
-  ShelfButton* drag_view_ = nullptr;
+  ShelfAppButton* drag_view_ = nullptr;
 
   // The view showing a context menu. This can be either a ShelfView or
-  // ShelfButton.
+  // ShelfAppButton.
   views::View* menu_owner_ = nullptr;
 
   // Position of the mouse down event in |drag_view_|'s coordinates.
diff --git a/ash/shelf/shelf_view_test_api.cc b/ash/shelf/shelf_view_test_api.cc
index a10a057..8976f940f 100644
--- a/ash/shelf/shelf_view_test_api.cc
+++ b/ash/shelf/shelf_view_test_api.cc
@@ -6,7 +6,7 @@
 
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/shelf/overflow_button.h"
-#include "ash/shelf/shelf_button.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/shelf_menu_model_adapter.h"
 #include "ash/shelf/shelf_view.h"
@@ -46,13 +46,13 @@
   return shelf_view_->view_model_->view_size();
 }
 
-ShelfButton* ShelfViewTestAPI::GetButton(int index) {
-  // App list and back button are not ShelfButtons.
+ShelfAppButton* ShelfViewTestAPI::GetButton(int index) {
+  // App list and back button are not ShelfAppButtons.
   if (shelf_view_->model_->items()[index].type == ash::TYPE_APP_LIST ||
       shelf_view_->model_->items()[index].type == ash::TYPE_BACK_BUTTON)
     return nullptr;
 
-  return static_cast<ShelfButton*>(GetViewAt(index));
+  return static_cast<ShelfAppButton*>(GetViewAt(index));
 }
 
 views::View* ShelfViewTestAPI::GetViewAt(int index) {
diff --git a/ash/shelf/shelf_view_test_api.h b/ash/shelf/shelf_view_test_api.h
index ec7233a..f70c7fa 100644
--- a/ash/shelf/shelf_view_test_api.h
+++ b/ash/shelf/shelf_view_test_api.h
@@ -21,7 +21,7 @@
 namespace ash {
 class OverflowBubble;
 class OverflowButton;
-class ShelfButton;
+class ShelfAppButton;
 class ShelfButtonPressedMetricTracker;
 class ShelfTooltipManager;
 class ShelfView;
@@ -36,8 +36,8 @@
   int GetButtonCount();
 
   // Retrieve the button at |index|, doesn't support the app list button,
-  // because the app list button is not a ShelfButton.
-  ShelfButton* GetButton(int index);
+  // because the app list button is not a ShelfAppButton.
+  ShelfAppButton* GetButton(int index);
 
   // Retrieve the view at |index|.
   views::View* GetViewAt(int index);
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 4870ff4..216b808 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -27,7 +27,7 @@
 #include "ash/shelf/overflow_bubble_view_test_api.h"
 #include "ash/shelf/overflow_button.h"
 #include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_button.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/shelf_observer.h"
 #include "ash/shelf/shelf_tooltip_manager.h"
@@ -318,7 +318,7 @@
     test_api_->RunMessageLoopUntilAnimationsDone();
   }
 
-  ShelfButton* GetButtonByID(const ShelfID& id) {
+  ShelfAppButton* GetButtonByID(const ShelfID& id) {
     return test_api_->GetButton(model_->ItemIndexByID(id));
   }
 
@@ -366,18 +366,19 @@
   }
 
   // Similar to SimulateViewPressed, but the index must not be for the app list,
-  // since the app list button is not a ShelfButton.
-  ShelfButton* SimulateButtonPressed(ShelfView::Pointer pointer,
-                                     int button_index) {
+  // since the app list button is not a ShelfAppButton.
+  ShelfAppButton* SimulateButtonPressed(ShelfView::Pointer pointer,
+                                        int button_index) {
     EXPECT_NE(TYPE_APP_LIST, model_->items()[button_index].type);
-    ShelfButton* button = test_api_->GetButton(button_index);
+    ShelfAppButton* button = test_api_->GetButton(button_index);
     EXPECT_EQ(button, SimulateViewPressed(pointer, button_index));
     return button;
   }
 
   // Simulates a single mouse click.
   void SimulateClick(int button_index) {
-    ShelfButton* button = SimulateButtonPressed(ShelfView::MOUSE, button_index);
+    ShelfAppButton* button =
+        SimulateButtonPressed(ShelfView::MOUSE, button_index);
     ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
                                  button->GetBoundsInScreen().origin(),
                                  ui::EventTimeForNow(), 0, 0);
@@ -389,7 +390,8 @@
 
   // Simulates the second click of a double click.
   void SimulateDoubleClick(int button_index) {
-    ShelfButton* button = SimulateButtonPressed(ShelfView::MOUSE, button_index);
+    ShelfAppButton* button =
+        SimulateButtonPressed(ShelfView::MOUSE, button_index);
     ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, gfx::Point(),
                                  button->GetBoundsInScreen().origin(),
                                  ui::EventTimeForNow(), ui::EF_IS_DOUBLE_CLICK,
@@ -478,7 +480,7 @@
   void SetupForDragTest(std::vector<std::pair<ShelfID, views::View*>>* id_map) {
     // Initialize |id_map| with the automatically-created shelf buttons.
     for (size_t i = 0; i < model_->items().size(); ++i) {
-      ShelfButton* button = test_api_->GetButton(i);
+      ShelfAppButton* button = test_api_->GetButton(i);
       id_map->push_back(std::make_pair(model_->items()[i].id, button));
     }
     ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
@@ -542,7 +544,7 @@
     // Set the item to be dragged depending on |main_to_overflow|.
     int drag_item_index = main_to_overflow ? 3 : src_api->GetLastVisibleIndex();
     ShelfID drag_item_id = GetItemId(drag_item_index);
-    ShelfButton* drag_button = src_api->GetButton(drag_item_index);
+    ShelfAppButton* drag_button = src_api->GetButton(drag_item_index);
     gfx::Point center_point_of_drag_item = GetButtonCenter(drag_button);
 
     ui::test::EventGenerator* generator = GetEventGenerator();
@@ -558,7 +560,7 @@
 
     // Move a dragged item into the destination shelf at |drop_index|.
     int drop_index = main_to_overflow ? dest_api->GetLastVisibleIndex() : 3;
-    ShelfButton* drop_button = dest_api->GetButton(drop_index);
+    ShelfAppButton* drop_button = dest_api->GetButton(drop_index);
     gfx::Point drop_point = GetButtonCenter(drop_button);
     // To insert at |drop_index|, a smaller x-axis value of |drop_point|
     // should be used. If |drop_index| is the last item, a larger x-axis
@@ -650,7 +652,7 @@
     return GetButtonCenter(GetButtonByID(button_id));
   }
 
-  gfx::Point GetButtonCenter(ShelfButton* button) {
+  gfx::Point GetButtonCenter(ShelfAppButton* button) {
     return button->GetBoundsInScreen().CenterPoint();
   }
 
@@ -941,7 +943,7 @@
   // Verifies non-overflow buttons are visible. The back button at index 0 is
   // not visible.
   for (int i = 1; i <= test_api_->GetLastVisibleIndex(); ++i) {
-    ShelfButton* button = test_api_->GetButton(i);
+    ShelfAppButton* button = test_api_->GetButton(i);
     if (button) {
       EXPECT_TRUE(button->visible()) << "button index=" << i;
       EXPECT_EQ(1.0f, button->layer()->opacity()) << "button index=" << i;
@@ -1154,11 +1156,11 @@
   ShelfID last_added = AddApp();
   ShelfItem item = GetItemByID(last_added);
   int index = model_->ItemIndexByID(last_added);
-  ShelfButton* button = GetButtonByID(last_added);
-  ASSERT_EQ(ShelfButton::STATE_RUNNING, button->state());
+  ShelfAppButton* button = GetButtonByID(last_added);
+  ASSERT_EQ(ShelfAppButton::STATE_RUNNING, button->state());
   item.status = STATUS_ATTENTION;
   model_->Set(index, item);
-  ASSERT_EQ(ShelfButton::STATE_ATTENTION, button->state());
+  ASSERT_EQ(ShelfAppButton::STATE_ATTENTION, button->state());
 }
 
 // Test what drag movements will rip an item off the shelf.
@@ -1267,11 +1269,11 @@
   ShelfID last_added = AddApp();
   ShelfItem item = GetItemByID(last_added);
   int index = model_->ItemIndexByID(last_added);
-  ShelfButton* button = GetButtonByID(last_added);
-  ASSERT_EQ(ShelfButton::STATE_RUNNING, button->state());
+  ShelfAppButton* button = GetButtonByID(last_added);
+  ASSERT_EQ(ShelfAppButton::STATE_RUNNING, button->state());
   item.status = STATUS_ATTENTION;
   model_->Set(index, item);
-  ASSERT_EQ(ShelfButton::STATE_ATTENTION, button->state());
+  ASSERT_EQ(ShelfAppButton::STATE_ATTENTION, button->state());
 }
 
 // Confirm that shelf item bounds are correctly updated on shelf changes.
@@ -1292,8 +1294,8 @@
   ShelfID app_button_id = AddAppShortcut();
   ShelfID platform_button_id = AddApp();
 
-  ShelfButton* app_button = GetButtonByID(app_button_id);
-  ShelfButton* platform_button = GetButtonByID(platform_button_id);
+  ShelfAppButton* app_button = GetButtonByID(app_button_id);
+  ShelfAppButton* platform_button = GetButtonByID(platform_button_id);
 
   ShelfTooltipManager* tooltip_manager = test_api_->tooltip_manager();
   EXPECT_TRUE(shelf_view_->GetWidget()->GetNativeWindow());
@@ -1338,7 +1340,7 @@
 
   // Add an item to the shelf.
   ShelfID app_button_id = AddAppShortcut();
-  ShelfButton* app_button = GetButtonByID(app_button_id);
+  ShelfAppButton* app_button = GetButtonByID(app_button_id);
 
   // Spawn a tooltip on that item.
   tooltip_manager->ShowTooltip(app_button);
@@ -1359,7 +1361,7 @@
 
   // Add an item to the shelf.
   ShelfID app_button_id = AddAppShortcut();
-  ShelfButton* app_button = GetButtonByID(app_button_id);
+  ShelfAppButton* app_button = GetButtonByID(app_button_id);
 
   // Spawn a tooltip on the item.
   tooltip_manager->ShowTooltip(app_button);
@@ -1385,7 +1387,7 @@
 
   // The tooltip shouldn't hide if the mouse is on normal buttons.
   for (int i = 0; i < test_api_->GetButtonCount(); i++) {
-    ShelfButton* button = test_api_->GetButton(i);
+    ShelfAppButton* button = test_api_->GetButton(i);
     if (!button)
       continue;
     EXPECT_FALSE(shelf_view_->ShouldHideTooltip(
@@ -1399,7 +1401,7 @@
   // Find the first shelf button that's to the right of the app list button.
   int right = 0;
   for (int i = 0; i < test_api_->GetButtonCount(); ++i) {
-    ShelfButton* button = test_api_->GetButton(i);
+    ShelfAppButton* button = test_api_->GetButton(i);
     if (!button)
       continue;
     right = button->bounds().x();
@@ -1427,7 +1429,7 @@
   // The tooltip should hide if it's outside of all buttons.
   gfx::Rect all_area;
   for (int i = 0; i < test_api_->GetButtonCount(); i++) {
-    ShelfButton* button = test_api_->GetButton(i);
+    ShelfAppButton* button = test_api_->GetButton(i);
     if (!button)
       continue;
 
@@ -1453,7 +1455,7 @@
 
   // The tooltip shouldn't hide if the mouse is on normal buttons.
   for (int i = 2; i < test_api_->GetButtonCount(); i++) {
-    ShelfButton* button = test_api_->GetButton(i);
+    ShelfAppButton* button = test_api_->GetButton(i);
     if (!button)
       continue;
 
@@ -1564,7 +1566,7 @@
       ShelfConstants::button_size() + ShelfConstants::button_spacing();
 
   ui::test::EventGenerator* generator = GetEventGenerator();
-  ShelfButton* button = test_for_overflow_view.GetButton(ripped_index);
+  ShelfAppButton* button = test_for_overflow_view.GetButton(ripped_index);
   // Rip off the last visible item.
   gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
   gfx::Point rip_off_point(start_point.x(), 0);
@@ -1639,8 +1641,8 @@
   int first_index = test_for_overflow_view.GetFirstVisibleIndex();
   int last_index = test_for_overflow_view.GetLastVisibleIndex();
 
-  ShelfButton* first_button = test_for_overflow_view.GetButton(first_index);
-  ShelfButton* last_button = test_for_overflow_view.GetButton(last_index);
+  ShelfAppButton* first_button = test_for_overflow_view.GetButton(first_index);
+  ShelfAppButton* last_button = test_for_overflow_view.GetButton(last_index);
   gfx::Point first_point = first_button->GetBoundsInScreen().CenterPoint();
   gfx::Point last_point = last_button->GetBoundsInScreen().CenterPoint();
   gfx::Rect drag_reinsert_bounds =
@@ -1683,7 +1685,7 @@
   ShelfViewTestAPI test_api_for_overflow_view(
       test_api_->overflow_bubble()->bubble_view()->shelf_view());
 
-  ShelfButton* button = test_api_for_overflow_view.GetButton(
+  ShelfAppButton* button = test_api_for_overflow_view.GetButton(
       test_api_for_overflow_view.GetLastVisibleIndex());
 
   // Checks that a point in shelf is contained in drag insert bounds.
@@ -1703,7 +1705,7 @@
   ShelfViewTestAPI test_api_for_overflow_view_of_secondary(
       test_api_for_secondary.overflow_bubble()->bubble_view()->shelf_view());
 
-  ShelfButton* button_in_secondary =
+  ShelfAppButton* button_in_secondary =
       test_api_for_overflow_view_of_secondary.GetButton(
           test_api_for_overflow_view_of_secondary.GetLastVisibleIndex());
 
@@ -1737,7 +1739,7 @@
       secondary_shelf->GetShelfViewForTesting();
 
   ShelfViewTestAPI test_api_for_secondary_shelf_view(shelf_view_for_secondary);
-  ShelfButton* button = test_api_for_secondary_shelf_view.GetButton(2);
+  ShelfAppButton* button = test_api_for_secondary_shelf_view.GetButton(2);
 
   // Fetch the start point of dragging.
   gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
@@ -1791,8 +1793,8 @@
   int item_b_initial_index = overflow_api.GetLastVisibleIndex();
   ShelfID item_a = GetItemId(item_a_initial_index);
   ShelfID item_b = GetItemId(item_b_initial_index);
-  ShelfButton* item_a_button = overflow_api.GetButton(item_a_initial_index);
-  ShelfButton* item_b_button = overflow_api.GetButton(item_b_initial_index);
+  ShelfAppButton* item_a_button = overflow_api.GetButton(item_a_initial_index);
+  ShelfAppButton* item_b_button = overflow_api.GetButton(item_b_initial_index);
   gfx::Point drag_point = GetButtonCenter(item_a_button);
   gfx::Point drop_point = GetButtonCenter(item_b_button);
 
@@ -1930,7 +1932,7 @@
   test_api_->ShowOverflowBubble();
   ShelfViewTestAPI test_api_for_overflow(
       test_api_->overflow_bubble()->bubble_view()->shelf_view());
-  ShelfButton* button_on_overflow_shelf =
+  ShelfAppButton* button_on_overflow_shelf =
       test_api_for_overflow.GetButton(model_->ItemIndexByID(overflow_app_id2));
   generator->set_current_screen_location(
       GetButtonCenter(button_on_overflow_shelf));
@@ -1954,7 +1956,7 @@
       test_api_->overflow_bubble()->bubble_view()->shelf_view());
   button_on_overflow_shelf =
       test_api_for_overflow2.GetButton(model_->ItemIndexByID(overflow_app_id1));
-  ShelfButton* button_on_overflow_shelf1 =
+  ShelfAppButton* button_on_overflow_shelf1 =
       test_api_for_overflow2.GetButton(model_->ItemIndexByID(overflow_app_id2));
   generator->set_current_screen_location(
       GetButtonCenter(button_on_overflow_shelf));
@@ -2107,7 +2109,7 @@
   ShelfID shelf_id("123");
   window->SetProperty(kShelfIDKey, new std::string(shelf_id.Serialize()));
   window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
-  ShelfButton* button = GetButtonByID(shelf_id);
+  ShelfAppButton* button = GetButtonByID(shelf_id);
   ASSERT_TRUE(button);
   generator->MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
   generator->PressRightButton();
@@ -2123,7 +2125,7 @@
   ShelfID shelf_id("123");
   window->SetProperty(kShelfIDKey, new std::string(shelf_id.Serialize()));
   window->SetProperty(kShelfItemTypeKey, static_cast<int32_t>(TYPE_DIALOG));
-  ShelfButton* button = GetButtonByID(shelf_id);
+  ShelfAppButton* button = GetButtonByID(shelf_id);
   ASSERT_TRUE(button);
 
   // Context menu is shown on right button press and no drag view is set.
@@ -2163,7 +2165,7 @@
 
   // Add |STATE_DRAGGING| state to emulate the gesture drag after context menu
   // is shown.
-  GetButtonByID(first_app_id)->AddState(ShelfButton::STATE_DRAGGING);
+  GetButtonByID(first_app_id)->AddState(ShelfAppButton::STATE_DRAGGING);
   generator->GestureScrollSequence(start, end,
                                    base::TimeDelta::FromMilliseconds(100), 3);
 
@@ -2196,7 +2198,7 @@
 
   // Add |STATE_DRAGGING| state to emulate the gesture drag after context menu
   // is shown.
-  GetButtonByID(first_app_id)->AddState(ShelfButton::STATE_DRAGGING);
+  GetButtonByID(first_app_id)->AddState(ShelfAppButton::STATE_DRAGGING);
   generator->GestureScrollSequence(start, end,
                                    base::TimeDelta::FromMilliseconds(100), 3);
 
@@ -2226,7 +2228,7 @@
 
 // Tests that menu anchor points are aligned with the shelf button bounds.
 TEST_P(ShelfViewMenuTest, ShelfViewMenuAnchorPoint) {
-  const ShelfButton* shelf_button = GetButtonByID(AddApp());
+  const ShelfAppButton* shelf_button = GetButtonByID(AddApp());
   const bool context_menu = GetParam();
   EXPECT_EQ(ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM,
             GetPrimaryShelf()->alignment());
@@ -2277,16 +2279,16 @@
 TEST_F(NotificationIndicatorTest, AddedItemHasNotificationIndicator) {
   const ShelfID id_0 = AddApp();
   const std::string notification_id_0("notification_id_0");
-  const ShelfButton* button_0 = GetButtonByID(id_0);
+  const ShelfAppButton* button_0 = GetButtonByID(id_0);
 
   EXPECT_FALSE(GetItemByID(id_0).has_notification);
-  EXPECT_FALSE(button_0->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_FALSE(button_0->state() & ShelfAppButton::STATE_NOTIFICATION);
 
   // Post a test notification after the item was added.
   model_->AddNotificationRecord(id_0.app_id, notification_id_0);
 
   EXPECT_TRUE(GetItemByID(id_0).has_notification);
-  EXPECT_TRUE(button_0->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_TRUE(button_0->state() & ShelfAppButton::STATE_NOTIFICATION);
 
   // Post another notification for a non existing item.
   const std::string next_app_id(GetNextAppId());
@@ -2298,18 +2300,18 @@
 
   // Ensure that the app id assigned to |id_1| is the same as |next_app_id|.
   EXPECT_EQ(next_app_id, id_1.app_id);
-  const ShelfButton* button_1 = GetButtonByID(id_1);
+  const ShelfAppButton* button_1 = GetButtonByID(id_1);
   EXPECT_TRUE(GetItemByID(id_1).has_notification);
-  EXPECT_TRUE(button_1->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_TRUE(button_1->state() & ShelfAppButton::STATE_NOTIFICATION);
 
   // Remove all notifications.
   model_->RemoveNotificationRecord(notification_id_0);
   model_->RemoveNotificationRecord(notification_id_1);
 
   EXPECT_FALSE(GetItemByID(id_0).has_notification);
-  EXPECT_FALSE(button_0->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_FALSE(button_0->state() & ShelfAppButton::STATE_NOTIFICATION);
   EXPECT_FALSE(GetItemByID(id_1).has_notification);
-  EXPECT_FALSE(button_1->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_FALSE(button_1->state() & ShelfAppButton::STATE_NOTIFICATION);
 }
 
 // Tests that the notification indicator is active until all notifications have
@@ -2317,7 +2319,7 @@
 TEST_F(NotificationIndicatorTest,
        NotificationIndicatorStaysActiveUntilNotificationsAreGone) {
   const ShelfID app = AddApp();
-  const ShelfButton* button = GetButtonByID(app);
+  const ShelfAppButton* button = GetButtonByID(app);
 
   // Add two notifications for the same app.
   const std::string notification_id_0("notification_id_0");
@@ -2326,19 +2328,19 @@
   model_->AddNotificationRecord(app.app_id, notification_id_1);
 
   EXPECT_TRUE(GetItemByID(app).has_notification);
-  EXPECT_TRUE(button->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_TRUE(button->state() & ShelfAppButton::STATE_NOTIFICATION);
 
   // Remove one notification, indicator should stay active.
   model_->RemoveNotificationRecord(notification_id_0);
 
   EXPECT_TRUE(GetItemByID(app).has_notification);
-  EXPECT_TRUE(button->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_TRUE(button->state() & ShelfAppButton::STATE_NOTIFICATION);
 
   // Remove the last notification, indicator should not be active.
   model_->RemoveNotificationRecord(notification_id_1);
 
   EXPECT_FALSE(GetItemByID(app).has_notification);
-  EXPECT_FALSE(button->state() & ShelfButton::STATE_NOTIFICATION);
+  EXPECT_FALSE(button->state() & ShelfAppButton::STATE_NOTIFICATION);
 }
 
 class ShelfViewVisibleBoundsTest : public ShelfViewTest,
@@ -2351,7 +2353,7 @@
     gfx::Rect shelf_bounds = shelf_view_->GetBoundsInScreen();
     EXPECT_TRUE(shelf_bounds.Contains(visible_bounds));
     for (int i = 0; i < test_api_->GetButtonCount(); ++i)
-      if (ShelfButton* button = test_api_->GetButton(i)) {
+      if (ShelfAppButton* button = test_api_->GetButton(i)) {
         if (button->visible())
           EXPECT_TRUE(visible_bounds.Contains(button->GetBoundsInScreen()));
       }
@@ -2521,7 +2523,7 @@
 
   AppListButton* app_list_button_ = nullptr;
   InkDropSpy* app_list_button_ink_drop_ = nullptr;
-  ShelfButton* browser_button_ = nullptr;
+  ShelfAppButton* browser_button_ = nullptr;
   InkDropSpy* browser_button_ink_drop_ = nullptr;
 
  private:
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index c00fb76e..b3c54b0 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -9,7 +9,7 @@
 #include "ash/public/cpp/shelf_item_delegate.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_button.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_view_test_api.h"
 #include "ash/shell.h"
 #include "base/macros.h"
@@ -331,7 +331,7 @@
 
   controller->FlushForTesting();
 
-  ash::ShelfButton* const button = test_api.GetButton(item_index);
+  ash::ShelfAppButton* const button = test_api.GetButton(item_index);
   ASSERT_TRUE(button);
 
   views::InkDrop* const ink_drop = button->GetInkDropForTesting();
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index db1ce09d..2d9407d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -14,7 +14,7 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shelf/app_list_button.h"
 #include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_button.h"
+#include "ash/shelf/shelf_app_button.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shelf/shelf_view_test_api.h"
 #include "ash/shelf/shelf_widget.h"
@@ -302,7 +302,7 @@
                        ui::test::EventGenerator* generator,
                        ash::ShelfViewTestAPI* test,
                        RipOffCommand command) {
-    ash::ShelfButton* button = test->GetButton(index);
+    ash::ShelfAppButton* button = test->GetButton(index);
     gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
     gfx::Point rip_off_point(start_point.x(), 0);
     generator->MoveMouseTo(start_point.x(), start_point.y());
@@ -1600,8 +1600,8 @@
   EXPECT_EQ(browser_index, GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT));
   // Make sure that the hide state has been unset after the snap back animation
   // finished.
-  ash::ShelfButton* button = test.GetButton(browser_index);
-  EXPECT_FALSE(button->state() & ash::ShelfButton::STATE_HIDDEN);
+  ash::ShelfAppButton* button = test.GetButton(browser_index);
+  EXPECT_FALSE(button->state() & ash::ShelfAppButton::STATE_HIDDEN);
 
   // Test #2: Ripping out the application and canceling the operation should
   // not change anything.