Home | History | Annotate | Download | only in download
      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_danger_prompt.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/download/chrome_download_manager_delegate.h"
     11 #include "chrome/browser/download/download_stats.h"
     12 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
     13 #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
     14 #include "content/public/browser/download_danger_type.h"
     15 #include "content/public/browser/download_item.h"
     16 #include "grit/chromium_strings.h"
     17 #include "grit/generated_resources.h"
     18 #include "ui/base/l10n/l10n_util.h"
     19 
     20 namespace {
     21 
     22 // TODO(wittman): Create a native web contents modal dialog implementation of
     23 // this dialog for non-Views platforms, to support bold formatting of the
     24 // message lead.
     25 
     26 // Implements DownloadDangerPrompt using a TabModalConfirmDialog.
     27 class DownloadDangerPromptImpl : public DownloadDangerPrompt,
     28                                  public content::DownloadItem::Observer,
     29                                  public TabModalConfirmDialogDelegate {
     30  public:
     31   DownloadDangerPromptImpl(content::DownloadItem* item,
     32                            content::WebContents* web_contents,
     33                            bool show_context,
     34                            const OnDone& done);
     35   virtual ~DownloadDangerPromptImpl();
     36 
     37   // DownloadDangerPrompt:
     38   virtual void InvokeActionForTesting(Action action) OVERRIDE;
     39 
     40  private:
     41   // content::DownloadItem::Observer:
     42   virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
     43 
     44   // TabModalConfirmDialogDelegate:
     45   virtual base::string16 GetTitle() OVERRIDE;
     46   virtual base::string16 GetDialogMessage() OVERRIDE;
     47   virtual base::string16 GetAcceptButtonTitle() OVERRIDE;
     48   virtual base::string16 GetCancelButtonTitle() OVERRIDE;
     49   virtual void OnAccepted() OVERRIDE;
     50   virtual void OnCanceled() OVERRIDE;
     51   virtual void OnClosed() OVERRIDE;
     52 
     53   void RunDone(Action action);
     54 
     55   content::DownloadItem* download_;
     56   bool show_context_;
     57   OnDone done_;
     58 
     59   DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptImpl);
     60 };
     61 
     62 DownloadDangerPromptImpl::DownloadDangerPromptImpl(
     63     content::DownloadItem* download,
     64     content::WebContents* web_contents,
     65     bool show_context,
     66     const OnDone& done)
     67     : TabModalConfirmDialogDelegate(web_contents),
     68       download_(download),
     69       show_context_(show_context),
     70       done_(done) {
     71   DCHECK(!done_.is_null());
     72   download_->AddObserver(this);
     73   RecordOpenedDangerousConfirmDialog(download_->GetDangerType());
     74 }
     75 
     76 DownloadDangerPromptImpl::~DownloadDangerPromptImpl() {
     77   // |this| might be deleted without invoking any callbacks. E.g. pressing Esc
     78   // on GTK or if the user navigates away from the page showing the prompt.
     79   RunDone(DISMISS);
     80 }
     81 
     82 void DownloadDangerPromptImpl::InvokeActionForTesting(Action action) {
     83   switch (action) {
     84     case ACCEPT: Accept(); break;
     85     case CANCEL: Cancel(); break;
     86     case DISMISS:
     87       RunDone(DISMISS);
     88       Cancel();
     89       break;
     90   }
     91 }
     92 
     93 void DownloadDangerPromptImpl::OnDownloadUpdated(
     94     content::DownloadItem* download) {
     95   // If the download is nolonger dangerous (accepted externally) or the download
     96   // is in a terminal state, then the download danger prompt is no longer
     97   // necessary.
     98   if (!download->IsDangerous() || download->IsDone()) {
     99     RunDone(DISMISS);
    100     Cancel();
    101   }
    102 }
    103 
    104 base::string16 DownloadDangerPromptImpl::GetTitle() {
    105   if (show_context_)
    106     return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
    107   switch (download_->GetDangerType()) {
    108     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
    109     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
    110     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
    111     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
    112       return l10n_util::GetStringUTF16(
    113           IDS_RESTORE_KEEP_DANGEROUS_DOWNLOAD_TITLE);
    114     }
    115     default: {
    116       return l10n_util::GetStringUTF16(
    117           IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
    118     }
    119   }
    120 }
    121 
    122 base::string16 DownloadDangerPromptImpl::GetDialogMessage() {
    123   if (show_context_) {
    124     switch (download_->GetDangerType()) {
    125       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
    126         return l10n_util::GetStringFUTF16(
    127             IDS_PROMPT_DANGEROUS_DOWNLOAD,
    128             download_->GetFileNameToReportUser().LossyDisplayName());
    129       }
    130       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through
    131       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
    132       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
    133         return l10n_util::GetStringFUTF16(
    134             IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
    135             download_->GetFileNameToReportUser().LossyDisplayName());
    136       }
    137       case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
    138         return l10n_util::GetStringFUTF16(
    139             IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
    140             download_->GetFileNameToReportUser().LossyDisplayName());
    141       }
    142       case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
    143         return l10n_util::GetStringFUTF16(
    144             IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
    145             download_->GetFileNameToReportUser().LossyDisplayName());
    146       }
    147       case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
    148       case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
    149       case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
    150       case content::DOWNLOAD_DANGER_TYPE_MAX: {
    151         break;
    152       }
    153     }
    154   } else {
    155     switch (download_->GetDangerType()) {
    156       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
    157       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
    158       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
    159         return l10n_util::GetStringUTF16(
    160             IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD) +
    161             base::ASCIIToUTF16("\n\n") +
    162             l10n_util::GetStringUTF16(
    163                 IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY);
    164       }
    165       default: {
    166         return l10n_util::GetStringUTF16(
    167             IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
    168       }
    169     }
    170   }
    171   NOTREACHED();
    172   return base::string16();
    173 }
    174 
    175 base::string16 DownloadDangerPromptImpl::GetAcceptButtonTitle() {
    176   if (show_context_)
    177     return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
    178   switch (download_->GetDangerType()) {
    179     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
    180     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
    181     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
    182     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
    183       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN_MALICIOUS);
    184     }
    185     default:
    186       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN);
    187   }
    188 }
    189 
    190 base::string16 DownloadDangerPromptImpl::GetCancelButtonTitle() {
    191   if (show_context_)
    192     return l10n_util::GetStringUTF16(IDS_CANCEL);
    193   switch (download_->GetDangerType()) {
    194     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
    195     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
    196     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
    197     case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
    198       return l10n_util::GetStringUTF16(IDS_CONFIRM_CANCEL_AGAIN_MALICIOUS);
    199     }
    200     default:
    201       return l10n_util::GetStringUTF16(IDS_CANCEL);
    202   }
    203 }
    204 
    205 void DownloadDangerPromptImpl::OnAccepted() {
    206   RunDone(ACCEPT);
    207 }
    208 
    209 void DownloadDangerPromptImpl::OnCanceled() {
    210   RunDone(CANCEL);
    211 }
    212 
    213 void DownloadDangerPromptImpl::OnClosed() {
    214   RunDone(DISMISS);
    215 }
    216 
    217 void DownloadDangerPromptImpl::RunDone(Action action) {
    218   // Invoking the callback can cause the download item state to change or cause
    219   // the constrained window to close, and |callback| refers to a member
    220   // variable.
    221   OnDone done = done_;
    222   done_.Reset();
    223   if (download_ != NULL) {
    224     download_->RemoveObserver(this);
    225     download_ = NULL;
    226   }
    227   if (!done.is_null())
    228     done.Run(action);
    229 }
    230 
    231 }  // namespace
    232 
    233 #if !defined(USE_AURA)
    234 // static
    235 DownloadDangerPrompt* DownloadDangerPrompt::Create(
    236     content::DownloadItem* item,
    237     content::WebContents* web_contents,
    238     bool show_context,
    239     const OnDone& done) {
    240   DownloadDangerPromptImpl* prompt = new DownloadDangerPromptImpl(
    241       item, web_contents, show_context, done);
    242   // |prompt| will be deleted when the dialog is done.
    243   TabModalConfirmDialog::Create(prompt, web_contents);
    244   return prompt;
    245 }
    246 #endif
    247