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(); |
+ } |
+} |