download_danger_prompt.cc revision 3551c9c881056c480085172ff9840cab31610854
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/metrics/field_trial.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_field_trial.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
20namespace {
21
22// Implements DownloadDangerPrompt using a TabModalConfirmDialog.
23class DownloadDangerPromptImpl : public DownloadDangerPrompt,
24                                 public content::DownloadItem::Observer,
25                                 public TabModalConfirmDialogDelegate {
26 public:
27  DownloadDangerPromptImpl(content::DownloadItem* item,
28                           content::WebContents* web_contents,
29                           bool show_context,
30                           const OnDone& done);
31  virtual ~DownloadDangerPromptImpl();
32
33  // DownloadDangerPrompt:
34  virtual void InvokeActionForTesting(Action action) OVERRIDE;
35
36 private:
37  // content::DownloadItem::Observer:
38  virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
39
40  // TabModalConfirmDialogDelegate:
41  virtual string16 GetTitle() OVERRIDE;
42  virtual string16 GetMessage() OVERRIDE;
43  virtual string16 GetAcceptButtonTitle() OVERRIDE;
44  virtual void OnAccepted() OVERRIDE;
45  virtual void OnCanceled() OVERRIDE;
46  virtual void OnClosed() OVERRIDE;
47
48  void RunDone(Action action);
49
50  content::DownloadItem* download_;
51  bool show_context_;
52  OnDone done_;
53
54  DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptImpl);
55};
56
57DownloadDangerPromptImpl::DownloadDangerPromptImpl(
58    content::DownloadItem* download,
59    content::WebContents* web_contents,
60    bool show_context,
61    const OnDone& done)
62    : TabModalConfirmDialogDelegate(web_contents),
63      download_(download),
64      show_context_(show_context),
65      done_(done) {
66  DCHECK(!done_.is_null());
67  download_->AddObserver(this);
68}
69
70DownloadDangerPromptImpl::~DownloadDangerPromptImpl() {
71  // |this| might be deleted without invoking any callbacks. E.g. pressing Esc
72  // on GTK or if the user navigates away from the page showing the prompt.
73  RunDone(DISMISS);
74}
75
76void DownloadDangerPromptImpl::InvokeActionForTesting(Action action) {
77  switch (action) {
78    case ACCEPT: Accept(); break;
79    case CANCEL: Cancel(); break;
80    case DISMISS:
81      RunDone(DISMISS);
82      Cancel();
83      break;
84  }
85}
86
87void DownloadDangerPromptImpl::OnDownloadUpdated(
88    content::DownloadItem* download) {
89  // If the download is nolonger dangerous (accepted externally) or the download
90  // is in a terminal state, then the download danger prompt is no longer
91  // necessary.
92  if (!download->IsDangerous() || download->IsDone()) {
93    RunDone(DISMISS);
94    Cancel();
95  }
96}
97
98string16 DownloadDangerPromptImpl::GetTitle() {
99  return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
100}
101
102string16 DownloadDangerPromptImpl::GetMessage() {
103  if (!show_context_)
104    return l10n_util::GetStringUTF16(
105        IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
106  switch (download_->GetDangerType()) {
107    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
108      return l10n_util::GetStringFUTF16(
109          IDS_PROMPT_DANGEROUS_DOWNLOAD,
110          download_->GetFileNameToReportUser().LossyDisplayName());
111    }
112    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through
113    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
114    case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
115      std::string trial_condition =
116          base::FieldTrialList::FindFullName(kMalwareWarningFinchTrialName);
117      if (trial_condition.empty()) {
118        return l10n_util::GetStringFUTF16(
119            IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
120            download_->GetFileNameToReportUser().LossyDisplayName());
121      }
122      return AssembleMalwareFinchString(
123          trial_condition,
124          download_->GetFileNameToReportUser().LossyDisplayName());
125    }
126    case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
127      return l10n_util::GetStringFUTF16(
128          IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
129          download_->GetFileNameToReportUser().LossyDisplayName());
130    }
131    case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
132      return l10n_util::GetStringFUTF16(
133          IDS_PROMPT_DOWNLOAD_CHANGES_SEARCH_SETTINGS,
134          download_->GetFileNameToReportUser().LossyDisplayName());
135    }
136    case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
137    case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
138    case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
139    case content::DOWNLOAD_DANGER_TYPE_MAX: {
140      break;
141    }
142  }
143  NOTREACHED();
144  return string16();
145}
146
147string16 DownloadDangerPromptImpl::GetAcceptButtonTitle() {
148  return l10n_util::GetStringUTF16(
149      show_context_ ? IDS_CONFIRM_DOWNLOAD : IDS_CONFIRM_DOWNLOAD_AGAIN);
150}
151
152void DownloadDangerPromptImpl::OnAccepted() {
153  RunDone(ACCEPT);
154}
155
156void DownloadDangerPromptImpl::OnCanceled() {
157  RunDone(CANCEL);
158}
159
160void DownloadDangerPromptImpl::OnClosed() {
161  RunDone(DISMISS);
162}
163
164void DownloadDangerPromptImpl::RunDone(Action action) {
165  // Invoking the callback can cause the download item state to change or cause
166  // the constrained window to close, and |callback| refers to a member
167  // variable.
168  OnDone done = done_;
169  done_.Reset();
170  if (download_ != NULL) {
171    download_->RemoveObserver(this);
172    download_ = NULL;
173  }
174  if (!done.is_null())
175    done.Run(action);
176}
177
178}  // namespace
179
180// static
181DownloadDangerPrompt* DownloadDangerPrompt::Create(
182    content::DownloadItem* item,
183    content::WebContents* web_contents,
184    bool show_context,
185    const OnDone& done) {
186  DownloadDangerPromptImpl* prompt = new DownloadDangerPromptImpl(
187      item, web_contents, show_context, done);
188  // |prompt| will be deleted when the dialog is done.
189  TabModalConfirmDialog::Create(prompt, web_contents);
190  return prompt;
191}
192