0

ash::ShelfView: CHECK against potentially bad static_casts.

There are a number of static downcasts in ShelfView that are *probably*
correct, but there is no clear proof that they are casting to the
correct type. This patch adds explicit CHECKs before every static_cast
to ensure that we are not casting from an incompatible dynamic type.

drag_view_ now has type ShelfButton*, so it is downcast on assignment,
rather than on many of its uses.

BUG=418460

Review URL: https://codereview.chromium.org/614653002

Cr-Commit-Position: refs/heads/master@{#297335}
This commit is contained in:
mgiuca
2014-09-29 18:44:42 -07:00
committed by Commit bot
parent 48714b9bfc
commit 1373851514
4 changed files with 20 additions and 7 deletions

@ -204,6 +204,9 @@ ShelfButton::IconView::~IconView() {
////////////////////////////////////////////////////////////////////////////////
// ShelfButton
// static
const char ShelfButton::kViewClassName[] = "ash/ShelfButton";
ShelfButton* ShelfButton::Create(views::ButtonListener* listener,
ShelfButtonHost* host,
ShelfLayoutManager* shelf_layout_manager) {
@ -321,6 +324,10 @@ void ShelfButton::ShowContextMenu(const gfx::Point& p,
}
}
const char* ShelfButton::GetClassName() const {
return kViewClassName;
}
bool ShelfButton::OnMousePressed(const ui::MouseEvent& event) {
CustomButton::OnMousePressed(event);
host_->PointerPressedOnButton(this, ShelfButtonHost::MOUSE, event);

@ -17,6 +17,8 @@ class ShelfLayoutManager;
// Button used for items on the launcher, except for the AppList.
class ASH_EXPORT ShelfButton : public views::CustomButton {
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
@ -91,6 +93,7 @@ class ASH_EXPORT ShelfButton : public views::CustomButton {
};
// View overrides:
virtual const char* GetClassName() const OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;

@ -462,7 +462,9 @@ gfx::Rect ShelfView::GetIdealBoundsOfItemIcon(ShelfID id) {
index = last_visible_index_ + 1;
const gfx::Rect& ideal_bounds(view_model_->ideal_bounds(index));
DCHECK_NE(TYPE_APP_LIST, model_->items()[index].type);
ShelfButton* button = static_cast<ShelfButton*>(view_model_->view_at(index));
views::View* view = view_model_->view_at(index);
CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
ShelfButton* button = static_cast<ShelfButton*>(view);
gfx::Rect icon_bounds = button->GetIconBounds();
return gfx::Rect(GetMirroredXWithWidthInView(
ideal_bounds.x() + icon_bounds.x(), icon_bounds.width()),
@ -1068,9 +1070,8 @@ bool ShelfView::HandleRipOffDrag(const ui::LocatedEvent& event) {
int delta = CalculateShelfDistance(screen_location);
if (delta > kRipOffDistance) {
// Create a proxy view item which can be moved anywhere.
ShelfButton* button = static_cast<ShelfButton*>(drag_view_);
CreateDragIconProxy(event.root_location(),
button->GetImage(),
drag_view_->GetImage(),
drag_view_,
gfx::Vector2d(0, 0),
kDragAndDropProxyScale);
@ -1152,8 +1153,7 @@ void ShelfView::FinalizeRipOffDrag(bool cancel) {
// animation end the flag gets cleared if |snap_back_from_rip_off_view_|
// is set.
snap_back_from_rip_off_view_ = drag_view_;
ShelfButton* button = static_cast<ShelfButton*>(drag_view_);
button->AddState(ShelfButton::STATE_HIDDEN);
drag_view_->AddState(ShelfButton::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_);
@ -1528,6 +1528,7 @@ void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) {
case TYPE_PLATFORM_APP:
case TYPE_DIALOG:
case TYPE_APP_PANEL: {
CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
ShelfButton* button = static_cast<ShelfButton*>(view);
ReflectItemStatus(item, button);
// The browser shortcut is currently not a "real" item and as such the
@ -1572,7 +1573,8 @@ void ShelfView::PointerPressedOnButton(views::View* view,
if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
return; // View is being deleted or not draggable, ignore request.
drag_view_ = view;
CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName());
drag_view_ = static_cast<ShelfButton*>(view);
drag_origin_ = gfx::Point(event.x(), event.y());
UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
layout_manager_->SelectValueForShelfAlignment(
@ -1866,6 +1868,7 @@ void ShelfView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
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);
break;

@ -356,7 +356,7 @@ class ASH_EXPORT ShelfView : public views::View,
// The view being dragged. This is set immediately when the mouse is pressed.
// |dragging_| is set only if the mouse is dragged far enough.
views::View* drag_view_;
ShelfButton* drag_view_;
// Position of the mouse down event in |drag_view_|'s coordinates.
gfx::Point drag_origin_;