| Index: chrome/browser/views/download_tab_view.cc
|
| ===================================================================
|
| --- chrome/browser/views/download_tab_view.cc (revision 2758)
|
| +++ chrome/browser/views/download_tab_view.cc (working copy)
|
| @@ -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 @@
|
| // 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 @@
|
| // 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 @@
|
| 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 @@
|
|
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| // 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 @@
|
|
|
| // 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
|
|
| // 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 @@
|
| 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 @@
|
| // DownloadManager owns the contents.
|
| downloads_.clear();
|
| ClearDownloadInProgress();
|
| + ClearDangerousDownloads();
|
|
|
| icon_consumer_.CancelAllRequests();
|
| }
|
| @@ -720,6 +849,21 @@
|
| 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 @@
|
| }
|
|
|
| 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 @@
|
| 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::ModelChanged() {
|
| downloads_.clear();
|
| ClearDownloadInProgress();
|
| + ClearDangerousDownloads();
|
| DetachAllFloatingViews();
|
|
|
| // Issue the query.
|
| @@ -890,6 +1041,7 @@
|
| // 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 @@
|
| 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 @@
|
| 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
|
|
|