| Index: chrome/browser/ui/views/download/download_item_view.cc
|
| diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
|
| index b6294b5bfbe60c35909eb0b48431d3ecbe0b96ae..c37cc915edbedfe1cde8178ec36406bd83fe7d2a 100644
|
| --- a/chrome/browser/ui/views/download/download_item_view.cc
|
| +++ b/chrome/browser/ui/views/download/download_item_view.cc
|
| @@ -91,6 +91,7 @@ DownloadItemView::DownloadItemView(DownloadItem* download,
|
| status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)),
|
| body_state_(NORMAL),
|
| drop_down_state_(NORMAL),
|
| + mode_(NORMAL_MODE),
|
| progress_angle_(download_util::kStartAngleDegrees),
|
| drop_down_pressed_(false),
|
| dragging_(false),
|
| @@ -102,7 +103,7 @@ DownloadItemView::DownloadItemView(DownloadItem* download,
|
| dangerous_download_label_sized_(false),
|
| disabled_while_opening_(false),
|
| creation_time_(base::Time::Now()),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) {
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
|
| DCHECK(download_);
|
| download_->AddObserver(this);
|
|
|
| @@ -181,6 +182,8 @@ DownloadItemView::DownloadItemView(DownloadItem* download,
|
| };
|
| dangerous_mode_body_image_set_ = dangerous_mode_body_image_set;
|
|
|
| + malicious_mode_body_image_set_ = normal_body_image_set;
|
| +
|
| LoadIcon();
|
| tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName();
|
|
|
| @@ -196,23 +199,13 @@ DownloadItemView::DownloadItemView(DownloadItem* download,
|
| else
|
| box_y_ = kVerticalPadding;
|
|
|
| - gfx::Size size = GetPreferredSize();
|
| - if (base::i18n::IsRTL()) {
|
| - // Drop down button is glued to the left of the download shelf.
|
| - drop_down_x_left_ = 0;
|
| - drop_down_x_right_ = normal_drop_down_image_set_.top->width();
|
| - } else {
|
| - // Drop down button is glued to the right of the download shelf.
|
| - drop_down_x_left_ =
|
| - size.width() - normal_drop_down_image_set_.top->width();
|
| - drop_down_x_right_ = size.width();
|
| - }
|
| -
|
| body_hover_animation_.reset(new ui::SlideAnimation(this));
|
| drop_hover_animation_.reset(new ui::SlideAnimation(this));
|
|
|
| + UpdateDropDownButtonPosition();
|
| +
|
| if (download->GetSafetyState() == DownloadItem::DANGEROUS)
|
| - EnterDangerousMode();
|
| + ShowWarningDialog();
|
|
|
| UpdateAccessibleName();
|
| set_accessibility_focusable(true);
|
| @@ -222,8 +215,6 @@ DownloadItemView::DownloadItemView(DownloadItem* download,
|
| }
|
|
|
| DownloadItemView::~DownloadItemView() {
|
| - if (context_menu_.get())
|
| - context_menu_->Stop();
|
| icon_consumer_.CancelAllRequests();
|
| StopDownloadProgress();
|
| download_->RemoveObserver(this);
|
| @@ -263,13 +254,13 @@ void DownloadItemView::OnExtractIconComplete(IconManager::Handle handle,
|
| void DownloadItemView::OnDownloadUpdated(DownloadItem* download) {
|
| DCHECK(download == download_);
|
|
|
| - if (body_state_ == DANGEROUS &&
|
| + if (IsShowingWarningDialog() &&
|
| download->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
|
| // We have been approved.
|
| - ClearDangerousMode();
|
| - } else if (body_state_ != DANGEROUS &&
|
| - download->GetSafetyState() == DownloadItem::DANGEROUS) {
|
| - EnterDangerousMode();
|
| + ClearWarningDialog();
|
| + } else if (!IsShowingWarningDialog() &&
|
| + download->GetSafetyState() == DownloadItem::DANGEROUS) {
|
| + ShowWarningDialog();
|
| // Force the shelf to layout again as our size has changed.
|
| parent_->Layout();
|
| SchedulePaint();
|
| @@ -329,7 +320,7 @@ void DownloadItemView::OnDownloadOpened(DownloadItem* download) {
|
| MessageLoop::current()->PostDelayedTask(
|
| FROM_HERE,
|
| base::Bind(&DownloadItemView::Reenable,
|
| - reenable_method_factory_.GetWeakPtr()),
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| kDisabledOnOpenDuration);
|
|
|
| // Notify our parent.
|
| @@ -340,12 +331,15 @@ void DownloadItemView::OnDownloadOpened(DownloadItem* download) {
|
|
|
| // In dangerous mode we have to layout our buttons.
|
| void DownloadItemView::Layout() {
|
| - if (IsDangerousMode()) {
|
| + if (IsShowingWarningDialog()) {
|
| + BodyImageSet* body_image_set =
|
| + (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
|
| + &malicious_mode_body_image_set_;
|
| dangerous_download_label_->SetEnabledColor(
|
| GetThemeProvider()->GetColor(ThemeService::COLOR_BOOKMARK_TEXT));
|
|
|
| - int x = kLeftPadding + dangerous_mode_body_image_set_.top_left->width() +
|
| - warning_icon_->width() + kLabelPadding;
|
| + int x = kLeftPadding + body_image_set->top_left->width() +
|
| + warning_icon_->width() + kLabelPadding;
|
| int y = (height() - dangerous_download_label_->height()) / 2;
|
| dangerous_download_label_->SetBounds(x, y,
|
| dangerous_download_label_->width(),
|
| @@ -353,8 +347,10 @@ void DownloadItemView::Layout() {
|
| gfx::Size button_size = GetButtonSize();
|
| x += dangerous_download_label_->width() + kLabelPadding;
|
| y = (height() - button_size.height()) / 2;
|
| - save_button_->SetBounds(x, y, button_size.width(), button_size.height());
|
| - x += button_size.width() + kButtonPadding;
|
| + if (save_button_) {
|
| + save_button_->SetBounds(x, y, button_size.width(), button_size.height());
|
| + x += button_size.width() + kButtonPadding;
|
| + }
|
| discard_button_->SetBounds(x, y, button_size.width(), button_size.height());
|
| }
|
| }
|
| @@ -367,8 +363,11 @@ gfx::Size DownloadItemView::GetPreferredSize() {
|
| // Then we increase the size if the progress icon doesn't fit.
|
| height = std::max<int>(height, download_util::kSmallProgressIconSize);
|
|
|
| - if (IsDangerousMode()) {
|
| - width = kLeftPadding + dangerous_mode_body_image_set_.top_left->width();
|
| + if (IsShowingWarningDialog()) {
|
| + BodyImageSet* body_image_set =
|
| + (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
|
| + &malicious_mode_body_image_set_;
|
| + width = kLeftPadding + body_image_set->top_left->width();
|
| width += warning_icon_->width() + kLabelPadding;
|
| width += dangerous_download_label_->width() + kLabelPadding;
|
| gfx::Size button_size = GetButtonSize();
|
| @@ -377,8 +376,12 @@ gfx::Size DownloadItemView::GetPreferredSize() {
|
| // Then we make sure the warning icon fits.
|
| height = std::max<int>(height, 2 * kVerticalPadding +
|
| warning_icon_->height());
|
| - width += button_size.width() * 2 + kButtonPadding;
|
| - width += dangerous_mode_body_image_set_.top_right->width();
|
| + if (save_button_)
|
| + width += button_size.width() + kButtonPadding;
|
| + width += button_size.width();
|
| + width += body_image_set->top_right->width();
|
| + if (mode_ == MALICIOUS_MODE)
|
| + width += normal_drop_down_image_set_.top->width();
|
| } else {
|
| width = kLeftPadding + normal_body_image_set_.top_left->width();
|
| width += download_util::kSmallProgressIconSize;
|
| @@ -393,7 +396,7 @@ gfx::Size DownloadItemView::GetPreferredSize() {
|
| // over the drop-down region.
|
| bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (mode_ == DANGEROUS_MODE)
|
| return true;
|
|
|
| // Stop any completion animation.
|
| @@ -409,7 +412,9 @@ bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) {
|
| // keyboard invocation. I.e. we want the menu to always be positioned
|
| // next to the drop down button instead of the next to the pointer.
|
| ShowContextMenu(event.location(), false);
|
| - } else {
|
| + // Once called, it is possible that *this was deleted (e.g.: due to
|
| + // invoking the 'Discard' action.)
|
| + } else if (!IsShowingWarningDialog()) {
|
| SetState(PUSHED, NORMAL);
|
| }
|
| }
|
| @@ -419,7 +424,7 @@ bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) {
|
| // Handle drag (file copy) operations.
|
| bool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (IsShowingWarningDialog())
|
| return true;
|
|
|
| if (!starting_drag_) {
|
| @@ -447,11 +452,12 @@ bool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) {
|
|
|
| void DownloadItemView::OnMouseReleased(const views::MouseEvent& event) {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (mode_ == DANGEROUS_MODE)
|
| return;
|
|
|
| if (event.IsOnlyLeftMouseButton() &&
|
| - !InDropDownButtonXCoordinateRange(event.x())) {
|
| + !InDropDownButtonXCoordinateRange(event.x()) &&
|
| + !IsShowingWarningDialog()) {
|
| OpenDownload();
|
| }
|
|
|
| @@ -460,7 +466,7 @@ void DownloadItemView::OnMouseReleased(const views::MouseEvent& event) {
|
|
|
| void DownloadItemView::OnMouseCaptureLost() {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (mode_ == DANGEROUS_MODE)
|
| return;
|
|
|
| if (dragging_) {
|
| @@ -474,33 +480,36 @@ void DownloadItemView::OnMouseCaptureLost() {
|
|
|
| void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (mode_ == DANGEROUS_MODE)
|
| return;
|
|
|
| bool on_body = !InDropDownButtonXCoordinateRange(event.x());
|
| SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT);
|
| if (on_body) {
|
| - body_hover_animation_->Show();
|
| + if (!IsShowingWarningDialog())
|
| + body_hover_animation_->Show();
|
| drop_hover_animation_->Hide();
|
| } else {
|
| - body_hover_animation_->Hide();
|
| + if (!IsShowingWarningDialog())
|
| + body_hover_animation_->Hide();
|
| drop_hover_animation_->Show();
|
| }
|
| }
|
|
|
| void DownloadItemView::OnMouseExited(const views::MouseEvent& event) {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (mode_ == DANGEROUS_MODE)
|
| return;
|
|
|
| SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL);
|
| - body_hover_animation_->Hide();
|
| + if (!IsShowingWarningDialog())
|
| + body_hover_animation_->Hide();
|
| drop_hover_animation_->Hide();
|
| }
|
|
|
| bool DownloadItemView::OnKeyPressed(const views::KeyEvent& event) {
|
| // Key press should not activate us in dangerous mode.
|
| - if (IsDangerousMode())
|
| + if (IsShowingWarningDialog())
|
| return true;
|
|
|
| if (event.key_code() == ui::VKEY_SPACE ||
|
| @@ -544,24 +553,20 @@ void DownloadItemView::ShowContextMenu(const gfx::Point& p,
|
| point.SetPoint(drop_down_x_left_, box_y_);
|
| size.SetSize(drop_down_x_right_ - drop_down_x_left_, box_height_);
|
| }
|
| -
|
| + // Post a task to release the button. When we call the Run method on the menu
|
| + // below, it runs an inner message loop that might cause us to be deleted.
|
| + // Posting a task with a WeakPtr lets us safely handle the button release.
|
| + MessageLoop::current()->PostNonNestableTask(
|
| + FROM_HERE,
|
| + base::Bind(&DownloadItemView::ReleaseDropDown,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| views::View::ConvertPointToScreen(this, &point);
|
|
|
| if (!context_menu_.get())
|
| context_menu_.reset(new DownloadShelfContextMenuView(model_.get()));
|
| - // When we call the Run method on the menu, it runs an inner message loop
|
| - // that might causes us to be deleted.
|
| - if (context_menu_->Run(GetWidget()->GetTopLevelWidget(),
|
| - gfx::Rect(point, size)))
|
| - return; // We have been deleted! Don't access 'this'.
|
| -
|
| - // If the menu action was to remove the download, this view will also be
|
| - // invalid so we must not access 'this' in this case.
|
| - if (context_menu_->download_item()) {
|
| - drop_down_pressed_ = false;
|
| - // Showing the menu blocks. Here we revert the state.
|
| - SetState(NORMAL, NORMAL);
|
| - }
|
| + context_menu_->Run(GetWidget()->GetTopLevelWidget(),
|
| + gfx::Rect(point, size));
|
| + // We could be deleted now.
|
| }
|
|
|
| void DownloadItemView::GetAccessibleState(ui::AccessibleViewState* state) {
|
| @@ -583,7 +588,7 @@ void DownloadItemView::ButtonPressed(
|
| download_->Cancel(true);
|
| download_->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD);
|
| // WARNING: we are deleted at this point. Don't access 'this'.
|
| - } else if (sender == save_button_) {
|
| + } else if (save_button_ && sender == save_button_) {
|
| // The user has confirmed a dangerous download. We'd record how quickly the
|
| // user did this to detect whether we're being clickjacked.
|
| UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download",
|
| @@ -599,33 +604,74 @@ void DownloadItemView::AnimationProgressed(const ui::Animation* animation) {
|
| SchedulePaint();
|
| }
|
|
|
| +// The DownloadItemView can be in three major modes (NORMAL_MODE, DANGEROUS_MODE
|
| +// and MALICIOUS_MODE).
|
| +//
|
| +// NORMAL_MODE: We are displaying an in-progress or completed download.
|
| +// .-------------------------------+-.
|
| +// | [icon] Filename |v|
|
| +// | [ ] Status | |
|
| +// `-------------------------------+-'
|
| +// | | \_ Drop down button. Invokes menu. Responds
|
| +// | | to mouse. (NORMAL, HOT or PUSHED).
|
| +// | \_ Icon is overlaid on top of in-progress animation.
|
| +// \_ Both the body and the drop down button respond to mouse hover and can be
|
| +// pushed (NORMAL, HOT or PUSHED).
|
| +//
|
| +// DANGEROUS_MODE: The file could be potentially dangerous.
|
| +// .-------------------------------------------------------.
|
| +// | [ ! ] [This type of file can ] [ Keep ] [ Discard ] |
|
| +// | [ ] [destroy your computer..] [ ] [ ] |
|
| +// `-------------------------------------------------------'
|
| +// | | | | \_ No drop down button.
|
| +// | | | \_ Buttons are views::TextButtons.
|
| +// | | \_ Text is in a label (dangerous_download_label_)
|
| +// | \_ Warning icon. No progress animation.
|
| +// \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
|
| +//
|
| +// MALICIOUS_MODE: The file is known malware.
|
| +// .---------------------------------------------+-.
|
| +// | [ - ] [This file is malicious.] [ Discard ] |v|
|
| +// | [ ] [ ] [ ] | |-.
|
| +// `---------------------------------------------+-' |
|
| +// | | | | Drop down button. Responds to
|
| +// | | | | mouse.(NORMAL, HOT or PUSHED)
|
| +// | | | \_ Button is a views::TextButton.
|
| +// | | \_ Text is in a label (dangerous_download_label_)
|
| +// | \_ Warning icon. No progress animation.
|
| +// \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
|
| +//
|
| void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| BodyImageSet* body_image_set = NULL;
|
| - switch (body_state_) {
|
| - case NORMAL:
|
| - case HOT:
|
| - body_image_set = &normal_body_image_set_;
|
| - break;
|
| - case PUSHED:
|
| - body_image_set = &pushed_body_image_set_;
|
| + switch (mode_) {
|
| + case NORMAL_MODE:
|
| + if (body_state_ == PUSHED)
|
| + body_image_set = &pushed_body_image_set_;
|
| + else // NORMAL or HOT
|
| + body_image_set = &normal_body_image_set_;
|
| break;
|
| - case DANGEROUS:
|
| + case DANGEROUS_MODE:
|
| body_image_set = &dangerous_mode_body_image_set_;
|
| break;
|
| + case MALICIOUS_MODE:
|
| + body_image_set = &malicious_mode_body_image_set_;
|
| + break;
|
| default:
|
| NOTREACHED();
|
| }
|
| +
|
| DropDownImageSet* drop_down_image_set = NULL;
|
| - switch (drop_down_state_) {
|
| - case NORMAL:
|
| - case HOT:
|
| - drop_down_image_set = &normal_drop_down_image_set_;
|
| + switch (mode_) {
|
| + case NORMAL_MODE:
|
| + case MALICIOUS_MODE:
|
| + if (drop_down_state_ == PUSHED)
|
| + drop_down_image_set = &pushed_drop_down_image_set_;
|
| + else // NORMAL or HOT
|
| + drop_down_image_set = &normal_drop_down_image_set_;
|
| break;
|
| - case PUSHED:
|
| - drop_down_image_set = &pushed_drop_down_image_set_;
|
| - break;
|
| - case DANGEROUS:
|
| - drop_down_image_set = NULL; // No drop-down in dangerous mode.
|
| + case DANGEROUS_MODE:
|
| + // We don't use a drop down button for mode_ == DANGEROUS_MODE. So we let
|
| + // drop_down_image_set == NULL.
|
| break;
|
| default:
|
| NOTREACHED();
|
| @@ -642,8 +688,9 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| if (center_width <= 0)
|
| return;
|
|
|
| - // Draw status before button image to effectively lighten text.
|
| - if (!IsDangerousMode()) {
|
| + // Draw status before button image to effectively lighten text. No status for
|
| + // warning dialogs.
|
| + if (!IsShowingWarningDialog()) {
|
| if (!status_text_.empty()) {
|
| int mirrored_x = GetMirroredXWithWidthInView(
|
| download_util::kSmallProgressIconSize, kTextWidth);
|
| @@ -695,8 +742,9 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| body_image_set->bottom_right,
|
| x, box_y_, box_height_, body_image_set->top_right->width());
|
|
|
| - // Overlay our body hot state.
|
| - if (body_hover_animation_->GetCurrentValue() > 0) {
|
| + // Overlay our body hot state. Warning dialogs don't display body a hot state.
|
| + if (!IsShowingWarningDialog() &&
|
| + body_hover_animation_->GetCurrentValue() > 0) {
|
| canvas->SaveLayerAlpha(
|
| static_cast<int>(body_hover_animation_->GetCurrentValue() * 255));
|
| canvas->GetSkCanvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode);
|
| @@ -753,7 +801,7 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| // Print the text, left aligned and always print the file extension.
|
| // Last value of x was the end of the right image, just before the button.
|
| // Note that in dangerous mode we use a label (as the text is multi-line).
|
| - if (!IsDangerousMode()) {
|
| + if (!IsShowingWarningDialog()) {
|
| string16 filename;
|
| if (!disabled_while_opening_) {
|
| filename = ui::ElideFilename(download_->GetFileNameToReportUser(),
|
| @@ -792,7 +840,7 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| gfx::Image* image = im->LookupIcon(download_->GetUserVerifiedFilePath(),
|
| IconLoader::SMALL);
|
| const SkBitmap* icon = NULL;
|
| - if (IsDangerousMode())
|
| + if (IsShowingWarningDialog())
|
| icon = warning_icon_;
|
| else if (image)
|
| icon = *image;
|
| @@ -803,7 +851,7 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| // loaded, in which case LookupIcon will always be NULL. The loading will be
|
| // triggered only when we think the status might change.
|
| if (icon) {
|
| - if (!IsDangerousMode()) {
|
| + if (!IsShowingWarningDialog()) {
|
| if (download_->IsInProgress()) {
|
| download_util::PaintDownloadProgress(canvas, this, 0, 0,
|
| progress_angle_,
|
| @@ -827,7 +875,7 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| // Draw the icon image.
|
| int icon_x, icon_y;
|
|
|
| - if (IsDangerousMode()) {
|
| + if (IsShowingWarningDialog()) {
|
| icon_x = kLeftPadding + body_image_set->top_left->width();
|
| icon_y = (height() - icon->height()) / 2;
|
| } else {
|
| @@ -847,6 +895,7 @@ void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| }
|
|
|
| void DownloadItemView::OpenDownload() {
|
| + DCHECK(!IsShowingWarningDialog());
|
| // We're interested in how long it takes users to open downloads. If they
|
| // open downloads super quickly, we should be concerned about clickjacking.
|
| UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
|
| @@ -897,6 +946,16 @@ void DownloadItemView::PaintBitmaps(gfx::Canvas* canvas,
|
| }
|
|
|
| void DownloadItemView::SetState(State body_state, State drop_down_state) {
|
| + // If we are showing a warning dialog, we don't change body state.
|
| + if (IsShowingWarningDialog()) {
|
| + body_state = NORMAL;
|
| +
|
| + // Current body_state_ should always be NORMAL for warning dialogs.
|
| + DCHECK(body_state_ == NORMAL);
|
| + // We shouldn't be calling SetState if we are in DANGEROUS_MODE.
|
| + DCHECK(mode_ != DANGEROUS_MODE);
|
| + }
|
| + // Avoid extra SchedulePaint()s if the state is going to be the same.
|
| if (body_state_ == body_state && drop_down_state_ == drop_down_state)
|
| return;
|
|
|
| @@ -905,17 +964,20 @@ void DownloadItemView::SetState(State body_state, State drop_down_state) {
|
| SchedulePaint();
|
| }
|
|
|
| -void DownloadItemView::ClearDangerousMode() {
|
| +void DownloadItemView::ClearWarningDialog() {
|
| DCHECK(download_->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED &&
|
| - body_state_ == DANGEROUS && drop_down_state_ == DANGEROUS);
|
| + (mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE));
|
|
|
| + mode_ = NORMAL_MODE;
|
| body_state_ = NORMAL;
|
| drop_down_state_ = NORMAL;
|
|
|
| - // Remove the views used by the dangerous mode.
|
| - RemoveChildView(save_button_);
|
| - delete save_button_;
|
| - save_button_ = NULL;
|
| + // Remove the views used by the warning dialog.
|
| + if (save_button_) {
|
| + RemoveChildView(save_button_);
|
| + delete save_button_;
|
| + save_button_ = NULL;
|
| + }
|
| RemoveChildView(discard_button_);
|
| delete discard_button_;
|
| discard_button_ = NULL;
|
| @@ -923,10 +985,12 @@ void DownloadItemView::ClearDangerousMode() {
|
| delete dangerous_download_label_;
|
| dangerous_download_label_ = NULL;
|
| dangerous_download_label_sized_ = false;
|
| + cached_button_size_.SetSize(0,0);
|
|
|
| // Set the accessible name back to the status and filename instead of the
|
| // download warning.
|
| UpdateAccessibleName();
|
| + UpdateDropDownButtonPosition();
|
|
|
| // We need to load the icon now that the download_ has the real path.
|
| LoadIcon();
|
| @@ -937,20 +1001,29 @@ void DownloadItemView::ClearDangerousMode() {
|
| parent_->SchedulePaint();
|
| }
|
|
|
| -void DownloadItemView::EnterDangerousMode() {
|
| - DCHECK(body_state_ != DANGEROUS && drop_down_state_ != DANGEROUS);
|
| +void DownloadItemView::ShowWarningDialog() {
|
| + DCHECK(mode_ != DANGEROUS_MODE && mode_ != MALICIOUS_MODE);
|
| + if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL ||
|
| + download_->GetDangerType() == DownloadStateInfo::DANGEROUS_CONTENT) {
|
| + mode_ = MALICIOUS_MODE;
|
| + } else {
|
| + DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE);
|
| + mode_ = DANGEROUS_MODE;
|
| + }
|
| + body_state_ = NORMAL;
|
| + drop_down_state_ = NORMAL;
|
| tooltip_text_.clear();
|
| - body_state_ = DANGEROUS;
|
| - drop_down_state_ = DANGEROUS;
|
| - save_button_ = new views::NativeTextButton(this,
|
| - l10n_util::GetStringUTF16(
|
| - ChromeDownloadManagerDelegate::IsExtensionDownload(download_) ?
|
| - IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD));
|
| - save_button_->set_ignore_minimum_size(true);
|
| + if (mode_ == DANGEROUS_MODE) {
|
| + save_button_ = new views::NativeTextButton(this,
|
| + l10n_util::GetStringUTF16(
|
| + ChromeDownloadManagerDelegate::IsExtensionDownload(download_) ?
|
| + IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD));
|
| + save_button_->set_ignore_minimum_size(true);
|
| + AddChildView(save_button_);
|
| + }
|
| discard_button_ = new views::NativeTextButton(
|
| this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
|
| discard_button_->set_ignore_minimum_size(true);
|
| - AddChildView(save_button_);
|
| AddChildView(discard_button_);
|
|
|
| // Ensure the file name is not too long.
|
| @@ -982,11 +1055,11 @@ void DownloadItemView::EnterDangerousMode() {
|
| ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| // The dangerous download label text and icon are different
|
| // under different cases.
|
| - if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL ||
|
| - download_->GetDangerType() == DownloadStateInfo::DANGEROUS_CONTENT) {
|
| + if (mode_ == MALICIOUS_MODE) {
|
| warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING);
|
| } else {
|
| DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE);
|
| + // The download file has dangerous file type (e.g.: an executable).
|
| warning_icon_ = rb.GetBitmapNamed(IDR_WARNING);
|
| }
|
| string16 dangerous_label;
|
| @@ -1017,15 +1090,15 @@ void DownloadItemView::EnterDangerousMode() {
|
|
|
| dangerous_download_label_ = new views::Label(dangerous_label);
|
| dangerous_download_label_->SetMultiLine(true);
|
| - dangerous_download_label_->SetHorizontalAlignment(
|
| - views::Label::ALIGN_LEFT);
|
| + dangerous_download_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| dangerous_download_label_->SetAutoColorReadabilityEnabled(false);
|
| AddChildView(dangerous_download_label_);
|
| SizeLabelToMinWidth();
|
| + UpdateDropDownButtonPosition();
|
| }
|
|
|
| gfx::Size DownloadItemView::GetButtonSize() {
|
| - DCHECK(save_button_ && discard_button_);
|
| + DCHECK(discard_button_ && (mode_ == MALICIOUS_MODE || save_button_));
|
| gfx::Size size;
|
|
|
| // We cache the size when successfully retrieved, not for performance reasons
|
| @@ -1035,7 +1108,8 @@ gfx::Size DownloadItemView::GetButtonSize() {
|
| if (cached_button_size_.width() != 0)
|
| return cached_button_size_;
|
|
|
| - size = save_button_->GetMinimumSize();
|
| + if (save_button_)
|
| + size = save_button_->GetMinimumSize();
|
| gfx::Size discard_size = discard_button_->GetMinimumSize();
|
|
|
| size.SetSize(std::max(size.width(), discard_size.width()),
|
| @@ -1062,8 +1136,6 @@ void DownloadItemView::SizeLabelToMinWidth() {
|
| // current width.
|
| dangerous_download_label_->SetBounds(0, 0, 1000, 1000);
|
|
|
| - gfx::Size size;
|
| - int min_width = -1;
|
| // Using BREAK_WORD can work in most cases, but it can also break
|
| // lines where it should not. Using BREAK_LINE is safer although
|
| // slower for Chinese/Japanese. This is not perf-critical at all, though.
|
| @@ -1073,7 +1145,15 @@ void DownloadItemView::SizeLabelToMinWidth() {
|
|
|
| string16 current_text = text;
|
| string16 prev_text = text;
|
| - while (iter.Advance()) {
|
| + gfx::Size size = dangerous_download_label_->GetPreferredSize();
|
| + int min_width = size.width();
|
| +
|
| + // Go through the string and try each line break (starting with no line break)
|
| + // searching for the optimal line break position. Stop if we find one that
|
| + // yields one that is less than kDangerousTextWidth wide. This is to prevent
|
| + // a short string (e.g.: "This file is malicious") from being broken up
|
| + // unnecessarily.
|
| + while (iter.Advance() && min_width > kDangerousTextWidth) {
|
| size_t pos = iter.pos();
|
| if (pos >= text.length())
|
| break;
|
| @@ -1088,9 +1168,6 @@ void DownloadItemView::SizeLabelToMinWidth() {
|
| dangerous_download_label_->SetText(current_text);
|
| size = dangerous_download_label_->GetPreferredSize();
|
|
|
| - if (min_width == -1)
|
| - min_width = size.width();
|
| -
|
| // If the width is growing again, it means we passed the optimal width spot.
|
| if (size.width() > min_width) {
|
| dangerous_download_label_->SetText(prev_text);
|
| @@ -1104,11 +1181,6 @@ void DownloadItemView::SizeLabelToMinWidth() {
|
| current_text = text;
|
| }
|
|
|
| - // If we have a line with no line breaking opportunity (which is very
|
| - // unlikely), we won't cut it.
|
| - if (min_width == -1)
|
| - size = dangerous_download_label_->GetPreferredSize();
|
| -
|
| dangerous_download_label_->SetBounds(0, 0, size.width(), size.height());
|
| dangerous_download_label_sized_ = true;
|
| }
|
| @@ -1118,6 +1190,11 @@ void DownloadItemView::Reenable() {
|
| SetEnabled(true); // Triggers a repaint.
|
| }
|
|
|
| +void DownloadItemView::ReleaseDropDown() {
|
| + drop_down_pressed_ = false;
|
| + SetState(NORMAL, NORMAL);
|
| +}
|
| +
|
| bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) {
|
| if (x > drop_down_x_left_ && x < drop_down_x_right_)
|
| return true;
|
| @@ -1126,7 +1203,7 @@ bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) {
|
|
|
| void DownloadItemView::UpdateAccessibleName() {
|
| string16 new_name;
|
| - if (download_->GetSafetyState() == DownloadItem::DANGEROUS) {
|
| + if (IsShowingWarningDialog()) {
|
| new_name = dangerous_download_label_->GetText();
|
| } else {
|
| new_name = status_text_ + char16(' ') +
|
| @@ -1143,3 +1220,17 @@ void DownloadItemView::UpdateAccessibleName() {
|
| }
|
| }
|
| }
|
| +
|
| +void DownloadItemView::UpdateDropDownButtonPosition() {
|
| + gfx::Size size = GetPreferredSize();
|
| + if (base::i18n::IsRTL()) {
|
| + // Drop down button is glued to the left of the download shelf.
|
| + drop_down_x_left_ = 0;
|
| + drop_down_x_right_ = normal_drop_down_image_set_.top->width();
|
| + } else {
|
| + // Drop down button is glued to the right of the download shelf.
|
| + drop_down_x_left_ =
|
| + size.width() - normal_drop_down_image_set_.top->width();
|
| + drop_down_x_right_ = size.width();
|
| + }
|
| +}
|
|
|