Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / download / download_item_model.cc
blobcd741a43ffda67aef224680b8be369fd7845c2a9
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
3 // found in the LICENSE file.
5 #include "chrome/browser/download/download_item_model.h"
7 #include "base/i18n/number_formatting.h"
8 #include "base/i18n/rtl.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/supports_user_data.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/download/chrome_download_manager_delegate.h"
16 #include "chrome/browser/download/download_crx_util.h"
17 #include "chrome/browser/download/download_service.h"
18 #include "chrome/browser/download/download_service_factory.h"
19 #include "chrome/browser/download/download_stats.h"
20 #include "chrome/browser/safe_browsing/download_feedback_service.h"
21 #include "content/public/browser/download_danger_type.h"
22 #include "content/public/browser/download_interrupt_reasons.h"
23 #include "content/public/browser/download_item.h"
24 #include "grit/chromium_strings.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/l10n/time_format.h"
28 #include "ui/base/text/bytes_formatting.h"
29 #include "ui/gfx/text_elider.h"
31 using base::TimeDelta;
32 using content::DownloadItem;
34 namespace {
36 // Per DownloadItem data used by DownloadItemModel. The model doesn't keep any
37 // state since there could be multiple models associated with a single
38 // DownloadItem, and the lifetime of the model is shorter than the DownloadItem.
39 class DownloadItemModelData : public base::SupportsUserData::Data {
40 public:
41 // Get the DownloadItemModelData object for |download|. Returns NULL if
42 // there's no model data.
43 static const DownloadItemModelData* Get(const DownloadItem* download);
45 // Get the DownloadItemModelData object for |download|. Creates a model data
46 // object if not found. Always returns a non-NULL pointer, unless OOM.
47 static DownloadItemModelData* GetOrCreate(DownloadItem* download);
49 bool should_show_in_shelf() const { return should_show_in_shelf_; }
50 void set_should_show_in_shelf(bool should_show_in_shelf) {
51 should_show_in_shelf_ = should_show_in_shelf;
54 bool should_notify_ui() const { return should_notify_ui_; }
55 void set_should_notify_ui(bool should_notify_ui) {
56 should_notify_ui_ = should_notify_ui;
59 bool should_prefer_opening_in_browser() const {
60 return should_prefer_opening_in_browser_;
62 void set_should_prefer_opening_in_browser(bool preference) {
63 should_prefer_opening_in_browser_ = preference;
66 private:
67 DownloadItemModelData();
68 virtual ~DownloadItemModelData() {}
70 static const char kKey[];
72 // Whether the download should be displayed in the download shelf. True by
73 // default.
74 bool should_show_in_shelf_;
76 // Whether the UI should be notified when the download is ready to be
77 // presented.
78 bool should_notify_ui_;
80 // Whether the download should be opened in the browser vs. the system handler
81 // for the file type.
82 bool should_prefer_opening_in_browser_;
85 // static
86 const char DownloadItemModelData::kKey[] = "DownloadItemModelData key";
88 // static
89 const DownloadItemModelData* DownloadItemModelData::Get(
90 const DownloadItem* download) {
91 return static_cast<const DownloadItemModelData*>(download->GetUserData(kKey));
94 // static
95 DownloadItemModelData* DownloadItemModelData::GetOrCreate(
96 DownloadItem* download) {
97 DownloadItemModelData* data =
98 static_cast<DownloadItemModelData*>(download->GetUserData(kKey));
99 if (data == NULL) {
100 data = new DownloadItemModelData();
101 download->SetUserData(kKey, data);
103 return data;
106 DownloadItemModelData::DownloadItemModelData()
107 : should_show_in_shelf_(true),
108 should_notify_ui_(false),
109 should_prefer_opening_in_browser_(false) {
112 base::string16 InterruptReasonStatusMessage(int reason) {
113 int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
115 switch (static_cast<content::DownloadInterruptReason>(reason)) {
116 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
117 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_ACCESS_DENIED;
118 break;
119 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
120 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_DISK_FULL;
121 break;
122 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
123 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_PATH_TOO_LONG;
124 break;
125 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
126 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_LARGE;
127 break;
128 case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
129 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_VIRUS;
130 break;
131 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
132 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_TEMPORARY_PROBLEM;
133 break;
134 case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
135 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_BLOCKED;
136 break;
137 case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
138 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SECURITY_CHECK_FAILED;
139 break;
140 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
141 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_SHORT;
142 break;
143 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
144 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
145 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_ERROR;
146 break;
147 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
148 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_TIMEOUT;
149 break;
150 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
151 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_DISCONNECTED;
152 break;
153 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
154 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_DOWN;
155 break;
156 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
157 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_PROBLEM;
158 break;
159 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
160 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NO_FILE;
161 break;
162 case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
163 string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
164 break;
165 case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
166 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SHUTDOWN;
167 break;
168 case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
169 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_CRASH;
170 break;
171 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
172 NOTREACHED();
173 // fallthrough
174 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
175 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
176 case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
177 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
180 return l10n_util::GetStringUTF16(string_id);
183 base::string16 InterruptReasonMessage(int reason) {
184 int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
185 base::string16 status_text;
187 switch (static_cast<content::DownloadInterruptReason>(reason)) {
188 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
189 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_ACCESS_DENIED;
190 break;
191 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
192 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_DISK_FULL;
193 break;
194 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
195 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_PATH_TOO_LONG;
196 break;
197 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
198 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_LARGE;
199 break;
200 case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
201 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_VIRUS;
202 break;
203 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
204 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_TEMPORARY_PROBLEM;
205 break;
206 case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
207 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_BLOCKED;
208 break;
209 case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
210 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SECURITY_CHECK_FAILED;
211 break;
212 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
213 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_SHORT;
214 break;
215 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
216 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
217 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_ERROR;
218 break;
219 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
220 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_TIMEOUT;
221 break;
222 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
223 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_DISCONNECTED;
224 break;
225 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
226 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_DOWN;
227 break;
228 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
229 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_PROBLEM;
230 break;
231 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
232 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NO_FILE;
233 break;
234 case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
235 string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
236 break;
237 case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
238 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SHUTDOWN;
239 break;
240 case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
241 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_CRASH;
242 break;
243 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
244 NOTREACHED();
245 // fallthrough
246 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
247 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
248 case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
249 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
252 status_text = l10n_util::GetStringUTF16(string_id);
254 return status_text;
257 } // namespace
259 // -----------------------------------------------------------------------------
260 // DownloadItemModel
262 DownloadItemModel::DownloadItemModel(DownloadItem* download)
263 : download_(download) {}
265 DownloadItemModel::~DownloadItemModel() {}
267 base::string16 DownloadItemModel::GetInterruptReasonText() const {
268 if (download_->GetState() != DownloadItem::INTERRUPTED ||
269 download_->GetLastReason() ==
270 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
271 return base::string16();
273 return InterruptReasonMessage(download_->GetLastReason());
276 base::string16 DownloadItemModel::GetStatusText() const {
277 base::string16 status_text;
278 switch (download_->GetState()) {
279 case DownloadItem::IN_PROGRESS:
280 status_text = GetInProgressStatusString();
281 break;
282 case DownloadItem::COMPLETE:
283 if (download_->GetFileExternallyRemoved()) {
284 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_REMOVED);
285 } else {
286 status_text.clear();
288 break;
289 case DownloadItem::CANCELLED:
290 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
291 break;
292 case DownloadItem::INTERRUPTED: {
293 content::DownloadInterruptReason reason = download_->GetLastReason();
294 if (reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
295 base::string16 interrupt_reason = InterruptReasonStatusMessage(reason);
296 status_text = l10n_util::GetStringFUTF16(
297 IDS_DOWNLOAD_STATUS_INTERRUPTED, interrupt_reason);
298 } else {
299 // Same as DownloadItem::CANCELLED.
300 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
302 break;
304 default:
305 NOTREACHED();
308 return status_text;
311 base::string16 DownloadItemModel::GetTabProgressStatusText() const {
312 int64 total = GetTotalBytes();
313 int64 size = download_->GetReceivedBytes();
314 base::string16 received_size = ui::FormatBytes(size);
315 base::string16 amount = received_size;
317 // Adjust both strings for the locale direction since we don't yet know which
318 // string we'll end up using for constructing the final progress string.
319 base::i18n::AdjustStringForLocaleDirection(&amount);
321 if (total) {
322 base::string16 total_text = ui::FormatBytes(total);
323 base::i18n::AdjustStringForLocaleDirection(&total_text);
325 base::i18n::AdjustStringForLocaleDirection(&received_size);
326 amount = l10n_util::GetStringFUTF16(
327 IDS_DOWNLOAD_TAB_PROGRESS_SIZE, received_size, total_text);
328 } else {
329 amount.assign(received_size);
331 int64 current_speed = download_->CurrentSpeed();
332 base::string16 speed_text = ui::FormatSpeed(current_speed);
333 base::i18n::AdjustStringForLocaleDirection(&speed_text);
335 base::TimeDelta remaining;
336 base::string16 time_remaining;
337 if (download_->IsPaused()) {
338 time_remaining = l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED);
339 } else if (download_->TimeRemaining(&remaining)) {
340 time_remaining = ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
341 ui::TimeFormat::LENGTH_SHORT,
342 remaining);
345 if (time_remaining.empty()) {
346 base::i18n::AdjustStringForLocaleDirection(&amount);
347 return l10n_util::GetStringFUTF16(
348 IDS_DOWNLOAD_TAB_PROGRESS_STATUS_TIME_UNKNOWN, speed_text, amount);
350 return l10n_util::GetStringFUTF16(
351 IDS_DOWNLOAD_TAB_PROGRESS_STATUS, speed_text, amount, time_remaining);
354 base::string16 DownloadItemModel::GetTooltipText(const gfx::FontList& font_list,
355 int max_width) const {
356 base::string16 tooltip = gfx::ElideFilename(
357 download_->GetFileNameToReportUser(), font_list, max_width);
358 content::DownloadInterruptReason reason = download_->GetLastReason();
359 if (download_->GetState() == DownloadItem::INTERRUPTED &&
360 reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
361 tooltip += base::ASCIIToUTF16("\n");
362 tooltip += gfx::ElideText(InterruptReasonStatusMessage(reason),
363 font_list, max_width, gfx::ELIDE_AT_END);
365 return tooltip;
368 base::string16 DownloadItemModel::GetWarningText(const gfx::FontList& font_list,
369 int base_width) const {
370 // Should only be called if IsDangerous().
371 DCHECK(IsDangerous());
372 base::string16 elided_filename =
373 gfx::ElideFilename(download_->GetFileNameToReportUser(), font_list,
374 base_width);
375 switch (download_->GetDangerType()) {
376 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
377 return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
379 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
380 if (download_crx_util::IsExtensionDownload(*download_)) {
381 return l10n_util::GetStringUTF16(
382 IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
383 } else {
384 return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
385 elided_filename);
388 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
389 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
390 return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
391 elided_filename);
393 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
394 return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
395 elided_filename);
397 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
398 return l10n_util::GetStringFUTF16(
399 IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS, elided_filename);
401 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
402 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
403 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
404 case content::DOWNLOAD_DANGER_TYPE_MAX: {
405 break;
408 NOTREACHED();
409 return base::string16();
412 base::string16 DownloadItemModel::GetWarningConfirmButtonText() const {
413 // Should only be called if IsDangerous()
414 DCHECK(IsDangerous());
415 if (download_->GetDangerType() ==
416 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE &&
417 download_crx_util::IsExtensionDownload(*download_)) {
418 return l10n_util::GetStringUTF16(IDS_CONTINUE_EXTENSION_DOWNLOAD);
419 } else {
420 return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
424 int64 DownloadItemModel::GetCompletedBytes() const {
425 return download_->GetReceivedBytes();
428 int64 DownloadItemModel::GetTotalBytes() const {
429 return download_->AllDataSaved() ? download_->GetReceivedBytes() :
430 download_->GetTotalBytes();
433 // TODO(asanka,rdsmith): Once 'open' moves exclusively to the
434 // ChromeDownloadManagerDelegate, we should calculate the percentage here
435 // instead of calling into the DownloadItem.
436 int DownloadItemModel::PercentComplete() const {
437 return download_->PercentComplete();
440 bool DownloadItemModel::IsDangerous() const {
441 return download_->IsDangerous();
444 bool DownloadItemModel::MightBeMalicious() const {
445 if (!IsDangerous())
446 return false;
447 switch (download_->GetDangerType()) {
448 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
449 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
450 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
451 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
452 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
453 return true;
455 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
456 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
457 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
458 case content::DOWNLOAD_DANGER_TYPE_MAX:
459 // We shouldn't get any of these due to the IsDangerous() test above.
460 NOTREACHED();
461 // Fallthrough.
462 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
463 return false;
465 NOTREACHED();
466 return false;
469 // If you change this definition of malicious, also update
470 // DownloadManagerImpl::NonMaliciousInProgressCount.
471 bool DownloadItemModel::IsMalicious() const {
472 if (!MightBeMalicious())
473 return false;
474 switch (download_->GetDangerType()) {
475 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
476 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
477 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
478 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
479 return true;
481 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
482 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
483 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
484 case content::DOWNLOAD_DANGER_TYPE_MAX:
485 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
486 // We shouldn't get any of these due to the MightBeMalicious() test above.
487 NOTREACHED();
488 // Fallthrough.
489 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
490 return false;
492 NOTREACHED();
493 return false;
496 bool DownloadItemModel::ShouldAllowDownloadFeedback() const {
497 #if defined(FULL_SAFE_BROWSING)
498 if (!IsDangerous())
499 return false;
500 return safe_browsing::DownloadFeedbackService::IsEnabledForDownload(
501 *download_);
502 #else
503 return false;
504 #endif
507 bool DownloadItemModel::ShouldRemoveFromShelfWhenComplete() const {
508 switch (download_->GetState()) {
509 case DownloadItem::IN_PROGRESS:
510 // If the download is dangerous or malicious, we should display a warning
511 // on the shelf until the user accepts the download.
512 if (IsDangerous())
513 return false;
515 // If the download is an extension, temporary, or will be opened
516 // automatically, then it should be removed from the shelf on completion.
517 // TODO(asanka): The logic for deciding opening behavior should be in a
518 // central location. http://crbug.com/167702
519 return (download_crx_util::IsExtensionDownload(*download_) ||
520 download_->IsTemporary() ||
521 download_->GetOpenWhenComplete() ||
522 download_->ShouldOpenFileBasedOnExtension());
524 case DownloadItem::COMPLETE:
525 // If the download completed, then rely on GetAutoOpened() to check for
526 // opening behavior. This should accurately reflect whether the download
527 // was successfully opened. Extensions, for example, may fail to open.
528 return download_->GetAutoOpened() || download_->IsTemporary();
530 case DownloadItem::CANCELLED:
531 case DownloadItem::INTERRUPTED:
532 // Interrupted or cancelled downloads should remain on the shelf.
533 return false;
535 case DownloadItem::MAX_DOWNLOAD_STATE:
536 NOTREACHED();
539 NOTREACHED();
540 return false;
543 bool DownloadItemModel::ShouldShowDownloadStartedAnimation() const {
544 return !download_->IsSavePackageDownload() &&
545 !download_crx_util::IsExtensionDownload(*download_);
548 bool DownloadItemModel::ShouldShowInShelf() const {
549 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
550 return !data || data->should_show_in_shelf();
553 void DownloadItemModel::SetShouldShowInShelf(bool should_show) {
554 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
555 data->set_should_show_in_shelf(should_show);
558 bool DownloadItemModel::ShouldNotifyUI() const {
559 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
560 return data && data->should_notify_ui();
563 void DownloadItemModel::SetShouldNotifyUI(bool should_notify) {
564 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
565 data->set_should_notify_ui(should_notify);
568 bool DownloadItemModel::ShouldPreferOpeningInBrowser() const {
569 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
570 return data && data->should_prefer_opening_in_browser();
573 void DownloadItemModel::SetShouldPreferOpeningInBrowser(bool preference) {
574 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
575 data->set_should_prefer_opening_in_browser(preference);
578 base::string16 DownloadItemModel::GetProgressSizesString() const {
579 base::string16 size_ratio;
580 int64 size = GetCompletedBytes();
581 int64 total = GetTotalBytes();
582 if (total > 0) {
583 ui::DataUnits amount_units = ui::GetByteDisplayUnits(total);
584 base::string16 simple_size = ui::FormatBytesWithUnits(size, amount_units, false);
586 // In RTL locales, we render the text "size/total" in an RTL context. This
587 // is problematic since a string such as "123/456 MB" is displayed
588 // as "MB 123/456" because it ends with an LTR run. In order to solve this,
589 // we mark the total string as an LTR string if the UI layout is
590 // right-to-left so that the string "456 MB" is treated as an LTR run.
591 base::string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality(
592 ui::FormatBytesWithUnits(total, amount_units, true));
593 size_ratio = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_SIZES,
594 simple_size, simple_total);
595 } else {
596 size_ratio = ui::FormatBytes(size);
598 return size_ratio;
601 base::string16 DownloadItemModel::GetInProgressStatusString() const {
602 DCHECK_EQ(DownloadItem::IN_PROGRESS, download_->GetState());
604 TimeDelta time_remaining;
605 // time_remaining is only known if the download isn't paused.
606 bool time_remaining_known = (!download_->IsPaused() &&
607 download_->TimeRemaining(&time_remaining));
609 // Indication of progress. (E.g.:"100/200 MB" or "100MB")
610 base::string16 size_ratio = GetProgressSizesString();
612 // The download is a CRX (app, extension, theme, ...) and it is being unpacked
613 // and validated.
614 if (download_->AllDataSaved() &&
615 download_crx_util::IsExtensionDownload(*download_)) {
616 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING);
619 // A paused download: "100/120 MB, Paused"
620 if (download_->IsPaused()) {
621 return l10n_util::GetStringFUTF16(
622 IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
623 l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED));
626 // A download scheduled to be opened when complete: "Opening in 10 secs"
627 if (download_->GetOpenWhenComplete()) {
628 if (!time_remaining_known)
629 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_OPEN_WHEN_COMPLETE);
631 return l10n_util::GetStringFUTF16(
632 IDS_DOWNLOAD_STATUS_OPEN_IN,
633 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
634 ui::TimeFormat::LENGTH_SHORT, time_remaining));
637 // In progress download with known time left: "100/120 MB, 10 secs left"
638 if (time_remaining_known) {
639 return l10n_util::GetStringFUTF16(
640 IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
641 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
642 ui::TimeFormat::LENGTH_SHORT, time_remaining));
645 // In progress download with no known time left and non-zero completed bytes:
646 // "100/120 MB" or "100 MB"
647 if (GetCompletedBytes() > 0)
648 return size_ratio;
650 // Instead of displaying "0 B" we say "Starting..."
651 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING);
654 void DownloadItemModel::OpenUsingPlatformHandler() {
655 DownloadService* download_service =
656 DownloadServiceFactory::GetForBrowserContext(
657 download_->GetBrowserContext());
658 if (!download_service)
659 return;
661 ChromeDownloadManagerDelegate* delegate =
662 download_service->GetDownloadManagerDelegate();
663 if (!delegate)
664 return;
665 delegate->OpenDownloadUsingPlatformHandler(download_);
666 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_USER_PLATFORM);