| 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 |