OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/download/download_item_view.h" | 5 #include "chrome/browser/ui/views/download/download_item_view.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/callback.h" | 13 #include "base/callback.h" |
14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
15 #include "base/i18n/break_iterator.h" | 15 #include "base/i18n/break_iterator.h" |
16 #include "base/i18n/rtl.h" | 16 #include "base/i18n/rtl.h" |
17 #include "base/location.h" | 17 #include "base/location.h" |
| 18 #include "base/macros.h" |
| 19 #include "base/memory/ptr_util.h" |
18 #include "base/metrics/histogram_macros.h" | 20 #include "base/metrics/histogram_macros.h" |
19 #include "base/single_thread_task_runner.h" | 21 #include "base/single_thread_task_runner.h" |
20 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
21 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
22 #include "base/strings/sys_string_conversions.h" | 24 #include "base/strings/sys_string_conversions.h" |
23 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
24 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
25 #include "chrome/browser/browser_process.h" | 27 #include "chrome/browser/browser_process.h" |
26 #include "chrome/browser/download/chrome_download_manager_delegate.h" | 28 #include "chrome/browser/download/chrome_download_manager_delegate.h" |
27 #include "chrome/browser/download/download_item_model.h" | 29 #include "chrome/browser/download/download_item_model.h" |
28 #include "chrome/browser/download/download_stats.h" | 30 #include "chrome/browser/download/download_stats.h" |
29 #include "chrome/browser/download/drag_download_item.h" | 31 #include "chrome/browser/download/drag_download_item.h" |
30 #include "chrome/browser/extensions/api/experience_sampling_private/experience_s
ampling.h" | 32 #include "chrome/browser/extensions/api/experience_sampling_private/experience_s
ampling.h" |
31 #include "chrome/browser/profiles/profile.h" | 33 #include "chrome/browser/profiles/profile.h" |
32 #include "chrome/browser/safe_browsing/download_feedback_service.h" | 34 #include "chrome/browser/safe_browsing/download_feedback_service.h" |
33 #include "chrome/browser/safe_browsing/download_protection_service.h" | 35 #include "chrome/browser/safe_browsing/download_protection_service.h" |
34 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 36 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
35 #include "chrome/browser/themes/theme_properties.h" | 37 #include "chrome/browser/themes/theme_properties.h" |
36 #include "chrome/browser/ui/views/download/download_feedback_dialog_view.h" | 38 #include "chrome/browser/ui/views/download/download_feedback_dialog_view.h" |
37 #include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h" | 39 #include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h" |
38 #include "chrome/browser/ui/views/download/download_shelf_view.h" | 40 #include "chrome/browser/ui/views/download/download_shelf_view.h" |
39 #include "chrome/browser/ui/views/frame/browser_view.h" | 41 #include "chrome/browser/ui/views/frame/browser_view.h" |
40 #include "chrome/common/pref_names.h" | 42 #include "chrome/common/pref_names.h" |
41 #include "chrome/grit/generated_resources.h" | 43 #include "chrome/grit/generated_resources.h" |
42 #include "chrome/grit/theme_resources.h" | |
43 #include "components/prefs/pref_service.h" | 44 #include "components/prefs/pref_service.h" |
44 #include "content/public/browser/download_danger_type.h" | 45 #include "content/public/browser/download_danger_type.h" |
45 #include "third_party/icu/source/common/unicode/uchar.h" | 46 #include "third_party/icu/source/common/unicode/uchar.h" |
46 #include "ui/accessibility/ax_view_state.h" | 47 #include "ui/accessibility/ax_view_state.h" |
47 #include "ui/base/l10n/l10n_util.h" | 48 #include "ui/base/l10n/l10n_util.h" |
| 49 #include "ui/base/material_design/material_design_controller.h" |
48 #include "ui/base/resource/resource_bundle.h" | 50 #include "ui/base/resource/resource_bundle.h" |
49 #include "ui/base/theme_provider.h" | 51 #include "ui/base/theme_provider.h" |
50 #include "ui/events/event.h" | 52 #include "ui/events/event.h" |
51 #include "ui/gfx/animation/slide_animation.h" | 53 #include "ui/gfx/animation/slide_animation.h" |
52 #include "ui/gfx/canvas.h" | 54 #include "ui/gfx/canvas.h" |
| 55 #include "ui/gfx/color_palette.h" |
53 #include "ui/gfx/color_utils.h" | 56 #include "ui/gfx/color_utils.h" |
54 #include "ui/gfx/image/image.h" | 57 #include "ui/gfx/image/image.h" |
55 #include "ui/gfx/scoped_canvas.h" | 58 #include "ui/gfx/paint_vector_icon.h" |
56 #include "ui/gfx/text_elider.h" | 59 #include "ui/gfx/text_elider.h" |
57 #include "ui/gfx/text_utils.h" | 60 #include "ui/gfx/text_utils.h" |
58 #include "ui/views/controls/button/label_button.h" | 61 #include "ui/gfx/vector_icons_public.h" |
| 62 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" |
| 63 #include "ui/views/animation/ink_drop_highlight.h" |
| 64 #include "ui/views/border.h" |
| 65 #include "ui/views/controls/button/image_button.h" |
| 66 #include "ui/views/controls/button/md_text_button.h" |
| 67 #include "ui/views/controls/button/vector_icon_button.h" |
| 68 #include "ui/views/controls/focusable_border.h" |
59 #include "ui/views/controls/label.h" | 69 #include "ui/views/controls/label.h" |
60 #include "ui/views/mouse_constants.h" | 70 #include "ui/views/mouse_constants.h" |
61 #include "ui/views/widget/root_view.h" | 71 #include "ui/views/widget/root_view.h" |
62 #include "ui/views/widget/widget.h" | 72 #include "ui/views/widget/widget.h" |
63 | 73 |
64 using content::DownloadItem; | 74 using content::DownloadItem; |
65 using extensions::ExperienceSamplingEvent; | 75 using extensions::ExperienceSamplingEvent; |
66 | 76 |
67 namespace { | 77 namespace { |
68 | 78 |
69 // TODO(paulg): These may need to be adjusted when download progress | 79 // All values in dp. |
70 // animation is added, and also possibly to take into account | 80 const int kTextWidth = 140; |
71 // different screen resolutions. | 81 const int kDangerousTextWidth = 200; |
72 const int kTextWidth = 140; // Pixels | |
73 const int kDangerousTextWidth = 200; // Pixels | |
74 const int kVerticalPadding = 3; // Pixels | |
75 const int kVerticalTextPadding = 2; // Pixels | |
76 const int kTooltipMaxWidth = 800; // Pixels | |
77 | 82 |
78 // Padding around progress indicator, on all sides. | 83 // The normal height of the item which may be exceeded if text is large. |
79 const int kProgressPadding = 7; | 84 const int kDefaultHeight = 48; |
80 | 85 |
81 // We add some padding before the left image so that the progress animation icon | 86 // The vertical distance between the item's visual upper bound (as delineated by |
82 // hides the corners of the left image. | 87 // the separator on the right) and the edge of the shelf. |
83 const int kLeftPadding = 0; // Pixels. | 88 const int kTopBottomPadding = 6; |
| 89 |
| 90 // The minimum vertical padding above and below contents of the download item. |
| 91 // This is only used when the text size is large. |
| 92 const int kMinimumVerticalPadding = 2 + kTopBottomPadding; |
| 93 |
| 94 // Vertical padding between filename and status text. |
| 95 const int kVerticalTextPadding = 1; |
| 96 |
| 97 const int kTooltipMaxWidth = 800; |
| 98 |
| 99 // Padding before the icon and at end of the item. |
| 100 const int kStartPadding = 12; |
| 101 const int kEndPadding = 6; |
| 102 |
| 103 // Horizontal padding between progress indicator and filename/status text. |
| 104 const int kProgressTextPadding = 8; |
84 | 105 |
85 // The space between the Save and Discard buttons when prompting for a dangerous | 106 // The space between the Save and Discard buttons when prompting for a dangerous |
86 // download. | 107 // download. |
87 const int kButtonPadding = 5; // Pixels. | 108 const int kButtonPadding = 5; |
88 | 109 |
89 // The space on the left and right side of the dangerous download label. | 110 // The touchable space around the dropdown button's icon. |
90 const int kLabelPadding = 4; // Pixels. | 111 const int kDropdownBorderWidth = 10; |
91 | 112 |
92 const SkColor kFileNameDisabledColor = SkColorSetRGB(171, 192, 212); | 113 // The space on the right side of the dangerous download label. |
| 114 const int kLabelPadding = 8; |
| 115 |
| 116 // Height/width of the warning icon, also in dp. |
| 117 const int kWarningIconSize = 24; |
93 | 118 |
94 // How long the 'download complete' animation should last for. | 119 // How long the 'download complete' animation should last for. |
95 const int kCompleteAnimationDurationMs = 2500; | 120 const int kCompleteAnimationDurationMs = 2500; |
96 | 121 |
97 // How long the 'download interrupted' animation should last for. | 122 // How long the 'download interrupted' animation should last for. |
98 const int kInterruptedAnimationDurationMs = 2500; | 123 const int kInterruptedAnimationDurationMs = 2500; |
99 | 124 |
100 // How long we keep the item disabled after the user clicked it to open the | 125 // How long we keep the item disabled after the user clicked it to open the |
101 // downloaded item. | 126 // downloaded item. |
102 const int kDisabledOnOpenDuration = 3000; | 127 const int kDisabledOnOpenDuration = 3000; |
103 | 128 |
| 129 // The separator is drawn as a border. It's one dp wide. |
| 130 class SeparatorBorder : public views::FocusableBorder { |
| 131 public: |
| 132 explicit SeparatorBorder(SkColor color) : color_(color) {} |
| 133 ~SeparatorBorder() override {} |
| 134 |
| 135 void Paint(const views::View& view, gfx::Canvas* canvas) override { |
| 136 if (view.HasFocus()) |
| 137 return FocusableBorder::Paint(view, canvas); |
| 138 |
| 139 int end_x = base::i18n::IsRTL() ? 0 : view.width() - 1; |
| 140 canvas->DrawLine(gfx::Point(end_x, kTopBottomPadding), |
| 141 gfx::Point(end_x, view.height() - kTopBottomPadding), |
| 142 color_); |
| 143 } |
| 144 |
| 145 gfx::Insets GetInsets() const override { return gfx::Insets(0, 0, 0, 1); } |
| 146 |
| 147 gfx::Size GetMinimumSize() const override { |
| 148 return gfx::Size(1, 2 * kTopBottomPadding + 1); |
| 149 } |
| 150 |
| 151 private: |
| 152 SkColor color_; |
| 153 |
| 154 DISALLOW_COPY_AND_ASSIGN(SeparatorBorder); |
| 155 }; |
| 156 |
104 } // namespace | 157 } // namespace |
105 | 158 |
| 159 // Allows the DownloadItemView to control the InkDrop on the drop down button. |
| 160 class DownloadItemView::DropDownButton : public views::VectorIconButton { |
| 161 public: |
| 162 explicit DropDownButton(views::VectorIconButtonDelegate* delegate) |
| 163 : views::VectorIconButton(delegate) {} |
| 164 ~DropDownButton() override {} |
| 165 |
| 166 // Promoted visibility to public. |
| 167 void AnimateInkDrop(views::InkDropState state) { |
| 168 // TODO(bruthig): Plumb in the proper Event. |
| 169 views::VectorIconButton::AnimateInkDrop(state, nullptr /* event */); |
| 170 } |
| 171 |
| 172 private: |
| 173 DISALLOW_COPY_AND_ASSIGN(DropDownButton); |
| 174 }; |
| 175 |
106 DownloadItemView::DownloadItemView(DownloadItem* download_item, | 176 DownloadItemView::DownloadItemView(DownloadItem* download_item, |
107 DownloadShelfView* parent) | 177 DownloadShelfView* parent) |
108 : warning_icon_(NULL), | 178 : shelf_(parent), |
109 shelf_(parent), | 179 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), |
110 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), | 180 dropdown_state_(NORMAL), |
111 body_state_(NORMAL), | 181 mode_(NORMAL_MODE), |
112 drop_down_state_(NORMAL), | 182 dragging_(false), |
113 mode_(NORMAL_MODE), | 183 starting_drag_(false), |
114 drop_down_pressed_(false), | 184 model_(download_item), |
115 dragging_(false), | 185 save_button_(nullptr), |
116 starting_drag_(false), | 186 discard_button_(nullptr), |
117 model_(download_item), | 187 dropdown_button_(new DropDownButton(this)), |
118 save_button_(NULL), | 188 dangerous_download_label_(nullptr), |
119 discard_button_(NULL), | 189 dangerous_download_label_sized_(false), |
120 dangerous_download_label_(NULL), | 190 disabled_while_opening_(false), |
121 dangerous_download_label_sized_(false), | 191 creation_time_(base::Time::Now()), |
122 disabled_while_opening_(false), | 192 time_download_warning_shown_(base::Time()), |
123 creation_time_(base::Time::Now()), | 193 weak_ptr_factory_(this) { |
124 time_download_warning_shown_(base::Time()), | 194 SetInkDropMode(InkDropMode::ON); |
125 weak_ptr_factory_(this) { | |
126 DCHECK(download()); | 195 DCHECK(download()); |
| 196 DCHECK(ui::MaterialDesignController::IsModeMaterial()); |
127 download()->AddObserver(this); | 197 download()->AddObserver(this); |
128 set_context_menu_controller(this); | 198 set_context_menu_controller(this); |
129 | 199 |
130 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 200 dropdown_button_->SetBorder( |
131 | 201 views::Border::CreateEmptyBorder(gfx::Insets(kDropdownBorderWidth))); |
132 BodyImageSet normal_body_image_set = { | 202 dropdown_button_->set_ink_drop_size(gfx::Size(32, 32)); |
133 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), | 203 AddChildView(dropdown_button_); |
134 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), | |
135 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), | |
136 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), | |
137 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), | |
138 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), | |
139 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP), | |
140 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE), | |
141 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM) | |
142 }; | |
143 normal_body_image_set_ = normal_body_image_set; | |
144 | |
145 DropDownImageSet normal_drop_down_image_set = { | |
146 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP), | |
147 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE), | |
148 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM) | |
149 }; | |
150 normal_drop_down_image_set_ = normal_drop_down_image_set; | |
151 | |
152 BodyImageSet hot_body_image_set = { | |
153 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_H), | |
154 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H), | |
155 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H), | |
156 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_H), | |
157 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H), | |
158 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H), | |
159 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H), | |
160 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H), | |
161 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H) | |
162 }; | |
163 hot_body_image_set_ = hot_body_image_set; | |
164 | |
165 DropDownImageSet hot_drop_down_image_set = { | |
166 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_H), | |
167 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H), | |
168 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H) | |
169 }; | |
170 hot_drop_down_image_set_ = hot_drop_down_image_set; | |
171 | |
172 BodyImageSet pushed_body_image_set = { | |
173 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_P), | |
174 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P), | |
175 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P), | |
176 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_P), | |
177 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P), | |
178 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P), | |
179 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P), | |
180 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P), | |
181 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P) | |
182 }; | |
183 pushed_body_image_set_ = pushed_body_image_set; | |
184 | |
185 DropDownImageSet pushed_drop_down_image_set = { | |
186 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_P), | |
187 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P), | |
188 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P) | |
189 }; | |
190 pushed_drop_down_image_set_ = pushed_drop_down_image_set; | |
191 | |
192 BodyImageSet dangerous_mode_body_image_set = { | |
193 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), | |
194 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), | |
195 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), | |
196 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), | |
197 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), | |
198 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), | |
199 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD), | |
200 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD), | |
201 rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD) | |
202 }; | |
203 dangerous_mode_body_image_set_ = dangerous_mode_body_image_set; | |
204 | |
205 malicious_mode_body_image_set_ = normal_body_image_set; | |
206 | 204 |
207 LoadIcon(); | 205 LoadIcon(); |
208 | 206 |
209 font_list_ = rb.GetFontList(ui::ResourceBundle::BaseFont); | 207 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
210 box_height_ = std::max<int>(2 * kVerticalPadding + font_list_.GetHeight() + | 208 font_list_ = |
211 kVerticalTextPadding + font_list_.GetHeight(), | 209 rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(1); |
212 2 * kVerticalPadding + | 210 status_font_list_ = |
213 normal_body_image_set_.top_left->height() + | 211 rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(-2); |
214 normal_body_image_set_.bottom_left->height()); | |
215 | |
216 box_y_ = std::max(0, (2 * kProgressPadding + | |
217 DownloadShelf::kProgressIndicatorSize - box_height_) / | |
218 2); | |
219 | |
220 body_hover_animation_.reset(new gfx::SlideAnimation(this)); | |
221 drop_hover_animation_.reset(new gfx::SlideAnimation(this)); | |
222 | 212 |
223 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); | 213 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); |
224 | 214 |
225 OnDownloadUpdated(download()); | 215 OnDownloadUpdated(download()); |
226 UpdateDropDownButtonPosition(); | 216 |
| 217 SetDropdownState(NORMAL); |
| 218 UpdateColorsFromTheme(); |
227 } | 219 } |
228 | 220 |
229 DownloadItemView::~DownloadItemView() { | 221 DownloadItemView::~DownloadItemView() { |
230 StopDownloadProgress(); | 222 StopDownloadProgress(); |
231 download()->RemoveObserver(this); | 223 download()->RemoveObserver(this); |
232 | 224 |
233 // ExperienceSampling: If the user took no action to remove the warning | 225 // ExperienceSampling: If the user took no action to remove the warning |
234 // before it disappeared, then the user effectively dismissed the download | 226 // before it disappeared, then the user effectively dismissed the download |
235 // without keeping it. | 227 // without keeping it. |
236 if (sampling_event_.get()) | 228 if (sampling_event_.get()) |
(...skipping 13 matching lines...) Expand all Loading... |
250 } | 242 } |
251 | 243 |
252 void DownloadItemView::StopDownloadProgress() { | 244 void DownloadItemView::StopDownloadProgress() { |
253 if (!progress_timer_.IsRunning()) | 245 if (!progress_timer_.IsRunning()) |
254 return; | 246 return; |
255 previous_progress_elapsed_ += base::TimeTicks::Now() - progress_start_time_; | 247 previous_progress_elapsed_ += base::TimeTicks::Now() - progress_start_time_; |
256 progress_start_time_ = base::TimeTicks(); | 248 progress_start_time_ = base::TimeTicks(); |
257 progress_timer_.Stop(); | 249 progress_timer_.Stop(); |
258 } | 250 } |
259 | 251 |
| 252 // static |
| 253 SkColor DownloadItemView::GetTextColorForThemeProvider( |
| 254 const ui::ThemeProvider* theme) { |
| 255 return theme ? theme->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT) |
| 256 : gfx::kPlaceholderColor; |
| 257 } |
| 258 |
260 void DownloadItemView::OnExtractIconComplete(gfx::Image* icon_bitmap) { | 259 void DownloadItemView::OnExtractIconComplete(gfx::Image* icon_bitmap) { |
261 if (icon_bitmap) | 260 if (icon_bitmap) |
262 shelf_->SchedulePaint(); | 261 shelf_->SchedulePaint(); |
263 } | 262 } |
264 | 263 |
265 // DownloadObserver interface. | 264 // DownloadObserver interface. |
266 | 265 |
267 // Update the progress graphic on the icon and our text status label | 266 // Update the progress graphic on the icon and our text status label |
268 // to reflect our current bytes downloaded, time remaining. | 267 // to reflect our current bytes downloaded, time remaining. |
269 void DownloadItemView::OnDownloadUpdated(DownloadItem* download_item) { | 268 void DownloadItemView::OnDownloadUpdated(DownloadItem* download_item) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 base::TimeDelta::FromMilliseconds(kDisabledOnOpenDuration)); | 337 base::TimeDelta::FromMilliseconds(kDisabledOnOpenDuration)); |
339 | 338 |
340 // Notify our parent. | 339 // Notify our parent. |
341 shelf_->OpenedDownload(); | 340 shelf_->OpenedDownload(); |
342 } | 341 } |
343 | 342 |
344 // View overrides | 343 // View overrides |
345 | 344 |
346 // In dangerous mode we have to layout our buttons. | 345 // In dangerous mode we have to layout our buttons. |
347 void DownloadItemView::Layout() { | 346 void DownloadItemView::Layout() { |
| 347 UpdateColorsFromTheme(); |
| 348 |
348 if (IsShowingWarningDialog()) { | 349 if (IsShowingWarningDialog()) { |
349 BodyImageSet* body_image_set = | 350 gfx::Point child_origin( |
350 (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ : | 351 kStartPadding + kWarningIconSize + kStartPadding, |
351 &malicious_mode_body_image_set_; | 352 (height() - dangerous_download_label_->height()) / 2); |
352 int x = kLeftPadding + body_image_set->top_left->width() + | 353 dangerous_download_label_->SetPosition(child_origin); |
353 warning_icon_->width() + kLabelPadding; | 354 |
354 int y = (height() - dangerous_download_label_->height()) / 2; | 355 child_origin.Offset(dangerous_download_label_->width() + kLabelPadding, 0); |
355 dangerous_download_label_->SetBounds(x, y, | |
356 dangerous_download_label_->width(), | |
357 dangerous_download_label_->height()); | |
358 gfx::Size button_size = GetButtonSize(); | 356 gfx::Size button_size = GetButtonSize(); |
359 x += dangerous_download_label_->width() + kLabelPadding; | 357 child_origin.set_y((height() - button_size.height()) / 2); |
360 y = (height() - button_size.height()) / 2; | |
361 if (save_button_) { | 358 if (save_button_) { |
362 save_button_->SetBounds(x, y, button_size.width(), button_size.height()); | 359 save_button_->SetBoundsRect(gfx::Rect(child_origin, button_size)); |
363 x += button_size.width() + kButtonPadding; | 360 child_origin.Offset(button_size.width() + kButtonPadding, 0); |
364 } | 361 } |
365 discard_button_->SetBounds(x, y, button_size.width(), button_size.height()); | 362 discard_button_->SetBoundsRect(gfx::Rect(child_origin, button_size)); |
366 UpdateColorsFromTheme(); | 363 } |
| 364 |
| 365 if (mode_ != DANGEROUS_MODE) { |
| 366 dropdown_button_->SizeToPreferredSize(); |
| 367 dropdown_button_->SetPosition( |
| 368 gfx::Point(width() - dropdown_button_->width() - kEndPadding, |
| 369 (height() - dropdown_button_->height()) / 2)); |
367 } | 370 } |
368 } | 371 } |
369 | 372 |
370 gfx::Size DownloadItemView::GetPreferredSize() const { | 373 gfx::Size DownloadItemView::GetPreferredSize() const { |
371 int width, height; | 374 int width = 0; |
372 | 375 // We set the height to the height of two rows or text plus margins. |
373 // First, we set the height to the height of two rows or text plus margins. | 376 int child_height = font_list_.GetBaseline() + kVerticalTextPadding + |
374 height = 2 * kVerticalPadding + 2 * font_list_.GetHeight() + | 377 status_font_list_.GetHeight(); |
375 kVerticalTextPadding; | |
376 // Then we increase the size if the progress icon doesn't fit. | |
377 height = std::max<int>( | |
378 height, DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding); | |
379 | 378 |
380 if (IsShowingWarningDialog()) { | 379 if (IsShowingWarningDialog()) { |
381 const BodyImageSet* body_image_set = | 380 // Width. |
382 (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ : | 381 width = kStartPadding + kWarningIconSize + kStartPadding + |
383 &malicious_mode_body_image_set_; | 382 dangerous_download_label_->width() + kLabelPadding; |
384 width = kLeftPadding + body_image_set->top_left->width(); | |
385 width += warning_icon_->width() + kLabelPadding; | |
386 width += dangerous_download_label_->width() + kLabelPadding; | |
387 gfx::Size button_size = GetButtonSize(); | 383 gfx::Size button_size = GetButtonSize(); |
388 // Make sure the button fits. | |
389 height = std::max<int>(height, 2 * kVerticalPadding + button_size.height()); | |
390 // Then we make sure the warning icon fits. | |
391 height = std::max<int>(height, 2 * kVerticalPadding + | |
392 warning_icon_->height()); | |
393 if (save_button_) | 384 if (save_button_) |
394 width += button_size.width() + kButtonPadding; | 385 width += button_size.width() + kButtonPadding; |
395 width += button_size.width(); | 386 width += button_size.width() + kEndPadding; |
396 width += body_image_set->top_right->width(); | 387 |
397 if (mode_ == MALICIOUS_MODE) | 388 // Height: make sure the button fits and the warning icon fits. |
398 width += normal_drop_down_image_set_.top->width(); | 389 child_height = |
| 390 std::max({child_height, button_size.height(), kWarningIconSize}); |
399 } else { | 391 } else { |
400 width = kLeftPadding + normal_body_image_set_.top_left->width(); | 392 width = kStartPadding + DownloadShelf::kProgressIndicatorSize + |
401 width += DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding; | 393 kProgressTextPadding + kTextWidth + kEndPadding; |
402 width += kTextWidth; | |
403 width += normal_body_image_set_.top_right->width(); | |
404 width += normal_drop_down_image_set_.top->width(); | |
405 } | 394 } |
406 return gfx::Size(width, height); | 395 |
| 396 if (mode_ != DANGEROUS_MODE) |
| 397 width += dropdown_button_->GetPreferredSize().width(); |
| 398 |
| 399 return gfx::Size(width, std::max(kDefaultHeight, |
| 400 2 * kMinimumVerticalPadding + child_height)); |
407 } | 401 } |
408 | 402 |
409 // Handle a mouse click and open the context menu if the mouse is | |
410 // over the drop-down region. | |
411 bool DownloadItemView::OnMousePressed(const ui::MouseEvent& event) { | 403 bool DownloadItemView::OnMousePressed(const ui::MouseEvent& event) { |
412 HandlePressEvent(event, event.IsOnlyLeftMouseButton()); | 404 HandlePressEvent(event, event.IsOnlyLeftMouseButton()); |
413 return true; | 405 return true; |
414 } | 406 } |
415 | 407 |
416 // Handle drag (file copy) operations. | 408 // Handle drag (file copy) operations. |
417 bool DownloadItemView::OnMouseDragged(const ui::MouseEvent& event) { | 409 bool DownloadItemView::OnMouseDragged(const ui::MouseEvent& event) { |
418 // Mouse should not activate us in dangerous mode. | 410 // Mouse should not activate us in dangerous mode. |
419 if (IsShowingWarningDialog()) | 411 if (IsShowingWarningDialog()) |
420 return true; | 412 return true; |
421 | 413 |
422 if (!starting_drag_) { | 414 if (!starting_drag_) { |
423 starting_drag_ = true; | 415 starting_drag_ = true; |
424 drag_start_point_ = event.location(); | 416 drag_start_point_ = event.location(); |
| 417 AnimateInkDrop(views::InkDropState::HIDDEN, &event); |
425 } | 418 } |
426 if (dragging_) { | 419 if (dragging_) { |
427 if (download()->GetState() == DownloadItem::COMPLETE) { | 420 if (download()->GetState() == DownloadItem::COMPLETE) { |
428 IconManager* im = g_browser_process->icon_manager(); | 421 IconManager* im = g_browser_process->icon_manager(); |
429 gfx::Image* icon = im->LookupIconFromFilepath( | 422 gfx::Image* icon = im->LookupIconFromFilepath( |
430 download()->GetTargetFilePath(), IconLoader::SMALL); | 423 download()->GetTargetFilePath(), IconLoader::SMALL); |
431 views::Widget* widget = GetWidget(); | 424 views::Widget* widget = GetWidget(); |
432 DragDownloadItem( | 425 DragDownloadItem(download(), icon, |
433 download(), icon, widget ? widget->GetNativeView() : NULL); | 426 widget ? widget->GetNativeView() : NULL); |
434 } | 427 } |
435 } else if (ExceededDragThreshold(event.location() - drag_start_point_)) { | 428 } else if (ExceededDragThreshold(event.location() - drag_start_point_)) { |
436 dragging_ = true; | 429 dragging_ = true; |
437 } | 430 } |
438 return true; | 431 return true; |
439 } | 432 } |
440 | 433 |
441 void DownloadItemView::OnMouseReleased(const ui::MouseEvent& event) { | 434 void DownloadItemView::OnMouseReleased(const ui::MouseEvent& event) { |
442 HandleClickEvent(event, event.IsOnlyLeftMouseButton()); | 435 HandleClickEvent(event, event.IsOnlyLeftMouseButton()); |
443 } | 436 } |
444 | 437 |
445 void DownloadItemView::OnMouseCaptureLost() { | 438 void DownloadItemView::OnMouseCaptureLost() { |
446 // Mouse should not activate us in dangerous mode. | 439 // Mouse should not activate us in dangerous mode. |
447 if (mode_ == DANGEROUS_MODE) | 440 if (mode_ != NORMAL_MODE) |
448 return; | 441 return; |
449 | 442 |
450 if (dragging_) { | 443 if (dragging_) { |
451 // Starting a drag results in a MouseCaptureLost. | 444 // Starting a drag results in a MouseCaptureLost. |
452 dragging_ = false; | 445 dragging_ = false; |
453 starting_drag_ = false; | 446 starting_drag_ = false; |
454 } | 447 } |
455 SetState(NORMAL, NORMAL); | |
456 } | |
457 | |
458 void DownloadItemView::OnMouseMoved(const ui::MouseEvent& event) { | |
459 // Mouse should not activate us in dangerous mode. | |
460 if (mode_ == DANGEROUS_MODE) | |
461 return; | |
462 | |
463 bool on_body = !InDropDownButtonXCoordinateRange(event.x()); | |
464 SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT); | |
465 } | |
466 | |
467 void DownloadItemView::OnMouseExited(const ui::MouseEvent& event) { | |
468 // Mouse should not activate us in dangerous mode. | |
469 if (mode_ == DANGEROUS_MODE) | |
470 return; | |
471 | |
472 SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL); | |
473 } | 448 } |
474 | 449 |
475 bool DownloadItemView::OnKeyPressed(const ui::KeyEvent& event) { | 450 bool DownloadItemView::OnKeyPressed(const ui::KeyEvent& event) { |
476 // Key press should not activate us in dangerous mode. | 451 // Key press should not activate us in dangerous mode. |
477 if (IsShowingWarningDialog()) | 452 if (IsShowingWarningDialog()) |
478 return true; | 453 return true; |
479 | 454 |
480 if (event.key_code() == ui::VKEY_SPACE || | 455 if (event.key_code() == ui::VKEY_SPACE || |
481 event.key_code() == ui::VKEY_RETURN) { | 456 event.key_code() == ui::VKEY_RETURN) { |
| 457 AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr /* &event */); |
482 // OpenDownload may delete this, so don't add any code after this line. | 458 // OpenDownload may delete this, so don't add any code after this line. |
483 OpenDownload(); | 459 OpenDownload(); |
484 return true; | 460 return true; |
485 } | 461 } |
486 return false; | 462 return false; |
487 } | 463 } |
488 | 464 |
489 bool DownloadItemView::GetTooltipText(const gfx::Point& p, | 465 bool DownloadItemView::GetTooltipText(const gfx::Point& p, |
490 base::string16* tooltip) const { | 466 base::string16* tooltip) const { |
491 if (IsShowingWarningDialog()) { | 467 if (IsShowingWarningDialog()) { |
(...skipping 10 matching lines...) Expand all Loading... |
502 state->name = accessible_name_; | 478 state->name = accessible_name_; |
503 state->role = ui::AX_ROLE_BUTTON; | 479 state->role = ui::AX_ROLE_BUTTON; |
504 if (model_.IsDangerous()) | 480 if (model_.IsDangerous()) |
505 state->AddStateFlag(ui::AX_STATE_DISABLED); | 481 state->AddStateFlag(ui::AX_STATE_DISABLED); |
506 else | 482 else |
507 state->AddStateFlag(ui::AX_STATE_HASPOPUP); | 483 state->AddStateFlag(ui::AX_STATE_HASPOPUP); |
508 } | 484 } |
509 | 485 |
510 void DownloadItemView::OnThemeChanged() { | 486 void DownloadItemView::OnThemeChanged() { |
511 UpdateColorsFromTheme(); | 487 UpdateColorsFromTheme(); |
| 488 SchedulePaint(); |
| 489 } |
| 490 |
| 491 void DownloadItemView::AddInkDropLayer(ui::Layer* ink_drop_layer) { |
| 492 InkDropHostView::AddInkDropLayer(ink_drop_layer); |
| 493 // The layer that's added to host the ink drop layer must mask to bounds |
| 494 // so the hover effect is clipped while animating open. |
| 495 layer()->SetMasksToBounds(true); |
| 496 } |
| 497 |
| 498 std::unique_ptr<views::InkDropRipple> DownloadItemView::CreateInkDropRipple() |
| 499 const { |
| 500 return base::MakeUnique<views::FloodFillInkDropRipple>( |
| 501 GetLocalBounds(), GetInkDropCenterBasedOnLastEvent(), |
| 502 color_utils::DeriveDefaultIconColor(GetTextColor()), |
| 503 ink_drop_visible_opacity()); |
| 504 } |
| 505 |
| 506 std::unique_ptr<views::InkDropHighlight> |
| 507 DownloadItemView::CreateInkDropHighlight() const { |
| 508 if (IsShowingWarningDialog()) |
| 509 return nullptr; |
| 510 |
| 511 gfx::Size size = GetPreferredSize(); |
| 512 return base::MakeUnique<views::InkDropHighlight>( |
| 513 size, kInkDropSmallCornerRadius, |
| 514 gfx::RectF(gfx::SizeF(size)).CenterPoint(), |
| 515 color_utils::DeriveDefaultIconColor(GetTextColor())); |
512 } | 516 } |
513 | 517 |
514 void DownloadItemView::OnGestureEvent(ui::GestureEvent* event) { | 518 void DownloadItemView::OnGestureEvent(ui::GestureEvent* event) { |
515 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { | 519 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { |
516 HandlePressEvent(*event, true); | 520 HandlePressEvent(*event, true); |
517 event->SetHandled(); | 521 event->SetHandled(); |
518 return; | 522 return; |
519 } | 523 } |
520 | 524 |
521 if (event->type() == ui::ET_GESTURE_TAP) { | 525 if (event->type() == ui::ET_GESTURE_TAP) { |
522 HandleClickEvent(*event, true); | 526 HandleClickEvent(*event, true); |
523 event->SetHandled(); | 527 event->SetHandled(); |
524 return; | 528 return; |
525 } | 529 } |
526 | 530 |
527 SetState(NORMAL, NORMAL); | |
528 views::View::OnGestureEvent(event); | 531 views::View::OnGestureEvent(event); |
529 } | 532 } |
530 | 533 |
531 void DownloadItemView::ShowContextMenuForView(View* source, | 534 void DownloadItemView::ShowContextMenuForView(View* source, |
532 const gfx::Point& point, | 535 const gfx::Point& point, |
533 ui::MenuSourceType source_type) { | 536 ui::MenuSourceType source_type) { |
534 // |point| is in screen coordinates. So convert it to local coordinates first. | 537 ShowContextMenuImpl(gfx::Rect(point, gfx::Size()), source_type); |
535 gfx::Point local_point = point; | |
536 ConvertPointFromScreen(this, &local_point); | |
537 ShowContextMenuImpl(local_point, source_type); | |
538 } | 538 } |
539 | 539 |
540 void DownloadItemView::ButtonPressed(views::Button* sender, | 540 void DownloadItemView::ButtonPressed(views::Button* sender, |
541 const ui::Event& event) { | 541 const ui::Event& event) { |
| 542 if (sender == dropdown_button_) { |
| 543 // TODO(estade): this is copied from ToolbarActionView but should be shared |
| 544 // one way or another. |
| 545 ui::MenuSourceType type = ui::MENU_SOURCE_NONE; |
| 546 if (event.IsMouseEvent()) |
| 547 type = ui::MENU_SOURCE_MOUSE; |
| 548 else if (event.IsKeyEvent()) |
| 549 type = ui::MENU_SOURCE_KEYBOARD; |
| 550 else if (event.IsGestureEvent()) |
| 551 type = ui::MENU_SOURCE_TOUCH; |
| 552 SetDropdownState(PUSHED); |
| 553 ShowContextMenuImpl(dropdown_button_->GetBoundsInScreen(), type); |
| 554 return; |
| 555 } |
| 556 |
542 base::TimeDelta warning_duration; | 557 base::TimeDelta warning_duration; |
543 if (!time_download_warning_shown_.is_null()) | 558 if (!time_download_warning_shown_.is_null()) |
544 warning_duration = base::Time::Now() - time_download_warning_shown_; | 559 warning_duration = base::Time::Now() - time_download_warning_shown_; |
545 | 560 |
546 if (save_button_ && sender == save_button_) { | 561 if (save_button_ && sender == save_button_) { |
547 // The user has confirmed a dangerous download. We'd record how quickly the | 562 // The user has confirmed a dangerous download. We'd record how quickly the |
548 // user did this to detect whether we're being clickjacked. | 563 // user did this to detect whether we're being clickjacked. |
549 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", warning_duration); | 564 UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", warning_duration); |
550 // ExperienceSampling: User chose to proceed with a dangerous download. | 565 // ExperienceSampling: User chose to proceed with a dangerous download. |
551 if (sampling_event_.get()) { | 566 if (sampling_event_.get()) { |
552 sampling_event_->CreateUserDecisionEvent( | 567 sampling_event_->CreateUserDecisionEvent( |
553 ExperienceSamplingEvent::kProceed); | 568 ExperienceSamplingEvent::kProceed); |
554 sampling_event_.reset(NULL); | 569 sampling_event_.reset(NULL); |
555 } | 570 } |
556 // This will change the state and notify us. | 571 // This will change the state and notify us. |
557 download()->ValidateDangerousDownload(); | 572 download()->ValidateDangerousDownload(); |
558 return; | 573 return; |
559 } | 574 } |
560 | 575 |
561 // WARNING: all end states after this point delete |this|. | 576 // WARNING: all end states after this point delete |this|. |
562 DCHECK_EQ(discard_button_, sender); | 577 DCHECK_EQ(discard_button_, sender); |
563 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration); | 578 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration); |
564 if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() && | 579 if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() && |
565 !shelf_->browser()->profile()->IsOffTheRecord()) { | 580 !shelf_->browser()->profile()->IsOffTheRecord()) { |
566 if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath( | 581 if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath( |
567 prefs::kSafeBrowsingExtendedReportingEnabled)) { | 582 prefs::kSafeBrowsingExtendedReportingEnabled)) { |
568 // Show dialog, because the dialog hasn't been shown before. | 583 // Show dialog, because the dialog hasn't been shown before. |
569 DownloadFeedbackDialogView::Show( | 584 DownloadFeedbackDialogView::Show( |
570 shelf_->get_parent()->GetNativeWindow(), | 585 shelf_->get_parent()->GetNativeWindow(), shelf_->browser()->profile(), |
571 shelf_->browser()->profile(), | |
572 shelf_->GetNavigator(), | 586 shelf_->GetNavigator(), |
573 base::Bind( | 587 base::Bind(&DownloadItemView::PossiblySubmitDownloadToFeedbackService, |
574 &DownloadItemView::PossiblySubmitDownloadToFeedbackService, | 588 weak_ptr_factory_.GetWeakPtr())); |
575 weak_ptr_factory_.GetWeakPtr())); | |
576 } else { | 589 } else { |
577 PossiblySubmitDownloadToFeedbackService( | 590 PossiblySubmitDownloadToFeedbackService( |
578 shelf_->browser()->profile()->GetPrefs()->GetBoolean( | 591 shelf_->browser()->profile()->GetPrefs()->GetBoolean( |
579 prefs::kSafeBrowsingExtendedReportingEnabled)); | 592 prefs::kSafeBrowsingExtendedReportingEnabled)); |
580 } | 593 } |
581 return; | 594 return; |
582 } | 595 } |
583 download()->Remove(); | 596 download()->Remove(); |
584 } | 597 } |
585 | 598 |
| 599 SkColor DownloadItemView::GetVectorIconBaseColor() const { |
| 600 return GetTextColor(); |
| 601 } |
| 602 |
586 void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) { | 603 void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) { |
587 // We don't care if what animation (body button/drop button/complete), | 604 // We don't care if what animation (body button/drop button/complete), |
588 // is calling back, as they all have to go through the same paint call. | 605 // is calling back, as they all have to go through the same paint call. |
589 SchedulePaint(); | 606 SchedulePaint(); |
590 } | 607 } |
591 | 608 |
592 void DownloadItemView::OnPaint(gfx::Canvas* canvas) { | 609 void DownloadItemView::OnPaint(gfx::Canvas* canvas) { |
593 OnPaintBackground(canvas); | 610 // Make sure to draw |this| opaquely. Since the toolbar color can be partially |
594 if (HasFocus()) | 611 // transparent, start with a black backdrop (which is the default initialized |
595 canvas->DrawFocusRect(GetLocalBounds()); | 612 // color for opaque canvases). |
| 613 canvas->DrawColor(SK_ColorBLACK); |
| 614 canvas->DrawColor( |
| 615 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR)); |
| 616 |
| 617 DrawStatusText(canvas); |
| 618 DrawFilename(canvas); |
| 619 DrawIcon(canvas); |
| 620 OnPaintBorder(canvas); |
596 } | 621 } |
597 | 622 |
598 // The DownloadItemView can be in three major modes (NORMAL_MODE, DANGEROUS_MODE | 623 int DownloadItemView::GetYForFilenameText() const { |
599 // and MALICIOUS_MODE). | 624 int text_height = font_list_.GetBaseline(); |
600 // | 625 if (!status_text_.empty()) |
601 // NORMAL_MODE: We are displaying an in-progress or completed download. | 626 text_height += kVerticalTextPadding + status_font_list_.GetBaseline(); |
602 // .-------------------------------+-. | 627 return (height() - text_height) / 2; |
603 // | [icon] Filename |v| | 628 } |
604 // | [ ] Status | | | |
605 // `-------------------------------+-' | |
606 // | | \_ Drop down button. Invokes menu. Responds | |
607 // | | to mouse. (NORMAL, HOT or PUSHED). | |
608 // | \_ Icon is overlaid on top of in-progress animation. | |
609 // \_ Both the body and the drop down button respond to mouse hover and can be | |
610 // pushed (NORMAL, HOT or PUSHED). | |
611 // | |
612 // DANGEROUS_MODE: The file could be potentially dangerous. | |
613 // .-------------------------------------------------------. | |
614 // | [ ! ] [This type of file can ] [ Keep ] [ Discard ] | | |
615 // | [ ] [destroy your computer..] [ ] [ ] | | |
616 // `-------------------------------------------------------' | |
617 // | | | | \_ No drop down button. | |
618 // | | | \_ Buttons are views::LabelButtons. | |
619 // | | \_ Text is in a label (dangerous_download_label_) | |
620 // | \_ Warning icon. No progress animation. | |
621 // \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only) | |
622 // | |
623 // MALICIOUS_MODE: The file is known malware. | |
624 // .---------------------------------------------+-. | |
625 // | [ - ] [This file is malicious.] [ Discard ] |v| | |
626 // | [ ] [ ] [ ] | |-. | |
627 // `---------------------------------------------+-' | | |
628 // | | | | Drop down button. Responds to | |
629 // | | | | mouse.(NORMAL, HOT or PUSHED) | |
630 // | | | \_ Button is a views::LabelButton. | |
631 // | | \_ Text is in a label (dangerous_download_label_) | |
632 // | \_ Warning icon. No progress animation. | |
633 // \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only) | |
634 // | |
635 void DownloadItemView::OnPaintBackground(gfx::Canvas* canvas) { | |
636 BodyImageSet* body_image_set = NULL; | |
637 switch (mode_) { | |
638 case NORMAL_MODE: | |
639 if (body_state_ == PUSHED) | |
640 body_image_set = &pushed_body_image_set_; | |
641 else // NORMAL or HOT | |
642 body_image_set = &normal_body_image_set_; | |
643 break; | |
644 case DANGEROUS_MODE: | |
645 body_image_set = &dangerous_mode_body_image_set_; | |
646 break; | |
647 case MALICIOUS_MODE: | |
648 body_image_set = &malicious_mode_body_image_set_; | |
649 break; | |
650 default: | |
651 NOTREACHED(); | |
652 } | |
653 | 629 |
654 DropDownImageSet* drop_down_image_set = NULL; | 630 void DownloadItemView::DrawStatusText(gfx::Canvas* canvas) { |
655 switch (mode_) { | 631 if (status_text_.empty() || IsShowingWarningDialog()) |
656 case NORMAL_MODE: | |
657 case MALICIOUS_MODE: | |
658 if (drop_down_state_ == PUSHED) | |
659 drop_down_image_set = &pushed_drop_down_image_set_; | |
660 else // NORMAL or HOT | |
661 drop_down_image_set = &normal_drop_down_image_set_; | |
662 break; | |
663 case DANGEROUS_MODE: | |
664 // We don't use a drop down button for mode_ == DANGEROUS_MODE. So we let | |
665 // drop_down_image_set == NULL. | |
666 break; | |
667 default: | |
668 NOTREACHED(); | |
669 } | |
670 | |
671 int center_width = width() - kLeftPadding - | |
672 body_image_set->left->width() - | |
673 body_image_set->right->width() - | |
674 (drop_down_image_set ? | |
675 normal_drop_down_image_set_.center->width() : | |
676 0); | |
677 | |
678 // May be caused by animation. | |
679 if (center_width <= 0) | |
680 return; | 632 return; |
681 | 633 |
682 // Draw status before button image to effectively lighten text. No status for | 634 int mirrored_x = GetMirroredXWithWidthInView( |
683 // warning dialogs. | 635 kStartPadding + DownloadShelf::kProgressIndicatorSize + |
684 if (!IsShowingWarningDialog()) { | 636 kProgressTextPadding, |
685 if (!status_text_.empty()) { | 637 kTextWidth); |
686 int mirrored_x = GetMirroredXWithWidthInView( | 638 int y = |
687 2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize, | 639 GetYForFilenameText() + font_list_.GetBaseline() + kVerticalTextPadding; |
688 kTextWidth); | 640 canvas->DrawStringRect( |
689 // Add font_list_.height() to compensate for title, which is drawn later. | 641 status_text_, status_font_list_, GetDimmedTextColor(), |
690 int y = box_y_ + kVerticalPadding + font_list_.GetHeight() + | 642 gfx::Rect(mirrored_x, y, kTextWidth, status_font_list_.GetHeight())); |
691 kVerticalTextPadding; | 643 } |
692 SkColor file_name_color = GetThemeProvider()->GetColor( | |
693 ThemeProperties::COLOR_BOOKMARK_TEXT); | |
694 // If text is light-on-dark, lightening it alone will do nothing. In this | |
695 // case we multiply color components by 80% before drawing. | |
696 if (!color_utils::IsDark(file_name_color)) { | |
697 file_name_color = | |
698 color_utils::AlphaBlend(SK_ColorBLACK, file_name_color, 255 / 5); | |
699 } | |
700 canvas->DrawStringRect(status_text_, font_list_, file_name_color, | |
701 gfx::Rect(mirrored_x, y, kTextWidth, | |
702 font_list_.GetHeight())); | |
703 } | |
704 } | |
705 | 644 |
706 // Paint the background images. | 645 void DownloadItemView::DrawFilename(gfx::Canvas* canvas) { |
707 { | 646 if (IsShowingWarningDialog()) |
708 gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width()); | 647 return; |
709 | |
710 int x = kLeftPadding; | |
711 PaintImages(canvas, | |
712 body_image_set->top_left, body_image_set->left, | |
713 body_image_set->bottom_left, | |
714 x, box_y_, box_height_, body_image_set->top_left->width()); | |
715 x += body_image_set->top_left->width(); | |
716 PaintImages(canvas, | |
717 body_image_set->top, body_image_set->center, | |
718 body_image_set->bottom, | |
719 x, box_y_, box_height_, center_width); | |
720 x += center_width; | |
721 PaintImages(canvas, | |
722 body_image_set->top_right, body_image_set->right, | |
723 body_image_set->bottom_right, | |
724 x, box_y_, box_height_, body_image_set->top_right->width()); | |
725 | |
726 // Overlay our body hot state. Warning dialogs don't display body a hot | |
727 // state. | |
728 if (!IsShowingWarningDialog() && | |
729 body_hover_animation_->GetCurrentValue() > 0) { | |
730 canvas->SaveLayerAlpha( | |
731 static_cast<int>(body_hover_animation_->GetCurrentValue() * 255)); | |
732 | |
733 int x = kLeftPadding; | |
734 PaintImages(canvas, | |
735 hot_body_image_set_.top_left, hot_body_image_set_.left, | |
736 hot_body_image_set_.bottom_left, | |
737 x, box_y_, box_height_, | |
738 hot_body_image_set_.top_left->width()); | |
739 x += body_image_set->top_left->width(); | |
740 PaintImages(canvas, | |
741 hot_body_image_set_.top, hot_body_image_set_.center, | |
742 hot_body_image_set_.bottom, | |
743 x, box_y_, box_height_, center_width); | |
744 x += center_width; | |
745 PaintImages(canvas, | |
746 hot_body_image_set_.top_right, hot_body_image_set_.right, | |
747 hot_body_image_set_.bottom_right, | |
748 x, box_y_, box_height_, | |
749 hot_body_image_set_.top_right->width()); | |
750 canvas->Restore(); | |
751 } | |
752 | |
753 x += body_image_set->top_right->width(); | |
754 | |
755 // Paint the drop-down. | |
756 if (drop_down_image_set) { | |
757 PaintImages(canvas, | |
758 drop_down_image_set->top, drop_down_image_set->center, | |
759 drop_down_image_set->bottom, | |
760 x, box_y_, box_height_, drop_down_image_set->top->width()); | |
761 | |
762 // Overlay our drop-down hot state. | |
763 if (drop_hover_animation_->GetCurrentValue() > 0) { | |
764 canvas->SaveLayerAlpha( | |
765 static_cast<int>(drop_hover_animation_->GetCurrentValue() * 255)); | |
766 | |
767 PaintImages(canvas, | |
768 drop_down_image_set->top, drop_down_image_set->center, | |
769 drop_down_image_set->bottom, | |
770 x, box_y_, box_height_, drop_down_image_set->top->width()); | |
771 | |
772 canvas->Restore(); | |
773 } | |
774 } | |
775 } | |
776 | 648 |
777 // Print the text, left aligned and always print the file extension. | 649 // Print the text, left aligned and always print the file extension. |
778 // Last value of x was the end of the right image, just before the button. | 650 // Last value of x was the end of the right image, just before the button. |
779 // Note that in dangerous mode we use a label (as the text is multi-line). | 651 // Note that in dangerous mode we use a label (as the text is multi-line). |
780 if (!IsShowingWarningDialog()) { | 652 base::string16 filename; |
781 base::string16 filename; | 653 if (!disabled_while_opening_) { |
782 if (!disabled_while_opening_) { | 654 filename = gfx::ElideFilename(download()->GetFileNameToReportUser(), |
783 filename = gfx::ElideFilename(download()->GetFileNameToReportUser(), | 655 font_list_, kTextWidth); |
784 font_list_, kTextWidth); | 656 } else { |
785 } else { | 657 // First, Calculate the download status opening string width. |
786 // First, Calculate the download status opening string width. | 658 base::string16 status_string = l10n_util::GetStringFUTF16( |
787 base::string16 status_string = | 659 IDS_DOWNLOAD_STATUS_OPENING, base::string16()); |
788 l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, | 660 int status_string_width = gfx::GetStringWidth(status_string, font_list_); |
789 base::string16()); | 661 // Then, elide the file name. |
790 int status_string_width = gfx::GetStringWidth(status_string, font_list_); | 662 base::string16 filename_string = |
791 // Then, elide the file name. | 663 gfx::ElideFilename(download()->GetFileNameToReportUser(), font_list_, |
792 base::string16 filename_string = | 664 kTextWidth - status_string_width); |
793 gfx::ElideFilename(download()->GetFileNameToReportUser(), font_list_, | 665 // Last, concat the whole string. |
794 kTextWidth - status_string_width); | 666 filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, |
795 // Last, concat the whole string. | 667 filename_string); |
796 filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, | |
797 filename_string); | |
798 } | |
799 | |
800 int mirrored_x = GetMirroredXWithWidthInView( | |
801 2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize, | |
802 kTextWidth); | |
803 SkColor file_name_color = GetThemeProvider()->GetColor( | |
804 ThemeProperties::COLOR_BOOKMARK_TEXT); | |
805 int y = | |
806 box_y_ + (status_text_.empty() ? | |
807 ((box_height_ - font_list_.GetHeight()) / 2) : kVerticalPadding); | |
808 | |
809 // Draw the file's name. | |
810 canvas->DrawStringRect( | |
811 filename, font_list_, | |
812 enabled() ? file_name_color : kFileNameDisabledColor, | |
813 gfx::Rect(mirrored_x, y, kTextWidth, font_list_.GetHeight())); | |
814 } | 668 } |
815 | 669 |
816 // Load the icon. | 670 int mirrored_x = GetMirroredXWithWidthInView( |
817 IconManager* im = g_browser_process->icon_manager(); | 671 kStartPadding + DownloadShelf::kProgressIndicatorSize + |
818 gfx::Image* image = im->LookupIconFromFilepath( | 672 kProgressTextPadding, |
819 download()->GetTargetFilePath(), IconLoader::SMALL); | 673 kTextWidth); |
820 const gfx::ImageSkia* icon = NULL; | 674 canvas->DrawStringRect(filename, font_list_, |
821 if (IsShowingWarningDialog()) | 675 enabled() ? GetTextColor() : GetDimmedTextColor(), |
822 icon = warning_icon_; | 676 gfx::Rect(mirrored_x, GetYForFilenameText(), |
823 else if (image) | 677 kTextWidth, font_list_.GetHeight())); |
824 icon = image->ToImageSkia(); | 678 } |
825 | 679 |
826 // We count on the fact that the icon manager will cache the icons and if one | 680 void DownloadItemView::DrawIcon(gfx::Canvas* canvas) { |
827 // is available, it will be cached here. We *don't* want to request the icon | 681 if (IsShowingWarningDialog()) { |
828 // to be loaded here, since this will also get called if the icon can't be | 682 int icon_x = base::i18n::IsRTL() |
829 // loaded, in which case LookupIcon will always be NULL. The loading will be | 683 ? width() - kWarningIconSize - kStartPadding |
830 // triggered only when we think the status might change. | 684 : kStartPadding; |
831 if (icon) { | 685 int icon_y = (height() - kWarningIconSize) / 2; |
832 int progress_x = | 686 canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y); |
833 base::i18n::IsRTL() | 687 return; |
834 ? width() - kProgressPadding - DownloadShelf::kProgressIndicatorSize | 688 } |
835 : kProgressPadding; | |
836 int progress_y = kProgressPadding; | |
837 | 689 |
838 if (!IsShowingWarningDialog()) { | 690 // Paint download progress. |
839 canvas->Save(); | 691 DownloadItem::DownloadState state = download()->GetState(); |
840 canvas->Translate(gfx::Vector2d(progress_x, progress_y)); | 692 canvas->Save(); |
| 693 int progress_x = |
| 694 base::i18n::IsRTL() |
| 695 ? width() - kStartPadding - DownloadShelf::kProgressIndicatorSize |
| 696 : kStartPadding; |
| 697 int progress_y = (height() - DownloadShelf::kProgressIndicatorSize) / 2; |
| 698 canvas->Translate(gfx::Vector2d(progress_x, progress_y)); |
841 | 699 |
842 DownloadItem::DownloadState state = download()->GetState(); | 700 if (state == DownloadItem::IN_PROGRESS) { |
843 if (state == DownloadItem::IN_PROGRESS) { | 701 base::TimeDelta progress_time = previous_progress_elapsed_; |
844 base::TimeDelta progress_time = previous_progress_elapsed_; | 702 if (!download()->IsPaused()) |
845 if (!download()->IsPaused()) | 703 progress_time += base::TimeTicks::Now() - progress_start_time_; |
846 progress_time += base::TimeTicks::Now() - progress_start_time_; | 704 DownloadShelf::PaintDownloadProgress( |
847 DownloadShelf::PaintDownloadProgress(canvas, *GetThemeProvider(), | 705 canvas, *GetThemeProvider(), progress_time, model_.PercentComplete()); |
848 progress_time, | 706 } else if (complete_animation_.get() && complete_animation_->is_animating()) { |
849 model_.PercentComplete()); | 707 if (state == DownloadItem::INTERRUPTED) { |
850 } else if (complete_animation_.get() && | 708 DownloadShelf::PaintDownloadInterrupted( |
851 complete_animation_->is_animating()) { | 709 canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue()); |
852 if (state == DownloadItem::INTERRUPTED) { | |
853 DownloadShelf::PaintDownloadInterrupted( | |
854 canvas, *GetThemeProvider(), | |
855 complete_animation_->GetCurrentValue()); | |
856 } else { | |
857 DCHECK_EQ(DownloadItem::COMPLETE, state); | |
858 DownloadShelf::PaintDownloadComplete( | |
859 canvas, *GetThemeProvider(), | |
860 complete_animation_->GetCurrentValue()); | |
861 } | |
862 } | |
863 canvas->Restore(); | |
864 } | |
865 | |
866 // Draw the icon image. | |
867 int icon_x, icon_y; | |
868 | |
869 if (IsShowingWarningDialog()) { | |
870 icon_x = kLeftPadding + body_image_set->top_left->width(); | |
871 icon_x = GetMirroredXWithWidthInView(icon_x, icon->width()); | |
872 icon_y = (height() - icon->height()) / 2; | |
873 } else { | 710 } else { |
874 icon_x = progress_x + DownloadShelf::kFiletypeIconOffset; | 711 DCHECK_EQ(DownloadItem::COMPLETE, state); |
875 icon_y = progress_y + DownloadShelf::kFiletypeIconOffset; | 712 DownloadShelf::PaintDownloadComplete( |
876 } | 713 canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue()); |
877 if (enabled()) { | |
878 canvas->DrawImageInt(*icon, icon_x, icon_y); | |
879 } else { | |
880 // Use an alpha to make the image look disabled. | |
881 SkPaint paint; | |
882 paint.setAlpha(120); | |
883 canvas->DrawImageInt(*icon, icon_x, icon_y, paint); | |
884 } | 714 } |
885 } | 715 } |
| 716 canvas->Restore(); |
| 717 |
| 718 // Fetch the already-loaded icon. |
| 719 IconManager* im = g_browser_process->icon_manager(); |
| 720 gfx::Image* icon = im->LookupIconFromFilepath(download()->GetTargetFilePath(), |
| 721 IconLoader::SMALL); |
| 722 if (!icon) |
| 723 return; |
| 724 |
| 725 // Draw the icon image. |
| 726 int icon_x = progress_x + DownloadShelf::kFiletypeIconOffset; |
| 727 int icon_y = progress_y + DownloadShelf::kFiletypeIconOffset; |
| 728 SkPaint paint; |
| 729 // Use an alpha to make the image look disabled. |
| 730 if (!enabled()) |
| 731 paint.setAlpha(120); |
| 732 canvas->DrawImageInt(*icon->ToImageSkia(), icon_x, icon_y, paint); |
886 } | 733 } |
887 | 734 |
888 void DownloadItemView::OnFocus() { | 735 void DownloadItemView::OnFocus() { |
889 View::OnFocus(); | 736 View::OnFocus(); |
890 // We render differently when focused. | 737 // We render differently when focused. |
891 SchedulePaint(); | 738 SchedulePaint(); |
892 } | 739 } |
893 | 740 |
894 void DownloadItemView::OnBlur() { | 741 void DownloadItemView::OnBlur() { |
895 View::OnBlur(); | 742 View::OnBlur(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 | 780 |
934 void DownloadItemView::PossiblySubmitDownloadToFeedbackService(bool enabled) { | 781 void DownloadItemView::PossiblySubmitDownloadToFeedbackService(bool enabled) { |
935 if (!enabled || !SubmitDownloadToFeedbackService()) | 782 if (!enabled || !SubmitDownloadToFeedbackService()) |
936 download()->Remove(); | 783 download()->Remove(); |
937 // WARNING: 'this' is deleted at this point. Don't access 'this'. | 784 // WARNING: 'this' is deleted at this point. Don't access 'this'. |
938 } | 785 } |
939 | 786 |
940 void DownloadItemView::LoadIcon() { | 787 void DownloadItemView::LoadIcon() { |
941 IconManager* im = g_browser_process->icon_manager(); | 788 IconManager* im = g_browser_process->icon_manager(); |
942 last_download_item_path_ = download()->GetTargetFilePath(); | 789 last_download_item_path_ = download()->GetTargetFilePath(); |
943 im->LoadIcon(last_download_item_path_, | 790 im->LoadIcon(last_download_item_path_, IconLoader::SMALL, |
944 IconLoader::SMALL, | |
945 base::Bind(&DownloadItemView::OnExtractIconComplete, | 791 base::Bind(&DownloadItemView::OnExtractIconComplete, |
946 base::Unretained(this)), | 792 base::Unretained(this)), |
947 &cancelable_task_tracker_); | 793 &cancelable_task_tracker_); |
948 } | 794 } |
949 | 795 |
950 void DownloadItemView::LoadIconIfItemPathChanged() { | 796 void DownloadItemView::LoadIconIfItemPathChanged() { |
951 base::FilePath current_download_path = download()->GetTargetFilePath(); | 797 base::FilePath current_download_path = download()->GetTargetFilePath(); |
952 if (last_download_item_path_ == current_download_path) | 798 if (last_download_item_path_ == current_download_path) |
953 return; | 799 return; |
954 | 800 |
955 LoadIcon(); | 801 LoadIcon(); |
956 } | 802 } |
957 | 803 |
958 void DownloadItemView::UpdateColorsFromTheme() { | 804 void DownloadItemView::UpdateColorsFromTheme() { |
959 if (dangerous_download_label_ && GetThemeProvider()) { | 805 if (!GetThemeProvider()) |
960 dangerous_download_label_->SetEnabledColor( | 806 return; |
961 GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)); | 807 |
962 } | 808 SetBorder(base::MakeUnique<SeparatorBorder>(GetThemeProvider()->GetColor( |
| 809 ThemeProperties::COLOR_TOOLBAR_VERTICAL_SEPARATOR))); |
| 810 |
| 811 SkColor text_color = GetTextColor(); |
| 812 if (dangerous_download_label_) |
| 813 dangerous_download_label_->SetEnabledColor(text_color); |
| 814 if (save_button_) |
| 815 save_button_->SetEnabledTextColors(text_color); |
| 816 if (discard_button_) |
| 817 discard_button_->SetEnabledTextColors(text_color); |
963 } | 818 } |
964 | 819 |
965 void DownloadItemView::ShowContextMenuImpl(const gfx::Point& p, | 820 void DownloadItemView::ShowContextMenuImpl(const gfx::Rect& rect, |
966 ui::MenuSourceType source_type) { | 821 ui::MenuSourceType source_type) { |
967 gfx::Point point = p; | |
968 gfx::Size size; | |
969 | |
970 // Similar hack as in MenuButton. | 822 // Similar hack as in MenuButton. |
971 // We're about to show the menu from a mouse press. By showing from the | 823 // We're about to show the menu from a mouse press. By showing from the |
972 // mouse press event we block RootView in mouse dispatching. This also | 824 // mouse press event we block RootView in mouse dispatching. This also |
973 // appears to cause RootView to get a mouse pressed BEFORE the mouse | 825 // appears to cause RootView to get a mouse pressed BEFORE the mouse |
974 // release is seen, which means RootView sends us another mouse press no | 826 // release is seen, which means RootView sends us another mouse press no |
975 // matter where the user pressed. To force RootView to recalculate the | 827 // matter where the user pressed. To force RootView to recalculate the |
976 // mouse target during the mouse press we explicitly set the mouse handler | 828 // mouse target during the mouse press we explicitly set the mouse handler |
977 // to NULL. | 829 // to NULL. |
978 static_cast<views::internal::RootView*>(GetWidget()->GetRootView())-> | 830 static_cast<views::internal::RootView*>(GetWidget()->GetRootView()) |
979 SetMouseHandler(NULL); | 831 ->SetMouseHandler(NULL); |
980 | |
981 // If |is_mouse_gesture| is false, |p| is ignored. The menu is shown aligned | |
982 // to drop down arrow button. | |
983 if (source_type != ui::MENU_SOURCE_MOUSE && | |
984 source_type != ui::MENU_SOURCE_TOUCH) { | |
985 drop_down_pressed_ = true; | |
986 SetState(NORMAL, PUSHED); | |
987 point.SetPoint(drop_down_x_left_, box_y_); | |
988 size.SetSize(drop_down_x_right_ - drop_down_x_left_, box_height_); | |
989 } | |
990 views::View::ConvertPointToScreen(this, &point); | |
991 | 832 |
992 if (!context_menu_.get()) | 833 if (!context_menu_.get()) |
993 context_menu_.reset(new DownloadShelfContextMenuView(download())); | 834 context_menu_.reset(new DownloadShelfContextMenuView(download())); |
994 | 835 context_menu_->Run(GetWidget()->GetTopLevelWidget(), rect, source_type, |
995 context_menu_->Run(GetWidget()->GetTopLevelWidget(), gfx::Rect(point, size), | 836 base::Bind(&DownloadItemView::ReleaseDropdown, |
996 source_type, base::Bind(&DownloadItemView::ReleaseDropDown, | 837 weak_ptr_factory_.GetWeakPtr())); |
997 weak_ptr_factory_.GetWeakPtr())); | |
998 } | 838 } |
999 | 839 |
1000 void DownloadItemView::HandlePressEvent(const ui::LocatedEvent& event, | 840 void DownloadItemView::HandlePressEvent(const ui::LocatedEvent& event, |
1001 bool active_event) { | 841 bool active_event) { |
1002 // The event should not activate us in dangerous mode. | 842 // The event should not activate us in dangerous/malicious mode. |
1003 if (mode_ == DANGEROUS_MODE) | 843 if (IsShowingWarningDialog()) |
1004 return; | 844 return; |
1005 | 845 |
1006 // Stop any completion animation. | 846 // Stop any completion animation. |
1007 if (complete_animation_.get() && complete_animation_->is_animating()) | 847 if (complete_animation_.get() && complete_animation_->is_animating()) |
1008 complete_animation_->End(); | 848 complete_animation_->End(); |
1009 | 849 |
1010 if (active_event) { | 850 // Don't show the ripple for right clicks. |
1011 if (InDropDownButtonXCoordinateRange(event.x())) { | 851 if (!active_event) |
1012 if (context_menu_.get()) { | 852 return; |
1013 // Ignore two close clicks. This typically happens when the user clicks | 853 |
1014 // the button to close the menu. | 854 AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event); |
1015 base::TimeDelta delta = | |
1016 base::TimeTicks::Now() - context_menu_->close_time(); | |
1017 if (delta.InMilliseconds() < views::kMinimumMsBetweenButtonClicks) | |
1018 return; | |
1019 } | |
1020 drop_down_pressed_ = true; | |
1021 SetState(NORMAL, PUSHED); | |
1022 // We are setting is_mouse_gesture to false when calling ShowContextMenu | |
1023 // so that the positioning of the context menu will be similar to a | |
1024 // keyboard invocation. I.e. we want the menu to always be positioned | |
1025 // next to the drop down button instead of the next to the pointer. | |
1026 ShowContextMenuImpl(event.location(), ui::MENU_SOURCE_KEYBOARD); | |
1027 // Once called, it is possible that *this was deleted (e.g.: due to | |
1028 // invoking the 'Discard' action.) | |
1029 } else if (!IsShowingWarningDialog()) { | |
1030 SetState(PUSHED, NORMAL); | |
1031 } | |
1032 } | |
1033 } | 855 } |
1034 | 856 |
1035 void DownloadItemView::HandleClickEvent(const ui::LocatedEvent& event, | 857 void DownloadItemView::HandleClickEvent(const ui::LocatedEvent& event, |
1036 bool active_event) { | 858 bool active_event) { |
1037 // Mouse should not activate us in dangerous mode. | 859 // The event should not activate us in dangerous/malicious mode. |
1038 if (mode_ == DANGEROUS_MODE) | 860 if (!active_event || IsShowingWarningDialog()) |
1039 return; | 861 return; |
1040 | 862 |
1041 SetState(NORMAL, NORMAL); | 863 AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, &event); |
1042 | |
1043 if (!active_event || | |
1044 InDropDownButtonXCoordinateRange(event.x()) || | |
1045 IsShowingWarningDialog()) { | |
1046 return; | |
1047 } | |
1048 | 864 |
1049 // OpenDownload may delete this, so don't add any code after this line. | 865 // OpenDownload may delete this, so don't add any code after this line. |
1050 OpenDownload(); | 866 OpenDownload(); |
1051 } | 867 } |
1052 | 868 |
1053 // Load an icon for the file type we're downloading, and animate any in progress | 869 void DownloadItemView::SetDropdownState(State new_state) { |
1054 // download state. | 870 // Avoid extra SchedulePaint()s if the state is going to be the same and |
1055 void DownloadItemView::PaintImages(gfx::Canvas* canvas, | 871 // |dropdown_button_| has already been initialized. |
1056 const gfx::ImageSkia* top_image, | 872 if (dropdown_state_ == new_state && |
1057 const gfx::ImageSkia* center_image, | 873 !dropdown_button_->GetImage(views::CustomButton::STATE_NORMAL).isNull()) |
1058 const gfx::ImageSkia* bottom_image, | |
1059 int x, int y, int height, int width) { | |
1060 int middle_height = height - top_image->height() - bottom_image->height(); | |
1061 // Draw the top. | |
1062 canvas->DrawImageInt(*top_image, | |
1063 0, 0, top_image->width(), top_image->height(), | |
1064 x, y, width, top_image->height(), false); | |
1065 y += top_image->height(); | |
1066 // Draw the center. | |
1067 canvas->DrawImageInt(*center_image, | |
1068 0, 0, center_image->width(), center_image->height(), | |
1069 x, y, width, middle_height, false); | |
1070 y += middle_height; | |
1071 // Draw the bottom. | |
1072 canvas->DrawImageInt(*bottom_image, | |
1073 0, 0, bottom_image->width(), bottom_image->height(), | |
1074 x, y, width, bottom_image->height(), false); | |
1075 } | |
1076 | |
1077 void DownloadItemView::SetState(State new_body_state, State new_drop_state) { | |
1078 // If we are showing a warning dialog, we don't change body state. | |
1079 if (IsShowingWarningDialog()) { | |
1080 new_body_state = NORMAL; | |
1081 | |
1082 // Current body_state_ should always be NORMAL for warning dialogs. | |
1083 DCHECK_EQ(NORMAL, body_state_); | |
1084 // We shouldn't be calling SetState if we are in DANGEROUS_MODE. | |
1085 DCHECK_NE(DANGEROUS_MODE, mode_); | |
1086 } | |
1087 // Avoid extra SchedulePaint()s if the state is going to be the same. | |
1088 if (body_state_ == new_body_state && drop_down_state_ == new_drop_state) | |
1089 return; | 874 return; |
1090 | 875 |
1091 AnimateStateTransition(body_state_, new_body_state, | 876 dropdown_button_->SetIcon(new_state == PUSHED ? gfx::VectorIconId::FIND_NEXT |
1092 body_hover_animation_.get()); | 877 : gfx::VectorIconId::FIND_PREV); |
1093 AnimateStateTransition(drop_down_state_, new_drop_state, | 878 if (new_state != dropdown_state_) { |
1094 drop_hover_animation_.get()); | 879 dropdown_button_->AnimateInkDrop(new_state == PUSHED |
1095 body_state_ = new_body_state; | 880 ? views::InkDropState::ACTIVATED |
1096 drop_down_state_ = new_drop_state; | 881 : views::InkDropState::DEACTIVATED); |
| 882 } |
| 883 dropdown_button_->OnThemeChanged(); |
| 884 dropdown_state_ = new_state; |
1097 SchedulePaint(); | 885 SchedulePaint(); |
1098 } | 886 } |
1099 | 887 |
1100 void DownloadItemView::ToggleWarningDialog() { | 888 void DownloadItemView::ToggleWarningDialog() { |
1101 if (model_.IsDangerous()) | 889 if (model_.IsDangerous()) |
1102 ShowWarningDialog(); | 890 ShowWarningDialog(); |
1103 else | 891 else |
1104 ClearWarningDialog(); | 892 ClearWarningDialog(); |
1105 | 893 |
1106 UpdateDropDownButtonPosition(); | 894 // We need to load the icon now that the download has the real path. |
| 895 LoadIcon(); |
1107 | 896 |
1108 // Force the shelf to layout again as our size has changed. | 897 // Force the shelf to layout again as our size has changed. |
1109 shelf_->Layout(); | 898 shelf_->Layout(); |
1110 shelf_->SchedulePaint(); | 899 shelf_->SchedulePaint(); |
1111 } | 900 } |
1112 | 901 |
1113 void DownloadItemView::ClearWarningDialog() { | 902 void DownloadItemView::ClearWarningDialog() { |
1114 DCHECK(download()->GetDangerType() == | 903 DCHECK(download()->GetDangerType() == |
1115 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); | 904 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); |
1116 DCHECK(mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE); | 905 DCHECK(IsShowingWarningDialog()); |
1117 | 906 |
1118 mode_ = NORMAL_MODE; | 907 mode_ = NORMAL_MODE; |
1119 body_state_ = NORMAL; | 908 dropdown_state_ = NORMAL; |
1120 drop_down_state_ = NORMAL; | |
1121 | 909 |
1122 // ExperienceSampling: User proceeded through the warning. | 910 // ExperienceSampling: User proceeded through the warning. |
1123 if (sampling_event_.get()) { | 911 if (sampling_event_.get()) { |
1124 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed); | 912 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed); |
1125 sampling_event_.reset(NULL); | 913 sampling_event_.reset(NULL); |
1126 } | 914 } |
1127 // Remove the views used by the warning dialog. | 915 // Remove the views used by the warning dialog. |
1128 if (save_button_) { | 916 if (save_button_) { |
1129 RemoveChildView(save_button_); | 917 RemoveChildView(save_button_); |
1130 delete save_button_; | 918 delete save_button_; |
1131 save_button_ = NULL; | 919 save_button_ = NULL; |
1132 } | 920 } |
1133 RemoveChildView(discard_button_); | 921 RemoveChildView(discard_button_); |
1134 delete discard_button_; | 922 delete discard_button_; |
1135 discard_button_ = NULL; | 923 discard_button_ = NULL; |
1136 RemoveChildView(dangerous_download_label_); | 924 RemoveChildView(dangerous_download_label_); |
1137 delete dangerous_download_label_; | 925 delete dangerous_download_label_; |
1138 dangerous_download_label_ = NULL; | 926 dangerous_download_label_ = NULL; |
1139 dangerous_download_label_sized_ = false; | 927 dangerous_download_label_sized_ = false; |
1140 | 928 |
1141 // We need to load the icon now that the download has the real path. | 929 // We need to load the icon now that the download has the real path. |
1142 LoadIcon(); | 930 LoadIcon(); |
| 931 |
| 932 dropdown_button_->SetVisible(true); |
1143 } | 933 } |
1144 | 934 |
1145 void DownloadItemView::ShowWarningDialog() { | 935 void DownloadItemView::ShowWarningDialog() { |
1146 DCHECK(mode_ != DANGEROUS_MODE && mode_ != MALICIOUS_MODE); | 936 DCHECK(mode_ != DANGEROUS_MODE && mode_ != MALICIOUS_MODE); |
1147 time_download_warning_shown_ = base::Time::Now(); | 937 time_download_warning_shown_ = base::Time::Now(); |
1148 content::DownloadDangerType danger_type = download()->GetDangerType(); | 938 content::DownloadDangerType danger_type = download()->GetDangerType(); |
1149 RecordDangerousDownloadWarningShown(danger_type); | 939 RecordDangerousDownloadWarningShown(danger_type); |
1150 #if defined(FULL_SAFE_BROWSING) | 940 #if defined(FULL_SAFE_BROWSING) |
1151 if (model_.ShouldAllowDownloadFeedback()) { | 941 if (model_.ShouldAllowDownloadFeedback()) { |
1152 safe_browsing::DownloadFeedbackService::RecordEligibleDownloadShown( | 942 safe_browsing::DownloadFeedbackService::RecordEligibleDownloadShown( |
1153 danger_type); | 943 danger_type); |
1154 } | 944 } |
1155 #endif | 945 #endif |
1156 mode_ = model_.MightBeMalicious() ? MALICIOUS_MODE : DANGEROUS_MODE; | 946 mode_ = model_.MightBeMalicious() ? MALICIOUS_MODE : DANGEROUS_MODE; |
1157 | 947 |
1158 // ExperienceSampling: Dangerous or malicious download warning is being shown | 948 // ExperienceSampling: Dangerous or malicious download warning is being shown |
1159 // to the user, so we start a new SamplingEvent and track it. | 949 // to the user, so we start a new SamplingEvent and track it. |
1160 std::string event_name = model_.MightBeMalicious() | 950 std::string event_name = model_.MightBeMalicious() |
1161 ? ExperienceSamplingEvent::kMaliciousDownload | 951 ? ExperienceSamplingEvent::kMaliciousDownload |
1162 : ExperienceSamplingEvent::kDangerousDownload; | 952 : ExperienceSamplingEvent::kDangerousDownload; |
1163 sampling_event_.reset( | 953 sampling_event_.reset(new ExperienceSamplingEvent( |
1164 new ExperienceSamplingEvent(event_name, | 954 event_name, download()->GetURL(), download()->GetReferrerUrl(), |
1165 download()->GetURL(), | 955 download()->GetBrowserContext())); |
1166 download()->GetReferrerUrl(), | |
1167 download()->GetBrowserContext())); | |
1168 | 956 |
1169 body_state_ = NORMAL; | 957 dropdown_state_ = NORMAL; |
1170 drop_down_state_ = NORMAL; | |
1171 if (mode_ == DANGEROUS_MODE) { | 958 if (mode_ == DANGEROUS_MODE) { |
1172 save_button_ = new views::LabelButton( | 959 save_button_ = |
1173 this, model_.GetWarningConfirmButtonText()); | 960 views::MdTextButton::Create(this, model_.GetWarningConfirmButtonText()); |
1174 save_button_->SetStyle(views::Button::STYLE_BUTTON); | |
1175 AddChildView(save_button_); | 961 AddChildView(save_button_); |
1176 } | 962 } |
1177 discard_button_ = new views::LabelButton( | 963 discard_button_ = views::MdTextButton::Create( |
1178 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); | 964 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); |
1179 discard_button_->SetStyle(views::Button::STYLE_BUTTON); | |
1180 AddChildView(discard_button_); | 965 AddChildView(discard_button_); |
1181 | 966 |
1182 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
1183 switch (danger_type) { | |
1184 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: | |
1185 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: | |
1186 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: | |
1187 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: | |
1188 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: | |
1189 warning_icon_ = rb.GetImageSkiaNamed(IDR_SAFEBROWSING_WARNING); | |
1190 break; | |
1191 | |
1192 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: | |
1193 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: | |
1194 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: | |
1195 case content::DOWNLOAD_DANGER_TYPE_MAX: | |
1196 NOTREACHED(); | |
1197 // fallthrough | |
1198 | |
1199 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: | |
1200 warning_icon_ = rb.GetImageSkiaNamed(IDR_WARNING); | |
1201 } | |
1202 base::string16 dangerous_label = | 967 base::string16 dangerous_label = |
1203 model_.GetWarningText(font_list_, kTextWidth); | 968 model_.GetWarningText(font_list_, kTextWidth); |
1204 dangerous_download_label_ = new views::Label(dangerous_label); | 969 dangerous_download_label_ = new views::Label(dangerous_label); |
1205 dangerous_download_label_->SetMultiLine(true); | 970 dangerous_download_label_->SetMultiLine(true); |
1206 dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 971 dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
1207 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); | 972 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); |
1208 AddChildView(dangerous_download_label_); | 973 AddChildView(dangerous_download_label_); |
1209 SizeLabelToMinWidth(); | 974 SizeLabelToMinWidth(); |
| 975 |
| 976 dropdown_button_->SetVisible(mode_ == MALICIOUS_MODE); |
| 977 } |
| 978 |
| 979 gfx::ImageSkia DownloadItemView::GetWarningIcon() { |
| 980 switch (download()->GetDangerType()) { |
| 981 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: |
| 982 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: |
| 983 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: |
| 984 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: |
| 985 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: |
| 986 return gfx::CreateVectorIcon(gfx::VectorIconId::REMOVE_CIRCLE, |
| 987 kWarningIconSize, gfx::kGoogleRed700); |
| 988 |
| 989 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: |
| 990 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: |
| 991 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: |
| 992 case content::DOWNLOAD_DANGER_TYPE_MAX: |
| 993 NOTREACHED(); |
| 994 break; |
| 995 |
| 996 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: |
| 997 return gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, kWarningIconSize, |
| 998 gfx::kGoogleYellow700); |
| 999 } |
| 1000 return gfx::ImageSkia(); |
1210 } | 1001 } |
1211 | 1002 |
1212 gfx::Size DownloadItemView::GetButtonSize() const { | 1003 gfx::Size DownloadItemView::GetButtonSize() const { |
1213 DCHECK(discard_button_ && (mode_ == MALICIOUS_MODE || save_button_)); | 1004 DCHECK(discard_button_ && (mode_ == MALICIOUS_MODE || save_button_)); |
1214 gfx::Size size = discard_button_->GetPreferredSize(); | 1005 gfx::Size size = discard_button_->GetPreferredSize(); |
1215 if (save_button_) | 1006 if (save_button_) |
1216 size.SetToMax(save_button_->GetPreferredSize()); | 1007 size.SetToMax(save_button_->GetPreferredSize()); |
1217 return size; | 1008 return size; |
1218 } | 1009 } |
1219 | 1010 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 // If the width is growing again, it means we passed the optimal width spot. | 1062 // If the width is growing again, it means we passed the optimal width spot. |
1272 if (size.width() > min_width) { | 1063 if (size.width() > min_width) { |
1273 dangerous_download_label_->SetText(prev_text); | 1064 dangerous_download_label_->SetText(prev_text); |
1274 break; | 1065 break; |
1275 } else { | 1066 } else { |
1276 min_width = size.width(); | 1067 min_width = size.width(); |
1277 } | 1068 } |
1278 prev_text = current_text; | 1069 prev_text = current_text; |
1279 } | 1070 } |
1280 | 1071 |
1281 dangerous_download_label_->SetBounds(0, 0, size.width(), size.height()); | 1072 dangerous_download_label_->SetSize(size); |
1282 dangerous_download_label_sized_ = true; | 1073 dangerous_download_label_sized_ = true; |
1283 } | 1074 } |
1284 | 1075 |
1285 void DownloadItemView::Reenable() { | 1076 void DownloadItemView::Reenable() { |
1286 disabled_while_opening_ = false; | 1077 disabled_while_opening_ = false; |
1287 SetEnabled(true); // Triggers a repaint. | 1078 SetEnabled(true); // Triggers a repaint. |
1288 } | 1079 } |
1289 | 1080 |
1290 void DownloadItemView::ReleaseDropDown() { | 1081 void DownloadItemView::ReleaseDropdown() { |
1291 drop_down_pressed_ = false; | 1082 SetDropdownState(NORMAL); |
1292 SetState(NORMAL, NORMAL); | |
1293 } | |
1294 | |
1295 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { | |
1296 if (x > drop_down_x_left_ && x < drop_down_x_right_) | |
1297 return true; | |
1298 return false; | |
1299 } | 1083 } |
1300 | 1084 |
1301 void DownloadItemView::UpdateAccessibleName() { | 1085 void DownloadItemView::UpdateAccessibleName() { |
1302 base::string16 new_name; | 1086 base::string16 new_name; |
1303 if (IsShowingWarningDialog()) { | 1087 if (IsShowingWarningDialog()) { |
1304 new_name = dangerous_download_label_->text(); | 1088 new_name = dangerous_download_label_->text(); |
1305 } else { | 1089 } else { |
1306 new_name = status_text_ + base::char16(' ') + | 1090 new_name = status_text_ + base::char16(' ') + |
1307 download()->GetFileNameToReportUser().LossyDisplayName(); | 1091 download()->GetFileNameToReportUser().LossyDisplayName(); |
1308 } | 1092 } |
1309 | 1093 |
1310 // If the name has changed, notify assistive technology that the name | 1094 // If the name has changed, notify assistive technology that the name |
1311 // has changed so they can announce it immediately. | 1095 // has changed so they can announce it immediately. |
1312 if (new_name != accessible_name_) { | 1096 if (new_name != accessible_name_) { |
1313 accessible_name_ = new_name; | 1097 accessible_name_ = new_name; |
1314 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); | 1098 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); |
1315 } | 1099 } |
1316 } | 1100 } |
1317 | 1101 |
1318 void DownloadItemView::UpdateDropDownButtonPosition() { | 1102 void DownloadItemView::AnimateStateTransition(State from, |
1319 gfx::Size size = GetPreferredSize(); | 1103 State to, |
1320 if (base::i18n::IsRTL()) { | |
1321 // Drop down button is glued to the left of the download shelf. | |
1322 drop_down_x_left_ = 0; | |
1323 drop_down_x_right_ = normal_drop_down_image_set_.top->width(); | |
1324 } else { | |
1325 // Drop down button is glued to the right of the download shelf. | |
1326 drop_down_x_left_ = | |
1327 size.width() - normal_drop_down_image_set_.top->width(); | |
1328 drop_down_x_right_ = size.width(); | |
1329 } | |
1330 } | |
1331 | |
1332 void DownloadItemView::AnimateStateTransition(State from, State to, | |
1333 gfx::SlideAnimation* animation) { | 1104 gfx::SlideAnimation* animation) { |
1334 if (from == NORMAL && to == HOT) { | 1105 if (from == NORMAL && to == HOT) { |
1335 animation->Show(); | 1106 animation->Show(); |
1336 } else if (from == HOT && to == NORMAL) { | 1107 } else if (from == HOT && to == NORMAL) { |
1337 animation->Hide(); | 1108 animation->Hide(); |
1338 } else if (from != to) { | 1109 } else if (from != to) { |
1339 animation->Reset((to == HOT) ? 1.0 : 0.0); | 1110 animation->Reset((to == HOT) ? 1.0 : 0.0); |
1340 } | 1111 } |
1341 } | 1112 } |
1342 | 1113 |
1343 void DownloadItemView::ProgressTimerFired() { | 1114 void DownloadItemView::ProgressTimerFired() { |
1344 // Only repaint for the indeterminate size case. Otherwise, we'll repaint only | 1115 // Only repaint for the indeterminate size case. Otherwise, we'll repaint only |
1345 // when there's an update notified via OnDownloadUpdated(). | 1116 // when there's an update notified via OnDownloadUpdated(). |
1346 if (model_.PercentComplete() < 0) | 1117 if (model_.PercentComplete() < 0) |
1347 SchedulePaint(); | 1118 SchedulePaint(); |
1348 } | 1119 } |
| 1120 |
| 1121 SkColor DownloadItemView::GetTextColor() const { |
| 1122 return GetTextColorForThemeProvider(GetThemeProvider()); |
| 1123 } |
| 1124 |
| 1125 SkColor DownloadItemView::GetDimmedTextColor() const { |
| 1126 return SkColorSetA(GetTextColor(), 0xC7); |
| 1127 } |
OLD | NEW |