OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 save_button_(NULL), | 99 save_button_(NULL), |
100 discard_button_(NULL), | 100 discard_button_(NULL), |
101 dangerous_download_label_(NULL), | 101 dangerous_download_label_(NULL), |
102 dangerous_download_label_sized_(false), | 102 dangerous_download_label_sized_(false), |
103 disabled_while_opening_(false), | 103 disabled_while_opening_(false), |
104 creation_time_(base::Time::Now()), | 104 creation_time_(base::Time::Now()), |
105 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) { | 105 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) { |
106 DCHECK(download_); | 106 DCHECK(download_); |
107 download_->AddObserver(this); | 107 download_->AddObserver(this); |
108 | 108 |
109 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); | 109 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
110 | 110 |
111 BodyImageSet normal_body_image_set = { | 111 BodyImageSet normal_body_image_set = { |
112 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), | 112 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), |
113 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), | 113 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), |
114 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), | 114 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), |
115 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), | 115 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), |
116 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), | 116 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE), |
117 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), | 117 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM), |
118 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP), | 118 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP), |
119 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE), | 119 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE), |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } else { | 204 } else { |
205 // Drop down button is glued to the right of the download shelf. | 205 // Drop down button is glued to the right of the download shelf. |
206 drop_down_x_left_ = | 206 drop_down_x_left_ = |
207 size.width() - normal_drop_down_image_set_.top->width(); | 207 size.width() - normal_drop_down_image_set_.top->width(); |
208 drop_down_x_right_ = size.width(); | 208 drop_down_x_right_ = size.width(); |
209 } | 209 } |
210 | 210 |
211 body_hover_animation_.reset(new ui::SlideAnimation(this)); | 211 body_hover_animation_.reset(new ui::SlideAnimation(this)); |
212 drop_hover_animation_.reset(new ui::SlideAnimation(this)); | 212 drop_hover_animation_.reset(new ui::SlideAnimation(this)); |
213 | 213 |
214 if (download->safety_state() == DownloadItem::DANGEROUS) { | 214 if (download->safety_state() == DownloadItem::DANGEROUS) |
215 tooltip_text_.clear(); | 215 EnterDangerousMode(); |
216 body_state_ = DANGEROUS; | |
217 drop_down_state_ = DANGEROUS; | |
218 save_button_ = new views::NativeTextButton(this, | |
219 l10n_util::GetStringUTF16( | |
220 ChromeDownloadManagerDelegate::IsExtensionDownload(download) ? | |
221 IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD)); | |
222 save_button_->set_ignore_minimum_size(true); | |
223 discard_button_ = new views::NativeTextButton( | |
224 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); | |
225 discard_button_->set_ignore_minimum_size(true); | |
226 AddChildView(save_button_); | |
227 AddChildView(discard_button_); | |
228 | |
229 // Ensure the file name is not too long. | |
230 | |
231 // Extract the file extension (if any). | |
232 FilePath filename(download->target_name()); | |
233 #if defined(OS_POSIX) | |
234 string16 extension = WideToUTF16(base::SysNativeMBToWide( | |
235 filename.Extension())); | |
236 #else | |
237 string16 extension = filename.Extension(); | |
238 #endif | |
239 | |
240 // Remove leading '.' | |
241 if (extension.length() > 0) | |
242 extension = extension.substr(1); | |
243 #if defined(OS_POSIX) | |
244 string16 rootname = WideToUTF16(base::SysNativeMBToWide( | |
245 filename.RemoveExtension().value())); | |
246 #else | |
247 string16 rootname = filename.RemoveExtension().value(); | |
248 #endif | |
249 | |
250 // Elide giant extensions (this shouldn't currently be hit, but might | |
251 // in future, should we ever notice unsafe giant extensions). | |
252 if (extension.length() > kFileNameMaxLength / 2) | |
253 ui::ElideString(extension, kFileNameMaxLength / 2, &extension); | |
254 | |
255 // The dangerous download label text and icon are different | |
256 // under different cases. | |
257 string16 dangerous_label; | |
258 if (download->GetDangerType() == DownloadStateInfo::DANGEROUS_URL) { | |
259 // Safebrowsing shows the download URL leads to malicious file. | |
260 warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING); | |
261 dangerous_label = | |
262 l10n_util::GetStringUTF16(IDS_PROMPT_UNSAFE_DOWNLOAD_URL); | |
263 } else { | |
264 // The download file has dangerous file type (e.g.: an executable). | |
265 DCHECK(download->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE); | |
266 warning_icon_ = rb.GetBitmapNamed(IDR_WARNING); | |
267 if (ChromeDownloadManagerDelegate::IsExtensionDownload(download)) { | |
268 dangerous_label = | |
269 l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION); | |
270 } else { | |
271 ui::ElideString(rootname, | |
272 kFileNameMaxLength - extension.length(), | |
273 &rootname); | |
274 string16 filename = rootname + ASCIIToUTF16(".") + extension; | |
275 filename = base::i18n::GetDisplayStringInLTRDirectionality(filename); | |
276 dangerous_label = | |
277 l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD, filename); | |
278 } | |
279 } | |
280 | |
281 dangerous_download_label_ = new views::Label(dangerous_label); | |
282 dangerous_download_label_->SetMultiLine(true); | |
283 dangerous_download_label_->SetHorizontalAlignment( | |
284 views::Label::ALIGN_LEFT); | |
285 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); | |
286 AddChildView(dangerous_download_label_); | |
287 SizeLabelToMinWidth(); | |
288 } | |
289 | 216 |
290 UpdateAccessibleName(); | 217 UpdateAccessibleName(); |
291 set_accessibility_focusable(true); | 218 set_accessibility_focusable(true); |
292 | 219 |
293 // Set up our animation. | 220 // Set up our animation. |
294 StartDownloadProgress(); | 221 StartDownloadProgress(); |
295 } | 222 } |
296 | 223 |
297 DownloadItemView::~DownloadItemView() { | 224 DownloadItemView::~DownloadItemView() { |
298 if (context_menu_.get()) | 225 if (context_menu_.get()) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 | 260 |
334 // Update the progress graphic on the icon and our text status label | 261 // Update the progress graphic on the icon and our text status label |
335 // to reflect our current bytes downloaded, time remaining. | 262 // to reflect our current bytes downloaded, time remaining. |
336 void DownloadItemView::OnDownloadUpdated(DownloadItem* download) { | 263 void DownloadItemView::OnDownloadUpdated(DownloadItem* download) { |
337 DCHECK(download == download_); | 264 DCHECK(download == download_); |
338 | 265 |
339 if (body_state_ == DANGEROUS && | 266 if (body_state_ == DANGEROUS && |
340 download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { | 267 download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { |
341 // We have been approved. | 268 // We have been approved. |
342 ClearDangerousMode(); | 269 ClearDangerousMode(); |
343 } | 270 } else if (body_state_ != DANGEROUS && |
344 | 271 download->safety_state() == DownloadItem::DANGEROUS) { |
345 string16 status_text = model_->GetStatusText(); | 272 EnterDangerousMode(); |
346 switch (download_->state()) { | 273 // Force the shelf to layout again as our size has changed. |
347 case DownloadItem::IN_PROGRESS: | 274 parent_->Layout(); |
348 download_->is_paused() ? StopDownloadProgress() : StartDownloadProgress(); | 275 SchedulePaint(); |
349 LoadIconIfItemPathChanged(); | 276 } else { |
350 break; | 277 string16 status_text = model_->GetStatusText(); |
351 case DownloadItem::INTERRUPTED: | 278 switch (download_->state()) { |
352 StopDownloadProgress(); | 279 case DownloadItem::IN_PROGRESS: |
353 complete_animation_.reset(new ui::SlideAnimation(this)); | 280 download_->is_paused() ? |
354 complete_animation_->SetSlideDuration(kInterruptedAnimationDurationMs); | 281 StopDownloadProgress() : StartDownloadProgress(); |
355 complete_animation_->SetTweenType(ui::Tween::LINEAR); | 282 LoadIconIfItemPathChanged(); |
356 complete_animation_->Show(); | 283 break; |
357 SchedulePaint(); | 284 case DownloadItem::INTERRUPTED: |
358 LoadIcon(); | 285 StopDownloadProgress(); |
359 break; | 286 complete_animation_.reset(new ui::SlideAnimation(this)); |
360 case DownloadItem::COMPLETE: | 287 complete_animation_->SetSlideDuration(kInterruptedAnimationDurationMs); |
361 if (download_->auto_opened()) { | 288 complete_animation_->SetTweenType(ui::Tween::LINEAR); |
| 289 complete_animation_->Show(); |
| 290 SchedulePaint(); |
| 291 LoadIcon(); |
| 292 break; |
| 293 case DownloadItem::COMPLETE: |
| 294 if (download_->auto_opened()) { |
| 295 parent_->RemoveDownloadView(this); // This will delete us! |
| 296 return; |
| 297 } |
| 298 StopDownloadProgress(); |
| 299 complete_animation_.reset(new ui::SlideAnimation(this)); |
| 300 complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs); |
| 301 complete_animation_->SetTweenType(ui::Tween::LINEAR); |
| 302 complete_animation_->Show(); |
| 303 SchedulePaint(); |
| 304 LoadIcon(); |
| 305 break; |
| 306 case DownloadItem::CANCELLED: |
| 307 StopDownloadProgress(); |
| 308 LoadIcon(); |
| 309 break; |
| 310 case DownloadItem::REMOVING: |
362 parent_->RemoveDownloadView(this); // This will delete us! | 311 parent_->RemoveDownloadView(this); // This will delete us! |
363 return; | 312 return; |
364 } | 313 default: |
365 StopDownloadProgress(); | 314 NOTREACHED(); |
366 complete_animation_.reset(new ui::SlideAnimation(this)); | 315 } |
367 complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs); | 316 status_text_ = status_text; |
368 complete_animation_->SetTweenType(ui::Tween::LINEAR); | |
369 complete_animation_->Show(); | |
370 SchedulePaint(); | |
371 LoadIcon(); | |
372 break; | |
373 case DownloadItem::CANCELLED: | |
374 StopDownloadProgress(); | |
375 LoadIcon(); | |
376 break; | |
377 case DownloadItem::REMOVING: | |
378 parent_->RemoveDownloadView(this); // This will delete us! | |
379 return; | |
380 default: | |
381 NOTREACHED(); | |
382 } | 317 } |
383 | |
384 status_text_ = status_text; | |
385 UpdateAccessibleName(); | 318 UpdateAccessibleName(); |
386 | 319 |
387 // We use the parent's (DownloadShelfView's) SchedulePaint, since there | 320 // We use the parent's (DownloadShelfView's) SchedulePaint, since there |
388 // are spaces between each DownloadItemView that the parent is responsible | 321 // are spaces between each DownloadItemView that the parent is responsible |
389 // for painting. | 322 // for painting. |
390 parent()->SchedulePaint(); | 323 parent()->SchedulePaint(); |
391 } | 324 } |
392 | 325 |
393 void DownloadItemView::OnDownloadOpened(DownloadItem* download) { | 326 void DownloadItemView::OnDownloadOpened(DownloadItem* download) { |
394 disabled_while_opening_ = true; | 327 disabled_while_opening_ = true; |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 // Remove the views used by the dangerous mode. | 909 // Remove the views used by the dangerous mode. |
977 RemoveChildView(save_button_); | 910 RemoveChildView(save_button_); |
978 delete save_button_; | 911 delete save_button_; |
979 save_button_ = NULL; | 912 save_button_ = NULL; |
980 RemoveChildView(discard_button_); | 913 RemoveChildView(discard_button_); |
981 delete discard_button_; | 914 delete discard_button_; |
982 discard_button_ = NULL; | 915 discard_button_ = NULL; |
983 RemoveChildView(dangerous_download_label_); | 916 RemoveChildView(dangerous_download_label_); |
984 delete dangerous_download_label_; | 917 delete dangerous_download_label_; |
985 dangerous_download_label_ = NULL; | 918 dangerous_download_label_ = NULL; |
| 919 dangerous_download_label_sized_ = false; |
986 | 920 |
987 // Set the accessible name back to the status and filename instead of the | 921 // Set the accessible name back to the status and filename instead of the |
988 // download warning. | 922 // download warning. |
989 UpdateAccessibleName(); | 923 UpdateAccessibleName(); |
990 | 924 |
991 // We need to load the icon now that the download_ has the real path. | 925 // We need to load the icon now that the download_ has the real path. |
992 LoadIcon(); | 926 LoadIcon(); |
993 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName(); | 927 tooltip_text_ = download_->GetFileNameToReportUser().LossyDisplayName(); |
994 | 928 |
995 // Force the shelf to layout again as our size has changed. | 929 // Force the shelf to layout again as our size has changed. |
996 parent_->Layout(); | 930 parent_->Layout(); |
997 parent_->SchedulePaint(); | 931 parent_->SchedulePaint(); |
998 } | 932 } |
999 | 933 |
| 934 void DownloadItemView::EnterDangerousMode() { |
| 935 DCHECK(body_state_ != DANGEROUS && drop_down_state_ != DANGEROUS); |
| 936 tooltip_text_.clear(); |
| 937 body_state_ = DANGEROUS; |
| 938 drop_down_state_ = DANGEROUS; |
| 939 save_button_ = new views::NativeTextButton(this, |
| 940 l10n_util::GetStringUTF16( |
| 941 ChromeDownloadManagerDelegate::IsExtensionDownload(download_) ? |
| 942 IDS_CONTINUE_EXTENSION_DOWNLOAD : IDS_CONFIRM_DOWNLOAD)); |
| 943 save_button_->set_ignore_minimum_size(true); |
| 944 discard_button_ = new views::NativeTextButton( |
| 945 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); |
| 946 discard_button_->set_ignore_minimum_size(true); |
| 947 AddChildView(save_button_); |
| 948 AddChildView(discard_button_); |
| 949 |
| 950 // Ensure the file name is not too long. |
| 951 |
| 952 // Extract the file extension (if any). |
| 953 FilePath filename(download_->target_name()); |
| 954 #if defined(OS_POSIX) |
| 955 string16 extension = WideToUTF16(base::SysNativeMBToWide( |
| 956 filename.Extension())); |
| 957 #else |
| 958 string16 extension = filename.Extension(); |
| 959 #endif |
| 960 |
| 961 // Remove leading '.' |
| 962 if (extension.length() > 0) |
| 963 extension = extension.substr(1); |
| 964 #if defined(OS_POSIX) |
| 965 string16 rootname = WideToUTF16(base::SysNativeMBToWide( |
| 966 filename.RemoveExtension().value())); |
| 967 #else |
| 968 string16 rootname = filename.RemoveExtension().value(); |
| 969 #endif |
| 970 |
| 971 // Elide giant extensions (this shouldn't currently be hit, but might |
| 972 // in future, should we ever notice unsafe giant extensions). |
| 973 if (extension.length() > kFileNameMaxLength / 2) |
| 974 ui::ElideString(extension, kFileNameMaxLength / 2, &extension); |
| 975 |
| 976 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 977 // The dangerous download label text and icon are different |
| 978 // under different cases. |
| 979 string16 dangerous_label; |
| 980 if (download_->GetDangerType() == DownloadStateInfo::DANGEROUS_URL || |
| 981 download_->GetDangerType() == DownloadStateInfo::DANGEROUS_CONTENT) { |
| 982 // TODO(noelutz): add the target filename to the warning message in the |
| 983 // case of a dangerous content warning. |
| 984 // Safebrowsing shows the download URL or content leads to malicious file. |
| 985 warning_icon_ = rb.GetBitmapNamed(IDR_SAFEBROWSING_WARNING); |
| 986 dangerous_label = |
| 987 l10n_util::GetStringUTF16(IDS_PROMPT_UNSAFE_DOWNLOAD_URL); |
| 988 } else { |
| 989 // The download file has dangerous file type (e.g.: an executable). |
| 990 DCHECK(download_->GetDangerType() == DownloadStateInfo::DANGEROUS_FILE); |
| 991 warning_icon_ = rb.GetBitmapNamed(IDR_WARNING); |
| 992 if (ChromeDownloadManagerDelegate::IsExtensionDownload(download_)) { |
| 993 dangerous_label = |
| 994 l10n_util::GetStringUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION); |
| 995 } else { |
| 996 ui::ElideString(rootname, |
| 997 kFileNameMaxLength - extension.length(), |
| 998 &rootname); |
| 999 string16 filename = rootname + ASCIIToUTF16(".") + extension; |
| 1000 filename = base::i18n::GetDisplayStringInLTRDirectionality(filename); |
| 1001 dangerous_label = |
| 1002 l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD, filename); |
| 1003 } |
| 1004 } |
| 1005 |
| 1006 dangerous_download_label_ = new views::Label(dangerous_label); |
| 1007 dangerous_download_label_->SetMultiLine(true); |
| 1008 dangerous_download_label_->SetHorizontalAlignment( |
| 1009 views::Label::ALIGN_LEFT); |
| 1010 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); |
| 1011 AddChildView(dangerous_download_label_); |
| 1012 SizeLabelToMinWidth(); |
| 1013 } |
| 1014 |
1000 gfx::Size DownloadItemView::GetButtonSize() { | 1015 gfx::Size DownloadItemView::GetButtonSize() { |
1001 DCHECK(save_button_ && discard_button_); | 1016 DCHECK(save_button_ && discard_button_); |
1002 gfx::Size size; | 1017 gfx::Size size; |
1003 | 1018 |
1004 // We cache the size when successfully retrieved, not for performance reasons | 1019 // We cache the size when successfully retrieved, not for performance reasons |
1005 // but because if this DownloadItemView is being animated while the tab is | 1020 // but because if this DownloadItemView is being animated while the tab is |
1006 // not showing, the native buttons are not parented and their preferred size | 1021 // not showing, the native buttons are not parented and their preferred size |
1007 // is 0, messing-up the layout. | 1022 // is 0, messing-up the layout. |
1008 if (cached_button_size_.width() != 0) | 1023 if (cached_button_size_.width() != 0) |
1009 return cached_button_size_; | 1024 return cached_button_size_; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 // If the name has changed, notify assistive technology that the name | 1124 // If the name has changed, notify assistive technology that the name |
1110 // has changed so they can announce it immediately. | 1125 // has changed so they can announce it immediately. |
1111 if (new_name != accessible_name_) { | 1126 if (new_name != accessible_name_) { |
1112 accessible_name_ = new_name; | 1127 accessible_name_ = new_name; |
1113 if (GetWidget()) { | 1128 if (GetWidget()) { |
1114 GetWidget()->NotifyAccessibilityEvent( | 1129 GetWidget()->NotifyAccessibilityEvent( |
1115 this, ui::AccessibilityTypes::EVENT_NAME_CHANGED, true); | 1130 this, ui::AccessibilityTypes::EVENT_NAME_CHANGED, true); |
1116 } | 1131 } |
1117 } | 1132 } |
1118 } | 1133 } |
OLD | NEW |