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

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

Issue 8757007: Implement additional UI changes for dangerous download warnings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/ui/views/download/download_item_view.h" 5 #include "chrome/browser/ui/views/download/download_item_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 84
85 DownloadItemView::DownloadItemView(DownloadItem* download, 85 DownloadItemView::DownloadItemView(DownloadItem* download,
86 DownloadShelfView* parent, 86 DownloadShelfView* parent,
87 BaseDownloadItemModel* model) 87 BaseDownloadItemModel* model)
88 : warning_icon_(NULL), 88 : warning_icon_(NULL),
89 download_(download), 89 download_(download),
90 parent_(parent), 90 parent_(parent),
91 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), 91 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)),
92 body_state_(NORMAL), 92 body_state_(NORMAL),
93 drop_down_state_(NORMAL), 93 drop_down_state_(NORMAL),
94 mode_(NORMAL_MODE),
94 progress_angle_(download_util::kStartAngleDegrees), 95 progress_angle_(download_util::kStartAngleDegrees),
95 drop_down_pressed_(false), 96 drop_down_pressed_(false),
96 dragging_(false), 97 dragging_(false),
97 starting_drag_(false), 98 starting_drag_(false),
98 model_(model), 99 model_(model),
99 save_button_(NULL), 100 save_button_(NULL),
100 discard_button_(NULL), 101 discard_button_(NULL),
101 dangerous_download_label_(NULL), 102 dangerous_download_label_(NULL),
102 dangerous_download_label_sized_(false), 103 dangerous_download_label_sized_(false),
103 disabled_while_opening_(false), 104 disabled_while_opening_(false),
104 creation_time_(base::Time::Now()), 105 creation_time_(base::Time::Now()),
105 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) { 106 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
106 DCHECK(download_); 107 DCHECK(download_);
107 download_->AddObserver(this); 108 download_->AddObserver(this);
108 109
109 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 110 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
110 111
111 BodyImageSet normal_body_image_set = { 112 BodyImageSet normal_body_image_set = {
112 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), 113 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP),
113 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), 114 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE),
114 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), 115 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM),
115 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), 116 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP),
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), 175 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM),
175 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), 176 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP),
176 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), 177 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE),
177 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), 178 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM),
178 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD), 179 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD),
179 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD), 180 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD),
180 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD) 181 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD)
181 }; 182 };
182 dangerous_mode_body_image_set_ = dangerous_mode_body_image_set; 183 dangerous_mode_body_image_set_ = dangerous_mode_body_image_set;
183 184
185 malicious_mode_body_image_set_ = normal_body_image_set;
186
184 LoadIcon(); 187 LoadIcon();
185 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName(); 188 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName();
186 189
187 font_ = ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); 190 font_ = ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont);
188 box_height_ = std::max<int>(2 * kVerticalPadding + font_.GetHeight() + 191 box_height_ = std::max<int>(2 * kVerticalPadding + font_.GetHeight() +
189 kVerticalTextPadding + font_.GetHeight(), 192 kVerticalTextPadding + font_.GetHeight(),
190 2 * kVerticalPadding + 193 2 * kVerticalPadding +
191 normal_body_image_set_.top_left->height() + 194 normal_body_image_set_.top_left->height() +
192 normal_body_image_set_.bottom_left->height()); 195 normal_body_image_set_.bottom_left->height());
193 196
194 if (download_util::kSmallProgressIconSize > box_height_) 197 if (download_util::kSmallProgressIconSize > box_height_)
195 box_y_ = (download_util::kSmallProgressIconSize - box_height_) / 2; 198 box_y_ = (download_util::kSmallProgressIconSize - box_height_) / 2;
196 else 199 else
197 box_y_ = kVerticalPadding; 200 box_y_ = kVerticalPadding;
198 201
199 gfx::Size size = GetPreferredSize();
200 if (base::i18n::IsRTL()) {
201 // Drop down button is glued to the left of the download shelf.
202 drop_down_x_left_ = 0;
203 drop_down_x_right_ = normal_drop_down_image_set_.top->width();
204 } else {
205 // Drop down button is glued to the right of the download shelf.
206 drop_down_x_left_ =
207 size.width() - normal_drop_down_image_set_.top->width();
208 drop_down_x_right_ = size.width();
209 }
210
211 body_hover_animation_.reset(new ui::SlideAnimation(this)); 202 body_hover_animation_.reset(new ui::SlideAnimation(this));
212 drop_hover_animation_.reset(new ui::SlideAnimation(this)); 203 drop_hover_animation_.reset(new ui::SlideAnimation(this));
213 204
205 UpdateDropDownButtonPosition();
206
214 if (download->GetSafetyState() == DownloadItem::DANGEROUS) 207 if (download->GetSafetyState() == DownloadItem::DANGEROUS)
215 EnterDangerousMode(); 208 ShowWarningDialog();
216 209
217 UpdateAccessibleName(); 210 UpdateAccessibleName();
218 set_accessibility_focusable(true); 211 set_accessibility_focusable(true);
219 212
220 // Set up our animation. 213 // Set up our animation.
221 StartDownloadProgress(); 214 StartDownloadProgress();
222 } 215 }
223 216
224 DownloadItemView::~DownloadItemView() { 217 DownloadItemView::~DownloadItemView() {
225 if (context_menu_.get())
226 context_menu_->Stop();
227 icon_consumer_.CancelAllRequests(); 218 icon_consumer_.CancelAllRequests();
228 StopDownloadProgress(); 219 StopDownloadProgress();
229 download_->RemoveObserver(this); 220 download_->RemoveObserver(this);
230 } 221 }
231 222
232 // Progress animation handlers. 223 // Progress animation handlers.
233 224
234 void DownloadItemView::UpdateDownloadProgress() { 225 void DownloadItemView::UpdateDownloadProgress() {
235 progress_angle_ = (progress_angle_ + 226 progress_angle_ = (progress_angle_ +
236 download_util::kUnknownIncrementDegrees) % 227 download_util::kUnknownIncrementDegrees) %
(...skipping 19 matching lines...) Expand all
256 parent()->SchedulePaint(); 247 parent()->SchedulePaint();
257 } 248 }
258 249
259 // DownloadObserver interface. 250 // DownloadObserver interface.
260 251
261 // Update the progress graphic on the icon and our text status label 252 // Update the progress graphic on the icon and our text status label
262 // to reflect our current bytes downloaded, time remaining. 253 // to reflect our current bytes downloaded, time remaining.
263 void DownloadItemView::OnDownloadUpdated(DownloadItem* download) { 254 void DownloadItemView::OnDownloadUpdated(DownloadItem* download) {
264 DCHECK(download == download_); 255 DCHECK(download == download_);
265 256
266 if (body_state_ == DANGEROUS && 257 if (IsShowingWarningDialog() &&
267 download->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED) { 258 download->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
268 // We have been approved. 259 // We have been approved.
269 ClearDangerousMode(); 260 ClearWarningDialog();
270 } else if (body_state_ != DANGEROUS && 261 } else if (!IsShowingWarningDialog() &&
271 download->GetSafetyState() == DownloadItem::DANGEROUS) { 262 download->GetSafetyState() == DownloadItem::DANGEROUS) {
272 EnterDangerousMode(); 263 ShowWarningDialog();
273 // Force the shelf to layout again as our size has changed. 264 // Force the shelf to layout again as our size has changed.
274 parent_->Layout(); 265 parent_->Layout();
275 SchedulePaint(); 266 SchedulePaint();
276 } else { 267 } else {
277 string16 status_text = model_->GetStatusText(); 268 string16 status_text = model_->GetStatusText();
278 switch (download_->GetState()) { 269 switch (download_->GetState()) {
279 case DownloadItem::IN_PROGRESS: 270 case DownloadItem::IN_PROGRESS:
280 download_->IsPaused() ? 271 download_->IsPaused() ?
281 StopDownloadProgress() : StartDownloadProgress(); 272 StopDownloadProgress() : StartDownloadProgress();
282 LoadIconIfItemPathChanged(); 273 LoadIconIfItemPathChanged();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // for painting. 313 // for painting.
323 parent()->SchedulePaint(); 314 parent()->SchedulePaint();
324 } 315 }
325 316
326 void DownloadItemView::OnDownloadOpened(DownloadItem* download) { 317 void DownloadItemView::OnDownloadOpened(DownloadItem* download) {
327 disabled_while_opening_ = true; 318 disabled_while_opening_ = true;
328 SetEnabled(false); 319 SetEnabled(false);
329 MessageLoop::current()->PostDelayedTask( 320 MessageLoop::current()->PostDelayedTask(
330 FROM_HERE, 321 FROM_HERE,
331 base::Bind(&DownloadItemView::Reenable, 322 base::Bind(&DownloadItemView::Reenable,
332 reenable_method_factory_.GetWeakPtr()), 323 weak_ptr_factory_.GetWeakPtr()),
333 kDisabledOnOpenDuration); 324 kDisabledOnOpenDuration);
334 325
335 // Notify our parent. 326 // Notify our parent.
336 parent_->OpenedDownload(this); 327 parent_->OpenedDownload(this);
337 } 328 }
338 329
339 // View overrides 330 // View overrides
340 331
341 // In dangerous mode we have to layout our buttons. 332 // In dangerous mode we have to layout our buttons.
342 void DownloadItemView::Layout() { 333 void DownloadItemView::Layout() {
343 if (IsDangerousMode()) { 334 if (IsShowingWarningDialog()) {
335 BodyImageSet* body_image_set =
336 (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
337 &malicious_mode_body_image_set_;
344 dangerous_download_label_->SetEnabledColor( 338 dangerous_download_label_->SetEnabledColor(
345 GetThemeProvider()->GetColor(ThemeService::COLOR_BOOKMARK_TEXT)); 339 GetThemeProvider()->GetColor(ThemeService::COLOR_BOOKMARK_TEXT));
346 340
347 int x = kLeftPadding + dangerous_mode_body_image_set_.top_left->width() + 341 int x = kLeftPadding + body_image_set->top_left->width() +
348 warning_icon_->width() + kLabelPadding; 342 warning_icon_->width() + kLabelPadding;
349 int y = (height() - dangerous_download_label_->height()) / 2; 343 int y = (height() - dangerous_download_label_->height()) / 2;
350 dangerous_download_label_->SetBounds(x, y, 344 dangerous_download_label_->SetBounds(x, y,
351 dangerous_download_label_->width(), 345 dangerous_download_label_->width(),
352 dangerous_download_label_->height()); 346 dangerous_download_label_->height());
353 gfx::Size button_size = GetButtonSize(); 347 gfx::Size button_size = GetButtonSize();
354 x += dangerous_download_label_->width() + kLabelPadding; 348 x += dangerous_download_label_->width() + kLabelPadding;
355 y = (height() - button_size.height()) / 2; 349 y = (height() - button_size.height()) / 2;
356 save_button_->SetBounds(x, y, button_size.width(), button_size.height()); 350 if (save_button_) {
357 x += button_size.width() + kButtonPadding; 351 save_button_->SetBounds(x, y, button_size.width(), button_size.height());
352 x += button_size.width() + kButtonPadding;
353 }
358 discard_button_->SetBounds(x, y, button_size.width(), button_size.height()); 354 discard_button_->SetBounds(x, y, button_size.width(), button_size.height());
359 } 355 }
360 } 356 }
361 357
362 gfx::Size DownloadItemView::GetPreferredSize() { 358 gfx::Size DownloadItemView::GetPreferredSize() {
363 int width, height; 359 int width, height;
364 360
365 // First, we set the height to the height of two rows or text plus margins. 361 // First, we set the height to the height of two rows or text plus margins.
366 height = 2 * kVerticalPadding + 2 * font_.GetHeight() + kVerticalTextPadding; 362 height = 2 * kVerticalPadding + 2 * font_.GetHeight() + kVerticalTextPadding;
367 // Then we increase the size if the progress icon doesn't fit. 363 // Then we increase the size if the progress icon doesn't fit.
368 height = std::max<int>(height, download_util::kSmallProgressIconSize); 364 height = std::max<int>(height, download_util::kSmallProgressIconSize);
369 365
370 if (IsDangerousMode()) { 366 if (IsShowingWarningDialog()) {
371 width = kLeftPadding + dangerous_mode_body_image_set_.top_left->width(); 367 BodyImageSet* body_image_set =
368 (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
369 &malicious_mode_body_image_set_;
370 width = kLeftPadding + body_image_set->top_left->width();
372 width += warning_icon_->width() + kLabelPadding; 371 width += warning_icon_->width() + kLabelPadding;
373 width += dangerous_download_label_->width() + kLabelPadding; 372 width += dangerous_download_label_->width() + kLabelPadding;
374 gfx::Size button_size = GetButtonSize(); 373 gfx::Size button_size = GetButtonSize();
375 // Make sure the button fits. 374 // Make sure the button fits.
376 height = std::max<int>(height, 2 * kVerticalPadding + button_size.height()); 375 height = std::max<int>(height, 2 * kVerticalPadding + button_size.height());
377 // Then we make sure the warning icon fits. 376 // Then we make sure the warning icon fits.
378 height = std::max<int>(height, 2 * kVerticalPadding + 377 height = std::max<int>(height, 2 * kVerticalPadding +
379 warning_icon_->height()); 378 warning_icon_->height());
380 width += button_size.width() * 2 + kButtonPadding; 379 if (save_button_)
381 width += dangerous_mode_body_image_set_.top_right->width(); 380 width += button_size.width() + kButtonPadding;
381 width += button_size.width();
382 width += body_image_set->top_right->width();
383 if (mode_ == MALICIOUS_MODE)
384 width += normal_drop_down_image_set_.top->width();
382 } else { 385 } else {
383 width = kLeftPadding + normal_body_image_set_.top_left->width(); 386 width = kLeftPadding + normal_body_image_set_.top_left->width();
384 width += download_util::kSmallProgressIconSize; 387 width += download_util::kSmallProgressIconSize;
385 width += kTextWidth; 388 width += kTextWidth;
386 width += normal_body_image_set_.top_right->width(); 389 width += normal_body_image_set_.top_right->width();
387 width += normal_drop_down_image_set_.top->width(); 390 width += normal_drop_down_image_set_.top->width();
388 } 391 }
389 return gfx::Size(width, height); 392 return gfx::Size(width, height);
390 } 393 }
391 394
392 // Handle a mouse click and open the context menu if the mouse is 395 // Handle a mouse click and open the context menu if the mouse is
393 // over the drop-down region. 396 // over the drop-down region.
394 bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) { 397 bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) {
395 // Mouse should not activate us in dangerous mode. 398 // Mouse should not activate us in dangerous mode.
396 if (IsDangerousMode()) 399 if (mode_ == DANGEROUS_MODE)
397 return true; 400 return true;
398 401
399 // Stop any completion animation. 402 // Stop any completion animation.
400 if (complete_animation_.get() && complete_animation_->is_animating()) 403 if (complete_animation_.get() && complete_animation_->is_animating())
401 complete_animation_->End(); 404 complete_animation_->End();
402 405
403 if (event.IsOnlyLeftMouseButton()) { 406 if (event.IsOnlyLeftMouseButton()) {
404 if (InDropDownButtonXCoordinateRange(event.x())) { 407 if (InDropDownButtonXCoordinateRange(event.x())) {
405 drop_down_pressed_ = true; 408 drop_down_pressed_ = true;
406 SetState(NORMAL, PUSHED); 409 SetState(NORMAL, PUSHED);
407 // We are setting is_mouse_gesture to false when calling ShowContextMenu 410 // We are setting is_mouse_gesture to false when calling ShowContextMenu
408 // so that the positioning of the context menu will be similar to a 411 // so that the positioning of the context menu will be similar to a
409 // keyboard invocation. I.e. we want the menu to always be positioned 412 // keyboard invocation. I.e. we want the menu to always be positioned
410 // next to the drop down button instead of the next to the pointer. 413 // next to the drop down button instead of the next to the pointer.
411 ShowContextMenu(event.location(), false); 414 ShowContextMenu(event.location(), false);
412 } else { 415 // Once called, it is possible that *this was deleted (e.g.: due to
416 // invoking the 'Discard' action.)
417 } else if (!IsShowingWarningDialog()) {
413 SetState(PUSHED, NORMAL); 418 SetState(PUSHED, NORMAL);
414 } 419 }
415 } 420 }
416 return true; 421 return true;
417 } 422 }
418 423
419 // Handle drag (file copy) operations. 424 // Handle drag (file copy) operations.
420 bool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) { 425 bool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) {
421 // Mouse should not activate us in dangerous mode. 426 // Mouse should not activate us in dangerous mode.
422 if (IsDangerousMode()) 427 if (IsShowingWarningDialog())
423 return true; 428 return true;
424 429
425 if (!starting_drag_) { 430 if (!starting_drag_) {
426 starting_drag_ = true; 431 starting_drag_ = true;
427 drag_start_point_ = event.location(); 432 drag_start_point_ = event.location();
428 } 433 }
429 if (dragging_) { 434 if (dragging_) {
430 if (download_->IsComplete()) { 435 if (download_->IsComplete()) {
431 IconManager* im = g_browser_process->icon_manager(); 436 IconManager* im = g_browser_process->icon_manager();
432 gfx::Image* icon = im->LookupIcon(download_->GetUserVerifiedFilePath(), 437 gfx::Image* icon = im->LookupIcon(download_->GetUserVerifiedFilePath(),
433 IconLoader::SMALL); 438 IconLoader::SMALL);
434 if (icon) { 439 if (icon) {
435 views::Widget* widget = GetWidget(); 440 views::Widget* widget = GetWidget();
436 download_util::DragDownload(download_, icon, 441 download_util::DragDownload(download_, icon,
437 widget ? widget->GetNativeView() : NULL); 442 widget ? widget->GetNativeView() : NULL);
438 } 443 }
439 } 444 }
440 } else if (ExceededDragThreshold( 445 } else if (ExceededDragThreshold(
441 event.location().x() - drag_start_point_.x(), 446 event.location().x() - drag_start_point_.x(),
442 event.location().y() - drag_start_point_.y())) { 447 event.location().y() - drag_start_point_.y())) {
443 dragging_ = true; 448 dragging_ = true;
444 } 449 }
445 return true; 450 return true;
446 } 451 }
447 452
448 void DownloadItemView::OnMouseReleased(const views::MouseEvent& event) { 453 void DownloadItemView::OnMouseReleased(const views::MouseEvent& event) {
449 // Mouse should not activate us in dangerous mode. 454 // Mouse should not activate us in dangerous mode.
450 if (IsDangerousMode()) 455 if (mode_ == DANGEROUS_MODE)
451 return; 456 return;
452 457
453 if (event.IsOnlyLeftMouseButton() && 458 if (event.IsOnlyLeftMouseButton() &&
454 !InDropDownButtonXCoordinateRange(event.x())) { 459 !InDropDownButtonXCoordinateRange(event.x()) &&
460 !IsShowingWarningDialog()) {
455 OpenDownload(); 461 OpenDownload();
456 } 462 }
457 463
458 SetState(NORMAL, NORMAL); 464 SetState(NORMAL, NORMAL);
459 } 465 }
460 466
461 void DownloadItemView::OnMouseCaptureLost() { 467 void DownloadItemView::OnMouseCaptureLost() {
462 // Mouse should not activate us in dangerous mode. 468 // Mouse should not activate us in dangerous mode.
463 if (IsDangerousMode()) 469 if (mode_ == DANGEROUS_MODE)
464 return; 470 return;
465 471
466 if (dragging_) { 472 if (dragging_) {
467 // Starting a drag results in a MouseCaptureLost. 473 // Starting a drag results in a MouseCaptureLost.
468 dragging_ = false; 474 dragging_ = false;
469 starting_drag_ = false; 475 starting_drag_ = false;
470 } else { 476 } else {
471 SetState(NORMAL, NORMAL); 477 SetState(NORMAL, NORMAL);
472 } 478 }
473 } 479 }
474 480
475 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) { 481 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) {
476 // Mouse should not activate us in dangerous mode. 482 // Mouse should not activate us in dangerous mode.
477 if (IsDangerousMode()) 483 if (mode_ == DANGEROUS_MODE)
478 return; 484 return;
479 485
480 bool on_body = !InDropDownButtonXCoordinateRange(event.x()); 486 bool on_body = !InDropDownButtonXCoordinateRange(event.x());
481 SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT); 487 SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT);
482 if (on_body) { 488 if (on_body) {
483 body_hover_animation_->Show(); 489 if (!IsShowingWarningDialog())
490 body_hover_animation_->Show();
484 drop_hover_animation_->Hide(); 491 drop_hover_animation_->Hide();
485 } else { 492 } else {
486 body_hover_animation_->Hide(); 493 if (!IsShowingWarningDialog())
494 body_hover_animation_->Hide();
487 drop_hover_animation_->Show(); 495 drop_hover_animation_->Show();
488 } 496 }
489 } 497 }
490 498
491 void DownloadItemView::OnMouseExited(const views::MouseEvent& event) { 499 void DownloadItemView::OnMouseExited(const views::MouseEvent& event) {
492 // Mouse should not activate us in dangerous mode. 500 // Mouse should not activate us in dangerous mode.
493 if (IsDangerousMode()) 501 if (mode_ == DANGEROUS_MODE)
494 return; 502 return;
495 503
496 SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL); 504 SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL);
497 body_hover_animation_->Hide(); 505 if (!IsShowingWarningDialog())
506 body_hover_animation_->Hide();
498 drop_hover_animation_->Hide(); 507 drop_hover_animation_->Hide();
499 } 508 }
500 509
501 bool DownloadItemView::OnKeyPressed(const views::KeyEvent& event) { 510 bool DownloadItemView::OnKeyPressed(const views::KeyEvent& event) {
502 // Key press should not activate us in dangerous mode. 511 // Key press should not activate us in dangerous mode.
503 if (IsDangerousMode()) 512 if (IsShowingWarningDialog())
504 return true; 513 return true;
505 514
506 if (event.key_code() == ui::VKEY_SPACE || 515 if (event.key_code() == ui::VKEY_SPACE ||
507 event.key_code() == ui::VKEY_RETURN) { 516 event.key_code() == ui::VKEY_RETURN) {
508 OpenDownload(); 517 OpenDownload();
509 return true; 518 return true;
510 } 519 }
511 return false; 520 return false;
512 } 521 }
513 522
(...skipping 23 matching lines...) Expand all
537 SetMouseHandler(NULL); 546 SetMouseHandler(NULL);
538 547
539 // If |is_mouse_gesture| is false, |p| is ignored. The menu is shown aligned 548 // If |is_mouse_gesture| is false, |p| is ignored. The menu is shown aligned
540 // to drop down arrow button. 549 // to drop down arrow button.
541 if (!is_mouse_gesture) { 550 if (!is_mouse_gesture) {
542 drop_down_pressed_ = true; 551 drop_down_pressed_ = true;
543 SetState(NORMAL, PUSHED); 552 SetState(NORMAL, PUSHED);
544 point.SetPoint(drop_down_x_left_, box_y_); 553 point.SetPoint(drop_down_x_left_, box_y_);
545 size.SetSize(drop_down_x_right_ - drop_down_x_left_, box_height_); 554 size.SetSize(drop_down_x_right_ - drop_down_x_left_, box_height_);
546 } 555 }
547 556 // Post a task to release the button. When we call the Run method on the menu
557 // below, it runs an inner message loop that might cause us to be deleted.
558 // Posting a task with a WeakPtr lets us safely handle the button release.
559 MessageLoop::current()->PostNonNestableTask(
560 FROM_HERE,
561 base::Bind(&DownloadItemView::ReleaseDropDown,
562 weak_ptr_factory_.GetWeakPtr()));
548 views::View::ConvertPointToScreen(this, &point); 563 views::View::ConvertPointToScreen(this, &point);
549 564
550 if (!context_menu_.get()) 565 if (!context_menu_.get())
551 context_menu_.reset(new DownloadShelfContextMenuView(model_.get())); 566 context_menu_.reset(new DownloadShelfContextMenuView(model_.get()));
552 // When we call the Run method on the menu, it runs an inner message loop 567 context_menu_->Run(GetWidget()->GetTopLevelWidget(),
553 // that might causes us to be deleted. 568 gfx::Rect(point, size));
554 if (context_menu_->Run(GetWidget()->GetTopLevelWidget(), 569 // We could be deleted now.
555 gfx::Rect(point, size)))
556 return; // We have been deleted! Don't access 'this'.
557
558 // If the menu action was to remove the download, this view will also be
559 // invalid so we must not access 'this' in this case.
560 if (context_menu_->download_item()) {
561 drop_down_pressed_ = false;
562 // Showing the menu blocks. Here we revert the state.
563 SetState(NORMAL, NORMAL);
564 }
565 } 570 }
566 571
567 void DownloadItemView::GetAccessibleState(ui::AccessibleViewState* state) { 572 void DownloadItemView::GetAccessibleState(ui::AccessibleViewState* state) {
568 state->name = accessible_name_; 573 state->name = accessible_name_;
569 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 574 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
570 if (download_->GetSafetyState() == DownloadItem::DANGEROUS) { 575 if (download_->GetSafetyState() == DownloadItem::DANGEROUS) {
571 state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE; 576 state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE;
572 } else { 577 } else {
573 state->state = ui::AccessibilityTypes::STATE_HASPOPUP; 578 state->state = ui::AccessibilityTypes::STATE_HASPOPUP;
574 } 579 }
575 } 580 }
576 581
577 void DownloadItemView::ButtonPressed( 582 void DownloadItemView::ButtonPressed(
578 views::Button* sender, const views::Event& event) { 583 views::Button* sender, const views::Event& event) {
579 if (sender == discard_button_) { 584 if (sender == discard_button_) {
580 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", 585 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download",
581 base::Time::Now() - creation_time_); 586 base::Time::Now() - creation_time_);
582 if (download_->IsPartialDownload()) 587 if (download_->IsPartialDownload())
583 download_->Cancel(true); 588 download_->Cancel(true);
584 download_->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); 589 download_->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD);
585 // WARNING: we are deleted at this point. Don't access 'this'. 590 // WARNING: we are deleted at this point. Don't access 'this'.
586 } else if (sender == save_button_) { 591 } else if (save_button_ && sender == save_button_) {
587 // The user has confirmed a dangerous download. We'd record how quickly the 592 // The user has confirmed a dangerous download. We'd record how quickly the
588 // user did this to detect whether we're being clickjacked. 593 // user did this to detect whether we're being clickjacked.
589 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", 594 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download",
590 base::Time::Now() - creation_time_); 595 base::Time::Now() - creation_time_);
591 // This will change the state and notify us. 596 // This will change the state and notify us.
592 download_->DangerousDownloadValidated(); 597 download_->DangerousDownloadValidated();
593 } 598 }
594 } 599 }
595 600
596 void DownloadItemView::AnimationProgressed(const ui::Animation* animation) { 601 void DownloadItemView::AnimationProgressed(const ui::Animation* animation) {
597 // We don't care if what animation (body button/drop button/complete), 602 // We don't care if what animation (body button/drop button/complete),
598 // is calling back, as they all have to go through the same paint call. 603 // is calling back, as they all have to go through the same paint call.
599 SchedulePaint(); 604 SchedulePaint();
600 } 605 }
601 606
607 // The DownloadItemView can be in three major modes (NORMAL_MODE, DANGEROUS_MODE
608 // and MALICIOUS_MODE).
609 //
610 // NORMAL_MODE: We are displaying an in-progress or completed download.
611 // .-------------------------------+-.
612 // | [icon] Filename |v|
613 // | [ ] Status | |
614 // `-------------------------------+-'
615 // | | \_ Drop down button. Invokes menu. Responds
616 // | | to mouse. (NORMAL, HOT or PUSHED).
617 // | \_ Icon is overlaid on top of in-progress animation.
618 // \_ Both the body and the drop down button respond to mouse hover and can be
619 // pushed (NORMAL, HOT or PUSHED).
620 //
621 // DANGEROUS_MODE: The file could be potentially dangerous.
622 // .-------------------------------------------------------.
623 // | [ ! ] [This type of file can ] [ Keep ] [ Discard ] |
624 // | [ ] [destroy your computer..] [ ] [ ] |
625 // `-------------------------------------------------------'
626 // | | | | \_ No drop down button.
627 // | | | \_ Buttons are views::TextButtons.
628 // | | \_ Text is in a label (dangerous_download_label_)
629 // | \_ Warning icon. No progress animation.
630 // \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
631 //
632 // MALICIOUS_MODE: The file is known malware.
633 // .---------------------------------------------+-.
634 // | [ - ] [This file is malicious.] [ Discard ] |v|
635 // | [ ] [ ] [ ] | |-.
636 // `---------------------------------------------+-' |
637 // | | | | Drop down button. Responds to
638 // | | | | mouse.(NORMAL, HOT or PUSHED)
639 // | | | \_ Button is a views::TextButton.
640 // | | \_ Text is in a label (dangerous_download_label_)
641 // | \_ Warning icon. No progress animation.
642 // \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
643 //
602 void DownloadItemView::OnPaint(gfx::Canvas* canvas) { 644 void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
603 BodyImageSet* body_image_set = NULL; 645 BodyImageSet* body_image_set = NULL;
604 switch (body_state_) { 646 switch (mode_) {
605 case NORMAL: 647 case NORMAL_MODE:
606 case HOT: 648 if (body_state_ == PUSHED)
607 body_image_set = &normal_body_image_set_; 649 body_image_set = &pushed_body_image_set_;
650 else // NORMAL or HOT
651 body_image_set = &normal_body_image_set_;
608 break; 652 break;
609 case PUSHED: 653 case DANGEROUS_MODE:
610 body_image_set = &pushed_body_image_set_; 654 body_image_set = &dangerous_mode_body_image_set_;
611 break; 655 break;
612 case DANGEROUS: 656 case MALICIOUS_MODE:
613 body_image_set = &dangerous_mode_body_image_set_; 657 body_image_set = &malicious_mode_body_image_set_;
614 break; 658 break;
615 default: 659 default:
616 NOTREACHED(); 660 NOTREACHED();
617 } 661 }
662
618 DropDownImageSet* drop_down_image_set = NULL; 663 DropDownImageSet* drop_down_image_set = NULL;
619 switch (drop_down_state_) { 664 switch (mode_) {
620 case NORMAL: 665 case NORMAL_MODE:
621 case HOT: 666 case MALICIOUS_MODE:
622 drop_down_image_set = &normal_drop_down_image_set_; 667 if (drop_down_state_ == PUSHED)
668 drop_down_image_set = &pushed_drop_down_image_set_;
669 else // NORMAL or HOT
670 drop_down_image_set = &normal_drop_down_image_set_;
623 break; 671 break;
624 case PUSHED: 672 case DANGEROUS_MODE:
625 drop_down_image_set = &pushed_drop_down_image_set_; 673 // We don't use a drop down button for mode_ == DANGEROUS_MODE. So we let
626 break; 674 // drop_down_image_set == NULL.
627 case DANGEROUS:
628 drop_down_image_set = NULL; // No drop-down in dangerous mode.
629 break; 675 break;
630 default: 676 default:
631 NOTREACHED(); 677 NOTREACHED();
632 } 678 }
633 679
634 int center_width = width() - kLeftPadding - 680 int center_width = width() - kLeftPadding -
635 body_image_set->left->width() - 681 body_image_set->left->width() -
636 body_image_set->right->width() - 682 body_image_set->right->width() -
637 (drop_down_image_set ? 683 (drop_down_image_set ?
638 normal_drop_down_image_set_.center->width() : 684 normal_drop_down_image_set_.center->width() :
639 0); 685 0);
640 686
641 // May be caused by animation. 687 // May be caused by animation.
642 if (center_width <= 0) 688 if (center_width <= 0)
643 return; 689 return;
644 690
645 // Draw status before button image to effectively lighten text. 691 // Draw status before button image to effectively lighten text. No status for
646 if (!IsDangerousMode()) { 692 // warning dialogs.
693 if (!IsShowingWarningDialog()) {
647 if (!status_text_.empty()) { 694 if (!status_text_.empty()) {
648 int mirrored_x = GetMirroredXWithWidthInView( 695 int mirrored_x = GetMirroredXWithWidthInView(
649 download_util::kSmallProgressIconSize, kTextWidth); 696 download_util::kSmallProgressIconSize, kTextWidth);
650 // Add font_.height() to compensate for title, which is drawn later. 697 // Add font_.height() to compensate for title, which is drawn later.
651 int y = box_y_ + kVerticalPadding + font_.GetHeight() + 698 int y = box_y_ + kVerticalPadding + font_.GetHeight() +
652 kVerticalTextPadding; 699 kVerticalTextPadding;
653 SkColor file_name_color = GetThemeProvider()->GetColor( 700 SkColor file_name_color = GetThemeProvider()->GetColor(
654 ThemeService::COLOR_BOOKMARK_TEXT); 701 ThemeService::COLOR_BOOKMARK_TEXT);
655 // If text is light-on-dark, lightening it alone will do nothing. 702 // If text is light-on-dark, lightening it alone will do nothing.
656 // Therefore we mute luminance a wee bit before drawing in this case. 703 // Therefore we mute luminance a wee bit before drawing in this case.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 PaintBitmaps(canvas, 735 PaintBitmaps(canvas,
689 body_image_set->top, body_image_set->center, 736 body_image_set->top, body_image_set->center,
690 body_image_set->bottom, 737 body_image_set->bottom,
691 x, box_y_, box_height_, center_width); 738 x, box_y_, box_height_, center_width);
692 x += center_width; 739 x += center_width;
693 PaintBitmaps(canvas, 740 PaintBitmaps(canvas,
694 body_image_set->top_right, body_image_set->right, 741 body_image_set->top_right, body_image_set->right,
695 body_image_set->bottom_right, 742 body_image_set->bottom_right,
696 x, box_y_, box_height_, body_image_set->top_right->width()); 743 x, box_y_, box_height_, body_image_set->top_right->width());
697 744
698 // Overlay our body hot state. 745 // Overlay our body hot state. Warning dialogs don't display body a hot state.
699 if (body_hover_animation_->GetCurrentValue() > 0) { 746 if (!IsShowingWarningDialog() &&
747 body_hover_animation_->GetCurrentValue() > 0) {
700 canvas->SaveLayerAlpha( 748 canvas->SaveLayerAlpha(
701 static_cast<int>(body_hover_animation_->GetCurrentValue() * 255)); 749 static_cast<int>(body_hover_animation_->GetCurrentValue() * 255));
702 canvas->GetSkCanvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); 750 canvas->GetSkCanvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
703 751
704 int x = kLeftPadding; 752 int x = kLeftPadding;
705 PaintBitmaps(canvas, 753 PaintBitmaps(canvas,
706 hot_body_image_set_.top_left, hot_body_image_set_.left, 754 hot_body_image_set_.top_left, hot_body_image_set_.left,
707 hot_body_image_set_.bottom_left, 755 hot_body_image_set_.bottom_left,
708 x, box_y_, box_height_, hot_body_image_set_.top_left->width()); 756 x, box_y_, box_height_, hot_body_image_set_.top_left->width());
709 x += body_image_set->top_left->width(); 757 x += body_image_set->top_left->width();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 } 794 }
747 795
748 // Restore the canvas to avoid file name etc. text are drawn flipped. 796 // Restore the canvas to avoid file name etc. text are drawn flipped.
749 // Consequently, the x-axis of following canvas->DrawXXX() method should be 797 // Consequently, the x-axis of following canvas->DrawXXX() method should be
750 // mirrored so the text and images are down in the right positions. 798 // mirrored so the text and images are down in the right positions.
751 canvas->Restore(); 799 canvas->Restore();
752 800
753 // Print the text, left aligned and always print the file extension. 801 // Print the text, left aligned and always print the file extension.
754 // Last value of x was the end of the right image, just before the button. 802 // Last value of x was the end of the right image, just before the button.
755 // Note that in dangerous mode we use a label (as the text is multi-line). 803 // Note that in dangerous mode we use a label (as the text is multi-line).
756 if (!IsDangerousMode()) { 804 if (!IsShowingWarningDialog()) {
757 string16 filename; 805 string16 filename;
758 if (!disabled_while_opening_) { 806 if (!disabled_while_opening_) {
759 filename = ui::ElideFilename(download_->GetFileNameToReportUser(), 807 filename = ui::ElideFilename(download_->GetFileNameToReportUser(),
760 font_, kTextWidth); 808 font_, kTextWidth);
761 } else { 809 } else {
762 // First, Calculate the download status opening string width. 810 // First, Calculate the download status opening string width.
763 string16 status_string = 811 string16 status_string =
764 l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, string16()); 812 l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, string16());
765 int status_string_width = font_.GetStringWidth(status_string); 813 int status_string_width = font_.GetStringWidth(status_string);
766 // Then, elide the file name. 814 // Then, elide the file name.
(...skipping 18 matching lines...) Expand all
785 IsEnabled() ? file_name_color : 833 IsEnabled() ? file_name_color :
786 kFileNameDisabledColor, 834 kFileNameDisabledColor,
787 mirrored_x, y, kTextWidth, font_.GetHeight()); 835 mirrored_x, y, kTextWidth, font_.GetHeight());
788 } 836 }
789 837
790 // Load the icon. 838 // Load the icon.
791 IconManager* im = g_browser_process->icon_manager(); 839 IconManager* im = g_browser_process->icon_manager();
792 gfx::Image* image = im->LookupIcon(download_->GetUserVerifiedFilePath(), 840 gfx::Image* image = im->LookupIcon(download_->GetUserVerifiedFilePath(),
793 IconLoader::SMALL); 841 IconLoader::SMALL);
794 const SkBitmap* icon = NULL; 842 const SkBitmap* icon = NULL;
795 if (IsDangerousMode()) 843 if (IsShowingWarningDialog())
796 icon = warning_icon_; 844 icon = warning_icon_;
797 else if (image) 845 else if (image)
798 icon = *image; 846 icon = *image;
799 847
800 // We count on the fact that the icon manager will cache the icons and if one 848 // We count on the fact that the icon manager will cache the icons and if one
801 // is available, it will be cached here. We *don't* want to request the icon 849 // is available, it will be cached here. We *don't* want to request the icon
802 // to be loaded here, since this will also get called if the icon can't be 850 // to be loaded here, since this will also get called if the icon can't be
803 // loaded, in which case LookupIcon will always be NULL. The loading will be 851 // loaded, in which case LookupIcon will always be NULL. The loading will be
804 // triggered only when we think the status might change. 852 // triggered only when we think the status might change.
805 if (icon) { 853 if (icon) {
806 if (!IsDangerousMode()) { 854 if (!IsShowingWarningDialog()) {
807 if (download_->IsInProgress()) { 855 if (download_->IsInProgress()) {
808 download_util::PaintDownloadProgress(canvas, this, 0, 0, 856 download_util::PaintDownloadProgress(canvas, this, 0, 0,
809 progress_angle_, 857 progress_angle_,
810 download_->PercentComplete(), 858 download_->PercentComplete(),
811 download_util::SMALL); 859 download_util::SMALL);
812 } else if (download_->IsComplete() && 860 } else if (download_->IsComplete() &&
813 complete_animation_.get() && 861 complete_animation_.get() &&
814 complete_animation_->is_animating()) { 862 complete_animation_->is_animating()) {
815 if (download_->IsInterrupted()) { 863 if (download_->IsInterrupted()) {
816 download_util::PaintDownloadInterrupted(canvas, this, 0, 0, 864 download_util::PaintDownloadInterrupted(canvas, this, 0, 0,
817 complete_animation_->GetCurrentValue(), 865 complete_animation_->GetCurrentValue(),
818 download_util::SMALL); 866 download_util::SMALL);
819 } else { 867 } else {
820 download_util::PaintDownloadComplete(canvas, this, 0, 0, 868 download_util::PaintDownloadComplete(canvas, this, 0, 0,
821 complete_animation_->GetCurrentValue(), 869 complete_animation_->GetCurrentValue(),
822 download_util::SMALL); 870 download_util::SMALL);
823 } 871 }
824 } 872 }
825 } 873 }
826 874
827 // Draw the icon image. 875 // Draw the icon image.
828 int icon_x, icon_y; 876 int icon_x, icon_y;
829 877
830 if (IsDangerousMode()) { 878 if (IsShowingWarningDialog()) {
831 icon_x = kLeftPadding + body_image_set->top_left->width(); 879 icon_x = kLeftPadding + body_image_set->top_left->width();
832 icon_y = (height() - icon->height()) / 2; 880 icon_y = (height() - icon->height()) / 2;
833 } else { 881 } else {
834 icon_x = download_util::kSmallProgressIconOffset; 882 icon_x = download_util::kSmallProgressIconOffset;
835 icon_y = download_util::kSmallProgressIconOffset; 883 icon_y = download_util::kSmallProgressIconOffset;
836 } 884 }
837 icon_x = GetMirroredXWithWidthInView(icon_x, icon->width()); 885 icon_x = GetMirroredXWithWidthInView(icon_x, icon->width());
838 if (IsEnabled()) { 886 if (IsEnabled()) {
839 canvas->DrawBitmapInt(*icon, icon_x, icon_y); 887 canvas->DrawBitmapInt(*icon, icon_x, icon_y);
840 } else { 888 } else {
841 // Use an alpha to make the image look disabled. 889 // Use an alpha to make the image look disabled.
842 SkPaint paint; 890 SkPaint paint;
843 paint.setAlpha(120); 891 paint.setAlpha(120);
844 canvas->DrawBitmapInt(*icon, icon_x, icon_y, paint); 892 canvas->DrawBitmapInt(*icon, icon_x, icon_y, paint);
845 } 893 }
846 } 894 }
847 } 895 }
848 896
849 void DownloadItemView::OpenDownload() { 897 void DownloadItemView::OpenDownload() {
898 DCHECK(!IsShowingWarningDialog());
850 // We're interested in how long it takes users to open downloads. If they 899 // We're interested in how long it takes users to open downloads. If they
851 // open downloads super quickly, we should be concerned about clickjacking. 900 // open downloads super quickly, we should be concerned about clickjacking.
852 UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download", 901 UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
853 base::Time::Now() - creation_time_); 902 base::Time::Now() - creation_time_);
854 download_->OpenDownload(); 903 download_->OpenDownload();
855 UpdateAccessibleName(); 904 UpdateAccessibleName();
856 } 905 }
857 906
858 void DownloadItemView::LoadIcon() { 907 void DownloadItemView::LoadIcon() {
859 IconManager* im = g_browser_process->icon_manager(); 908 IconManager* im = g_browser_process->icon_manager();
(...skipping 30 matching lines...) Expand all
890 0, 0, center_bitmap->width(), center_bitmap->height(), 939 0, 0, center_bitmap->width(), center_bitmap->height(),
891 x, y, width, middle_height, false); 940 x, y, width, middle_height, false);
892 y += middle_height; 941 y += middle_height;
893 // Draw the bottom. 942 // Draw the bottom.
894 canvas->DrawBitmapInt(*bottom_bitmap, 943 canvas->DrawBitmapInt(*bottom_bitmap,
895 0, 0, bottom_bitmap->width(), bottom_bitmap->height(), 944 0, 0, bottom_bitmap->width(), bottom_bitmap->height(),
896 x, y, width, bottom_bitmap->height(), false); 945 x, y, width, bottom_bitmap->height(), false);
897 } 946 }
898 947
899 void DownloadItemView::SetState(State body_state, State drop_down_state) { 948 void DownloadItemView::SetState(State body_state, State drop_down_state) {
949 // If we are showing a warning dialog, we don't change body state.
950 if (IsShowingWarningDialog()) {
951 body_state = NORMAL;
952
953 // Current body_state_ should always be NORMAL for warning dialogs.
954 DCHECK(body_state_ == NORMAL);
955 // We shouldn't be calling SetState if we are in DANGEROUS_MODE.
956 DCHECK(mode_ != DANGEROUS_MODE);
957 }
958 // Avoid extra SchedulePaint()s if the state is going to be the same.
900 if (body_state_ == body_state && drop_down_state_ == drop_down_state) 959 if (body_state_ == body_state && drop_down_state_ == drop_down_state)
901 return; 960 return;
902 961
903 body_state_ = body_state; 962 body_state_ = body_state;
904 drop_down_state_ = drop_down_state; 963 drop_down_state_ = drop_down_state;
905 SchedulePaint(); 964 SchedulePaint();
906 } 965 }
907 966
908 void DownloadItemView::ClearDangerousMode() { 967 void DownloadItemView::ClearWarningDialog() {
909 DCHECK(download_->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED && 968 DCHECK(download_->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED &&
910 body_state_ == DANGEROUS && drop_down_state_ == DANGEROUS); 969 (mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE));
911 970
971 mode_ = NORMAL_MODE;
912 body_state_ = NORMAL; 972 body_state_ = NORMAL;
913 drop_down_state_ = NORMAL; 973 drop_down_state_ = NORMAL;
914 974
915 // Remove the views used by the dangerous mode. 975 // Remove the views used by the warning dialog.
916 RemoveChildView(save_button_); 976 if (save_button_) {
917 delete save_button_; 977 RemoveChildView(save_button_);
918 save_button_ = NULL; 978 delete save_button_;
979 save_button_ = NULL;
980 }
919 RemoveChildView(discard_button_); 981 RemoveChildView(discard_button_);
920 delete discard_button_; 982 delete discard_button_;
921 discard_button_ = NULL; 983 discard_button_ = NULL;
922 RemoveChildView(dangerous_download_label_); 984 RemoveChildView(dangerous_download_label_);
923 delete dangerous_download_label_; 985 delete dangerous_download_label_;
924 dangerous_download_label_ = NULL; 986 dangerous_download_label_ = NULL;
925 dangerous_download_label_sized_ = false; 987 dangerous_download_label_sized_ = false;
988 cached_button_size_.SetSize(0,0);
926 989
927 // Set the accessible name back to the status and filename instead of the 990 // Set the accessible name back to the status and filename instead of the
928 // download warning. 991 // download warning.
929 UpdateAccessibleName(); 992 UpdateAccessibleName();
993 UpdateDropDownButtonPosition();
930 994
931 // We need to load the icon now that the download_ has the real path. 995 // We need to load the icon now that the download_ has the real path.
932 LoadIcon(); 996 LoadIcon();
933 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName(); 997 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName();
934 998
935 // Force the shelf to layout again as our size has changed. 999 // Force the shelf to layout again as our size has changed.
936 parent_->Layout(); 1000 parent_->Layout();
937 parent_->SchedulePaint(); 1001 parent_->SchedulePaint();
938 } 1002 }
939 1003
940 void DownloadItemView::EnterDangerousMode() { 1004 void DownloadItemView::ShowWarningDialog() {
941 DCHECK(body_state_ != DANGEROUS && drop_down_state_ != DANGEROUS); 1005 DCHECK(mode_ != DANGEROUS_MODE && mode_ != MALICIOUS_MODE);
1006 if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL ||
1007 download_->GetDangerType() == DownloadStateInfo::DANGEROUS_CONTENT) {
1008 mode_ = MALICIOUS_MODE;
1009 } else {
1010 DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE);
1011 mode_ = DANGEROUS_MODE;
1012 }
1013 body_state_ = NORMAL;
1014 drop_down_state_ = NORMAL;
942 tooltip_text_.clear(); 1015 tooltip_text_.clear();
943 body_state_ = DANGEROUS; 1016 if (mode_ == DANGEROUS_MODE) {
944 drop_down_state_ = DANGEROUS; 1017 save_button_ = new views::NativeTextButton(this,
945 save_button_ = new views::NativeTextButton(this, 1018 l10n_util::GetStringUTF16(
946 l10n_util::GetStringUTF16( 1019 ChromeDownloadManagerDelegate::IsExtensionDownload(download_) ?
947 ChromeDownloadManagerDelegate::IsExtensionDownload(download_) ? 1020 IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD));
948 IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD)); 1021 save_button_->set_ignore_minimum_size(true);
949 save_button_->set_ignore_minimum_size(true); 1022 AddChildView(save_button_);
1023 }
950 discard_button_ = new views::NativeTextButton( 1024 discard_button_ = new views::NativeTextButton(
951 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); 1025 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
952 discard_button_->set_ignore_minimum_size(true); 1026 discard_button_->set_ignore_minimum_size(true);
953 AddChildView(save_button_);
954 AddChildView(discard_button_); 1027 AddChildView(discard_button_);
955 1028
956 // Ensure the file name is not too long. 1029 // Ensure the file name is not too long.
957 1030
958 // Extract the file extension (if any). 1031 // Extract the file extension (if any).
959 FilePath filename(download_->GetTargetName()); 1032 FilePath filename(download_->GetTargetName());
960 #if defined(OS_POSIX) 1033 #if defined(OS_POSIX)
961 string16 extension = WideToUTF16(base::SysNativeMBToWide( 1034 string16 extension = WideToUTF16(base::SysNativeMBToWide(
962 filename.Extension())); 1035 filename.Extension()));
963 #else 1036 #else
(...skipping 11 matching lines...) Expand all
975 #endif 1048 #endif
976 1049
977 // Elide giant extensions (this shouldn't currently be hit, but might 1050 // Elide giant extensions (this shouldn't currently be hit, but might
978 // in future, should we ever notice unsafe giant extensions). 1051 // in future, should we ever notice unsafe giant extensions).
979 if (extension.length() > kFileNameMaxLength / 2) 1052 if (extension.length() > kFileNameMaxLength / 2)
980 ui::ElideString(extension, kFileNameMaxLength / 2, &extension); 1053 ui::ElideString(extension, kFileNameMaxLength / 2, &extension);
981 1054
982 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1055 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
983 // The dangerous download label text and icon are different 1056 // The dangerous download label text and icon are different
984 // under different cases. 1057 // under different cases.
985 if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL || 1058 if (mode_ == MALICIOUS_MODE) {
986 download_->GetDangerType() == DownloadStateInfo::DANGEROUS_CONTENT) {
987 warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING); 1059 warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING);
988 } else { 1060 } else {
989 DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE); 1061 DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE);
1062 // The download file has dangerous file type (e.g.: an executable).
990 warning_icon_ = rb.GetBitmapNamed(IDR_WARNING); 1063 warning_icon_ = rb.GetBitmapNamed(IDR_WARNING);
991 } 1064 }
992 string16 dangerous_label; 1065 string16 dangerous_label;
993 if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL) { 1066 if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL) {
994 // Safebrowsing shows the download URL or content leads to malicious file. 1067 // Safebrowsing shows the download URL or content leads to malicious file.
995 dangerous_label = l10n_util::GetStringUTF16( 1068 dangerous_label = l10n_util::GetStringUTF16(
996 IDS_PROMPT_MALICIOUS_DOWNLOAD_URL); 1069 IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
997 } else if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE && 1070 } else if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE &&
998 ChromeDownloadManagerDelegate::IsExtensionDownload(download_)) { 1071 ChromeDownloadManagerDelegate::IsExtensionDownload(download_)) {
999 dangerous_label = 1072 dangerous_label =
(...skipping 10 matching lines...) Expand all
1010 filename = base::i18n::GetDisplayStringInLTRDirectionality(filename); 1083 filename = base::i18n::GetDisplayStringInLTRDirectionality(filename);
1011 dangerous_label = l10n_util::GetStringFUTF16( 1084 dangerous_label = l10n_util::GetStringFUTF16(
1012 download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE ? 1085 download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE ?
1013 IDS_PROMPT_DANGEROUS_DOWNLOAD : 1086 IDS_PROMPT_DANGEROUS_DOWNLOAD :
1014 IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT, 1087 IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
1015 filename); 1088 filename);
1016 } 1089 }
1017 1090
1018 dangerous_download_label_ = new views::Label(dangerous_label); 1091 dangerous_download_label_ = new views::Label(dangerous_label);
1019 dangerous_download_label_->SetMultiLine(true); 1092 dangerous_download_label_->SetMultiLine(true);
1020 dangerous_download_label_->SetHorizontalAlignment( 1093 dangerous_download_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1021 views::Label::ALIGN_LEFT);
1022 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); 1094 dangerous_download_label_->SetAutoColorReadabilityEnabled(false);
1023 AddChildView(dangerous_download_label_); 1095 AddChildView(dangerous_download_label_);
1024 SizeLabelToMinWidth(); 1096 SizeLabelToMinWidth();
1097 UpdateDropDownButtonPosition();
1025 } 1098 }
1026 1099
1027 gfx::Size DownloadItemView::GetButtonSize() { 1100 gfx::Size DownloadItemView::GetButtonSize() {
1028 DCHECK(save_button_ && discard_button_); 1101 DCHECK(discard_button_ && (mode_ == MALICIOUS_MODE || save_button_));
1029 gfx::Size size; 1102 gfx::Size size;
1030 1103
1031 // We cache the size when successfully retrieved, not for performance reasons 1104 // We cache the size when successfully retrieved, not for performance reasons
1032 // but because if this DownloadItemView is being animated while the tab is 1105 // but because if this DownloadItemView is being animated while the tab is
1033 // not showing, the native buttons are not parented and their preferred size 1106 // not showing, the native buttons are not parented and their preferred size
1034 // is 0, messing-up the layout. 1107 // is 0, messing-up the layout.
1035 if (cached_button_size_.width() != 0) 1108 if (cached_button_size_.width() != 0)
1036 return cached_button_size_; 1109 return cached_button_size_;
1037 1110
1038 size = save_button_->GetMinimumSize(); 1111 if (save_button_)
1112 size = save_button_->GetMinimumSize();
1039 gfx::Size discard_size = discard_button_->GetMinimumSize(); 1113 gfx::Size discard_size = discard_button_->GetMinimumSize();
1040 1114
1041 size.SetSize(std::max(size.width(), discard_size.width()), 1115 size.SetSize(std::max(size.width(), discard_size.width()),
1042 std::max(size.height(), discard_size.height())); 1116 std::max(size.height(), discard_size.height()));
1043 1117
1044 if (size.width() != 0) 1118 if (size.width() != 0)
1045 cached_button_size_ = size; 1119 cached_button_size_ = size;
1046 1120
1047 return size; 1121 return size;
1048 } 1122 }
1049 1123
1050 // This method computes the minimum width of the label for displaying its text 1124 // This method computes the minimum width of the label for displaying its text
1051 // on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the 1125 // on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the
1052 // configuration with minimum width. 1126 // configuration with minimum width.
1053 void DownloadItemView::SizeLabelToMinWidth() { 1127 void DownloadItemView::SizeLabelToMinWidth() {
1054 if (dangerous_download_label_sized_) 1128 if (dangerous_download_label_sized_)
1055 return; 1129 return;
1056 1130
1057 string16 text = dangerous_download_label_->GetText(); 1131 string16 text = dangerous_download_label_->GetText();
1058 TrimWhitespace(text, TRIM_ALL, &text); 1132 TrimWhitespace(text, TRIM_ALL, &text);
1059 DCHECK_EQ(string16::npos, text.find('\n')); 1133 DCHECK_EQ(string16::npos, text.find('\n'));
1060 1134
1061 // Make the label big so that GetPreferredSize() is not constrained by the 1135 // Make the label big so that GetPreferredSize() is not constrained by the
1062 // current width. 1136 // current width.
1063 dangerous_download_label_->SetBounds(0, 0, 1000, 1000); 1137 dangerous_download_label_->SetBounds(0, 0, 1000, 1000);
1064 1138
1065 gfx::Size size;
1066 int min_width = -1;
1067 // Using BREAK_WORD can work in most cases, but it can also break 1139 // Using BREAK_WORD can work in most cases, but it can also break
1068 // lines where it should not. Using BREAK_LINE is safer although 1140 // lines where it should not. Using BREAK_LINE is safer although
1069 // slower for Chinese/Japanese. This is not perf-critical at all, though. 1141 // slower for Chinese/Japanese. This is not perf-critical at all, though.
1070 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_LINE); 1142 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_LINE);
1071 bool status = iter.Init(); 1143 bool status = iter.Init();
1072 DCHECK(status); 1144 DCHECK(status);
1073 1145
1074 string16 current_text = text; 1146 string16 current_text = text;
1075 string16 prev_text = text; 1147 string16 prev_text = text;
1076 while (iter.Advance()) { 1148 gfx::Size size = dangerous_download_label_->GetPreferredSize();
1149 int min_width = size.width();
1150
1151 // Go through the string and try each line break (starting with no line break)
1152 // searching for the optimal line break position. Stop if we find one that
1153 // yields one that is less than kDangerousTextWidth wide. This is to prevent
1154 // a short string (e.g.: "This file is malicious") from being broken up
1155 // unnecessarily.
1156 while (iter.Advance() && min_width > kDangerousTextWidth) {
1077 size_t pos = iter.pos(); 1157 size_t pos = iter.pos();
1078 if (pos >= text.length()) 1158 if (pos >= text.length())
1079 break; 1159 break;
1080 // This can be a low surrogate codepoint, but u_isUWhiteSpace will 1160 // This can be a low surrogate codepoint, but u_isUWhiteSpace will
1081 // return false and inserting a new line after a surrogate pair 1161 // return false and inserting a new line after a surrogate pair
1082 // is perfectly ok. 1162 // is perfectly ok.
1083 char16 line_end_char = text[pos - 1]; 1163 char16 line_end_char = text[pos - 1];
1084 if (u_isUWhiteSpace(line_end_char)) 1164 if (u_isUWhiteSpace(line_end_char))
1085 current_text.replace(pos - 1, 1, 1, char16('\n')); 1165 current_text.replace(pos - 1, 1, 1, char16('\n'));
1086 else 1166 else
1087 current_text.insert(pos, 1, char16('\n')); 1167 current_text.insert(pos, 1, char16('\n'));
1088 dangerous_download_label_->SetText(current_text); 1168 dangerous_download_label_->SetText(current_text);
1089 size = dangerous_download_label_->GetPreferredSize(); 1169 size = dangerous_download_label_->GetPreferredSize();
1090 1170
1091 if (min_width == -1)
1092 min_width = size.width();
1093
1094 // If the width is growing again, it means we passed the optimal width spot. 1171 // If the width is growing again, it means we passed the optimal width spot.
1095 if (size.width() > min_width) { 1172 if (size.width() > min_width) {
1096 dangerous_download_label_->SetText(prev_text); 1173 dangerous_download_label_->SetText(prev_text);
1097 break; 1174 break;
1098 } else { 1175 } else {
1099 min_width = size.width(); 1176 min_width = size.width();
1100 } 1177 }
1101 1178
1102 // Restore the string. 1179 // Restore the string.
1103 prev_text = current_text; 1180 prev_text = current_text;
1104 current_text = text; 1181 current_text = text;
1105 } 1182 }
1106 1183
1107 // If we have a line with no line breaking opportunity (which is very
1108 // unlikely), we won't cut it.
1109 if (min_width == -1)
1110 size = dangerous_download_label_->GetPreferredSize();
1111
1112 dangerous_download_label_->SetBounds(0, 0, size.width(), size.height()); 1184 dangerous_download_label_->SetBounds(0, 0, size.width(), size.height());
1113 dangerous_download_label_sized_ = true; 1185 dangerous_download_label_sized_ = true;
1114 } 1186 }
1115 1187
1116 void DownloadItemView::Reenable() { 1188 void DownloadItemView::Reenable() {
1117 disabled_while_opening_ = false; 1189 disabled_while_opening_ = false;
1118 SetEnabled(true); // Triggers a repaint. 1190 SetEnabled(true); // Triggers a repaint.
1119 } 1191 }
1120 1192
1193 void DownloadItemView::ReleaseDropDown() {
1194 drop_down_pressed_ = false;
1195 SetState(NORMAL, NORMAL);
1196 }
1197
1121 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { 1198 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) {
1122 if (x > drop_down_x_left_ && x < drop_down_x_right_) 1199 if (x > drop_down_x_left_ && x < drop_down_x_right_)
1123 return true; 1200 return true;
1124 return false; 1201 return false;
1125 } 1202 }
1126 1203
1127 void DownloadItemView::UpdateAccessibleName() { 1204 void DownloadItemView::UpdateAccessibleName() {
1128 string16 new_name; 1205 string16 new_name;
1129 if (download_->GetSafetyState() == DownloadItem::DANGEROUS) { 1206 if (IsShowingWarningDialog()) {
1130 new_name = dangerous_download_label_->GetText(); 1207 new_name = dangerous_download_label_->GetText();
1131 } else { 1208 } else {
1132 new_name = status_text_ + char16(' ') + 1209 new_name = status_text_ + char16(' ') +
1133 download_->GetFileNameToReportUser().LossyDisplayName(); 1210 download_->GetFileNameToReportUser().LossyDisplayName();
1134 } 1211 }
1135 1212
1136 // If the name has changed, notify assistive technology that the name 1213 // If the name has changed, notify assistive technology that the name
1137 // has changed so they can announce it immediately. 1214 // has changed so they can announce it immediately.
1138 if (new_name != accessible_name_) { 1215 if (new_name != accessible_name_) {
1139 accessible_name_ = new_name; 1216 accessible_name_ = new_name;
1140 if (GetWidget()) { 1217 if (GetWidget()) {
1141 GetWidget()->NotifyAccessibilityEvent( 1218 GetWidget()->NotifyAccessibilityEvent(
1142 this, ui::AccessibilityTypes::EVENT_NAME_CHANGED, true); 1219 this, ui::AccessibilityTypes::EVENT_NAME_CHANGED, true);
1143 } 1220 }
1144 } 1221 }
1145 } 1222 }
1223
1224 void DownloadItemView::UpdateDropDownButtonPosition() {
1225 gfx::Size size = GetPreferredSize();
1226 if (base::i18n::IsRTL()) {
1227 // Drop down button is glued to the left of the download shelf.
1228 drop_down_x_left_ = 0;
1229 drop_down_x_right_ = normal_drop_down_image_set_.top->width();
1230 } else {
1231 // Drop down button is glued to the right of the download shelf.
1232 drop_down_x_left_ =
1233 size.width() - normal_drop_down_image_set_.top->width();
1234 drop_down_x_right_ = size.width();
1235 }
1236 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698