Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / download / download_item_model.cc
blobf29d7e937c5156d71c9d092845afe9a20ff1a48e
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_history.h"
18 #include "chrome/browser/download/download_service.h"
19 #include "chrome/browser/download/download_service_factory.h"
20 #include "chrome/browser/download/download_stats.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/safe_browsing/download_feedback_service.h"
23 #include "chrome/grit/chromium_strings.h"
24 #include "chrome/grit/generated_resources.h"
25 #include "content/public/browser/download_danger_type.h"
26 #include "content/public/browser/download_interrupt_reasons.h"
27 #include "content/public/browser/download_item.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/l10n/time_format.h"
30 #include "ui/base/text/bytes_formatting.h"
31 #include "ui/gfx/text_elider.h"
33 using base::TimeDelta;
34 using content::DownloadItem;
36 namespace {
38 // Per DownloadItem data used by DownloadItemModel. The model doesn't keep any
39 // state since there could be multiple models associated with a single
40 // DownloadItem, and the lifetime of the model is shorter than the DownloadItem.
41 class DownloadItemModelData : public base::SupportsUserData::Data {
42 public:
43 // Get the DownloadItemModelData object for |download|. Returns NULL if
44 // there's no model data.
45 static const DownloadItemModelData* Get(const DownloadItem* download);
47 // Get the DownloadItemModelData object for |download|. Creates a model data
48 // object if not found. Always returns a non-NULL pointer, unless OOM.
49 static DownloadItemModelData* GetOrCreate(DownloadItem* download);
51 // Whether the download should be displayed in the download shelf. True by
52 // default.
53 bool should_show_in_shelf_;
55 // Whether the UI has been notified about this download.
56 bool was_ui_notified_;
58 // Whether the download should be opened in the browser vs. the system handler
59 // for the file type.
60 bool should_prefer_opening_in_browser_;
62 // Whether the download should be considered dangerous if SafeBrowsing doesn't
63 // come up with a verdict.
64 bool is_dangerous_file_based_on_type_;
66 // Whether the download is currently being revived.
67 bool is_being_revived_;
69 private:
70 DownloadItemModelData();
71 ~DownloadItemModelData() override {}
73 static const char kKey[];
76 // static
77 const char DownloadItemModelData::kKey[] = "DownloadItemModelData key";
79 // static
80 const DownloadItemModelData* DownloadItemModelData::Get(
81 const DownloadItem* download) {
82 return static_cast<const DownloadItemModelData*>(download->GetUserData(kKey));
85 // static
86 DownloadItemModelData* DownloadItemModelData::GetOrCreate(
87 DownloadItem* download) {
88 DownloadItemModelData* data =
89 static_cast<DownloadItemModelData*>(download->GetUserData(kKey));
90 if (data == NULL) {
91 data = new DownloadItemModelData();
92 download->SetUserData(kKey, data);
94 return data;
97 DownloadItemModelData::DownloadItemModelData()
98 : should_show_in_shelf_(true),
99 was_ui_notified_(false),
100 should_prefer_opening_in_browser_(false),
101 is_dangerous_file_based_on_type_(false),
102 is_being_revived_(false) {
105 base::string16 InterruptReasonStatusMessage(int reason) {
106 int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
108 switch (static_cast<content::DownloadInterruptReason>(reason)) {
109 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
110 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_ACCESS_DENIED;
111 break;
112 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
113 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_DISK_FULL;
114 break;
115 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
116 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_PATH_TOO_LONG;
117 break;
118 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
119 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_LARGE;
120 break;
121 case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
122 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_VIRUS;
123 break;
124 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
125 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_TEMPORARY_PROBLEM;
126 break;
127 case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
128 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_BLOCKED;
129 break;
130 case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
131 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SECURITY_CHECK_FAILED;
132 break;
133 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
134 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_SHORT;
135 break;
136 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
137 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
138 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_ERROR;
139 break;
140 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
141 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_TIMEOUT;
142 break;
143 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
144 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_DISCONNECTED;
145 break;
146 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
147 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_DOWN;
148 break;
149 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
150 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_PROBLEM;
151 break;
152 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
153 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NO_FILE;
154 break;
155 case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
156 string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
157 break;
158 case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
159 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SHUTDOWN;
160 break;
161 case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
162 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_CRASH;
163 break;
164 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
165 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_UNAUTHORIZED;
166 break;
167 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
168 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_CERT_PROBLEM;
169 break;
170 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
171 NOTREACHED();
172 // fallthrough
173 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
174 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
175 case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
176 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
179 return l10n_util::GetStringUTF16(string_id);
182 base::string16 InterruptReasonMessage(int reason) {
183 int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
184 base::string16 status_text;
186 switch (static_cast<content::DownloadInterruptReason>(reason)) {
187 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
188 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_ACCESS_DENIED;
189 break;
190 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
191 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_DISK_FULL;
192 break;
193 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
194 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_PATH_TOO_LONG;
195 break;
196 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
197 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_LARGE;
198 break;
199 case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
200 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_VIRUS;
201 break;
202 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
203 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_TEMPORARY_PROBLEM;
204 break;
205 case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
206 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_BLOCKED;
207 break;
208 case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
209 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SECURITY_CHECK_FAILED;
210 break;
211 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
212 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_SHORT;
213 break;
214 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
215 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
216 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_ERROR;
217 break;
218 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
219 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_TIMEOUT;
220 break;
221 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
222 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_DISCONNECTED;
223 break;
224 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
225 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_DOWN;
226 break;
227 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
228 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_PROBLEM;
229 break;
230 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
231 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NO_FILE;
232 break;
233 case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
234 string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
235 break;
236 case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
237 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SHUTDOWN;
238 break;
239 case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
240 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_CRASH;
241 break;
242 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
243 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_UNAUTHORIZED;
244 break;
245 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
246 string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_CERT_PROBLEM;
247 break;
248 case content::DOWNLOAD_INTERRUPT_REASON_NONE:
249 NOTREACHED();
250 // fallthrough
251 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
252 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
253 case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
254 string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
257 status_text = l10n_util::GetStringUTF16(string_id);
259 return status_text;
262 } // namespace
264 // -----------------------------------------------------------------------------
265 // DownloadItemModel
267 DownloadItemModel::DownloadItemModel(DownloadItem* download)
268 : download_(download) {}
270 DownloadItemModel::~DownloadItemModel() {}
272 base::string16 DownloadItemModel::GetInterruptReasonText() const {
273 if (download_->GetState() != DownloadItem::INTERRUPTED ||
274 download_->GetLastReason() ==
275 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
276 return base::string16();
278 return InterruptReasonMessage(download_->GetLastReason());
281 base::string16 DownloadItemModel::GetStatusText() const {
282 base::string16 status_text;
283 switch (download_->GetState()) {
284 case DownloadItem::IN_PROGRESS:
285 status_text = GetInProgressStatusString();
286 break;
287 case DownloadItem::COMPLETE:
288 if (download_->GetFileExternallyRemoved()) {
289 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_REMOVED);
290 } else {
291 status_text.clear();
293 break;
294 case DownloadItem::CANCELLED:
295 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
296 break;
297 case DownloadItem::INTERRUPTED: {
298 content::DownloadInterruptReason reason = download_->GetLastReason();
299 if (reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
300 base::string16 interrupt_reason = InterruptReasonStatusMessage(reason);
301 status_text = l10n_util::GetStringFUTF16(
302 IDS_DOWNLOAD_STATUS_INTERRUPTED, interrupt_reason);
303 } else {
304 // Same as DownloadItem::CANCELLED.
305 status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
307 break;
309 default:
310 NOTREACHED();
313 return status_text;
316 base::string16 DownloadItemModel::GetTabProgressStatusText() const {
317 int64 total = GetTotalBytes();
318 int64 size = download_->GetReceivedBytes();
319 base::string16 received_size = ui::FormatBytes(size);
320 base::string16 amount = received_size;
322 // Adjust both strings for the locale direction since we don't yet know which
323 // string we'll end up using for constructing the final progress string.
324 base::i18n::AdjustStringForLocaleDirection(&amount);
326 if (total) {
327 base::string16 total_text = ui::FormatBytes(total);
328 base::i18n::AdjustStringForLocaleDirection(&total_text);
330 base::i18n::AdjustStringForLocaleDirection(&received_size);
331 amount = l10n_util::GetStringFUTF16(
332 IDS_DOWNLOAD_TAB_PROGRESS_SIZE, received_size, total_text);
333 } else {
334 amount.assign(received_size);
336 int64 current_speed = download_->CurrentSpeed();
337 base::string16 speed_text = ui::FormatSpeed(current_speed);
338 base::i18n::AdjustStringForLocaleDirection(&speed_text);
340 base::TimeDelta remaining;
341 base::string16 time_remaining;
342 if (download_->IsPaused()) {
343 time_remaining = l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED);
344 } else if (download_->TimeRemaining(&remaining)) {
345 time_remaining = ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
346 ui::TimeFormat::LENGTH_SHORT,
347 remaining);
350 if (time_remaining.empty()) {
351 base::i18n::AdjustStringForLocaleDirection(&amount);
352 return l10n_util::GetStringFUTF16(
353 IDS_DOWNLOAD_TAB_PROGRESS_STATUS_TIME_UNKNOWN, speed_text, amount);
355 return l10n_util::GetStringFUTF16(
356 IDS_DOWNLOAD_TAB_PROGRESS_STATUS, speed_text, amount, time_remaining);
359 base::string16 DownloadItemModel::GetTooltipText(const gfx::FontList& font_list,
360 int max_width) const {
361 base::string16 tooltip = gfx::ElideFilename(
362 download_->GetFileNameToReportUser(), font_list, max_width);
363 content::DownloadInterruptReason reason = download_->GetLastReason();
364 if (download_->GetState() == DownloadItem::INTERRUPTED &&
365 reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
366 tooltip += base::ASCIIToUTF16("\n");
367 tooltip += gfx::ElideText(InterruptReasonStatusMessage(reason),
368 font_list, max_width, gfx::ELIDE_TAIL);
370 return tooltip;
373 base::string16 DownloadItemModel::GetWarningText(const gfx::FontList& font_list,
374 int base_width) const {
375 // Should only be called if IsDangerous().
376 DCHECK(IsDangerous());
377 base::string16 elided_filename =
378 gfx::ElideFilename(download_->GetFileNameToReportUser(), font_list,
379 base_width);
380 switch (download_->GetDangerType()) {
381 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
382 return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
384 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
385 if (download_crx_util::IsExtensionDownload(*download_)) {
386 return l10n_util::GetStringUTF16(
387 IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
388 } else {
389 return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
390 elided_filename);
393 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
394 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
395 return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
396 elided_filename);
398 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
399 return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
400 elided_filename);
402 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
403 return l10n_util::GetStringFUTF16(
404 IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS, elided_filename);
406 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
407 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
408 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
409 case content::DOWNLOAD_DANGER_TYPE_MAX: {
410 break;
413 NOTREACHED();
414 return base::string16();
417 base::string16 DownloadItemModel::GetWarningConfirmButtonText() const {
418 // Should only be called if IsDangerous()
419 DCHECK(IsDangerous());
420 if (download_->GetDangerType() ==
421 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE &&
422 download_crx_util::IsExtensionDownload(*download_)) {
423 return l10n_util::GetStringUTF16(IDS_CONTINUE_EXTENSION_DOWNLOAD);
424 } else {
425 return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
429 int64 DownloadItemModel::GetCompletedBytes() const {
430 return download_->GetReceivedBytes();
433 int64 DownloadItemModel::GetTotalBytes() const {
434 return download_->AllDataSaved() ? download_->GetReceivedBytes() :
435 download_->GetTotalBytes();
438 // TODO(asanka,rdsmith): Once 'open' moves exclusively to the
439 // ChromeDownloadManagerDelegate, we should calculate the percentage here
440 // instead of calling into the DownloadItem.
441 int DownloadItemModel::PercentComplete() const {
442 return download_->PercentComplete();
445 bool DownloadItemModel::IsDangerous() const {
446 return download_->IsDangerous();
449 bool DownloadItemModel::MightBeMalicious() const {
450 if (!IsDangerous())
451 return false;
452 switch (download_->GetDangerType()) {
453 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
454 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
455 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
456 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
457 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
458 return true;
460 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
461 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
462 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
463 case content::DOWNLOAD_DANGER_TYPE_MAX:
464 // We shouldn't get any of these due to the IsDangerous() test above.
465 NOTREACHED();
466 // Fallthrough.
467 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
468 return false;
470 NOTREACHED();
471 return false;
474 // If you change this definition of malicious, also update
475 // DownloadManagerImpl::NonMaliciousInProgressCount.
476 bool DownloadItemModel::IsMalicious() const {
477 if (!MightBeMalicious())
478 return false;
479 switch (download_->GetDangerType()) {
480 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
481 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
482 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
483 case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
484 return true;
486 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
487 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
488 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
489 case content::DOWNLOAD_DANGER_TYPE_MAX:
490 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
491 // We shouldn't get any of these due to the MightBeMalicious() test above.
492 NOTREACHED();
493 // Fallthrough.
494 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
495 return false;
497 NOTREACHED();
498 return false;
501 bool DownloadItemModel::ShouldAllowDownloadFeedback() const {
502 #if defined(FULL_SAFE_BROWSING)
503 if (!IsDangerous())
504 return false;
505 return safe_browsing::DownloadFeedbackService::IsEnabledForDownload(
506 *download_);
507 #else
508 return false;
509 #endif
512 bool DownloadItemModel::ShouldRemoveFromShelfWhenComplete() const {
513 switch (download_->GetState()) {
514 case DownloadItem::IN_PROGRESS:
515 // If the download is dangerous or malicious, we should display a warning
516 // on the shelf until the user accepts the download.
517 if (IsDangerous())
518 return false;
520 // If the download is an extension, temporary, or will be opened
521 // automatically, then it should be removed from the shelf on completion.
522 // TODO(asanka): The logic for deciding opening behavior should be in a
523 // central location. http://crbug.com/167702
524 return (download_crx_util::IsExtensionDownload(*download_) ||
525 download_->IsTemporary() ||
526 download_->GetOpenWhenComplete() ||
527 download_->ShouldOpenFileBasedOnExtension());
529 case DownloadItem::COMPLETE:
530 // If the download completed, then rely on GetAutoOpened() to check for
531 // opening behavior. This should accurately reflect whether the download
532 // was successfully opened. Extensions, for example, may fail to open.
533 return download_->GetAutoOpened() || download_->IsTemporary();
535 case DownloadItem::CANCELLED:
536 case DownloadItem::INTERRUPTED:
537 // Interrupted or cancelled downloads should remain on the shelf.
538 return false;
540 case DownloadItem::MAX_DOWNLOAD_STATE:
541 NOTREACHED();
544 NOTREACHED();
545 return false;
548 bool DownloadItemModel::ShouldShowDownloadStartedAnimation() const {
549 return !download_->IsSavePackageDownload() &&
550 !download_crx_util::IsExtensionDownload(*download_);
553 bool DownloadItemModel::ShouldShowInShelf() const {
554 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
555 return !data || data->should_show_in_shelf_;
558 void DownloadItemModel::SetShouldShowInShelf(bool should_show) {
559 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
560 data->should_show_in_shelf_ = should_show;
563 bool DownloadItemModel::ShouldNotifyUI() const {
564 Profile* profile =
565 Profile::FromBrowserContext(download_->GetBrowserContext());
566 DownloadService* download_service =
567 DownloadServiceFactory::GetForBrowserContext(profile);
568 DownloadHistory* download_history =
569 (download_service ? download_service->GetDownloadHistory() : NULL);
571 // The browser is only interested in new downloads. Ones that were restored
572 // from history are not displayed on the shelf. The downloads page
573 // independently listens for new downloads when it is active. Note that the UI
574 // will be notified of downloads even if they are not meant to be displayed on
575 // the shelf (i.e. ShouldShowInShelf() returns false). This is because:
576 // * The shelf isn't the only UI. E.g. on Android, the UI is the system
577 // DownloadManager.
578 // * There are other UI activities that need to be performed. E.g. if the
579 // download was initiated from a new tab, then that tab should be closed.
581 // TODO(asanka): If an interrupted download is restored from history and is
582 // resumed, then ideally the UI should be notified.
583 return !download_history ||
584 !download_history->WasRestoredFromHistory(download_);
587 bool DownloadItemModel::WasUINotified() const {
588 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
589 return data && data->was_ui_notified_;
592 void DownloadItemModel::SetWasUINotified(bool was_ui_notified) {
593 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
594 data->was_ui_notified_ = was_ui_notified;
597 bool DownloadItemModel::ShouldPreferOpeningInBrowser() const {
598 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
599 return data && data->should_prefer_opening_in_browser_;
602 void DownloadItemModel::SetShouldPreferOpeningInBrowser(bool preference) {
603 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
604 data->should_prefer_opening_in_browser_ = preference;
607 bool DownloadItemModel::IsDangerousFileBasedOnType() const {
608 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
609 return data && data->is_dangerous_file_based_on_type_;
612 void DownloadItemModel::SetIsDangerousFileBasedOnType(bool dangerous) {
613 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
614 data->is_dangerous_file_based_on_type_ = dangerous;
617 bool DownloadItemModel::IsBeingRevived() const {
618 const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
619 return data && data->is_being_revived_;
622 void DownloadItemModel::SetIsBeingRevived(bool is_being_revived) {
623 DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
624 data->is_being_revived_ = is_being_revived;
627 base::string16 DownloadItemModel::GetProgressSizesString() const {
628 base::string16 size_ratio;
629 int64 size = GetCompletedBytes();
630 int64 total = GetTotalBytes();
631 if (total > 0) {
632 ui::DataUnits amount_units = ui::GetByteDisplayUnits(total);
633 base::string16 simple_size = ui::FormatBytesWithUnits(size, amount_units, false);
635 // In RTL locales, we render the text "size/total" in an RTL context. This
636 // is problematic since a string such as "123/456 MB" is displayed
637 // as "MB 123/456" because it ends with an LTR run. In order to solve this,
638 // we mark the total string as an LTR string if the UI layout is
639 // right-to-left so that the string "456 MB" is treated as an LTR run.
640 base::string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality(
641 ui::FormatBytesWithUnits(total, amount_units, true));
642 size_ratio = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_SIZES,
643 simple_size, simple_total);
644 } else {
645 size_ratio = ui::FormatBytes(size);
647 return size_ratio;
650 base::string16 DownloadItemModel::GetInProgressStatusString() const {
651 DCHECK_EQ(DownloadItem::IN_PROGRESS, download_->GetState());
653 TimeDelta time_remaining;
654 // time_remaining is only known if the download isn't paused.
655 bool time_remaining_known = (!download_->IsPaused() &&
656 download_->TimeRemaining(&time_remaining));
658 // Indication of progress. (E.g.:"100/200 MB" or "100MB")
659 base::string16 size_ratio = GetProgressSizesString();
661 // The download is a CRX (app, extension, theme, ...) and it is being unpacked
662 // and validated.
663 if (download_->AllDataSaved() &&
664 download_crx_util::IsExtensionDownload(*download_)) {
665 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING);
668 // A paused download: "100/120 MB, Paused"
669 if (download_->IsPaused()) {
670 return l10n_util::GetStringFUTF16(
671 IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
672 l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED));
675 // A download scheduled to be opened when complete: "Opening in 10 secs"
676 if (download_->GetOpenWhenComplete()) {
677 if (!time_remaining_known)
678 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_OPEN_WHEN_COMPLETE);
680 return l10n_util::GetStringFUTF16(
681 IDS_DOWNLOAD_STATUS_OPEN_IN,
682 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
683 ui::TimeFormat::LENGTH_SHORT, time_remaining));
686 // In progress download with known time left: "100/120 MB, 10 secs left"
687 if (time_remaining_known) {
688 return l10n_util::GetStringFUTF16(
689 IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
690 ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
691 ui::TimeFormat::LENGTH_SHORT, time_remaining));
694 // In progress download with no known time left and non-zero completed bytes:
695 // "100/120 MB" or "100 MB"
696 if (GetCompletedBytes() > 0)
697 return size_ratio;
699 // Instead of displaying "0 B" we say "Starting..."
700 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING);
703 void DownloadItemModel::OpenUsingPlatformHandler() {
704 DownloadService* download_service =
705 DownloadServiceFactory::GetForBrowserContext(
706 download_->GetBrowserContext());
707 if (!download_service)
708 return;
710 ChromeDownloadManagerDelegate* delegate =
711 download_service->GetDownloadManagerDelegate();
712 if (!delegate)
713 return;
714 delegate->OpenDownloadUsingPlatformHandler(download_);
715 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_USER_PLATFORM);