summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/download_tab_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/download_tab_view.cc')
-rw-r--r--chrome/browser/views/download_tab_view.cc190
1 files changed, 177 insertions, 13 deletions
diff --git a/chrome/browser/views/download_tab_view.cc b/chrome/browser/views/download_tab_view.cc
index 62e5668..679aa54 100644
--- a/chrome/browser/views/download_tab_view.cc
+++ b/chrome/browser/views/download_tab_view.cc
@@ -30,7 +30,8 @@
// Approximate spacing, in pixels, taken from initial UI mock up screens
static const int kVerticalPadding = 5;
-static const int kHorizontalButtonPadding = 15;
+static const int kHorizontalLinkPadding = 15;
+static const int kHorizontalButtonPadding = 8;
// For vertical and horizontal element spacing
static const int kSpacer = 20;
@@ -65,12 +66,19 @@ static const SkColor kUrlColor = SkColorSetRGB(0, 128, 0);
// Paused download indicator (red)
static const SkColor kPauseColor = SkColorSetRGB(128, 0, 0);
+// Warning label color (blue)
+static const SkColor kWarningColor = SkColorSetRGB(87, 108, 149);
+
// Selected item background color
static const SkColor kSelectedItemColor = SkColorSetRGB(215, 232, 255);
// State key used to identify search text.
static const wchar_t kSearchTextKey[] = L"st";
+// The maximum number of characters we show in a file name when displaying the
+// dangerous download message.
+static const int kFileNameMaxLength = 20;
+
// Sorting functor for DownloadItem --------------------------------------------
// Sort DownloadItems into ascending order by their start time.
@@ -87,7 +95,8 @@ class DownloadItemSorter : public std::binary_function<DownloadItem*,
// DownloadItemTabView implementation ------------------------------------------
DownloadItemTabView::DownloadItemTabView()
: model_(NULL),
- parent_(NULL) {
+ parent_(NULL),
+ is_floating_view_renderer_(false) {
// Create our element views using empty strings for now,
// set them based on the model's state in Layout().
since_ = new ChromeViews::Label(L"");
@@ -111,6 +120,29 @@ DownloadItemTabView::DownloadItemTabView()
file_name_->SetFont(font);
AddChildView(file_name_);
+ // dangerous_download_warning_ is enabled when a dangerous download has been
+ // initiated.
+ dangerous_download_warning_ = new ChromeViews::Label();
+ dangerous_download_warning_ ->SetMultiLine(true);
+ dangerous_download_warning_->SetColor(kWarningColor);
+ dangerous_download_warning_->SetHorizontalAlignment(
+ ChromeViews::Label::ALIGN_LEFT);
+ dangerous_download_warning_->SetFont(font);
+ AddChildView(dangerous_download_warning_);
+
+ // The save and discard buttons are shown to prompt the user when a dangerous
+ // download was started.
+ save_button_ = new ChromeViews::NativeButton(
+ l10n_util::GetString(IDS_SAVE_DOWNLOAD));
+ save_button_->set_enforce_dlu_min_size(false);
+ save_button_->SetListener(this);
+ discard_button_ = new ChromeViews::NativeButton(
+ l10n_util::GetString(IDS_DISCARD_DOWNLOAD));
+ discard_button_->SetListener(this);
+ discard_button_->set_enforce_dlu_min_size(false);
+ AddChildView(save_button_);
+ AddChildView(discard_button_);
+
// Set our URL name
download_url_ = new ChromeViews::Label(L"");
download_url_->SetColor(kUrlColor);
@@ -172,9 +204,9 @@ void DownloadItemTabView::GetPreferredSize(CSize* out) {
out->cx = download_util::kBigProgressIconSize +
2 * kSpacer +
- kHorizontalButtonPadding +
+ kHorizontalLinkPadding +
kFilenameSize +
- std::max(pause_size.cx + cancel_size.cx + kHorizontalButtonPadding,
+ std::max(pause_size.cx + cancel_size.cx + kHorizontalLinkPadding,
show_size.cx);
out->cy = download_util::kBigProgressIconSize;
@@ -188,13 +220,19 @@ void DownloadItemTabView::Layout() {
DCHECK(model_);
switch (model_->state()) {
case DownloadItem::COMPLETE:
- LayoutComplete();
+ if (model_->safety_state() == DownloadItem::DANGEROUS)
+ LayoutPromptDangerousDownload();
+ else
+ LayoutComplete();
break;
case DownloadItem::CANCELLED:
LayoutCancelled();
break;
case DownloadItem::IN_PROGRESS:
- LayoutInProgress();
+ if (model_->safety_state() == DownloadItem::DANGEROUS)
+ LayoutPromptDangerousDownload();
+ else
+ LayoutInProgress();
break;
case DownloadItem::REMOVING:
break;
@@ -238,6 +276,11 @@ void DownloadItemTabView::LayoutComplete() {
cancel_->SetEnabled(false);
time_remaining_->SetVisible(false);
download_progress_->SetVisible(false);
+ dangerous_download_warning_->SetVisible(false);
+ save_button_->SetVisible(false);
+ save_button_->SetEnabled(false);
+ discard_button_->SetVisible(false);
+ discard_button_->SetEnabled(false);
LayoutDate();
int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
@@ -286,6 +329,11 @@ void DownloadItemTabView::LayoutCancelled() {
pause_->SetEnabled(false);
cancel_->SetVisible(false);
cancel_->SetEnabled(false);
+ dangerous_download_warning_->SetVisible(false);
+ save_button_->SetVisible(false);
+ save_button_->SetEnabled(false);
+ discard_button_->SetVisible(false);
+ discard_button_->SetEnabled(false);
LayoutDate();
int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
@@ -372,6 +420,11 @@ void DownloadItemTabView::LayoutInProgress() {
// Hide unused UI elements
show_->SetVisible(false);
show_->SetEnabled(false);
+ dangerous_download_warning_->SetVisible(false);
+ save_button_->SetVisible(false);
+ save_button_->SetEnabled(false);
+ discard_button_->SetVisible(false);
+ discard_button_->SetEnabled(false);
LayoutDate();
int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
@@ -380,7 +433,7 @@ void DownloadItemTabView::LayoutInProgress() {
// File name and URL, truncated to show progress status
CSize file_name_size;
- file_name_->SetText(model_->file_name());
+ file_name_->SetText(model_->GetFileName());
file_name_->GetPreferredSize(&file_name_size);
file_name_->SetBounds(dx, download_util::kBigProgressIconOffset,
kFilenameSize - kProgressSize - kSpacer,
@@ -514,7 +567,7 @@ void DownloadItemTabView::LayoutInProgress() {
pause_->GetPreferredSize(&pause_size);
pause_->SetBounds(dx, y_pos, pause_size.cx, pause_size.cy);
- dx += pause_size.cx + kHorizontalButtonPadding;
+ dx += pause_size.cx + kHorizontalLinkPadding;
CSize cancel_size;
cancel_->GetPreferredSize(&cancel_size);
@@ -523,10 +576,69 @@ void DownloadItemTabView::LayoutInProgress() {
cancel_->SetEnabled(true);
}
+void DownloadItemTabView::LayoutPromptDangerousDownload() {
+ // Hide unused UI elements
+ show_->SetVisible(false);
+ show_->SetEnabled(false);
+ file_name_->SetVisible(false);
+ file_name_->SetEnabled(false);
+ pause_->SetVisible(false);
+ pause_->SetEnabled(false);
+ cancel_->SetVisible(false);
+ cancel_->SetEnabled(false);
+ time_remaining_->SetVisible(false);
+ download_progress_->SetVisible(false);
+
+ LayoutDate();
+ int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize +
+ kInfoPadding;
+
+ // Warning message and URL.
+ CSize warning_size;
+ std::wstring file_name;
+ ElideString(model_->original_name(), kFileNameMaxLength, &file_name);
+ dangerous_download_warning_->SetText(
+ l10n_util::GetStringF(IDS_PROMPT_DANGEROUS_DOWNLOAD, file_name));
+ dangerous_download_warning_->GetPreferredSize(&warning_size);
+ dangerous_download_warning_->SetBounds(dx, 0,
+ kFilenameSize, warning_size.cy);
+ dangerous_download_warning_->SetVisible(true);
+
+ GURL url(model_->url());
+ download_url_->SetURL(url);
+ CSize url_size;
+ download_url_->GetPreferredSize(&url_size);
+ download_url_->SetBounds(dx, height() - url_size.cy,
+ std::min(kFilenameSize - kSpacer,
+ static_cast<int>(width() - dx)),
+ url_size.cy);
+ download_url_->SetVisible(true);
+
+ dx += kFilenameSize + kSpacer;
+
+ // Save/Discard buttons.
+ CSize button_size;
+ save_button_->GetPreferredSize(&button_size);
+ save_button_->SetBounds(dx, (height() - button_size.cy) / 2,
+ button_size.cx, button_size.cy);
+ save_button_->SetVisible(true);
+ save_button_->SetEnabled(true);
+
+ dx += button_size.cx + kHorizontalButtonPadding;
+
+ discard_button_->GetPreferredSize(&button_size);
+ discard_button_->SetBounds(dx, (height() - button_size.cy) / 2,
+ button_size.cx, button_size.cy);
+ discard_button_->SetVisible(true);
+ discard_button_->SetEnabled(true);
+}
+
void DownloadItemTabView::Paint(ChromeCanvas* canvas) {
PaintBackground(canvas);
- if (model_->state() == DownloadItem::IN_PROGRESS) {
+ if (model_->state() == DownloadItem::IN_PROGRESS &&
+ model_->safety_state() != DownloadItem::DANGEROUS) {
download_util::PaintDownloadProgress(canvas,
this,
kDownloadIconOffset -
@@ -605,7 +717,10 @@ bool DownloadItemTabView::OnMousePressed(const ChromeViews::MouseEvent& event) {
if (select_rect.PtInRect(point)) {
parent_->ItemBecameSelected(model_);
- if (event.IsRightMouseButton()) {
+ // Don't show the right-click menu if we are prompting the user for a
+ // dangerous download.
+ if (event.IsRightMouseButton() &&
+ model_->safety_state() != DownloadItem::DANGEROUS) {
ChromeViews::View::ConvertPointToScreen(this, &point);
download_util::DownloadDestinationContextMenu menu(
@@ -620,7 +735,8 @@ bool DownloadItemTabView::OnMousePressed(const ChromeViews::MouseEvent& event) {
// Handle drag (file copy) operations.
bool DownloadItemTabView::OnMouseDragged(const ChromeViews::MouseEvent& event) {
- if (model_->state() != DownloadItem::COMPLETE)
+ if (model_->state() != DownloadItem::COMPLETE ||
+ model_->safety_state() == DownloadItem::DANGEROUS)
return false;
CPoint point(event.x(), event.y());
@@ -665,6 +781,18 @@ void DownloadItemTabView::LinkActivated(ChromeViews::Link* source,
parent_->ItemBecameSelected(model_);
}
+void DownloadItemTabView::ButtonPressed(ChromeViews::NativeButton* sender) {
+ if (sender == save_button_) {
+ parent_->model()->DangerousDownloadValidated(model_);
+ // Relayout and repaint to display the right mode (complete or in progress).
+ Layout();
+ SchedulePaint();
+ } else if (sender == discard_button_) {
+ model_->Remove(true);
+ } else {
+ NOTREACHED();
+ }
+}
// DownloadTabView implementation ----------------------------------------------
@@ -683,6 +811,7 @@ DownloadTabView::~DownloadTabView() {
// DownloadManager owns the contents.
downloads_.clear();
ClearDownloadInProgress();
+ ClearDangerousDownloads();
icon_consumer_.CancelAllRequests();
}
@@ -720,6 +849,21 @@ void DownloadTabView::DidChangeBounds(const CRect& previous,
void DownloadTabView::Layout() {
CRect r;
DetachAllFloatingViews();
+ // Dangerous downloads items use NativeButtons, so they need to be attached
+ // as NativeControls are not supported yet in floating views.
+ gfx::Rect visible_bounds = GetVisibleBounds();
+ int row_start = (visible_bounds.y() - kSpacer) /
+ (download_util::kBigProgressIconSize + kSpacer);
+ int row_stop = (visible_bounds.y() - kSpacer + visible_bounds.height()) /
+ (download_util::kBigProgressIconSize + kSpacer);
+ row_stop = std::min(row_stop, static_cast<int>(downloads_.size()) - 1);
+ for (int i = row_start; i <= row_stop; ++i) {
+ // The DownloadManager stores downloads earliest first, but this view
+ // displays latest first, so adjust the index:
+ int index = static_cast<int>(downloads_.size()) - 1 - i;
+ if (downloads_[index]->safety_state() == DownloadItem::DANGEROUS)
+ ValidateFloatingViewForID(index);
+ }
View* v = GetParent();
if (v) {
v->GetLocalBounds(&r, true);
@@ -790,12 +934,15 @@ ChromeViews::View* DownloadTabView::CreateFloatingViewForIndex(int index) {
}
DownloadItemTabView* dl = new DownloadItemTabView();
+ // We attach the view before layout as the Save/Discard buttons are native
+ // and need to be in the tree hierarchy to compute their preferred size
+ // correctly.
+ AttachFloatingView(dl, index);
dl->SetModel(downloads_[index], this);
int row = static_cast<int>(downloads_.size()) - 1 - index;
int y_pos = row * (download_util::kBigProgressIconSize + kSpacer) + kSpacer;
dl->SetBounds(0, y_pos, width(), download_util::kBigProgressIconSize);
dl->Layout();
- AttachFloatingView(dl, index);
return dl;
}
@@ -817,7 +964,10 @@ void DownloadTabView::OnDownloadUpdated(DownloadItem* download) {
case DownloadItem::CANCELLED: {
base::hash_set<DownloadItem*>::iterator d = in_progress_.find(download);
if (d != in_progress_.end()) {
- (*d)->RemoveObserver(this);
+ // If this is a dangerous download not yet validated by the user, we
+ // still need to be notified when the validation happens.
+ if (download->safety_state() != DownloadItem::DANGEROUS)
+ (*d)->RemoveObserver(this);
in_progress_.erase(d);
}
if (in_progress_.empty())
@@ -877,6 +1027,7 @@ void DownloadTabView::OnDownloadUpdated(DownloadItem* download) {
void DownloadTabView::ModelChanged() {
downloads_.clear();
ClearDownloadInProgress();
+ ClearDangerousDownloads();
DetachAllFloatingViews();
// Issue the query.
@@ -890,6 +1041,7 @@ void DownloadTabView::SetDownloads(std::vector<DownloadItem*>& downloads) {
// Clear out old state and remove self as observer for each download.
downloads_.clear();
ClearDownloadInProgress();
+ ClearDangerousDownloads();
// Swap new downloads in.
downloads_.swap(downloads);
@@ -902,6 +1054,10 @@ void DownloadTabView::SetDownloads(std::vector<DownloadItem*>& downloads) {
if (download->state() == DownloadItem::IN_PROGRESS) {
download->AddObserver(this);
in_progress_.insert(download);
+ } else if (download->safety_state() == DownloadItem::DANGEROUS) {
+ // We need to be notified when the user validates the dangerous download.
+ download->AddObserver(this);
+ dangerous_downloads_.insert(download);
}
}
@@ -949,6 +1105,14 @@ void DownloadTabView::ClearDownloadInProgress() {
in_progress_.clear();
}
+void DownloadTabView::ClearDangerousDownloads() {
+ base::hash_set<DownloadItem*>::const_iterator it;
+ for (it = dangerous_downloads_.begin();
+ it != dangerous_downloads_.end(); ++it)
+ (*it)->RemoveObserver(this);
+ dangerous_downloads_.clear();
+}
+
// Check to see if the download is the latest download on a given day.
// We use this to determine when to draw the date next to a particular
// download view: if the DownloadItem is the latest download on a given