| Index: chrome/browser/gtk/download_item_gtk.cc
|
| ===================================================================
|
| --- chrome/browser/gtk/download_item_gtk.cc (revision 17020)
|
| +++ chrome/browser/gtk/download_item_gtk.cc (working copy)
|
| @@ -4,9 +4,11 @@
|
|
|
| #include "chrome/browser/gtk/download_item_gtk.h"
|
|
|
| +#include "app/l10n_util.h"
|
| #include "app/gfx/canvas.h"
|
| #include "app/gfx/font.h"
|
| #include "app/gfx/text_elider.h"
|
| +#include "app/resource_bundle.h"
|
| #include "app/slide_animation.h"
|
| #include "base/basictypes.h"
|
| #include "base/string_util.h"
|
| @@ -30,6 +32,9 @@
|
| // bitmap that we use to draw it, i.e. 16, but can be more.
|
| const int kMenuButtonWidth = 16;
|
|
|
| +// Padding on left and right of items in dangerous download prompt.
|
| +const int kDangerousElementPadding = 3;
|
| +
|
| // Amount of space we allot to showing the filename. If the filename is too wide
|
| // it will be elided.
|
| const int kTextWidth = 140;
|
| @@ -39,6 +44,9 @@
|
| // make the download item.
|
| const int kMinDownloadItemWidth = 13 + download_util::kSmallProgressIconSize;
|
|
|
| +// As above, but for the dangerous download prompt.
|
| +const int kMinDangerousDownloadWidth = 16;
|
| +
|
| const char* kLabelColorMarkup = "<span color='#%s'>%s</span>";
|
| const char* kFilenameColor = "576C95"; // 87, 108, 149
|
| const char* kStatusColor = "7B8DAE"; // 123, 141, 174
|
| @@ -155,6 +163,8 @@
|
| NineBox* DownloadItemGtk::menu_nine_box_prelight_ = NULL;
|
| NineBox* DownloadItemGtk::menu_nine_box_active_ = NULL;
|
|
|
| +NineBox* DownloadItemGtk::dangerous_nine_box_ = NULL;
|
| +
|
| DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
|
| BaseDownloadItemModel* download_model)
|
| : parent_shelf_(parent_shelf),
|
| @@ -162,6 +172,7 @@
|
| progress_angle_(download_util::kStartAngleDegrees),
|
| download_model_(download_model),
|
| bounding_widget_(parent_shelf->GetRightBoundingWidget()),
|
| + dangerous_prompt_(NULL),
|
| icon_(NULL) {
|
| InitNineBoxes();
|
| LoadIcon();
|
| @@ -185,7 +196,7 @@
|
| // much padding when we set the size request. We need to either use gfx::Font
|
| // or somehow extend TextElider.
|
| std::wstring elided_filename = gfx::ElideFilename(
|
| - download_model_->download()->GetFileName(),
|
| + get_download()->GetFileName(),
|
| gfx::Font(), kTextWidth);
|
| gchar* label_markup =
|
| g_markup_printf_escaped(kLabelColorMarkup, kFilenameColor,
|
| @@ -198,8 +209,8 @@
|
| gtk_misc_set_alignment(GTK_MISC(name_label_), 0, 0.5);
|
| gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5);
|
| // Until we switch to vector graphics, force the font size.
|
| - gtk_util::ForceFontSizePixels(name_label_, 13.4); // 13.4px == 10pt @ 96dpi
|
| - gtk_util::ForceFontSizePixels(status_label_, 13.4); // 13.4px == 10pt @ 96dpi
|
| + gtk_util::ForceFontSizePixels(name_label_, 13.4); // 13.4px == 10pt @ 96dpi
|
| + gtk_util::ForceFontSizePixels(status_label_, 13.4); // 13.4px == 10pt @ 96dpi
|
|
|
| // Stack the labels on top of one another.
|
| GtkWidget* text_stack = gtk_vbox_new(FALSE, 0);
|
| @@ -244,11 +255,92 @@
|
| resize_handler_id_ = g_signal_connect(G_OBJECT(shelf_hbox), "size-allocate",
|
| G_CALLBACK(OnShelfResized), this);
|
|
|
| - download_model_->download()->AddObserver(this);
|
| + get_download()->AddObserver(this);
|
|
|
| new_item_animation_.reset(new SlideAnimation(this));
|
| new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs);
|
| gtk_widget_show_all(hbox_);
|
| +
|
| + if (IsDangerous()) {
|
| + // Hide the download item components for now.
|
| + gtk_widget_hide(body_);
|
| + gtk_widget_hide(menu_button_);
|
| +
|
| + // Create an hbox to hold it all.
|
| + dangerous_hbox_ = gtk_hbox_new(FALSE, kDangerousElementPadding);
|
| +
|
| + // Add padding at the beginning and end. The hbox will add padding between
|
| + // the empty labels and the other elements.
|
| + GtkWidget* empty_label_a = gtk_label_new(NULL);
|
| + GtkWidget* empty_label_b = gtk_label_new(NULL);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_hbox_), empty_label_a,
|
| + FALSE, FALSE, 0);
|
| + gtk_box_pack_end(GTK_BOX(dangerous_hbox_), empty_label_b,
|
| + FALSE, FALSE, 0);
|
| +
|
| + // Create the warning icon.
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + GdkPixbuf* download_pixbuf = rb.GetPixbufNamed(IDR_WARNING);
|
| + GtkWidget* dangerous_image = gtk_image_new_from_pixbuf(download_pixbuf);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_image,
|
| + FALSE, FALSE, 0);
|
| +
|
| + // Create the warning text.
|
| + // TODO(estade): the encoding might not be UTF8.
|
| + std::string dangerous_warning =
|
| + l10n_util::GetStringFUTF8(IDS_PROMPT_DANGEROUS_DOWNLOAD,
|
| + UTF8ToUTF16(get_download()->original_name().value()));
|
| + gchar* label_markup =
|
| + g_markup_printf_escaped(kLabelColorMarkup, kFilenameColor,
|
| + dangerous_warning.c_str());
|
| + GtkWidget* dangerous_label = gtk_label_new(NULL);
|
| + // Until we switch to vector graphics, force the font size.
|
| + // 13.4px == 10pt @ 96dpi
|
| + gtk_util::ForceFontSizePixels(dangerous_label, 13.4);
|
| + gtk_label_set_markup(GTK_LABEL(dangerous_label), label_markup);
|
| + gtk_label_set_line_wrap(GTK_LABEL(dangerous_label), TRUE);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_label,
|
| + FALSE, FALSE, 0);
|
| + g_free(label_markup);
|
| +
|
| + // Create the ok button.
|
| + GtkWidget* dangerous_accept = gtk_button_new_with_label(
|
| + l10n_util::GetStringUTF8(IDS_SAVE_DOWNLOAD).c_str());
|
| + g_signal_connect(dangerous_accept, "clicked",
|
| + G_CALLBACK(OnDangerousAccept), this);
|
| + GtkWidget* dangerous_accept_vbox = gtk_vbox_new(FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_accept_vbox), dangerous_accept,
|
| + TRUE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_accept_vbox,
|
| + FALSE, FALSE, 0);
|
| +
|
| + // Create the nevermind button.
|
| + GtkWidget* dangerous_decline = gtk_button_new_with_label(
|
| + l10n_util::GetStringUTF8(IDS_DISCARD_DOWNLOAD).c_str());
|
| + g_signal_connect(dangerous_decline, "clicked",
|
| + G_CALLBACK(OnDangerousDecline), this);
|
| + GtkWidget* dangerous_decline_vbox = gtk_vbox_new(FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_decline_vbox), dangerous_decline,
|
| + TRUE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(dangerous_hbox_), dangerous_decline_vbox,
|
| + FALSE, FALSE, 0);
|
| +
|
| + // Put it in an alignment so that padding will be added on the left and
|
| + // right, and an event box so that drawing will be clipped correctly.
|
| + dangerous_prompt_ = gtk_util::CreateGtkBorderBin(dangerous_hbox_, NULL,
|
| + 0, 0, kDangerousElementPadding, kDangerousElementPadding);
|
| + gtk_box_pack_start(GTK_BOX(hbox_), dangerous_prompt_, FALSE, FALSE, 0);
|
| + gtk_widget_set_app_paintable(dangerous_prompt_, TRUE);
|
| + g_signal_connect(dangerous_prompt_, "expose-event",
|
| + G_CALLBACK(OnDangerousPromptExpose), this);
|
| + gtk_widget_show_all(dangerous_prompt_);
|
| +
|
| + // The full width will depend on the text.
|
| + GtkRequisition req;
|
| + gtk_widget_size_request(dangerous_hbox_, &req);
|
| + dangerous_hbox_full_width_ = req.width;
|
| + }
|
| +
|
| new_item_animation_->Show();
|
| }
|
|
|
| @@ -256,12 +348,20 @@
|
| StopDownloadProgress();
|
| g_signal_handler_disconnect(parent_shelf_->GetHBox(), resize_handler_id_);
|
| gtk_widget_destroy(hbox_);
|
| - download_model_->download()->RemoveObserver(this);
|
| + get_download()->RemoveObserver(this);
|
| }
|
|
|
| void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) {
|
| - DCHECK_EQ(download, download_model_->download());
|
| + DCHECK_EQ(download, get_download());
|
|
|
| + if (dangerous_prompt_ != NULL &&
|
| + download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) {
|
| + // We have been approved.
|
| + gtk_widget_show_all(hbox_);
|
| + gtk_widget_destroy(dangerous_prompt_);
|
| + dangerous_prompt_ = NULL;
|
| + }
|
| +
|
| switch (download->state()) {
|
| case DownloadItem::REMOVING:
|
| parent_shelf_->RemoveDownloadItem(this); // This will delete us!
|
| @@ -277,7 +377,7 @@
|
| complete_animation_->Show();
|
| break;
|
| case DownloadItem::IN_PROGRESS:
|
| - download_model_->download()->is_paused() ?
|
| + get_download()->is_paused() ?
|
| StopDownloadProgress() : StartDownloadProgress();
|
| break;
|
| default:
|
| @@ -309,17 +409,32 @@
|
| if (animation == complete_animation_.get()) {
|
| gtk_widget_queue_draw(progress_area_);
|
| } else {
|
| - DCHECK(animation == new_item_animation_.get());
|
| - // See above TODO for explanation of the extra 50.
|
| - int showing_width = std::max(kMinDownloadItemWidth,
|
| - static_cast<int>((kTextWidth + 50 +
|
| - download_util::kSmallProgressIconSize) *
|
| - new_item_animation_->GetCurrentValue()));
|
| - showing_width = std::max(showing_width, kMinDownloadItemWidth);
|
| - gtk_widget_set_size_request(body_, showing_width, -1);
|
| + if (IsDangerous()) {
|
| + int showing_width = std::max(kMinDangerousDownloadWidth,
|
| + static_cast<int>(dangerous_hbox_full_width_ *
|
| + new_item_animation_->GetCurrentValue()));
|
| + gtk_widget_set_size_request(dangerous_hbox_, showing_width, -1);
|
| + } else {
|
| + DCHECK(animation == new_item_animation_.get());
|
| + // See above TODO for explanation of the extra 50.
|
| + int showing_width = std::max(kMinDownloadItemWidth,
|
| + static_cast<int>((kTextWidth + 50 +
|
| + download_util::kSmallProgressIconSize) *
|
| + new_item_animation_->GetCurrentValue()));
|
| + showing_width = std::max(showing_width, kMinDownloadItemWidth);
|
| + gtk_widget_set_size_request(body_, showing_width, -1);
|
| + }
|
| }
|
| }
|
|
|
| +DownloadItem* DownloadItemGtk::get_download() {
|
| + return download_model_->download();
|
| +}
|
| +
|
| +bool DownloadItemGtk::IsDangerous() {
|
| + return get_download()->safety_state() == DownloadItem::DANGEROUS;
|
| +}
|
| +
|
| // Download progress animation functions.
|
|
|
| void DownloadItemGtk::UpdateDownloadProgress() {
|
| @@ -351,7 +466,7 @@
|
|
|
| void DownloadItemGtk::LoadIcon() {
|
| IconManager* im = g_browser_process->icon_manager();
|
| - im->LoadIcon(download_model_->download()->full_path(),
|
| + im->LoadIcon(get_download()->full_path(),
|
| IconLoader::SMALL, &icon_consumer_,
|
| NewCallback(this, &DownloadItemGtk::OnLoadIconComplete));
|
| }
|
| @@ -408,6 +523,17 @@
|
| IDR_DOWNLOAD_BUTTON_MENU_TOP_P, 0, 0,
|
| IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P, 0, 0,
|
| IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P, 0, 0);
|
| +
|
| + dangerous_nine_box_ = new NineBox(
|
| + IDR_DOWNLOAD_BUTTON_LEFT_TOP,
|
| + IDR_DOWNLOAD_BUTTON_CENTER_TOP,
|
| + IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD,
|
| + IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE,
|
| + IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE,
|
| + IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD,
|
| + IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM,
|
| + IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM,
|
| + IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD);
|
| }
|
|
|
| // static
|
| @@ -454,7 +580,7 @@
|
| download_util::PaintDownloadProgress(&canvas,
|
| widget->allocation.x, widget->allocation.y,
|
| download_item->progress_angle_,
|
| - download_item->download_model_->download()->PercentComplete(),
|
| + download_item->get_download()->PercentComplete(),
|
| download_util::SMALL);
|
| }
|
|
|
| @@ -508,3 +634,26 @@
|
| else
|
| gtk_widget_show(item->hbox_);
|
| }
|
| +
|
| +// static
|
| +gboolean DownloadItemGtk::OnDangerousPromptExpose(GtkWidget* widget,
|
| + GdkEventExpose* event, DownloadItemGtk* item) {
|
| + dangerous_nine_box_->RenderToWidget(widget);
|
| + return FALSE; // Continue propagation.
|
| +}
|
| +
|
| +// static
|
| +// TODO(estade): here and below, add clickjacking histogram code.
|
| +void DownloadItemGtk::OnDangerousAccept(GtkWidget* button,
|
| + DownloadItemGtk* item) {
|
| + item->get_download()->manager()->DangerousDownloadValidated(
|
| + item->get_download());
|
| +}
|
| +
|
| +// static
|
| +void DownloadItemGtk::OnDangerousDecline(GtkWidget* button,
|
| + DownloadItemGtk* item) {
|
| + if (item->get_download()->state() == DownloadItem::IN_PROGRESS)
|
| + item->get_download()->Cancel(true);
|
| + item->get_download()->Remove(true);
|
| +}
|
|
|