Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / download_item_model.cc
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.
4
5 #include "chrome/browser/download/download_item_model.h"
6
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"
32
33 using base::TimeDelta;
34 using content::DownloadItem;
35
36 namespace {
37
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);
46
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);
50
51   // Whether the download should be displayed in the download shelf. True by
52   // default.
53   bool should_show_in_shelf_;
54
55   // Whether the UI has been notified about this download.
56   bool was_ui_notified_;
57
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_;
61
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_;
65
66  private:
67   DownloadItemModelData();
68   ~DownloadItemModelData() override {}
69
70   static const char kKey[];
71 };
72
73 // static
74 const char DownloadItemModelData::kKey[] = "DownloadItemModelData key";
75
76 // static
77 const DownloadItemModelData* DownloadItemModelData::Get(
78     const DownloadItem* download) {
79   return static_cast<const DownloadItemModelData*>(download->GetUserData(kKey));
80 }
81
82 // static
83 DownloadItemModelData* DownloadItemModelData::GetOrCreate(
84     DownloadItem* download) {
85   DownloadItemModelData* data =
86       static_cast<DownloadItemModelData*>(download->GetUserData(kKey));
87   if (data == NULL) {
88     data = new DownloadItemModelData();
89     download->SetUserData(kKey, data);
90   }
91   return data;
92 }
93
94 DownloadItemModelData::DownloadItemModelData()
95     : should_show_in_shelf_(true),
96       was_ui_notified_(false),
97       should_prefer_opening_in_browser_(false),
98       is_dangerous_file_based_on_type_(false) {
99 }
100
101 base::string16 InterruptReasonStatusMessage(int reason) {
102   int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
103
104   switch (static_cast<content::DownloadInterruptReason>(reason)) {
105     case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
106       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_ACCESS_DENIED;
107       break;
108     case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
109       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_DISK_FULL;
110       break;
111     case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
112       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_PATH_TOO_LONG;
113       break;
114     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
115       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_LARGE;
116       break;
117     case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
118       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_VIRUS;
119       break;
120     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
121       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_TEMPORARY_PROBLEM;
122       break;
123     case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
124       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_BLOCKED;
125       break;
126     case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
127       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SECURITY_CHECK_FAILED;
128       break;
129     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
130       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_FILE_TOO_SHORT;
131       break;
132     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
133     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
134       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_ERROR;
135       break;
136     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
137       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_TIMEOUT;
138       break;
139     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
140       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NETWORK_DISCONNECTED;
141       break;
142     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
143       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_DOWN;
144       break;
145     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
146       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_PROBLEM;
147       break;
148     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
149       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_NO_FILE;
150       break;
151     case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
152       string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
153       break;
154     case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
155       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SHUTDOWN;
156       break;
157     case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
158       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_CRASH;
159       break;
160     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
161       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_UNAUTHORIZED;
162       break;
163     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
164       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS_SERVER_CERT_PROBLEM;
165       break;
166     case content::DOWNLOAD_INTERRUPT_REASON_NONE:
167       NOTREACHED();
168       // fallthrough
169     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
170     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
171     case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
172       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
173   }
174
175   return l10n_util::GetStringUTF16(string_id);
176 }
177
178 base::string16 InterruptReasonMessage(int reason) {
179   int string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
180   base::string16 status_text;
181
182   switch (static_cast<content::DownloadInterruptReason>(reason)) {
183     case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
184       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_ACCESS_DENIED;
185       break;
186     case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
187       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_DISK_FULL;
188       break;
189     case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
190       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_PATH_TOO_LONG;
191       break;
192     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
193       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_LARGE;
194       break;
195     case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
196       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_VIRUS;
197       break;
198     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
199       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_TEMPORARY_PROBLEM;
200       break;
201     case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
202       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_BLOCKED;
203       break;
204     case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
205       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SECURITY_CHECK_FAILED;
206       break;
207     case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
208       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_FILE_TOO_SHORT;
209       break;
210     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
211     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
212       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_ERROR;
213       break;
214     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
215       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_TIMEOUT;
216       break;
217     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
218       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_DISCONNECTED;
219       break;
220     case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
221       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_DOWN;
222       break;
223     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
224       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_PROBLEM;
225       break;
226     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
227       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NO_FILE;
228       break;
229     case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
230       string_id = IDS_DOWNLOAD_STATUS_CANCELLED;
231       break;
232     case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
233       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SHUTDOWN;
234       break;
235     case content::DOWNLOAD_INTERRUPT_REASON_CRASH:
236       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_CRASH;
237       break;
238     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
239       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_UNAUTHORIZED;
240       break;
241     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
242       string_id = IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_SERVER_CERT_PROBLEM;
243       break;
244     case content::DOWNLOAD_INTERRUPT_REASON_NONE:
245       NOTREACHED();
246       // fallthrough
247     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
248     case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
249     case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
250       string_id = IDS_DOWNLOAD_INTERRUPTED_STATUS;
251   }
252
253   status_text = l10n_util::GetStringUTF16(string_id);
254
255   return status_text;
256 }
257
258 } // namespace
259
260 // -----------------------------------------------------------------------------
261 // DownloadItemModel
262
263 DownloadItemModel::DownloadItemModel(DownloadItem* download)
264     : download_(download) {}
265
266 DownloadItemModel::~DownloadItemModel() {}
267
268 base::string16 DownloadItemModel::GetInterruptReasonText() const {
269   if (download_->GetState() != DownloadItem::INTERRUPTED ||
270       download_->GetLastReason() ==
271       content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
272     return base::string16();
273   }
274   return InterruptReasonMessage(download_->GetLastReason());
275 }
276
277 base::string16 DownloadItemModel::GetStatusText() const {
278   base::string16 status_text;
279   switch (download_->GetState()) {
280     case DownloadItem::IN_PROGRESS:
281       status_text = GetInProgressStatusString();
282       break;
283     case DownloadItem::COMPLETE:
284       if (download_->GetFileExternallyRemoved()) {
285         status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_REMOVED);
286       } else {
287         status_text.clear();
288       }
289       break;
290     case DownloadItem::CANCELLED:
291       status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
292       break;
293     case DownloadItem::INTERRUPTED: {
294       content::DownloadInterruptReason reason = download_->GetLastReason();
295       if (reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
296         base::string16 interrupt_reason = InterruptReasonStatusMessage(reason);
297         status_text = l10n_util::GetStringFUTF16(
298             IDS_DOWNLOAD_STATUS_INTERRUPTED, interrupt_reason);
299       } else {
300         // Same as DownloadItem::CANCELLED.
301         status_text = l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELLED);
302       }
303       break;
304     }
305     default:
306       NOTREACHED();
307   }
308
309   return status_text;
310 }
311
312 base::string16 DownloadItemModel::GetTabProgressStatusText() const {
313   int64 total = GetTotalBytes();
314   int64 size = download_->GetReceivedBytes();
315   base::string16 received_size = ui::FormatBytes(size);
316   base::string16 amount = received_size;
317
318   // Adjust both strings for the locale direction since we don't yet know which
319   // string we'll end up using for constructing the final progress string.
320   base::i18n::AdjustStringForLocaleDirection(&amount);
321
322   if (total) {
323     base::string16 total_text = ui::FormatBytes(total);
324     base::i18n::AdjustStringForLocaleDirection(&total_text);
325
326     base::i18n::AdjustStringForLocaleDirection(&received_size);
327     amount = l10n_util::GetStringFUTF16(
328         IDS_DOWNLOAD_TAB_PROGRESS_SIZE, received_size, total_text);
329   } else {
330     amount.assign(received_size);
331   }
332   int64 current_speed = download_->CurrentSpeed();
333   base::string16 speed_text = ui::FormatSpeed(current_speed);
334   base::i18n::AdjustStringForLocaleDirection(&speed_text);
335
336   base::TimeDelta remaining;
337   base::string16 time_remaining;
338   if (download_->IsPaused()) {
339     time_remaining = l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED);
340   } else if (download_->TimeRemaining(&remaining)) {
341     time_remaining = ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
342                                             ui::TimeFormat::LENGTH_SHORT,
343                                             remaining);
344   }
345
346   if (time_remaining.empty()) {
347     base::i18n::AdjustStringForLocaleDirection(&amount);
348     return l10n_util::GetStringFUTF16(
349         IDS_DOWNLOAD_TAB_PROGRESS_STATUS_TIME_UNKNOWN, speed_text, amount);
350   }
351   return l10n_util::GetStringFUTF16(
352       IDS_DOWNLOAD_TAB_PROGRESS_STATUS, speed_text, amount, time_remaining);
353 }
354
355 base::string16 DownloadItemModel::GetTooltipText(const gfx::FontList& font_list,
356                                                  int max_width) const {
357   base::string16 tooltip = gfx::ElideFilename(
358       download_->GetFileNameToReportUser(), font_list, max_width);
359   content::DownloadInterruptReason reason = download_->GetLastReason();
360   if (download_->GetState() == DownloadItem::INTERRUPTED &&
361       reason != content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) {
362     tooltip += base::ASCIIToUTF16("\n");
363     tooltip += gfx::ElideText(InterruptReasonStatusMessage(reason),
364                              font_list, max_width, gfx::ELIDE_TAIL);
365   }
366   return tooltip;
367 }
368
369 base::string16 DownloadItemModel::GetWarningText(const gfx::FontList& font_list,
370                                                  int base_width) const {
371   // Should only be called if IsDangerous().
372   DCHECK(IsDangerous());
373   base::string16 elided_filename =
374       gfx::ElideFilename(download_->GetFileNameToReportUser(), font_list,
375                         base_width);
376   switch (download_->GetDangerType()) {
377     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
378       return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
379     }
380     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
381       if (download_crx_util::IsExtensionDownload(*download_)) {
382         return l10n_util::GetStringUTF16(
383             IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
384       } else {
385         return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
386                                           elided_filename);
387       }
388     }
389     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
390     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
391       return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
392                                         elided_filename);
393     }
394     case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
395       return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
396                                         elided_filename);
397     }
398     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
399       return l10n_util::GetStringFUTF16(
400           IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS, elided_filename);
401     }
402     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
403     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
404     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
405     case content::DOWNLOAD_DANGER_TYPE_MAX: {
406       break;
407     }
408   }
409   NOTREACHED();
410   return base::string16();
411 }
412
413 base::string16 DownloadItemModel::GetWarningConfirmButtonText() const {
414   // Should only be called if IsDangerous()
415   DCHECK(IsDangerous());
416   if (download_->GetDangerType() ==
417           content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE &&
418       download_crx_util::IsExtensionDownload(*download_)) {
419     return l10n_util::GetStringUTF16(IDS_CONTINUE_EXTENSION_DOWNLOAD);
420   } else {
421     return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
422   }
423 }
424
425 int64 DownloadItemModel::GetCompletedBytes() const {
426   return download_->GetReceivedBytes();
427 }
428
429 int64 DownloadItemModel::GetTotalBytes() const {
430   return download_->AllDataSaved() ? download_->GetReceivedBytes() :
431                                      download_->GetTotalBytes();
432 }
433
434 // TODO(asanka,rdsmith): Once 'open' moves exclusively to the
435 //     ChromeDownloadManagerDelegate, we should calculate the percentage here
436 //     instead of calling into the DownloadItem.
437 int DownloadItemModel::PercentComplete() const {
438   return download_->PercentComplete();
439 }
440
441 bool DownloadItemModel::IsDangerous() const {
442   return download_->IsDangerous();
443 }
444
445 bool DownloadItemModel::MightBeMalicious() const {
446   if (!IsDangerous())
447     return false;
448   switch (download_->GetDangerType()) {
449     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
450     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
451     case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
452     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
453     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
454       return true;
455
456     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
457     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
458     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
459     case content::DOWNLOAD_DANGER_TYPE_MAX:
460       // We shouldn't get any of these due to the IsDangerous() test above.
461       NOTREACHED();
462       // Fallthrough.
463     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
464       return false;
465   }
466   NOTREACHED();
467   return false;
468 }
469
470 // If you change this definition of malicious, also update
471 // DownloadManagerImpl::NonMaliciousInProgressCount.
472 bool DownloadItemModel::IsMalicious() const {
473   if (!MightBeMalicious())
474     return false;
475   switch (download_->GetDangerType()) {
476     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
477     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
478     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
479     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
480       return true;
481
482     case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
483     case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
484     case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
485     case content::DOWNLOAD_DANGER_TYPE_MAX:
486     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
487       // We shouldn't get any of these due to the MightBeMalicious() test above.
488       NOTREACHED();
489       // Fallthrough.
490     case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
491       return false;
492   }
493   NOTREACHED();
494   return false;
495 }
496
497 bool DownloadItemModel::ShouldAllowDownloadFeedback() const {
498 #if defined(FULL_SAFE_BROWSING)
499   if (!IsDangerous())
500     return false;
501   return safe_browsing::DownloadFeedbackService::IsEnabledForDownload(
502       *download_);
503 #else
504   return false;
505 #endif
506 }
507
508 bool DownloadItemModel::ShouldRemoveFromShelfWhenComplete() const {
509   switch (download_->GetState()) {
510     case DownloadItem::IN_PROGRESS:
511       // If the download is dangerous or malicious, we should display a warning
512       // on the shelf until the user accepts the download.
513       if (IsDangerous())
514         return false;
515
516       // If the download is an extension, temporary, or will be opened
517       // automatically, then it should be removed from the shelf on completion.
518       // TODO(asanka): The logic for deciding opening behavior should be in a
519       //               central location. http://crbug.com/167702
520       return (download_crx_util::IsExtensionDownload(*download_) ||
521               download_->IsTemporary() ||
522               download_->GetOpenWhenComplete() ||
523               download_->ShouldOpenFileBasedOnExtension());
524
525     case DownloadItem::COMPLETE:
526       // If the download completed, then rely on GetAutoOpened() to check for
527       // opening behavior. This should accurately reflect whether the download
528       // was successfully opened.  Extensions, for example, may fail to open.
529       return download_->GetAutoOpened() || download_->IsTemporary();
530
531     case DownloadItem::CANCELLED:
532     case DownloadItem::INTERRUPTED:
533       // Interrupted or cancelled downloads should remain on the shelf.
534       return false;
535
536     case DownloadItem::MAX_DOWNLOAD_STATE:
537       NOTREACHED();
538   }
539
540   NOTREACHED();
541   return false;
542 }
543
544 bool DownloadItemModel::ShouldShowDownloadStartedAnimation() const {
545   return !download_->IsSavePackageDownload() &&
546       !download_crx_util::IsExtensionDownload(*download_);
547 }
548
549 bool DownloadItemModel::ShouldShowInShelf() const {
550   const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
551   return !data || data->should_show_in_shelf_;
552 }
553
554 void DownloadItemModel::SetShouldShowInShelf(bool should_show) {
555   DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
556   data->should_show_in_shelf_ = should_show;
557 }
558
559 bool DownloadItemModel::ShouldNotifyUI() const {
560   Profile* profile =
561       Profile::FromBrowserContext(download_->GetBrowserContext());
562   DownloadService* download_service =
563       DownloadServiceFactory::GetForBrowserContext(profile);
564   DownloadHistory* download_history =
565       (download_service ? download_service->GetDownloadHistory() : NULL);
566
567   // The browser is only interested in new downloads. Ones that were restored
568   // from history are not displayed on the shelf. The downloads page
569   // independently listens for new downloads when it is active. Note that the UI
570   // will be notified of downloads even if they are not meant to be displayed on
571   // the shelf (i.e. ShouldShowInShelf() returns false). This is because:
572   // *  The shelf isn't the only UI. E.g. on Android, the UI is the system
573   //    DownloadManager.
574   // *  There are other UI activities that need to be performed. E.g. if the
575   //    download was initiated from a new tab, then that tab should be closed.
576   //
577   // TODO(asanka): If an interrupted download is restored from history and is
578   // resumed, then ideally the UI should be notified.
579   return !download_history ||
580          !download_history->WasRestoredFromHistory(download_);
581 }
582
583 bool DownloadItemModel::WasUINotified() const {
584   const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
585   return data && data->was_ui_notified_;
586 }
587
588 void DownloadItemModel::SetWasUINotified(bool was_ui_notified) {
589   DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
590   data->was_ui_notified_ = was_ui_notified;
591 }
592
593 bool DownloadItemModel::ShouldPreferOpeningInBrowser() const {
594   const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
595   return data && data->should_prefer_opening_in_browser_;
596 }
597
598 void DownloadItemModel::SetShouldPreferOpeningInBrowser(bool preference) {
599   DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
600   data->should_prefer_opening_in_browser_ = preference;
601 }
602
603 bool DownloadItemModel::IsDangerousFileBasedOnType() const {
604   const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
605   return data && data->is_dangerous_file_based_on_type_;
606 }
607
608 void DownloadItemModel::SetIsDangerousFileBasedOnType(bool dangerous) {
609   DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
610   data->is_dangerous_file_based_on_type_ = dangerous;
611 }
612
613 base::string16 DownloadItemModel::GetProgressSizesString() const {
614   base::string16 size_ratio;
615   int64 size = GetCompletedBytes();
616   int64 total = GetTotalBytes();
617   if (total > 0) {
618     ui::DataUnits amount_units = ui::GetByteDisplayUnits(total);
619     base::string16 simple_size = ui::FormatBytesWithUnits(size, amount_units, false);
620
621     // In RTL locales, we render the text "size/total" in an RTL context. This
622     // is problematic since a string such as "123/456 MB" is displayed
623     // as "MB 123/456" because it ends with an LTR run. In order to solve this,
624     // we mark the total string as an LTR string if the UI layout is
625     // right-to-left so that the string "456 MB" is treated as an LTR run.
626     base::string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality(
627         ui::FormatBytesWithUnits(total, amount_units, true));
628     size_ratio = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_SIZES,
629                                             simple_size, simple_total);
630   } else {
631     size_ratio = ui::FormatBytes(size);
632   }
633   return size_ratio;
634 }
635
636 base::string16 DownloadItemModel::GetInProgressStatusString() const {
637   DCHECK_EQ(DownloadItem::IN_PROGRESS, download_->GetState());
638
639   TimeDelta time_remaining;
640   // time_remaining is only known if the download isn't paused.
641   bool time_remaining_known = (!download_->IsPaused() &&
642                                download_->TimeRemaining(&time_remaining));
643
644   // Indication of progress. (E.g.:"100/200 MB" or "100MB")
645   base::string16 size_ratio = GetProgressSizesString();
646
647   // The download is a CRX (app, extension, theme, ...) and it is being unpacked
648   // and validated.
649   if (download_->AllDataSaved() &&
650       download_crx_util::IsExtensionDownload(*download_)) {
651     return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING);
652   }
653
654   // A paused download: "100/120 MB, Paused"
655   if (download_->IsPaused()) {
656     return l10n_util::GetStringFUTF16(
657         IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
658         l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED));
659   }
660
661   // A download scheduled to be opened when complete: "Opening in 10 secs"
662   if (download_->GetOpenWhenComplete()) {
663     if (!time_remaining_known)
664       return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_OPEN_WHEN_COMPLETE);
665
666     return l10n_util::GetStringFUTF16(
667         IDS_DOWNLOAD_STATUS_OPEN_IN,
668         ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
669                                ui::TimeFormat::LENGTH_SHORT, time_remaining));
670   }
671
672   // In progress download with known time left: "100/120 MB, 10 secs left"
673   if (time_remaining_known) {
674     return l10n_util::GetStringFUTF16(
675         IDS_DOWNLOAD_STATUS_IN_PROGRESS, size_ratio,
676         ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING,
677                                ui::TimeFormat::LENGTH_SHORT, time_remaining));
678   }
679
680   // In progress download with no known time left and non-zero completed bytes:
681   // "100/120 MB" or "100 MB"
682   if (GetCompletedBytes() > 0)
683     return size_ratio;
684
685   // Instead of displaying "0 B" we say "Starting..."
686   return l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING);
687 }
688
689 void DownloadItemModel::OpenUsingPlatformHandler() {
690   DownloadService* download_service =
691       DownloadServiceFactory::GetForBrowserContext(
692           download_->GetBrowserContext());
693   if (!download_service)
694     return;
695
696   ChromeDownloadManagerDelegate* delegate =
697       download_service->GetDownloadManagerDelegate();
698   if (!delegate)
699     return;
700   delegate->OpenDownloadUsingPlatformHandler(download_);
701   RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_USER_PLATFORM);
702 }