Chromium Code Reviews| 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> |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 : shelf_(parent), | 176 : shelf_(parent), |
| 177 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), | 177 status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)), |
| 178 dropdown_state_(NORMAL), | 178 dropdown_state_(NORMAL), |
| 179 mode_(NORMAL_MODE), | 179 mode_(NORMAL_MODE), |
| 180 dragging_(false), | 180 dragging_(false), |
| 181 starting_drag_(false), | 181 starting_drag_(false), |
| 182 model_(download_item), | 182 model_(download_item), |
| 183 save_button_(nullptr), | 183 save_button_(nullptr), |
| 184 discard_button_(nullptr), | 184 discard_button_(nullptr), |
| 185 dropdown_button_(new DropDownButton(this)), | 185 dropdown_button_(new DropDownButton(this)), |
| 186 dangerous_download_label_(nullptr), | 186 dangerous_download_label_(new views::Label()), |
| 187 dangerous_download_label_sized_(false), | 187 dangerous_download_label_sized_(false), |
| 188 disabled_while_opening_(false), | 188 disabled_while_opening_(false), |
| 189 creation_time_(base::Time::Now()), | 189 creation_time_(base::Time::Now()), |
| 190 time_download_warning_shown_(base::Time()), | 190 time_download_warning_shown_(base::Time()), |
| 191 weak_ptr_factory_(this) { | 191 weak_ptr_factory_(this) { |
| 192 SetInkDropMode(InkDropMode::ON); | 192 SetInkDropMode(InkDropMode::ON); |
| 193 DCHECK(download()); | 193 DCHECK(download()); |
| 194 download()->AddObserver(this); | 194 download()->AddObserver(this); |
| 195 set_context_menu_controller(this); | 195 set_context_menu_controller(this); |
| 196 | 196 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 216 | 216 |
| 217 DownloadItemView::~DownloadItemView() { | 217 DownloadItemView::~DownloadItemView() { |
| 218 StopDownloadProgress(); | 218 StopDownloadProgress(); |
| 219 download()->RemoveObserver(this); | 219 download()->RemoveObserver(this); |
| 220 | 220 |
| 221 // ExperienceSampling: If the user took no action to remove the warning | 221 // ExperienceSampling: If the user took no action to remove the warning |
| 222 // before it disappeared, then the user effectively dismissed the download | 222 // before it disappeared, then the user effectively dismissed the download |
| 223 // without keeping it. | 223 // without keeping it. |
| 224 if (sampling_event_) | 224 if (sampling_event_) |
| 225 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kIgnore); | 225 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kIgnore); |
| 226 | |
| 227 delete dangerous_download_label_; | |
| 228 dangerous_download_label_ = nullptr; | |
|
Peter Kasting
2016/12/08 05:10:23
This potentially double-frees. Views is expecting
Jialiu Lin
2016/12/08 07:47:40
Ack.
| |
| 226 } | 229 } |
| 227 | 230 |
| 228 // Progress animation handlers. | 231 // Progress animation handlers. |
| 229 | 232 |
| 230 void DownloadItemView::StartDownloadProgress() { | 233 void DownloadItemView::StartDownloadProgress() { |
| 231 if (progress_timer_.IsRunning()) | 234 if (progress_timer_.IsRunning()) |
| 232 return; | 235 return; |
| 233 progress_start_time_ = base::TimeTicks::Now(); | 236 progress_start_time_ = base::TimeTicks::Now(); |
| 234 progress_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( | 237 progress_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( |
| 235 DownloadShelf::kProgressRateMs), | 238 DownloadShelf::kProgressRateMs), |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 base::string16 new_tip = model_.GetTooltipText(font_list_, kTooltipMaxWidth); | 339 base::string16 new_tip = model_.GetTooltipText(font_list_, kTooltipMaxWidth); |
| 337 if (new_tip != tooltip_text_) { | 340 if (new_tip != tooltip_text_) { |
| 338 tooltip_text_ = new_tip; | 341 tooltip_text_ = new_tip; |
| 339 TooltipTextChanged(); | 342 TooltipTextChanged(); |
| 340 } | 343 } |
| 341 | 344 |
| 342 UpdateAccessibleName(); | 345 UpdateAccessibleName(); |
| 343 } | 346 } |
| 344 | 347 |
| 345 void DownloadItemView::OnDownloadDestroyed(DownloadItem* download) { | 348 void DownloadItemView::OnDownloadDestroyed(DownloadItem* download) { |
| 346 shelf_->RemoveDownloadView(this); // This will delete us! | 349 if (shelf_) |
| 350 shelf_->RemoveDownloadView(this); // This will delete us! | |
| 347 } | 351 } |
| 348 | 352 |
| 349 void DownloadItemView::OnDownloadOpened(DownloadItem* download) { | 353 void DownloadItemView::OnDownloadOpened(DownloadItem* download) { |
| 350 disabled_while_opening_ = true; | 354 disabled_while_opening_ = true; |
| 351 SetEnabled(false); | 355 SetEnabled(false); |
| 352 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 356 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 353 FROM_HERE, | 357 FROM_HERE, |
| 354 base::Bind(&DownloadItemView::Reenable, weak_ptr_factory_.GetWeakPtr()), | 358 base::Bind(&DownloadItemView::Reenable, weak_ptr_factory_.GetWeakPtr()), |
| 355 base::TimeDelta::FromMilliseconds(kDisabledOnOpenDuration)); | 359 base::TimeDelta::FromMilliseconds(kDisabledOnOpenDuration)); |
| 356 | 360 |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 788 DownloadCommands::Command download_command, | 792 DownloadCommands::Command download_command, |
| 789 bool feedback_enabled) { | 793 bool feedback_enabled) { |
| 790 if (feedback_enabled && SubmitDownloadToFeedbackService(download_command)) | 794 if (feedback_enabled && SubmitDownloadToFeedbackService(download_command)) |
| 791 return; | 795 return; |
| 792 | 796 |
| 793 DownloadCommands(download()).ExecuteCommand(download_command); | 797 DownloadCommands(download()).ExecuteCommand(download_command); |
| 794 // WARNING: 'this' is deleted at this point. Don't access 'this'. | 798 // WARNING: 'this' is deleted at this point. Don't access 'this'. |
| 795 } | 799 } |
| 796 | 800 |
| 797 void DownloadItemView::LoadIcon() { | 801 void DownloadItemView::LoadIcon() { |
| 798 IconManager* im = g_browser_process->icon_manager(); | 802 // If there is no download shelf assigned, this is called in a test, then no |
| 799 last_download_item_path_ = download()->GetTargetFilePath(); | 803 // need to load the icon. |
|
Peter Kasting
2016/12/08 05:10:23
Does it actually hurt to load this icon in a test?
Jialiu Lin
2016/12/08 07:47:40
Unfortunately LoadIcon function involves shelf_. S
| |
| 800 im->LoadIcon(last_download_item_path_, IconLoader::SMALL, | 804 if (shelf_) { |
| 801 base::Bind(&DownloadItemView::OnExtractIconComplete, | 805 IconManager* im = g_browser_process->icon_manager(); |
| 802 base::Unretained(this)), | 806 last_download_item_path_ = download()->GetTargetFilePath(); |
| 803 &cancelable_task_tracker_); | 807 im->LoadIcon(last_download_item_path_, IconLoader::SMALL, |
| 808 base::Bind(&DownloadItemView::OnExtractIconComplete, | |
| 809 base::Unretained(this)), | |
| 810 &cancelable_task_tracker_); | |
| 811 } | |
| 804 } | 812 } |
| 805 | 813 |
| 806 void DownloadItemView::LoadIconIfItemPathChanged() { | 814 void DownloadItemView::LoadIconIfItemPathChanged() { |
| 807 base::FilePath current_download_path = download()->GetTargetFilePath(); | 815 base::FilePath current_download_path = download()->GetTargetFilePath(); |
| 808 if (last_download_item_path_ == current_download_path) | 816 if (last_download_item_path_ == current_download_path) |
| 809 return; | 817 return; |
| 810 | 818 |
| 811 LoadIcon(); | 819 LoadIcon(); |
| 812 } | 820 } |
| 813 | 821 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 963 save_button_ = | 971 save_button_ = |
| 964 views::MdTextButton::Create(this, model_.GetWarningConfirmButtonText()); | 972 views::MdTextButton::Create(this, model_.GetWarningConfirmButtonText()); |
| 965 AddChildView(save_button_); | 973 AddChildView(save_button_); |
| 966 } | 974 } |
| 967 discard_button_ = views::MdTextButton::Create( | 975 discard_button_ = views::MdTextButton::Create( |
| 968 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); | 976 this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD)); |
| 969 AddChildView(discard_button_); | 977 AddChildView(discard_button_); |
| 970 | 978 |
| 971 base::string16 dangerous_label = | 979 base::string16 dangerous_label = |
| 972 model_.GetWarningText(font_list_, kTextWidth); | 980 model_.GetWarningText(font_list_, kTextWidth); |
| 973 dangerous_download_label_ = new views::Label(dangerous_label); | 981 dangerous_download_label_->SetText(dangerous_label); |
| 974 dangerous_download_label_->SetMultiLine(true); | 982 dangerous_download_label_->SetMultiLine(true); |
| 975 dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 983 dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 976 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); | 984 dangerous_download_label_->SetAutoColorReadabilityEnabled(false); |
| 977 AddChildView(dangerous_download_label_); | 985 AddChildView(dangerous_download_label_); |
| 978 SizeLabelToMinWidth(); | 986 SizeLabelToMinWidth(); |
| 979 | 987 |
| 980 dropdown_button_->SetVisible(mode_ == MALICIOUS_MODE); | 988 dropdown_button_->SetVisible(mode_ == MALICIOUS_MODE); |
| 981 } | 989 } |
| 982 | 990 |
| 983 gfx::ImageSkia DownloadItemView::GetWarningIcon() { | 991 gfx::ImageSkia DownloadItemView::GetWarningIcon() { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1009 return size; | 1017 return size; |
| 1010 } | 1018 } |
| 1011 | 1019 |
| 1012 // This method computes the minimum width of the label for displaying its text | 1020 // This method computes the minimum width of the label for displaying its text |
| 1013 // on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the | 1021 // on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the |
| 1014 // configuration with minimum width. | 1022 // configuration with minimum width. |
| 1015 void DownloadItemView::SizeLabelToMinWidth() { | 1023 void DownloadItemView::SizeLabelToMinWidth() { |
| 1016 if (dangerous_download_label_sized_) | 1024 if (dangerous_download_label_sized_) |
| 1017 return; | 1025 return; |
| 1018 | 1026 |
| 1027 dangerous_download_label_->SetSize(GetLabelSize()); | |
| 1028 dangerous_download_label_sized_ = true; | |
| 1029 } | |
| 1030 | |
| 1031 gfx::Size DownloadItemView::GetLabelSize() { | |
| 1032 gfx::Size size = dangerous_download_label_->GetPreferredSize(); | |
| 1033 | |
| 1034 // If the label is already narrower than kDangerousTextWidth, we don't need to | |
| 1035 // linebreak it, as it will fit on a single line. | |
| 1036 if (size.width() <= kDangerousTextWidth) | |
| 1037 return size; | |
| 1038 | |
| 1019 base::string16 label_text = dangerous_download_label_->text(); | 1039 base::string16 label_text = dangerous_download_label_->text(); |
| 1020 base::TrimWhitespace(label_text, base::TRIM_ALL, &label_text); | 1040 base::TrimWhitespace(label_text, base::TRIM_ALL, &label_text); |
| 1021 DCHECK_EQ(base::string16::npos, label_text.find('\n')); | 1041 DCHECK_EQ(base::string16::npos, label_text.find('\n')); |
| 1022 | 1042 |
| 1023 // Make the label big so that GetPreferredSize() is not constrained by the | 1043 // Make the label big so that GetPreferredSize() is not constrained by the |
| 1024 // current width. | 1044 // current width. |
| 1025 dangerous_download_label_->SetBounds(0, 0, 1000, 1000); | 1045 dangerous_download_label_->SetBounds(0, 0, 1000, 1000); |
| 1026 | 1046 |
| 1027 // Use a const string from here. BreakIterator requies that text.data() not | 1047 // Use a const string from here. BreakIterator requies that text.data() not |
| 1028 // change during its lifetime. | 1048 // change during its lifetime. |
| 1029 const base::string16 original_text(label_text); | 1049 const base::string16 original_text(label_text); |
| 1030 // Using BREAK_WORD can work in most cases, but it can also break | 1050 // Using BREAK_WORD can work in most cases, but it can also break |
| 1031 // lines where it should not. Using BREAK_LINE is safer although | 1051 // lines where it should not. Using BREAK_LINE is safer although |
| 1032 // slower for Chinese/Japanese. This is not perf-critical at all, though. | 1052 // slower for Chinese/Japanese. This is not perf-critical at all, though. |
| 1033 base::i18n::BreakIterator iter(original_text, | 1053 base::i18n::BreakIterator iter(original_text, |
| 1034 base::i18n::BreakIterator::BREAK_LINE); | 1054 base::i18n::BreakIterator::BREAK_LINE); |
| 1035 bool status = iter.Init(); | 1055 bool status = iter.Init(); |
| 1036 DCHECK(status); | 1056 DCHECK(status); |
| 1037 | 1057 |
| 1058 // Go through the string and try each line break (starting with no line break) | |
| 1059 // searching for the optimal line break position. Stop if we find one that | |
| 1060 // yields minimum label width. | |
| 1038 base::string16 prev_text = original_text; | 1061 base::string16 prev_text = original_text; |
| 1039 gfx::Size size = dangerous_download_label_->GetPreferredSize(); | 1062 for (gfx::Size min_width_size = size; iter.Advance(); min_width_size = size) { |
| 1040 int min_width = size.width(); | |
| 1041 | |
| 1042 // Go through the string and try each line break (starting with no line break) | |
| 1043 // searching for the optimal line break position. Stop if we find one that | |
| 1044 // yields one that is less than kDangerousTextWidth wide. This is to prevent | |
| 1045 // a short string (e.g.: "This file is malicious") from being broken up | |
| 1046 // unnecessarily. | |
| 1047 while (iter.Advance() && min_width > kDangerousTextWidth) { | |
| 1048 size_t pos = iter.pos(); | 1063 size_t pos = iter.pos(); |
| 1049 if (pos >= original_text.length()) | 1064 if (pos >= original_text.length()) |
| 1050 break; | 1065 break; |
| 1051 base::string16 current_text = original_text; | 1066 base::string16 current_text = original_text; |
| 1052 // This can be a low surrogate codepoint, but u_isUWhiteSpace will | 1067 // This can be a low surrogate codepoint, but u_isUWhiteSpace will |
| 1053 // return false and inserting a new line after a surrogate pair | 1068 // return false and inserting a new line after a surrogate pair |
| 1054 // is perfectly ok. | 1069 // is perfectly ok. |
| 1055 base::char16 line_end_char = current_text[pos - 1]; | 1070 base::char16 line_end_char = current_text[pos - 1]; |
| 1056 if (u_isUWhiteSpace(line_end_char)) | 1071 if (u_isUWhiteSpace(line_end_char)) |
| 1057 current_text.replace(pos - 1, 1, 1, base::char16('\n')); | 1072 current_text.replace(pos - 1, 1, 1, base::char16('\n')); |
| 1058 else | 1073 else |
| 1059 current_text.insert(pos, 1, base::char16('\n')); | 1074 current_text.insert(pos, 1, base::char16('\n')); |
| 1060 dangerous_download_label_->SetText(current_text); | 1075 dangerous_download_label_->SetText(current_text); |
| 1061 size = dangerous_download_label_->GetPreferredSize(); | 1076 size = dangerous_download_label_->GetPreferredSize(); |
| 1062 | 1077 |
| 1063 // If the width is growing again, it means we passed the optimal width spot. | 1078 // If the width is growing again, it means we passed the optimal width spot. |
| 1064 if (size.width() > min_width) { | 1079 if (size.width() > min_width_size.width()) { |
| 1065 dangerous_download_label_->SetText(prev_text); | 1080 dangerous_download_label_->SetText(prev_text); |
| 1066 break; | 1081 return min_width_size; |
| 1067 } else { | |
| 1068 min_width = size.width(); | |
| 1069 } | 1082 } |
| 1070 prev_text = current_text; | 1083 prev_text = current_text; |
| 1071 } | 1084 } |
| 1072 | 1085 return size; |
| 1073 dangerous_download_label_->SetSize(size); | |
| 1074 dangerous_download_label_sized_ = true; | |
| 1075 } | 1086 } |
| 1076 | 1087 |
| 1077 void DownloadItemView::Reenable() { | 1088 void DownloadItemView::Reenable() { |
| 1078 disabled_while_opening_ = false; | 1089 disabled_while_opening_ = false; |
| 1079 SetEnabled(true); // Triggers a repaint. | 1090 SetEnabled(true); // Triggers a repaint. |
| 1080 } | 1091 } |
| 1081 | 1092 |
| 1082 void DownloadItemView::ReleaseDropdown() { | 1093 void DownloadItemView::ReleaseDropdown() { |
| 1083 SetDropdownState(NORMAL); | 1094 SetDropdownState(NORMAL); |
| 1084 } | 1095 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 SchedulePaint(); | 1130 SchedulePaint(); |
| 1120 } | 1131 } |
| 1121 | 1132 |
| 1122 SkColor DownloadItemView::GetTextColor() const { | 1133 SkColor DownloadItemView::GetTextColor() const { |
| 1123 return GetTextColorForThemeProvider(GetThemeProvider()); | 1134 return GetTextColorForThemeProvider(GetThemeProvider()); |
| 1124 } | 1135 } |
| 1125 | 1136 |
| 1126 SkColor DownloadItemView::GetDimmedTextColor() const { | 1137 SkColor DownloadItemView::GetDimmedTextColor() const { |
| 1127 return SkColorSetA(GetTextColor(), 0xC7); | 1138 return SkColorSetA(GetTextColor(), 0xC7); |
| 1128 } | 1139 } |
| OLD | NEW |