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:
@ -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_;
|
||||
|
Reference in New Issue
Block a user