172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/download/download_item_view.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/i18n/break_iterator.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/sys_string_conversions.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_item_model.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_util.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/themes/theme_service.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/download/download_shelf_view.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/accessibility/accessible_view_state.h" 253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/slide_animation.h" 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/text/text_elider.h" 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h" 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/color_utils.h" 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "ui/gfx/image.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "unicode/uchar.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/native_button.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/menu/menu_2.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(paulg): These may need to be adjusted when download progress 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// animation is added, and also possibly to take into account 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// different screen resolutions. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTextWidth = 140; // Pixels 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kDangerousTextWidth = 200; // Pixels 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kHorizontalTextPadding = 2; // Pixels 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kVerticalPadding = 3; // Pixels 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kVerticalTextSpacer = 2; // Pixels 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kVerticalTextPadding = 2; // Pixels 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The maximum number of characters we show in a file name when displaying the 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dangerous download message. 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kFileNameMaxLength = 20; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We add some padding before the left image so that the progress animation icon 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// hides the corners of the left image. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kLeftPadding = 0; // Pixels. 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The space between the Save and Discard buttons when prompting for a dangerous 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// download. 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kButtonPadding = 5; // Pixels. 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The space on the left and right side of the dangerous download label. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kLabelPadding = 4; // Pixels. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkColor kFileNameDisabledColor = SkColorSetRGB(171, 192, 212); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How long the 'download complete' animation should last for. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCompleteAnimationDurationMs = 2500; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// How long the 'download interrupted' animation should last for. 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kInterruptedAnimationDurationMs = 2500; 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How long we keep the item disabled after the user clicked it to open the 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// downloaded item. 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kDisabledOnOpenDuration = 3000; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Darken light-on-dark download status text by 20% before drawing, thus 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// creating a "muted" version of title text for both dark-on-light and 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// light-on-dark themes. 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const double kDownloadItemLuminanceMod = 0.8; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DownloadShelfContextMenuWin ------------------------------------------------- 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DownloadShelfContextMenuWin : public DownloadShelfContextMenu { 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit DownloadShelfContextMenuWin(BaseDownloadItemModel* model) 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : DownloadShelfContextMenu(model) { 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(model); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run(const gfx::Point& point) { 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->IsComplete()) 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch menu_.reset(new views::Menu2(GetFinishedMenuModel())); 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch menu_.reset(new views::Menu2(GetInProgressMenuModel())); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The menu's alignment is determined based on the UI layout. 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Menu2::Alignment alignment; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (base::i18n::IsRTL()) 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch alignment = views::Menu2::ALIGN_TOPRIGHT; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch alignment = views::Menu2::ALIGN_TOPLEFT; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch menu_->RunMenuAt(point, alignment); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This method runs when the caller has been deleted and we should not attempt 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to access |download_|. 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Stop() { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_ = NULL; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<views::Menu2> menu_; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DownloadItemView ------------------------------------------------------------ 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadItemView::DownloadItemView(DownloadItem* download, 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DownloadShelfView* parent, 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseDownloadItemModel* model) 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : warning_icon_(NULL), 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_(download), 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_(parent), 1243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen status_text_(UTF16ToWide( 1253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING))), 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch show_status_text_(true), 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_state_(NORMAL), 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_state_(NORMAL), 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch progress_angle_(download_util::kStartAngleDegrees), 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_pressed_(false), 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dragging_(false), 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch starting_drag_(false), 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_(model), 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_button_(NULL), 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_button_(NULL), 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_(NULL), 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_sized_(false), 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disabled_while_opening_(false), 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch creation_time_(base::Time::Now()), 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)), 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick deleted_(NULL) { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(download_); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_->AddObserver(this); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle &rb = ResourceBundle::GetSharedInstance(); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BodyImageSet normal_body_image_set = { 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP), 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE), 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM) 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_body_image_set_ = normal_body_image_set; 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DropDownImageSet normal_drop_down_image_set = { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP), 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE), 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM) 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_drop_down_image_set_ = normal_drop_down_image_set; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BodyImageSet hot_body_image_set = { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_H), 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H), 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H), 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_H), 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H), 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H), 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H), 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H), 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_ = hot_body_image_set; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DropDownImageSet hot_drop_down_image_set = { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_H), 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H), 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H) 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_drop_down_image_set_ = hot_drop_down_image_set; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BodyImageSet pushed_body_image_set = { 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_P), 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P), 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P), 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_P), 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P), 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P), 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P), 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P), 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P) 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pushed_body_image_set_ = pushed_body_image_set; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DropDownImageSet pushed_drop_down_image_set = { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_P), 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P), 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P) 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pushed_drop_down_image_set_ = pushed_drop_down_image_set; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BodyImageSet dangerous_mode_body_image_set = { 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD), 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD), 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_mode_body_image_set_ = dangerous_mode_body_image_set; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LoadIcon(); 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tooltip_text_ = 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UTF16ToWide(download_->GetFileNameToReportUser().LossyDisplayName()); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch font_ = ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick box_height_ = std::max<int>(2 * kVerticalPadding + font_.GetHeight() + 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kVerticalTextPadding + font_.GetHeight(), 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2 * kVerticalPadding + 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_body_image_set_.top_left->height() + 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_body_image_set_.bottom_left->height()); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (download_util::kSmallProgressIconSize > box_height_) 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch box_y_ = (download_util::kSmallProgressIconSize - box_height_) / 2; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch box_y_ = kVerticalPadding; 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size size = GetPreferredSize(); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (base::i18n::IsRTL()) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Drop down button is glued to the left of the download shelf. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_x_left_ = 0; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_x_right_ = normal_drop_down_image_set_.top->width(); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Drop down button is glued to the right of the download shelf. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_x_left_ = 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size.width() - normal_drop_down_image_set_.top->width(); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_x_right_ = size.width(); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen body_hover_animation_.reset(new ui::SlideAnimation(this)); 2493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen drop_hover_animation_.reset(new ui::SlideAnimation(this)); 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (download->safety_state() == DownloadItem::DANGEROUS) { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tooltip_text_.clear(); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_state_ = DANGEROUS; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_state_ = DANGEROUS; 2553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen save_button_ = new views::NativeButton(this, 2563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen UTF16ToWide(l10n_util::GetStringUTF16( 2573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen download->is_extension_install() ? 2583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_SAVE_DOWNLOAD))); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_button_->set_ignore_minimum_size(true); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_button_ = new views::NativeButton( 2613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD))); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_button_->set_ignore_minimum_size(true); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(save_button_); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(discard_button_); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ensure the file name is not too long. 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Extract the file extension (if any). 269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch FilePath filename(download->target_name()); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 extension = WideToUTF16(base::SysNativeMBToWide( 272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen filename.Extension())); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 extension = filename.Extension(); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove leading '.' 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (extension.length() > 0) 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension = extension.substr(1); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 rootname = WideToUTF16(base::SysNativeMBToWide( 282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen filename.RemoveExtension().value())); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 rootname = filename.RemoveExtension().value(); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Elide giant extensions (this shouldn't currently be hit, but might 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in future, should we ever notice unsafe giant extensions). 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (extension.length() > kFileNameMaxLength / 2) 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ElideString(extension, kFileNameMaxLength / 2, &extension); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The dangerous download label text and icon are different 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // under different cases. 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 dangerous_label; 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (download->danger_type() == DownloadItem::DANGEROUS_URL) { 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Safebrowsing shows the download URL leads to malicious file. 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING); 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dangerous_label = 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen l10n_util::GetStringUTF16(IDS_PROMPT_UNSAFE_DOWNLOAD_URL); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The download file has dangerous file type (e.g.: an executable). 302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(download->danger_type() == DownloadItem::DANGEROUS_FILE); 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen warning_icon_ = rb.GetBitmapNamed(IDR_WARNING); 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (download->is_extension_install()) { 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dangerous_label = 306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION); 307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ui::ElideString(rootname, 309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kFileNameMaxLength - extension.length(), 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &rootname); 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen string16 filename = rootname + ASCIIToUTF16(".") + extension; 312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen filename = base::i18n::GetDisplayStringInLTRDirectionality(filename); 313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dangerous_label = 314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD, filename); 315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dangerous_download_label_ = new views::Label(UTF16ToWide(dangerous_label)); 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetMultiLine(true); 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetHorizontalAlignment( 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Label::ALIGN_LEFT); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(dangerous_download_label_); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SizeLabelToMinWidth(); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UpdateAccessibleName(); 327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick set_accessibility_focusable(true); 328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up our animation. 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartDownloadProgress(); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadItemView::~DownloadItemView() { 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context_menu_.get()) { 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_->Stop(); 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icon_consumer_.CancelAllRequests(); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopDownloadProgress(); 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_->RemoveObserver(this); 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (deleted_) 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *deleted_ = true; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Progress animation handlers. 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::UpdateDownloadProgress() { 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch progress_angle_ = (progress_angle_ + 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kUnknownIncrementDegrees) % 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kMaxDegrees; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::StartDownloadProgress() { 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (progress_timer_.IsRunning()) 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch progress_timer_.Start( 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(download_util::kProgressRateMs), this, 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &DownloadItemView::UpdateDownloadProgress); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::StopDownloadProgress() { 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch progress_timer_.Stop(); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OnExtractIconComplete(IconManager::Handle handle, 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Image* icon_bitmap) { 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (icon_bitmap) 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent()->SchedulePaint(); 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DownloadObserver interface. 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Update the progress graphic on the icon and our text status label 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to reflect our current bytes downloaded, time remaining. 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::OnDownloadUpdated(DownloadItem* download) { 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(download == download_); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (body_state_ == DANGEROUS && 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We have been approved. 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClearDangerousMode(); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen string16 status_text = model_->GetStatusText(); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (download_->state()) { 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DownloadItem::IN_PROGRESS: 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_->is_paused() ? StopDownloadProgress() : StartDownloadProgress(); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case DownloadItem::INTERRUPTED: 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopDownloadProgress(); 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_.reset(new ui::SlideAnimation(this)); 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->SetSlideDuration(kInterruptedAnimationDurationMs); 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->SetTweenType(ui::Tween::LINEAR); 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->Show(); 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (status_text.empty()) 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_status_text_ = false; 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SchedulePaint(); 398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LoadIcon(); 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DownloadItem::COMPLETE: 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (download_->auto_opened()) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_->RemoveDownloadView(this); // This will delete us! 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopDownloadProgress(); 4063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen complete_animation_.reset(new ui::SlideAnimation(this)); 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs); 4083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen complete_animation_->SetTweenType(ui::Tween::LINEAR); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_animation_->Show(); 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status_text.empty()) 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch show_status_text_ = false; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LoadIcon(); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DownloadItem::CANCELLED: 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopDownloadProgress(); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LoadIcon(); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DownloadItem::REMOVING: 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_->RemoveDownloadView(this); // This will delete us! 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen status_text_ = UTF16ToWideHack(status_text); 427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UpdateAccessibleName(); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We use the parent's (DownloadShelfView's) SchedulePaint, since there 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // are spaces between each DownloadItemView that the parent is responsible 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for painting. 43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent()->SchedulePaint(); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::OnDownloadOpened(DownloadItem* download) { 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disabled_while_opening_ = true; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetEnabled(false); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask( 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reenable_method_factory_.NewRunnableMethod(&DownloadItemView::Reenable), 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDisabledOnOpenDuration); 4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Notify our parent. 4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick parent_->OpenedDownload(this); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// View overrides 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In dangerous mode we have to layout our buttons. 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::Layout() { 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsDangerousMode()) { 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetColor( 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetThemeProvider()->GetColor(ThemeService::COLOR_BOOKMARK_TEXT)); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x = kLeftPadding + dangerous_mode_body_image_set_.top_left->width() + 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch warning_icon_->width() + kLabelPadding; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y = (height() - dangerous_download_label_->height()) / 2; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetBounds(x, y, 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->width(), 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->height()); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size button_size = GetButtonSize(); 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += dangerous_download_label_->width() + kLabelPadding; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y = (height() - button_size.height()) / 2; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_button_->SetBounds(x, y, button_size.width(), button_size.height()); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += button_size.width() + kButtonPadding; 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_button_->SetBounds(x, y, button_size.width(), button_size.height()); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsengfx::Size DownloadItemView::GetPreferredSize() { 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int width, height; 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // First, we set the height to the height of two rows or text plus margins. 474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen height = 2 * kVerticalPadding + 2 * font_.GetHeight() + kVerticalTextPadding; 475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Then we increase the size if the progress icon doesn't fit. 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen height = std::max<int>(height, download_util::kSmallProgressIconSize); 477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) { 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width = kLeftPadding + dangerous_mode_body_image_set_.top_left->width(); 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += warning_icon_->width() + kLabelPadding; 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += dangerous_download_label_->width() + kLabelPadding; 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Size button_size = GetButtonSize(); 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure the button fits. 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen height = std::max<int>(height, 2 * kVerticalPadding + button_size.height()); 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Then we make sure the warning icon fits. 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen height = std::max<int>(height, 2 * kVerticalPadding + 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen warning_icon_->height()); 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += button_size.width() * 2 + kButtonPadding; 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += dangerous_mode_body_image_set_.top_right->width(); 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width = kLeftPadding + normal_body_image_set_.top_left->width(); 492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += download_util::kSmallProgressIconSize; 493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += kTextWidth; 494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += normal_body_image_set_.top_right->width(); 495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width += normal_drop_down_image_set_.top->width(); 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return gfx::Size(width, height); 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Handle a mouse click and open the context menu if the mouse is 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// over the drop-down region. 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DownloadItemView::OnMousePressed(const views::MouseEvent& event) { 503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Stop any completion animation. 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (complete_animation_.get() && complete_animation_->is_animating()) 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->End(); 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point menu_location(event.location()); 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.IsOnlyLeftMouseButton()) { 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!InDropDownButtonXCoordinateRange(event.x())) { 514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(PUSHED, NORMAL); 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Anchor the menu below the dropmarker. 519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen menu_location.SetPoint(base::i18n::IsRTL() ? 520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_down_x_right_ : drop_down_x_left_, 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen height()); 522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_down_pressed_ = true; 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, PUSHED); 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShowContextMenu(menu_location, true); 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Handle drag (file copy) operations. 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) { 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!starting_drag_) { 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen starting_drag_ = true; 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drag_start_point_ = event.location(); 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (dragging_) { 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->IsComplete()) { 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconManager* im = g_browser_process->icon_manager(); 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Image* icon = im->LookupIcon(download_->GetUserVerifiedFilePath(), 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconLoader::SMALL); 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (icon) { 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Widget* widget = GetWidget(); 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_util::DragDownload(download_, icon, 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen widget ? widget->GetNativeView() : NULL); 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (ExceededDragThreshold( 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.location().x() - drag_start_point_.x(), 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.location().y() - drag_start_point_.y())) { 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragging_ = true; 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OnMouseReleased(const views::MouseEvent& event) { 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.IsOnlyLeftMouseButton() && 564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !InDropDownButtonXCoordinateRange(event.x())) { 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OpenDownload(); 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, NORMAL); 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OnMouseCaptureLost() { 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (dragging_) { 577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Starting a drag results in a MouseCaptureLost. 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragging_ = false; 579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen starting_drag_ = false; 580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, NORMAL); 582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OnMouseMoved(const views::MouseEvent& event) { 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool on_body = !InDropDownButtonXCoordinateRange(event.x()); 591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT); 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (on_body) { 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen body_hover_animation_->Show(); 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_hover_animation_->Hide(); 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen body_hover_animation_->Hide(); 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_hover_animation_->Show(); 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OnMouseExited(const views::MouseEvent& event) { 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Mouse should not activate us in dangerous mode. 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL); 607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen body_hover_animation_->Hide(); 608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_hover_animation_->Hide(); 609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DownloadItemView::OnKeyPressed(const views::KeyEvent& event) { 612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Key press should not activate us in dangerous mode. 613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsDangerousMode()) 614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.key_code() == ui::VKEY_SPACE || 617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.key_code() == ui::VKEY_RETURN) { 618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OpenDownload(); 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DownloadItemView::GetTooltipText(const gfx::Point& p, 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring* tooltip) { 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tooltip_text_.empty()) 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tooltip->assign(tooltip_text_); 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::ShowContextMenu(const gfx::Point& p, 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_mouse_gesture) { 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point point = p; 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Similar hack as in MenuButton. 638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We're about to show the menu from a mouse press. By showing from the 639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // mouse press event we block RootView in mouse dispatching. This also 640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // appears to cause RootView to get a mouse pressed BEFORE the mouse 641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // release is seen, which means RootView sends us another mouse press no 642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // matter where the user pressed. To force RootView to recalculate the 643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // mouse target during the mouse press we explicitly set the mouse handler 644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to NULL. 645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetRootView()->SetMouseHandler(NULL); 646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If |is_mouse_gesture| is false, |p| is ignored. The menu is shown aligned 648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to drop down arrow button. 649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!is_mouse_gesture) { 650ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_down_pressed_ = true; 651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, PUSHED); 652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen point.set_y(height()); 654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (base::i18n::IsRTL()) 655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen point.set_x(drop_down_x_right_); 656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen point.set_x(drop_down_x_left_); 658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View::ConvertPointToScreen(this, &point); 661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!context_menu_.get()) 663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen context_menu_.reset(new DownloadShelfContextMenuWin(model_.get())); 664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When we call the Run method on the menu, it runs an inner message loop 665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that might causes us to be deleted. 666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool deleted = false; 667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen deleted_ = &deleted; 668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen context_menu_->Run(point); 669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (deleted) 670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; // We have been deleted! Don't access 'this'. 671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen deleted_ = NULL; 672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the menu action was to remove the download, this view will also be 674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // invalid so we must not access 'this' in this case. 675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (context_menu_->download()) { 676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen drop_down_pressed_ = false; 677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Showing the menu blocks. Here we revert the state. 678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetState(NORMAL, NORMAL); 679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::GetAccessibleState(ui::AccessibleViewState* state) { 683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state->name = accessible_name_; 684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->safety_state() == DownloadItem::DANGEROUS) { 686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE; 687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state->state = ui::AccessibilityTypes::STATE_HASPOPUP; 689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::ButtonPressed( 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Button* sender, const views::Event& event) { 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sender == discard_button_) { 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time::Now() - creation_time_); 697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->IsPartialDownload()) 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_->Cancel(true); 699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WARNING: we are deleted at this point. Don't access 'this'. 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (sender == save_button_) { 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The user has confirmed a dangerous download. We'd record how quickly the 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // user did this to detect whether we're being clickjacked. 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time::Now() - creation_time_); 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This will change the state and notify us. 7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick download_->DangerousDownloadValidated(); 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::AnimationProgressed(const ui::Animation* animation) { 712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We don't care if what animation (body button/drop button/complete), 713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is calling back, as they all have to go through the same paint call. 714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SchedulePaint(); 715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid DownloadItemView::OnPaint(gfx::Canvas* canvas) { 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BodyImageSet* body_image_set = NULL; 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (body_state_) { 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NORMAL: 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case HOT: 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set = &normal_body_image_set_; 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PUSHED: 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set = &pushed_body_image_set_; 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DANGEROUS: 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set = &dangerous_mode_body_image_set_; 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DropDownImageSet* drop_down_image_set = NULL; 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (drop_down_state_) { 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NORMAL: 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case HOT: 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set = &normal_drop_down_image_set_; 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PUSHED: 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set = &pushed_drop_down_image_set_; 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case DANGEROUS: 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set = NULL; // No drop-down in dangerous mode. 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int center_width = width() - kLeftPadding - 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->left->width() - 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->right->width() - 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (drop_down_image_set ? 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_drop_down_image_set_.center->width() : 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // May be caused by animation. 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (center_width <= 0) 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw status before button image to effectively lighten text. 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsDangerousMode()) { 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (show_status_text_) { 76372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int mirrored_x = GetMirroredXWithWidthInView( 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kSmallProgressIconSize, kTextWidth); 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add font_.height() to compensate for title, which is drawn later. 7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int y = box_y_ + kVerticalPadding + font_.GetHeight() + 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kVerticalTextPadding; 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColor file_name_color = GetThemeProvider()->GetColor( 769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ThemeService::COLOR_BOOKMARK_TEXT); 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If text is light-on-dark, lightening it alone will do nothing. 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Therefore we mute luminance a wee bit before drawing in this case. 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (color_utils::RelativeLuminance(file_name_color) > 0.5) 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_name_color = SkColorSetRGB( 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(kDownloadItemLuminanceMod * 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColorGetR(file_name_color)), 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(kDownloadItemLuminanceMod * 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColorGetG(file_name_color)), 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(kDownloadItemLuminanceMod * 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColorGetB(file_name_color))); 78072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen canvas->DrawStringInt(WideToUTF16Hack(status_text_), font_, 78172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen file_name_color, mirrored_x, y, kTextWidth, 78272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen font_.GetHeight()); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the background images. 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x = kLeftPadding; 7883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick canvas->Save(); 7893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (base::i18n::IsRTL()) { 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since we do not have the mirrored images for 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (hot_)body_image_set->top_left, (hot_)body_image_set->left, 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (hot_)body_image_set->bottom_left, and drop_down_image_set, 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for RTL UI, we flip the canvas to draw those images mirrored. 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Consequently, we do not need to mirror the x-axis of those images. 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TranslateInt(width(), 0); 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->ScaleInt(-1, 1); 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->top_left, body_image_set->left, 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->bottom_left, 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, body_image_set->top_left->width()); 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += body_image_set->top_left->width(); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->top, body_image_set->center, 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->bottom, 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, center_width); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += center_width; 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->top_right, body_image_set->right, 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_image_set->bottom_right, 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, body_image_set->top_right->width()); 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overlay our body hot state. 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (body_hover_animation_->GetCurrentValue() > 0) { 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->SaveLayerAlpha( 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(body_hover_animation_->GetCurrentValue() * 255)); 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x = kLeftPadding; 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.top_left, hot_body_image_set_.left, 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.bottom_left, 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, hot_body_image_set_.top_left->width()); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += body_image_set->top_left->width(); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.top, hot_body_image_set_.center, 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.bottom, 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, center_width); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += center_width; 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.top_right, hot_body_image_set_.right, 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.bottom_right, 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_body_image_set_.top_right->width()); 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->Restore(); 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x += body_image_set->top_right->width(); 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the drop-down. 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_down_image_set) { 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set->top, drop_down_image_set->center, 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set->bottom, 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, drop_down_image_set->top->width()); 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overlay our drop-down hot state. 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_hover_animation_->GetCurrentValue() > 0) { 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->SaveLayerAlpha( 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(drop_hover_animation_->GetCurrentValue() * 255)); 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkXfermode::kClear_Mode); 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintBitmaps(canvas, 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set->top, drop_down_image_set->center, 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_image_set->bottom, 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, box_y_, box_height_, drop_down_image_set->top->width()); 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->Restore(); 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Restore the canvas to avoid file name etc. text are drawn flipped. 8643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Consequently, the x-axis of following canvas->DrawXXX() method should be 8653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // mirrored so the text and images are down in the right positions. 8663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick canvas->Restore(); 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Print the text, left aligned and always print the file extension. 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last value of x was the end of the right image, just before the button. 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that in dangerous mode we use a label (as the text is multi-line). 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsDangerousMode()) { 8723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 filename; 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!disabled_while_opening_) { 87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen filename = ui::ElideFilename(download_->GetFileNameToReportUser(), 87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen font_, kTextWidth); 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, Calculate the download status opening string width. 8783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen string16 status_string = 8793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, string16()); 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int status_string_width = font_.GetStringWidth(status_string); 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Then, elide the file name. 8823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 filename_string = 88372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ElideFilename(download_->GetFileNameToReportUser(), font_, 88472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen kTextWidth - status_string_width); 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last, concat the whole string. 8863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, 8873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick filename_string); 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int mirrored_x = GetMirroredXWithWidthInView( 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kSmallProgressIconSize, kTextWidth); 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColor file_name_color = GetThemeProvider()->GetColor( 893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ThemeService::COLOR_BOOKMARK_TEXT); 8943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int y = 8953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick box_y_ + (show_status_text_ ? kVerticalPadding : 8963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick (box_height_ - font_.GetHeight()) / 2); 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the file's name. 89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen canvas->DrawStringInt(filename, font_, 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IsEnabled() ? file_name_color : 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kFileNameDisabledColor, 9023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mirrored_x, y, kTextWidth, font_.GetHeight()); 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 905dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Load the icon. 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IconManager* im = g_browser_process->icon_manager(); 907dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gfx::Image* image = im->LookupIcon(download_->GetUserVerifiedFilePath(), 908dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IconLoader::SMALL); 909dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SkBitmap* icon = NULL; 910dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (IsDangerousMode()) 911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen icon = warning_icon_; 912dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else if (image) 913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen icon = *image; 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We count on the fact that the icon manager will cache the icons and if one 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is available, it will be cached here. We *don't* want to request the icon 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to be loaded here, since this will also get called if the icon can't be 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // loaded, in which case LookupIcon will always be NULL. The loading will be 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // triggered only when we think the status might change. 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (icon) { 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsDangerousMode()) { 922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->IsInProgress()) { 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::PaintDownloadProgress(canvas, this, 0, 0, 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch progress_angle_, 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_->PercentComplete(), 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::SMALL); 927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (download_->IsComplete() && 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_animation_.get() && 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch complete_animation_->is_animating()) { 930ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (download_->IsInterrupted()) { 931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_util::PaintDownloadInterrupted(canvas, this, 0, 0, 932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->GetCurrentValue(), 933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_util::SMALL); 934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 935ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_util::PaintDownloadComplete(canvas, this, 0, 0, 936ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen complete_animation_->GetCurrentValue(), 937ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_util::SMALL); 938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the icon image. 94372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int mirrored_x = GetMirroredXWithWidthInView( 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kSmallProgressIconOffset, icon->width()); 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsEnabled()) { 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*icon, mirrored_x, 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kSmallProgressIconOffset); 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Use an alpha to make the image look disabled. 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkPaint paint; 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint.setAlpha(120); 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*icon, mirrored_x, 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::kSmallProgressIconOffset, paint); 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 958ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::OpenDownload() { 959ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We're interested in how long it takes users to open downloads. If they 960ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // open downloads super quickly, we should be concerned about clickjacking. 961ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download", 962ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time::Now() - creation_time_); 963ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen download_->OpenDownload(); 964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateAccessibleName(); 965ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 966ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadItemView::LoadIcon() { 968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconManager* im = g_browser_process->icon_manager(); 969ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen im->LoadIcon(download_->GetUserVerifiedFilePath(), 970ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconLoader::SMALL, &icon_consumer_, 971ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewCallback(this, &DownloadItemView::OnExtractIconComplete)); 972ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 973ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 974ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Load an icon for the file type we're downloading, and animate any in progress 975ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// download state. 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::PaintBitmaps(gfx::Canvas* canvas, 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* top_bitmap, 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* center_bitmap, 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* bottom_bitmap, 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x, int y, int height, int width) { 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int middle_height = height - top_bitmap->height() - bottom_bitmap->height(); 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the top. 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*top_bitmap, 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 0, top_bitmap->width(), top_bitmap->height(), 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, y, width, top_bitmap->height(), false); 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y += top_bitmap->height(); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the center. 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*center_bitmap, 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 0, center_bitmap->width(), center_bitmap->height(), 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, y, width, middle_height, false); 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y += middle_height; 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the bottom. 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*bottom_bitmap, 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 0, bottom_bitmap->width(), bottom_bitmap->height(), 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x, y, width, bottom_bitmap->height(), false); 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::SetState(State body_state, State drop_down_state) { 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (body_state_ == body_state && drop_down_state_ == drop_down_state) 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_state_ = body_state; 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_state_ = drop_down_state; 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::ClearDangerousMode() { 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(download_->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED && 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_state_ == DANGEROUS && drop_down_state_ == DANGEROUS); 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch body_state_ = NORMAL; 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_down_state_ = NORMAL; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove the views used by the dangerous mode. 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveChildView(save_button_); 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete save_button_; 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_button_ = NULL; 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveChildView(discard_button_); 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete discard_button_; 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_button_ = NULL; 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveChildView(dangerous_download_label_); 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete dangerous_download_label_; 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_ = NULL; 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1025731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Set the accessible name back to the status and filename instead of the 1026731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // download warning. 1027731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UpdateAccessibleName(); 1028731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to load the icon now that the download_ has the real path. 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LoadIcon(); 1031dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tooltip_text_ = 1032dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UTF16ToWide(download_->GetFileNameToReportUser().LossyDisplayName()); 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force the shelf to layout again as our size has changed. 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_->Layout(); 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_->SchedulePaint(); 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size DownloadItemView::GetButtonSize() { 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(save_button_ && discard_button_); 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size size; 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We cache the size when successfully retrieved, not for performance reasons 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but because if this DownloadItemView is being animated while the tab is 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not showing, the native buttons are not parented and their preferred size 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is 0, messing-up the layout. 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cached_button_size_.width() != 0) 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return cached_button_size_; 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size = save_button_->GetMinimumSize(); 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size discard_size = discard_button_->GetMinimumSize(); 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size.SetSize(std::max(size.width(), discard_size.width()), 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(size.height(), discard_size.height())); 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (size.width() != 0) 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cached_button_size_ = size; 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return size; 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This method computes the minimum width of the label for displaying its text 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// configuration with minimum width. 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::SizeLabelToMinWidth() { 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dangerous_download_label_sized_) 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring text = dangerous_download_label_->GetText(); 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TrimWhitespace(text, TRIM_ALL, &text); 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(std::wstring::npos, text.find(L"\n")); 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make the label big so that GetPreferredSize() is not constrained by the 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current width. 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetBounds(0, 0, 1000, 1000); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size size; 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int min_width = -1; 1079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 text16 = WideToUTF16(text); 1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Using BREAK_WORD can work in most cases, but it can also break 1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // lines where it should not. Using BREAK_LINE is safer although 1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // slower for Chinese/Japanese. This is not perf-critical at all, though. 1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::BreakIterator iter(&text16, base::BreakIterator::BREAK_LINE); 1084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool status = iter.Init(); 1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(status); 1086ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 current_text = text16; 1088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 prev_text = text16; 1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (iter.Advance()) { 1090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t pos = iter.pos(); 1091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (pos >= text16.length()) 1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 1093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This can be a low surrogate codepoint, but u_isUWhiteSpace will 1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // return false and inserting a new line after a surrogate pair 1095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is perfectly ok. 1096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen char16 line_end_char = text16[pos - 1]; 1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (u_isUWhiteSpace(line_end_char)) 1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen current_text.replace(pos - 1, 1, 1, char16('\n')); 1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen current_text.insert(pos, 1, char16('\n')); 1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dangerous_download_label_->SetText(UTF16ToWide(current_text)); 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size = dangerous_download_label_->GetPreferredSize(); 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (min_width == -1) 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch min_width = size.width(); 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the width is growing again, it means we passed the optimal width spot. 1108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (size.width() > min_width) { 1109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dangerous_download_label_->SetText(UTF16ToWide(prev_text)); 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch min_width = size.width(); 1113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Restore the string. 1116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prev_text = current_text; 1117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen current_text = text16; 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we have a line with no line breaking opportunity (which is very 1121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // unlikely), we won't cut it. 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (min_width == -1) 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size = dangerous_download_label_->GetPreferredSize(); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_->SetBounds(0, 0, size.width(), size.height()); 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dangerous_download_label_sized_ = true; 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadItemView::Reenable() { 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disabled_while_opening_ = false; 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetEnabled(true); // Triggers a repaint. 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (x > drop_down_x_left_ && x < drop_down_x_right_) 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid DownloadItemView::UpdateAccessibleName() { 114172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 new_name; 1142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (download_->safety_state() == DownloadItem::DANGEROUS) { 114372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new_name = WideToUTF16Hack(dangerous_download_label_->GetText()); 1144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 114572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new_name = WideToUTF16Hack(status_text_) + char16(' ') + 1146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen download_->GetFileNameToReportUser().LossyDisplayName(); 1147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the name has changed, notify assistive technology that the name 1150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // has changed so they can announce it immediately. 1151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (new_name != accessible_name_) { 1152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen accessible_name_ = new_name; 1153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (GetWidget()) { 1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetWidget()->NotifyAccessibilityEvent( 1155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this, ui::AccessibilityTypes::EVENT_NAME_CHANGED, true); 1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1159