Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: ui/app_list/views/apps_grid_view.cc

Issue 298963004: app_list: Fix possible out of bounds index. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: DCHECK -> CHECK Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/app_list/views/apps_grid_view.h ('k') | ui/app_list/views/test/apps_grid_view_test_api.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/app_list/views/apps_grid_view.h" 5 #include "ui/app_list/views/apps_grid_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 10
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 item_list_(NULL), 341 item_list_(NULL),
342 delegate_(delegate), 342 delegate_(delegate),
343 folder_delegate_(NULL), 343 folder_delegate_(NULL),
344 pagination_model_(pagination_model), 344 pagination_model_(pagination_model),
345 page_switcher_view_(new PageSwitcher(pagination_model)), 345 page_switcher_view_(new PageSwitcher(pagination_model)),
346 cols_(0), 346 cols_(0),
347 rows_per_page_(0), 347 rows_per_page_(0),
348 selected_view_(NULL), 348 selected_view_(NULL),
349 drag_view_(NULL), 349 drag_view_(NULL),
350 drag_start_page_(-1), 350 drag_start_page_(-1),
351 #if defined(OS_WIN)
352 use_synchronous_drag_(true),
353 #endif
351 drag_pointer_(NONE), 354 drag_pointer_(NONE),
352 drop_attempt_(DROP_FOR_NONE), 355 drop_attempt_(DROP_FOR_NONE),
353 drag_and_drop_host_(NULL), 356 drag_and_drop_host_(NULL),
354 forward_events_to_drag_and_drop_host_(false), 357 forward_events_to_drag_and_drop_host_(false),
355 page_flip_target_(-1), 358 page_flip_target_(-1),
356 page_flip_delay_in_ms_(kPageFlipDelayInMs), 359 page_flip_delay_in_ms_(kPageFlipDelayInMs),
357 bounds_animator_(this), 360 bounds_animator_(this),
358 activated_folder_item_view_(NULL), 361 activated_folder_item_view_(NULL),
359 dragging_for_reparent_item_(false) { 362 dragging_for_reparent_item_(false) {
360 SetPaintToLayer(true); 363 SetPaintToLayer(true);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 void AppsGridView::ResetForShowApps() { 398 void AppsGridView::ResetForShowApps() {
396 activated_folder_item_view_ = NULL; 399 activated_folder_item_view_ = NULL;
397 ClearDragState(); 400 ClearDragState();
398 layer()->SetOpacity(1.0f); 401 layer()->SetOpacity(1.0f);
399 SetVisible(true); 402 SetVisible(true);
400 // Set all views to visible in case they weren't made visible again by an 403 // Set all views to visible in case they weren't made visible again by an
401 // incomplete animation. 404 // incomplete animation.
402 for (int i = 0; i < view_model_.view_size(); ++i) { 405 for (int i = 0; i < view_model_.view_size(); ++i) {
403 view_model_.view_at(i)->SetVisible(true); 406 view_model_.view_at(i)->SetVisible(true);
404 } 407 }
408 CHECK_EQ(item_list_->item_count(),
409 static_cast<size_t>(view_model_.view_size()));
405 } 410 }
406 411
407 void AppsGridView::SetModel(AppListModel* model) { 412 void AppsGridView::SetModel(AppListModel* model) {
408 if (model_) 413 if (model_)
409 model_->RemoveObserver(this); 414 model_->RemoveObserver(this);
410 415
411 model_ = model; 416 model_ = model;
412 if (model_) 417 if (model_)
413 model_->AddObserver(this); 418 model_->AddObserver(this);
414 419
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 drag_view_ = view; 475 drag_view_ = view;
471 drag_view_init_index_ = GetIndexOfView(drag_view_); 476 drag_view_init_index_ = GetIndexOfView(drag_view_);
472 drag_view_offset_ = event.location(); 477 drag_view_offset_ = event.location();
473 drag_start_page_ = pagination_model_->selected_page(); 478 drag_start_page_ = pagination_model_->selected_page();
474 ExtractDragLocation(event, &drag_start_grid_view_); 479 ExtractDragLocation(event, &drag_start_grid_view_);
475 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y()); 480 drag_view_start_ = gfx::Point(drag_view_->x(), drag_view_->y());
476 } 481 }
477 482
478 void AppsGridView::StartSettingUpSynchronousDrag() { 483 void AppsGridView::StartSettingUpSynchronousDrag() {
479 #if defined(OS_WIN) 484 #if defined(OS_WIN)
480 if (!delegate_) 485 if (!delegate_ || !use_synchronous_drag_)
481 return; 486 return;
482 487
483 // Folders can't be integrated with the OS. 488 // Folders can't be integrated with the OS.
484 if (IsFolderItem(drag_view_->item())) 489 if (IsFolderItem(drag_view_->item()))
485 return; 490 return;
486 491
487 // Favor the drag and drop host over native win32 drag. For the Win8/ash 492 // Favor the drag and drop host over native win32 drag. For the Win8/ash
488 // launcher we want to have ashes drag and drop over win32's. 493 // launcher we want to have ashes drag and drop over win32's.
489 if (drag_and_drop_host_) 494 if (drag_and_drop_host_)
490 return; 495 return;
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 drop_attempt_ = DROP_FOR_NONE; 810 drop_attempt_ = DROP_FOR_NONE;
806 drag_pointer_ = NONE; 811 drag_pointer_ = NONE;
807 drop_target_ = Index(); 812 drop_target_ = Index();
808 drag_start_grid_view_ = gfx::Point(); 813 drag_start_grid_view_ = gfx::Point();
809 drag_start_page_ = -1; 814 drag_start_page_ = -1;
810 drag_view_offset_ = gfx::Point(); 815 drag_view_offset_ = gfx::Point();
811 816
812 if (drag_view_) { 817 if (drag_view_) {
813 drag_view_->OnDragEnded(); 818 drag_view_->OnDragEnded();
814 if (IsDraggingForReparentInRootLevelGridView()) { 819 if (IsDraggingForReparentInRootLevelGridView()) {
815 DeleteItemViewAtIndex(view_model_.GetIndexOfView(drag_view_)); 820 const int drag_view_index = view_model_.GetIndexOfView(drag_view_);
821 CHECK_EQ(view_model_.view_size() - 1, drag_view_index);
822 DeleteItemViewAtIndex(drag_view_index);
816 } 823 }
817 } 824 }
818 drag_view_ = NULL; 825 drag_view_ = NULL;
819 dragging_for_reparent_item_ = false; 826 dragging_for_reparent_item_ = false;
820 } 827 }
821 828
822 void AppsGridView::SetDragViewVisible(bool visible) { 829 void AppsGridView::SetDragViewVisible(bool visible) {
823 DCHECK(drag_view_); 830 DCHECK(drag_view_);
824 SetViewHidden(drag_view_, !visible, true); 831 SetViewHidden(drag_view_, !visible, true);
825 } 832 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 bool handled = false; 939 bool handled = false;
933 if (selected_view_) 940 if (selected_view_)
934 handled = selected_view_->OnKeyReleased(event); 941 handled = selected_view_->OnKeyReleased(event);
935 942
936 return handled; 943 return handled;
937 } 944 }
938 945
939 void AppsGridView::ViewHierarchyChanged( 946 void AppsGridView::ViewHierarchyChanged(
940 const ViewHierarchyChangedDetails& details) { 947 const ViewHierarchyChangedDetails& details) {
941 if (!details.is_add && details.parent == this) { 948 if (!details.is_add && details.parent == this) {
949 // The view being delete should not have reference in |view_model_|.
950 CHECK_EQ(-1, view_model_.GetIndexOfView(details.child));
951
942 if (selected_view_ == details.child) 952 if (selected_view_ == details.child)
943 selected_view_ = NULL; 953 selected_view_ = NULL;
944 if (activated_folder_item_view_ == details.child) 954 if (activated_folder_item_view_ == details.child)
945 activated_folder_item_view_ = NULL; 955 activated_folder_item_view_ = NULL;
946 956
947 if (drag_view_ == details.child) 957 if (drag_view_ == details.child)
948 EndDrag(true); 958 EndDrag(true);
949 959
950 bounds_animator_.StopAnimatingView(details.child); 960 bounds_animator_.StopAnimatingView(details.child);
951 } 961 }
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 const Index& target) { 1696 const Index& target) {
1687 item_list_->RemoveObserver(this); 1697 item_list_->RemoveObserver(this);
1688 model_->RemoveObserver(this); 1698 model_->RemoveObserver(this);
1689 1699
1690 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item(); 1700 AppListItem* reparent_item = static_cast<AppListItemView*>(item_view)->item();
1691 DCHECK(reparent_item->IsInFolder()); 1701 DCHECK(reparent_item->IsInFolder());
1692 const std::string source_folder_id = reparent_item->folder_id(); 1702 const std::string source_folder_id = reparent_item->folder_id();
1693 AppListFolderItem* source_folder = 1703 AppListFolderItem* source_folder =
1694 static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id)); 1704 static_cast<AppListFolderItem*>(item_list_->FindItem(source_folder_id));
1695 1705
1706 int target_model_index = GetModelIndexFromIndex(target);
1707
1696 // Remove the source folder view if there is only 1 item in it, since the 1708 // Remove the source folder view if there is only 1 item in it, since the
1697 // source folder will be deleted after its only child item removed from it. 1709 // source folder will be deleted after its only child item removed from it.
1698 if (source_folder->ChildItemCount() == 1u) 1710 if (source_folder->ChildItemCount() == 1u) {
1699 DeleteItemViewAtIndex( 1711 const int deleted_folder_index =
1700 view_model_.GetIndexOfView(activated_folder_item_view())); 1712 view_model_.GetIndexOfView(activated_folder_item_view());
1713 DeleteItemViewAtIndex(deleted_folder_index);
1714
1715 // Adjust |target_model_index| if it is beyond the deleted folder index.
1716 if (target_model_index > deleted_folder_index)
1717 --target_model_index;
1718 }
1701 1719
1702 // Move the item from its parent folder to top level item list. 1720 // Move the item from its parent folder to top level item list.
1703 // Must move to target_model_index, the location we expect the target item 1721 // Must move to target_model_index, the location we expect the target item
1704 // to be, not the item location we want to insert before. 1722 // to be, not the item location we want to insert before.
1705 int target_model_index = GetModelIndexFromIndex(target);
1706 int current_model_index = view_model_.GetIndexOfView(item_view); 1723 int current_model_index = view_model_.GetIndexOfView(item_view);
1707 syncer::StringOrdinal target_position; 1724 syncer::StringOrdinal target_position;
1708 if (target_model_index < static_cast<int>(item_list_->item_count())) 1725 if (target_model_index < static_cast<int>(item_list_->item_count()))
1709 target_position = item_list_->item_at(target_model_index)->position(); 1726 target_position = item_list_->item_at(target_model_index)->position();
1710 model_->MoveItemToFolderAt(reparent_item, "", target_position); 1727 model_->MoveItemToFolderAt(reparent_item, "", target_position);
1711 view_model_.Move(current_model_index, target_model_index); 1728 view_model_.Move(current_model_index, target_model_index);
1712 1729
1713 RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id); 1730 RemoveLastItemFromReparentItemFolderIfNecessary(source_folder_id);
1714 1731
1715 item_list_->AddObserver(this); 1732 item_list_->AddObserver(this);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 // Delete view associated with the folder item to be removed. 1814 // Delete view associated with the folder item to be removed.
1798 DeleteItemViewAtIndex( 1815 DeleteItemViewAtIndex(
1799 view_model_.GetIndexOfView(activated_folder_item_view())); 1816 view_model_.GetIndexOfView(activated_folder_item_view()));
1800 1817
1801 // Now make the data change to remove the folder item in model. 1818 // Now make the data change to remove the folder item in model.
1802 AppListItem* last_item = source_folder->item_list()->item_at(0); 1819 AppListItem* last_item = source_folder->item_list()->item_at(0);
1803 model_->MoveItemToFolderAt(last_item, "", source_folder->position()); 1820 model_->MoveItemToFolderAt(last_item, "", source_folder->position());
1804 1821
1805 // Create a new item view for the last item in folder. 1822 // Create a new item view for the last item in folder.
1806 size_t last_item_index; 1823 size_t last_item_index;
1807 item_list_->FindItemIndex(last_item->id(), &last_item_index); 1824 if (!item_list_->FindItemIndex(last_item->id(), &last_item_index) ||
1825 last_item_index > static_cast<size_t>(view_model_.view_size())) {
1826 NOTREACHED();
1827 return;
1828 }
1808 views::View* last_item_view = CreateViewForItemAtIndex(last_item_index); 1829 views::View* last_item_view = CreateViewForItemAtIndex(last_item_index);
1809 view_model_.Add(last_item_view, last_item_index); 1830 view_model_.Add(last_item_view, last_item_index);
1810 AddChildView(last_item_view); 1831 AddChildView(last_item_view);
1811 } 1832 }
1812 1833
1813 void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) { 1834 void AppsGridView::CancelFolderItemReparent(AppListItemView* drag_item_view) {
1814 // The icon of the dragged item must target to its final ideal bounds after 1835 // The icon of the dragged item must target to its final ideal bounds after
1815 // the animation completes. 1836 // the animation completes.
1816 CalculateIdealBounds(); 1837 CalculateIdealBounds();
1817 1838
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 pt = drag_view_->bounds().bottom_right(); 2030 pt = drag_view_->bounds().bottom_right();
2010 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min); 2031 CalculateNearestTileForVertex(pt, &nearest_tile, &d_min);
2011 2032
2012 const int d_folder_dropping = 2033 const int d_folder_dropping =
2013 kFolderDroppingCircleRadius + kPreferredIconDimension / 2; 2034 kFolderDroppingCircleRadius + kPreferredIconDimension / 2;
2014 const int d_reorder = 2035 const int d_reorder =
2015 kReorderDroppingCircleRadius + kPreferredIconDimension / 2; 2036 kReorderDroppingCircleRadius + kPreferredIconDimension / 2;
2016 2037
2017 // If user drags an item across pages to the last page, and targets it 2038 // If user drags an item across pages to the last page, and targets it
2018 // to the last empty slot on it, push the last item for re-ordering. 2039 // to the last empty slot on it, push the last item for re-ordering.
2019 if (IsFirstEmptySlot(nearest_tile) && d_min < d_reorder) { 2040 if (IsLastPossibleDropTarget(nearest_tile) && d_min < d_reorder) {
2020 drop_attempt_ = DROP_FOR_REORDER; 2041 drop_attempt_ = DROP_FOR_REORDER;
2021 nearest_tile.slot = nearest_tile.slot - 1; 2042 nearest_tile.slot = nearest_tile.slot - 1;
2022 return nearest_tile; 2043 return nearest_tile;
2023 } 2044 }
2024 2045
2025 if (IsValidIndex(nearest_tile)) { 2046 if (IsValidIndex(nearest_tile)) {
2026 if (d_min < d_folder_dropping) { 2047 if (d_min < d_folder_dropping) {
2027 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot); 2048 views::View* target_view = GetViewAtSlotOnCurrentPage(nearest_tile.slot);
2028 if (target_view && 2049 if (target_view &&
2029 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) { 2050 !IsFolderItem(static_cast<AppListItemView*>(drag_view_)->item())) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2112 gfx::Rect grid_rect(gfx::Size(tile_size.width() * cols_, 2133 gfx::Rect grid_rect(gfx::Size(tile_size.width() * cols_,
2113 tile_size.height() * rows_per_page_)); 2134 tile_size.height() * rows_per_page_));
2114 grid_rect.Intersect(bounds); 2135 grid_rect.Intersect(bounds);
2115 gfx::Rect tile_rect( 2136 gfx::Rect tile_rect(
2116 gfx::Point(grid_rect.x() + col * tile_size.width(), 2137 gfx::Point(grid_rect.x() + col * tile_size.width(),
2117 grid_rect.y() + row * tile_size.height()), 2138 grid_rect.y() + row * tile_size.height()),
2118 tile_size); 2139 tile_size);
2119 return tile_rect; 2140 return tile_rect;
2120 } 2141 }
2121 2142
2122 bool AppsGridView::IsFirstEmptySlot(const Index& index) const { 2143 bool AppsGridView::IsLastPossibleDropTarget(const Index& index) const {
2123 // Don't count the hidden drag_view_ created from the item_dragged out of a 2144 int last_possible_slot = view_model_.view_size() % tiles_per_page();
2124 // folder during re-parenting into the total number of views that are visible
2125 // on all grid view pages.
2126 int total_views = IsDraggingForReparentInRootLevelGridView()
2127 ? view_model_.view_size() - 1
2128 : view_model_.view_size();
2129 int last_possible_slot = (total_views - 1) % tiles_per_page();
2130 return (index.page == pagination_model_->total_pages() - 1 && 2145 return (index.page == pagination_model_->total_pages() - 1 &&
2131 index.slot == last_possible_slot + 1); 2146 index.slot == last_possible_slot + 1);
2132 } 2147 }
2133 2148
2134 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) { 2149 views::View* AppsGridView::GetViewAtSlotOnCurrentPage(int slot) {
2135 if (slot < 0) 2150 if (slot < 0)
2136 return NULL; 2151 return NULL;
2137 2152
2138 // Calculate the original bound of the tile at |index|. 2153 // Calculate the original bound of the tile at |index|.
2139 int row = slot / cols_; 2154 int row = slot / cols_;
(...skipping 11 matching lines...) Expand all
2151 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index, 2166 void AppsGridView::SetAsFolderDroppingTarget(const Index& target_index,
2152 bool is_target_folder) { 2167 bool is_target_folder) {
2153 AppListItemView* target_view = 2168 AppListItemView* target_view =
2154 static_cast<AppListItemView*>( 2169 static_cast<AppListItemView*>(
2155 GetViewAtSlotOnCurrentPage(target_index.slot)); 2170 GetViewAtSlotOnCurrentPage(target_index.slot));
2156 if (target_view) 2171 if (target_view)
2157 target_view->SetAsAttemptedFolderTarget(is_target_folder); 2172 target_view->SetAsAttemptedFolderTarget(is_target_folder);
2158 } 2173 }
2159 2174
2160 } // namespace app_list 2175 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/views/apps_grid_view.h ('k') | ui/app_list/views/test/apps_grid_view_test_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698