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

Side by Side Diff: chrome/browser/views/download_item_view.cc

Issue 213018: Fix a crash canceling a completed, auto-opened download (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 3 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 | « chrome/browser/views/download_item_view.h ('k') | no next file » | 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "chrome/browser/views/download_item_view.h" 5 #include "chrome/browser/views/download_item_view.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "app/gfx/canvas.h" 9 #include "app/gfx/canvas.h"
10 #include "app/gfx/text_elider.h" 10 #include "app/gfx/text_elider.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 // How long we keep the item disabled after the user clicked it to open the 66 // How long we keep the item disabled after the user clicked it to open the
67 // downloaded item. 67 // downloaded item.
68 static const int kDisabledOnOpenDuration = 3000; 68 static const int kDisabledOnOpenDuration = 3000;
69 69
70 // DownloadShelfContextMenuWin ------------------------------------------------- 70 // DownloadShelfContextMenuWin -------------------------------------------------
71 71
72 class DownloadShelfContextMenuWin : public DownloadShelfContextMenu, 72 class DownloadShelfContextMenuWin : public DownloadShelfContextMenu,
73 public views::Menu::Delegate { 73 public views::Menu::Delegate {
74 public: 74 public:
75 DownloadShelfContextMenuWin(BaseDownloadItemModel* model, 75 DownloadShelfContextMenuWin(BaseDownloadItemModel* model)
76 gfx::NativeView window,
77 const gfx::Point& point)
78 : DownloadShelfContextMenu(model) { 76 : DownloadShelfContextMenu(model) {
79 DCHECK(model); 77 DCHECK(model);
78 }
80 79
80 void Run(gfx::NativeView window, const gfx::Point& point) {
81 // The menu's anchor point is determined based on the UI layout. 81 // The menu's anchor point is determined based on the UI layout.
82 views::Menu::AnchorPoint anchor_point; 82 views::Menu::AnchorPoint anchor_point;
83 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) 83 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
84 anchor_point = views::Menu::TOPRIGHT; 84 anchor_point = views::Menu::TOPRIGHT;
85 else 85 else
86 anchor_point = views::Menu::TOPLEFT; 86 anchor_point = views::Menu::TOPLEFT;
87 87
88 scoped_ptr<views::Menu> context_menu( 88 scoped_ptr<views::Menu> context_menu(
89 views::Menu::Create(this, anchor_point, window)); 89 views::Menu::Create(this, anchor_point, window));
90 if (download_->state() == DownloadItem::COMPLETE) { 90 if (download_->state() == DownloadItem::COMPLETE) {
91 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", 91 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"",
92 views::Menu::NORMAL); 92 views::Menu::NORMAL);
93 } else { 93 } else {
94 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", 94 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"",
95 views::Menu::CHECKBOX); 95 views::Menu::CHECKBOX);
96 } 96 }
97 context_menu->AppendMenuItem(ALWAYS_OPEN_TYPE, L"", views::Menu::CHECKBOX); 97 context_menu->AppendMenuItem(ALWAYS_OPEN_TYPE, L"", views::Menu::CHECKBOX);
98 context_menu->AppendSeparator(); 98 context_menu->AppendSeparator();
99 if (download_->state() == DownloadItem::IN_PROGRESS) 99 if (download_->state() == DownloadItem::IN_PROGRESS)
100 context_menu->AppendMenuItem(TOGGLE_PAUSE, L"", views::Menu::NORMAL); 100 context_menu->AppendMenuItem(TOGGLE_PAUSE, L"", views::Menu::NORMAL);
101 context_menu->AppendMenuItem(SHOW_IN_FOLDER, L"", views::Menu::NORMAL); 101 context_menu->AppendMenuItem(SHOW_IN_FOLDER, L"", views::Menu::NORMAL);
102 context_menu->AppendSeparator(); 102 context_menu->AppendSeparator();
103 context_menu->AppendMenuItem(REMOVE_ITEM, L"", views::Menu::NORMAL); 103 context_menu->AppendMenuItem(REMOVE_ITEM, L"", views::Menu::NORMAL);
104 context_menu->AppendMenuItem(CANCEL, L"", views::Menu::NORMAL); 104 context_menu->AppendMenuItem(CANCEL, L"", views::Menu::NORMAL);
105 context_menu->RunMenuAt(point.x(), point.y()); 105 context_menu->RunMenuAt(point.x(), point.y());
106 } 106 }
107 107
108 // This method runs when the caller has been deleted and we should not attempt
109 // to access |download_|.
110 void Stop() {
111 download_ = NULL;
112 model_ = NULL;
113 }
114
108 // Menu::Delegate implementation --------------------------------------------- 115 // Menu::Delegate implementation ---------------------------------------------
109 116
110 virtual bool IsItemChecked(int id) const { 117 virtual bool IsItemChecked(int id) const {
118 if (!download_)
119 return false;
111 return ItemIsChecked(id); 120 return ItemIsChecked(id);
112 } 121 }
113 122
114 virtual bool IsItemDefault(int id) const { 123 virtual bool IsItemDefault(int id) const {
124 if (!download_)
125 return false;
115 return ItemIsDefault(id); 126 return ItemIsDefault(id);
116 } 127 }
117 128
118 virtual std::wstring GetLabel(int id) const { 129 virtual std::wstring GetLabel(int id) const {
130 if (!download_)
131 return std::wstring();
119 return GetItemLabel(id); 132 return GetItemLabel(id);
120 } 133 }
121 134
122 virtual bool SupportsCommand(int id) const { 135 virtual bool SupportsCommand(int id) const {
136 if (!download_)
137 return false;
123 return id > 0 && id < MENU_LAST; 138 return id > 0 && id < MENU_LAST;
124 } 139 }
125 140
126 virtual bool IsCommandEnabled(int id) const { 141 virtual bool IsCommandEnabled(int id) const {
142 if (!download_)
143 return false;
127 return IsItemCommandEnabled(id); 144 return IsItemCommandEnabled(id);
128 } 145 }
129 146
130 virtual void ExecuteCommand(int id) { 147 virtual void ExecuteCommand(int id) {
131 return ExecuteItemCommand(id); 148 if (download_)
149 ExecuteItemCommand(id);
132 } 150 }
133 }; 151 };
134 152
135 // DownloadItemView ------------------------------------------------------------ 153 // DownloadItemView ------------------------------------------------------------
136 154
137 DownloadItemView::DownloadItemView(DownloadItem* download, 155 DownloadItemView::DownloadItemView(DownloadItem* download,
138 DownloadShelfView* parent, 156 DownloadShelfView* parent,
139 BaseDownloadItemModel* model) 157 BaseDownloadItemModel* model)
140 : warning_icon_(NULL), 158 : warning_icon_(NULL),
141 download_(download), 159 download_(download),
142 parent_(parent), 160 parent_(parent),
143 status_text_(l10n_util::GetString(IDS_DOWNLOAD_STATUS_STARTING)), 161 status_text_(l10n_util::GetString(IDS_DOWNLOAD_STATUS_STARTING)),
144 show_status_text_(true), 162 show_status_text_(true),
145 body_state_(NORMAL), 163 body_state_(NORMAL),
146 drop_down_state_(NORMAL), 164 drop_down_state_(NORMAL),
147 progress_angle_(download_util::kStartAngleDegrees), 165 progress_angle_(download_util::kStartAngleDegrees),
148 drop_down_pressed_(false), 166 drop_down_pressed_(false),
149 dragging_(false), 167 dragging_(false),
150 starting_drag_(false), 168 starting_drag_(false),
151 model_(model), 169 model_(model),
152 save_button_(NULL), 170 save_button_(NULL),
153 discard_button_(NULL), 171 discard_button_(NULL),
154 dangerous_download_label_(NULL), 172 dangerous_download_label_(NULL),
155 dangerous_download_label_sized_(false), 173 dangerous_download_label_sized_(false),
156 disabled_while_opening_(false), 174 disabled_while_opening_(false),
157 creation_time_(base::Time::Now()), 175 creation_time_(base::Time::Now()),
158 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) { 176 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)),
177 active_menu_(NULL) {
159 DCHECK(download_); 178 DCHECK(download_);
160 download_->AddObserver(this); 179 download_->AddObserver(this);
161 180
162 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); 181 ResourceBundle &rb = ResourceBundle::GetSharedInstance();
163 182
164 BodyImageSet normal_body_image_set = { 183 BodyImageSet normal_body_image_set = {
165 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), 184 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP),
166 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), 185 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE),
167 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), 186 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM),
168 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), 187 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP),
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 views::Label::ALIGN_LEFT); 332 views::Label::ALIGN_LEFT);
314 AddChildView(dangerous_download_label_); 333 AddChildView(dangerous_download_label_);
315 SizeLabelToMinWidth(); 334 SizeLabelToMinWidth();
316 } 335 }
317 336
318 // Set up our animation. 337 // Set up our animation.
319 StartDownloadProgress(); 338 StartDownloadProgress();
320 } 339 }
321 340
322 DownloadItemView::~DownloadItemView() { 341 DownloadItemView::~DownloadItemView() {
342 if (active_menu_) {
343 active_menu_->Stop();
344 active_menu_ = NULL;
345 }
323 icon_consumer_.CancelAllRequests(); 346 icon_consumer_.CancelAllRequests();
324 StopDownloadProgress(); 347 StopDownloadProgress();
325 download_->RemoveObserver(this); 348 download_->RemoveObserver(this);
326 } 349 }
327 350
328 // Progress animation handlers. 351 // Progress animation handlers.
329 352
330 void DownloadItemView::UpdateDownloadProgress() { 353 void DownloadItemView::UpdateDownloadProgress() {
331 progress_angle_ = (progress_angle_ + 354 progress_angle_ = (progress_angle_ +
332 download_util::kUnknownIncrementDegrees) % 355 download_util::kUnknownIncrementDegrees) %
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 // The menu's position is different depending on the UI layout. 833 // The menu's position is different depending on the UI layout.
811 // DownloadShelfContextMenu will take care of setting the right anchor for 834 // DownloadShelfContextMenu will take care of setting the right anchor for
812 // the menu depending on the locale. 835 // the menu depending on the locale.
813 point.set_y(height()); 836 point.set_y(height());
814 if (UILayoutIsRightToLeft()) 837 if (UILayoutIsRightToLeft())
815 point.set_x(drop_down_x_right_); 838 point.set_x(drop_down_x_right_);
816 else 839 else
817 point.set_x(drop_down_x_left_); 840 point.set_x(drop_down_x_left_);
818 841
819 views::View::ConvertPointToScreen(this, &point); 842 views::View::ConvertPointToScreen(this, &point);
820 DownloadShelfContextMenuWin menu(model_.get(), 843 DownloadShelfContextMenuWin menu(model_.get());
821 GetWidget()->GetNativeView(), 844
822 point); 845 // Protect against deletion while the menu is running. This can happen if
846 // the menu is showing when an auto-opened download completes and the user
847 // chooses a menu entry.
848 active_menu_ = &menu;
849 menu.Run(GetWidget()->GetNativeView(), point);
850
823 // If the menu action was to remove the download, this view will also be 851 // If the menu action was to remove the download, this view will also be
824 // invalid so we must not access 'this' in this case. 852 // invalid so we must not access 'this' in this case.
825 if (menu.download()) { 853 if (menu.download()) {
854 active_menu_ = NULL;
826 drop_down_pressed_ = false; 855 drop_down_pressed_ = false;
827 // Showing the menu blocks. Here we revert the state. 856 // Showing the menu blocks. Here we revert the state.
828 SetState(NORMAL, NORMAL); 857 SetState(NORMAL, NORMAL);
829 } 858 }
830 } 859 }
831 return true; 860 return true;
832 } 861 }
833 862
834 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) { 863 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) {
835 // Mouse should not activate us in dangerous mode. 864 // Mouse should not activate us in dangerous mode.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 void DownloadItemView::Reenable() { 1023 void DownloadItemView::Reenable() {
995 disabled_while_opening_ = false; 1024 disabled_while_opening_ = false;
996 SetEnabled(true); // Triggers a repaint. 1025 SetEnabled(true); // Triggers a repaint.
997 } 1026 }
998 1027
999 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { 1028 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) {
1000 if (x > drop_down_x_left_ && x < drop_down_x_right_) 1029 if (x > drop_down_x_left_ && x < drop_down_x_right_)
1001 return true; 1030 return true;
1002 return false; 1031 return false;
1003 } 1032 }
OLDNEW
« no previous file with comments | « chrome/browser/views/download_item_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698