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