| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/i18n/break_iterator.h" | 13 #include "base/i18n/break_iterator.h" |
| 14 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/strings/sys_string_conversions.h" | 18 #include "base/strings/sys_string_conversions.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/supports_user_data.h" |
| 20 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
| 21 #include "chrome/browser/download/chrome_download_manager_delegate.h" | 22 #include "chrome/browser/download/chrome_download_manager_delegate.h" |
| 22 #include "chrome/browser/download/download_item_model.h" | 23 #include "chrome/browser/download/download_item_model.h" |
| 23 #include "chrome/browser/download/download_stats.h" | 24 #include "chrome/browser/download/download_stats.h" |
| 24 #include "chrome/browser/download/drag_download_item.h" | 25 #include "chrome/browser/download/drag_download_item.h" |
| 26 #include "chrome/browser/prefs/pref_service_syncable.h" |
| 25 #include "chrome/browser/safe_browsing/download_feedback_service.h" | 27 #include "chrome/browser/safe_browsing/download_feedback_service.h" |
| 26 #include "chrome/browser/safe_browsing/download_protection_service.h" | 28 #include "chrome/browser/safe_browsing/download_protection_service.h" |
| 27 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 29 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| 28 #include "chrome/browser/themes/theme_properties.h" | 30 #include "chrome/browser/themes/theme_properties.h" |
| 31 #include "chrome/browser/ui/views/download/download_feedback_dialog_view.h" |
| 29 #include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h" | 32 #include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h" |
| 30 #include "chrome/browser/ui/views/download/download_shelf_view.h" | 33 #include "chrome/browser/ui/views/download/download_shelf_view.h" |
| 31 #include "content/public/browser/download_danger_type.h" | 34 #include "content/public/browser/download_danger_type.h" |
| 32 #include "grit/generated_resources.h" | 35 #include "grit/generated_resources.h" |
| 33 #include "grit/theme_resources.h" | 36 #include "grit/theme_resources.h" |
| 34 #include "third_party/icu/source/common/unicode/uchar.h" | 37 #include "third_party/icu/source/common/unicode/uchar.h" |
| 35 #include "ui/base/accessibility/accessible_view_state.h" | 38 #include "ui/base/accessibility/accessible_view_state.h" |
| 36 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
| 37 #include "ui/base/resource/resource_bundle.h" | 40 #include "ui/base/resource/resource_bundle.h" |
| 38 #include "ui/base/theme_provider.h" | 41 #include "ui/base/theme_provider.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 // downloaded item. | 84 // downloaded item. |
| 82 static const int kDisabledOnOpenDuration = 3000; | 85 static const int kDisabledOnOpenDuration = 3000; |
| 83 | 86 |
| 84 // Darken light-on-dark download status text by 20% before drawing, thus | 87 // Darken light-on-dark download status text by 20% before drawing, thus |
| 85 // creating a "muted" version of title text for both dark-on-light and | 88 // creating a "muted" version of title text for both dark-on-light and |
| 86 // light-on-dark themes. | 89 // light-on-dark themes. |
| 87 static const double kDownloadItemLuminanceMod = 0.8; | 90 static const double kDownloadItemLuminanceMod = 0.8; |
| 88 | 91 |
| 89 using content::DownloadItem; | 92 using content::DownloadItem; |
| 90 | 93 |
| 94 const void* kDialogStatusKey = &kDialogStatusKey; |
| 95 |
| 96 class DialogStatusData : public base::SupportsUserData::Data { |
| 97 public: |
| 98 DialogStatusData() : currently_shown_(false) {} |
| 99 virtual ~DialogStatusData() {} |
| 100 bool currently_shown() const { return currently_shown_; } |
| 101 void set_currently_shown(bool shown) { currently_shown_ = shown; } |
| 102 private: |
| 103 bool currently_shown_; |
| 104 }; |
| 105 |
| 91 DownloadItemView::DownloadItemView(DownloadItem* download_item, | 106 DownloadItemView::DownloadItemView(DownloadItem* download_item, |
| 92 DownloadShelfView* parent) | 107 DownloadShelfView* parent) |
| 93 : warning_icon_(NULL), | 108 : warning_icon_(NULL), |
| 94 shelf_(parent), | 109 shelf_(parent), |
| 95 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), | 110 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), |
| 96 body_state_(NORMAL), | 111 body_state_(NORMAL), |
| 97 drop_down_state_(NORMAL), | 112 drop_down_state_(NORMAL), |
| 98 mode_(NORMAL_MODE), | 113 mode_(NORMAL_MODE), |
| 99 progress_angle_(DownloadShelf::kStartAngleDegrees), | 114 progress_angle_(DownloadShelf::kStartAngleDegrees), |
| 100 drop_down_pressed_(false), | 115 drop_down_pressed_(false), |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 return; | 558 return; |
| 544 } | 559 } |
| 545 | 560 |
| 546 // WARNING: all end states after this point delete |this|. | 561 // WARNING: all end states after this point delete |this|. |
| 547 DCHECK_EQ(discard_button_, sender); | 562 DCHECK_EQ(discard_button_, sender); |
| 548 if (model_.IsMalicious()) { | 563 if (model_.IsMalicious()) { |
| 549 UMA_HISTOGRAM_LONG_TIMES("clickjacking.dismiss_download", warning_duration); | 564 UMA_HISTOGRAM_LONG_TIMES("clickjacking.dismiss_download", warning_duration); |
| 550 shelf_->RemoveDownloadView(this); | 565 shelf_->RemoveDownloadView(this); |
| 551 return; | 566 return; |
| 552 } | 567 } |
| 553 if (model_.ShouldAllowDownloadFeedback() && BeginDownloadFeedback()) | 568 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration); |
| 569 if (model_.ShouldAllowDownloadFeedback() && |
| 570 !shelf_->browser()->profile()->IsOffTheRecord()) { |
| 571 DownloadFeedbackDialogView::DownloadReportingStatus pref_value = |
| 572 static_cast<DownloadFeedbackDialogView::DownloadReportingStatus>( |
| 573 shelf_->browser()->profile()->GetPrefs()->GetInteger( |
| 574 prefs::kSafeBrowsingDownloadReportingEnabled)); |
| 575 DialogStatusData* data = static_cast<DialogStatusData*>( |
| 576 shelf_->browser()->profile()->GetUserData(kDialogStatusKey)); |
| 577 if (data == NULL) { |
| 578 data = new DialogStatusData(); |
| 579 shelf_->browser()->profile()->SetUserData(kDialogStatusKey, data); |
| 580 } |
| 581 switch (pref_value) { |
| 582 case DownloadFeedbackDialogView::kDialogNotYetShown: |
| 583 // Need to check if the dialog is already displayed for this profile. |
| 584 // If it is, default to discarding the file and don't generate a second |
| 585 // instance of the dialog. |
| 586 if (data->currently_shown() == false) { |
| 587 data->set_currently_shown(true); |
| 588 DownloadFeedbackDialogView::Show( |
| 589 shelf_->get_parent()->GetNativeWindow(), |
| 590 shelf_->browser()->profile(), |
| 591 base::Bind( |
| 592 &DownloadItemView::PossiblySubmitDownloadToFeedbackService, |
| 593 weak_ptr_factory_.GetWeakPtr())); |
| 594 } else { |
| 595 PossiblySubmitDownloadToFeedbackService( |
| 596 DownloadFeedbackDialogView::kDialogDecisionPending); |
| 597 } |
| 598 break; |
| 599 |
| 600 case DownloadFeedbackDialogView::kDownloadReportingEnabled: |
| 601 case DownloadFeedbackDialogView::kDownloadReportingDisabled: |
| 602 PossiblySubmitDownloadToFeedbackService(pref_value); |
| 603 break; |
| 604 |
| 605 case DownloadFeedbackDialogView::kDialogDecisionPending: |
| 606 case DownloadFeedbackDialogView::kMaxValue: |
| 607 NOTREACHED(); |
| 608 } |
| 554 return; | 609 return; |
| 555 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration); | 610 } |
| 556 download()->Remove(); | 611 download()->Remove(); |
| 557 } | 612 } |
| 558 | 613 |
| 559 void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) { | 614 void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) { |
| 560 // We don't care if what animation (body button/drop button/complete), | 615 // We don't care if what animation (body button/drop button/complete), |
| 561 // is calling back, as they all have to go through the same paint call. | 616 // is calling back, as they all have to go through the same paint call. |
| 562 SchedulePaint(); | 617 SchedulePaint(); |
| 563 } | 618 } |
| 564 | 619 |
| 565 void DownloadItemView::OnPaint(gfx::Canvas* canvas) { | 620 void DownloadItemView::OnPaint(gfx::Canvas* canvas) { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 void DownloadItemView::OpenDownload() { | 938 void DownloadItemView::OpenDownload() { |
| 884 DCHECK(!IsShowingWarningDialog()); | 939 DCHECK(!IsShowingWarningDialog()); |
| 885 // We're interested in how long it takes users to open downloads. If they | 940 // We're interested in how long it takes users to open downloads. If they |
| 886 // open downloads super quickly, we should be concerned about clickjacking. | 941 // open downloads super quickly, we should be concerned about clickjacking. |
| 887 UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download", | 942 UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download", |
| 888 base::Time::Now() - creation_time_); | 943 base::Time::Now() - creation_time_); |
| 889 download()->OpenDownload(); | 944 download()->OpenDownload(); |
| 890 UpdateAccessibleName(); | 945 UpdateAccessibleName(); |
| 891 } | 946 } |
| 892 | 947 |
| 893 bool DownloadItemView::BeginDownloadFeedback() { | 948 bool DownloadItemView::SubmitDownloadToFeedbackService() { |
| 894 #if defined(FULL_SAFE_BROWSING) | 949 #if defined(FULL_SAFE_BROWSING) |
| 895 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); | 950 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); |
| 896 if (!sb_service) | 951 if (!sb_service) |
| 897 return false; | 952 return false; |
| 898 safe_browsing::DownloadProtectionService* download_protection_service = | 953 safe_browsing::DownloadProtectionService* download_protection_service = |
| 899 sb_service->download_protection_service(); | 954 sb_service->download_protection_service(); |
| 900 if (!download_protection_service) | 955 if (!download_protection_service) |
| 901 return false; | 956 return false; |
| 902 base::TimeDelta warning_duration = base::TimeDelta(); | |
| 903 if (!time_download_warning_shown_.is_null()) | |
| 904 warning_duration = base::Time::Now() - time_download_warning_shown_; | |
| 905 UMA_HISTOGRAM_LONG_TIMES("clickjacking.report_and_discard_download", | |
| 906 warning_duration); | |
| 907 download_protection_service->feedback_service()->BeginFeedbackForDownload( | 957 download_protection_service->feedback_service()->BeginFeedbackForDownload( |
| 908 download()); | 958 download()); |
| 909 // WARNING: we are deleted at this point. Don't access 'this'. | 959 // WARNING: we are deleted at this point. Don't access 'this'. |
| 910 return true; | 960 return true; |
| 911 #else | 961 #else |
| 912 NOTREACHED(); | 962 NOTREACHED(); |
| 913 return false; | 963 return false; |
| 914 #endif | 964 #endif |
| 915 } | 965 } |
| 916 | 966 |
| 967 void DownloadItemView::PossiblySubmitDownloadToFeedbackService( |
| 968 DownloadFeedbackDialogView::DownloadReportingStatus status) { |
| 969 if (status != DownloadFeedbackDialogView::kDialogDecisionPending) { |
| 970 DialogStatusData* data = static_cast<DialogStatusData*>( |
| 971 shelf_->browser()->profile()->GetUserData(kDialogStatusKey)); |
| 972 DCHECK(data); |
| 973 data->set_currently_shown(false); |
| 974 } |
| 975 |
| 976 if (status != DownloadFeedbackDialogView::kDownloadReportingEnabled || |
| 977 !SubmitDownloadToFeedbackService()) { |
| 978 download()->Remove(); |
| 979 } |
| 980 // WARNING: 'this' is deleted at this point. Don't access 'this'. |
| 981 } |
| 982 |
| 917 void DownloadItemView::LoadIcon() { | 983 void DownloadItemView::LoadIcon() { |
| 918 IconManager* im = g_browser_process->icon_manager(); | 984 IconManager* im = g_browser_process->icon_manager(); |
| 919 last_download_item_path_ = download()->GetTargetFilePath(); | 985 last_download_item_path_ = download()->GetTargetFilePath(); |
| 920 im->LoadIcon(last_download_item_path_, | 986 im->LoadIcon(last_download_item_path_, |
| 921 IconLoader::SMALL, | 987 IconLoader::SMALL, |
| 922 base::Bind(&DownloadItemView::OnExtractIconComplete, | 988 base::Bind(&DownloadItemView::OnExtractIconComplete, |
| 923 base::Unretained(this)), | 989 base::Unretained(this)), |
| 924 &cancelable_task_tracker_); | 990 &cancelable_task_tracker_); |
| 925 } | 991 } |
| 926 | 992 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 body_state_ = NORMAL; | 1200 body_state_ = NORMAL; |
| 1135 drop_down_state_ = NORMAL; | 1201 drop_down_state_ = NORMAL; |
| 1136 if (mode_ == DANGEROUS_MODE) { | 1202 if (mode_ == DANGEROUS_MODE) { |
| 1137 save_button_ = new views::LabelButton( | 1203 save_button_ = new views::LabelButton( |
| 1138 this, model_.GetWarningConfirmButtonText()); | 1204 this, model_.GetWarningConfirmButtonText()); |
| 1139 save_button_->SetStyle(views::Button::STYLE_BUTTON); | 1205 save_button_->SetStyle(views::Button::STYLE_BUTTON); |
| 1140 AddChildView(save_button_); | 1206 AddChildView(save_button_); |
| 1141 } | 1207 } |
| 1142 int discard_button_message = model_.IsMalicious() ? | 1208 int discard_button_message = model_.IsMalicious() ? |
| 1143 IDS_DISMISS_DOWNLOAD : IDS_DISCARD_DOWNLOAD; | 1209 IDS_DISMISS_DOWNLOAD : IDS_DISCARD_DOWNLOAD; |
| 1144 if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback()) | |
| 1145 discard_button_message = IDS_REPORT_AND_DISCARD_DOWNLOAD; | |
| 1146 discard_button_ = new views::LabelButton( | 1210 discard_button_ = new views::LabelButton( |
| 1147 this, l10n_util::GetStringUTF16(discard_button_message)); | 1211 this, l10n_util::GetStringUTF16(discard_button_message)); |
| 1148 discard_button_->SetStyle(views::Button::STYLE_BUTTON); | 1212 discard_button_->SetStyle(views::Button::STYLE_BUTTON); |
| 1149 AddChildView(discard_button_); | 1213 AddChildView(discard_button_); |
| 1150 | 1214 |
| 1151 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1215 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 1152 switch (danger_type) { | 1216 switch (danger_type) { |
| 1153 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: | 1217 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: |
| 1154 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: | 1218 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: |
| 1155 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: | 1219 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 void DownloadItemView::AnimateStateTransition(State from, State to, | 1383 void DownloadItemView::AnimateStateTransition(State from, State to, |
| 1320 gfx::SlideAnimation* animation) { | 1384 gfx::SlideAnimation* animation) { |
| 1321 if (from == NORMAL && to == HOT) { | 1385 if (from == NORMAL && to == HOT) { |
| 1322 animation->Show(); | 1386 animation->Show(); |
| 1323 } else if (from == HOT && to == NORMAL) { | 1387 } else if (from == HOT && to == NORMAL) { |
| 1324 animation->Hide(); | 1388 animation->Hide(); |
| 1325 } else if (from != to) { | 1389 } else if (from != to) { |
| 1326 animation->Reset((to == HOT) ? 1.0 : 0.0); | 1390 animation->Reset((to == HOT) ? 1.0 : 0.0); |
| 1327 } | 1391 } |
| 1328 } | 1392 } |
| OLD | NEW |