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