Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / download / download_danger_prompt_views.cc
1 // Copyright 2013 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 "base/compiler_specific.h"
6 #include "chrome/browser/download/download_danger_prompt.h"
7 #include "chrome/browser/download/download_stats.h"
8 #include "components/web_modal/web_contents_modal_dialog_host.h"
9 #include "components/web_modal/web_contents_modal_dialog_manager.h"
10 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/download_danger_type.h"
13 #include "content/public/browser/download_item.h"
14 #include "content/public/browser/web_contents.h"
15 #include "grit/chromium_strings.h"
16 #include "grit/generated_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/views/controls/button/label_button.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/layout/grid_layout.h"
22 #include "ui/views/view.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/window/dialog_client_view.h"
25 #include "ui/views/window/dialog_delegate.h"
26
27 using content::BrowserThread;
28 using web_modal::WebContentsModalDialogManager;
29 using web_modal::WebContentsModalDialogManagerDelegate;
30
31 namespace {
32
33 const int kMessageWidth = 320;
34 const int kParagraphPadding = 15;
35
36 // Views-specific implementation of download danger prompt dialog. We use this
37 // class rather than a TabModalConfirmDialog so that we can use custom
38 // formatting on the text in the body of the dialog.
39 class DownloadDangerPromptViews : public DownloadDangerPrompt,
40                                   public content::DownloadItem::Observer,
41                                   public views::DialogDelegate {
42  public:
43   DownloadDangerPromptViews(content::DownloadItem* item,
44                             content::WebContents* web_contents,
45                             bool show_context,
46                             const OnDone& done);
47
48   // DownloadDangerPrompt methods:
49   virtual void InvokeActionForTesting(Action action) OVERRIDE;
50
51   // views::DialogDelegate methods:
52   virtual base::string16 GetDialogButtonLabel(
53       ui::DialogButton button) const OVERRIDE;
54   virtual base::string16 GetWindowTitle() const OVERRIDE;
55   virtual void DeleteDelegate() OVERRIDE;
56   virtual ui::ModalType GetModalType() const OVERRIDE;
57   virtual bool Cancel() OVERRIDE;
58   virtual bool Accept() OVERRIDE;
59   virtual bool Close() OVERRIDE;
60   virtual views::View* GetInitiallyFocusedView() OVERRIDE;
61   virtual views::View* GetContentsView() OVERRIDE;
62   virtual views::Widget* GetWidget() OVERRIDE;
63   virtual const views::Widget* GetWidget() const OVERRIDE;
64
65   // content::DownloadItem::Observer:
66   virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
67
68  private:
69   base::string16 GetAcceptButtonTitle() const;
70   base::string16 GetCancelButtonTitle() const;
71   // The message lead is separated from the main text and is bolded.
72   base::string16 GetMessageLead() const;
73   base::string16 GetMessageBody() const;
74   void RunDone(Action action);
75
76   content::DownloadItem* download_;
77   bool show_context_;
78   OnDone done_;
79
80   views::View* contents_view_;
81 };
82
83 DownloadDangerPromptViews::DownloadDangerPromptViews(
84     content::DownloadItem* item,
85     content::WebContents* web_contents,
86     bool show_context,
87     const OnDone& done)
88     : download_(item),
89       show_context_(show_context),
90       done_(done),
91       contents_view_(NULL) {
92   DCHECK(!done_.is_null());
93   download_->AddObserver(this);
94
95   contents_view_ = new views::View;
96
97   views::GridLayout* layout = views::GridLayout::CreatePanel(contents_view_);
98   contents_view_->SetLayoutManager(layout);
99
100   views::ColumnSet* column_set = layout->AddColumnSet(0);
101   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
102                         views::GridLayout::FIXED, kMessageWidth, 0);
103
104   const base::string16 message_lead = GetMessageLead();
105
106   if (!message_lead.empty()) {
107     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
108     views::Label* message_lead_label = new views::Label(
109         message_lead, rb->GetFontList(ui::ResourceBundle::BoldFont));
110     message_lead_label->SetMultiLine(true);
111     message_lead_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
112     message_lead_label->SetAllowCharacterBreak(true);
113
114     layout->StartRow(0, 0);
115     layout->AddView(message_lead_label);
116
117     layout->AddPaddingRow(0, kParagraphPadding);
118   }
119
120   views::Label* message_body_label = new views::Label(GetMessageBody());
121   message_body_label->SetMultiLine(true);
122   message_body_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
123   message_body_label->SetAllowCharacterBreak(true);
124
125   layout->StartRow(0, 0);
126   layout->AddView(message_body_label);
127
128   RecordOpenedDangerousConfirmDialog(download_->GetDangerType());
129 }
130
131 // DownloadDangerPrompt methods:
132 void DownloadDangerPromptViews::InvokeActionForTesting(Action action) {
133   switch (action) {
134     case ACCEPT:
135       Accept();
136       break;
137
138     case CANCEL:
139     case DISMISS:
140       Cancel();
141       break;
142
143     default:
144       NOTREACHED();
145       break;
146   }
147 }
148
149 // views::DialogDelegate methods:
150 base::string16 DownloadDangerPromptViews::GetDialogButtonLabel(
151     ui::DialogButton button) const {
152   switch (button) {
153     case ui::DIALOG_BUTTON_OK:
154       return GetAcceptButtonTitle();
155
156     case ui::DIALOG_BUTTON_CANCEL:
157       return GetCancelButtonTitle();
158
159     default:
160       return DialogDelegate::GetDialogButtonLabel(button);
161   };
162 }
163
164 base::string16 DownloadDangerPromptViews::GetWindowTitle() const {
165   if (show_context_)
166     return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
167   else
168     return l10n_util::GetStringUTF16(IDS_RESTORE_KEEP_DANGEROUS_DOWNLOAD_TITLE);
169 }
170
171 void DownloadDangerPromptViews::DeleteDelegate() {
172   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
173
174   delete this;
175 }
176
177 ui::ModalType DownloadDangerPromptViews::GetModalType() const {
178 #if defined(USE_ASH)
179   return ui::MODAL_TYPE_CHILD;
180 #else
181   return views::WidgetDelegate::GetModalType();
182 #endif
183 }
184
185 bool DownloadDangerPromptViews::Cancel() {
186   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187
188   RunDone(CANCEL);
189   return true;
190 }
191
192 bool DownloadDangerPromptViews::Accept() {
193   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194
195   RunDone(ACCEPT);
196   return true;
197 }
198
199 bool DownloadDangerPromptViews::Close() {
200   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
201
202   RunDone(DISMISS);
203   return true;
204 }
205
206 views::View* DownloadDangerPromptViews::GetInitiallyFocusedView() {
207   return GetDialogClientView()->cancel_button();
208 }
209
210 views::View* DownloadDangerPromptViews::GetContentsView() {
211   return contents_view_;
212 }
213
214 views::Widget* DownloadDangerPromptViews::GetWidget() {
215   return contents_view_->GetWidget();
216 }
217
218 const views::Widget* DownloadDangerPromptViews::GetWidget() const {
219   return contents_view_->GetWidget();
220 }
221
222 // content::DownloadItem::Observer:
223 void DownloadDangerPromptViews::OnDownloadUpdated(
224     content::DownloadItem* download) {
225   // If the download is nolonger dangerous (accepted externally) or the download
226   // is in a terminal state, then the download danger prompt is no longer
227   // necessary.
228   if (!download_->IsDangerous() || download_->IsDone()) {
229     RunDone(DISMISS);
230     Cancel();
231   }
232 }
233
234 base::string16 DownloadDangerPromptViews::GetAcceptButtonTitle() const {
235   if (show_context_)
236     return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
237   switch (download_->GetDangerType()) {
238     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
239     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
240     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
241       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN_MALICIOUS);
242     }
243     default:
244       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN);
245   }
246 }
247
248 base::string16 DownloadDangerPromptViews::GetCancelButtonTitle() const {
249   if (show_context_)
250     return l10n_util::GetStringUTF16(IDS_CANCEL);
251   switch (download_->GetDangerType()) {
252     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
253     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
254     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
255       return l10n_util::GetStringUTF16(IDS_CONFIRM_CANCEL_AGAIN_MALICIOUS);
256     }
257     default:
258       return l10n_util::GetStringUTF16(IDS_CANCEL);
259   }
260 }
261
262 base::string16 DownloadDangerPromptViews::GetMessageLead() const {
263   if (!show_context_) {
264     switch (download_->GetDangerType()) {
265       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
266       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
267       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
268         return l10n_util::GetStringUTF16(
269             IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD);
270
271       default:
272         break;
273     }
274   }
275
276   return base::string16();
277 }
278
279 base::string16 DownloadDangerPromptViews::GetMessageBody() const {
280   if (show_context_) {
281     switch (download_->GetDangerType()) {
282       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
283         return l10n_util::GetStringFUTF16(
284             IDS_PROMPT_DANGEROUS_DOWNLOAD,
285             download_->GetFileNameToReportUser().LossyDisplayName());
286       }
287       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:  // Fall through
288       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
289       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
290         return l10n_util::GetStringFUTF16(
291             IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
292             download_->GetFileNameToReportUser().LossyDisplayName());
293       }
294       case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
295         return l10n_util::GetStringFUTF16(
296             IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
297             download_->GetFileNameToReportUser().LossyDisplayName());
298       }
299       case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
300         return l10n_util::GetStringFUTF16(
301             IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
302             download_->GetFileNameToReportUser().LossyDisplayName());
303       }
304       case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
305       case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
306       case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
307       case content::DOWNLOAD_DANGER_TYPE_MAX: {
308         break;
309       }
310     }
311   } else {
312     switch (download_->GetDangerType()) {
313       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
314       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
315       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
316         return l10n_util::GetStringUTF16(
317             IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY);
318       }
319       default: {
320         return l10n_util::GetStringUTF16(
321             IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
322       }
323     }
324   }
325   NOTREACHED();
326   return base::string16();
327 }
328
329 void DownloadDangerPromptViews::RunDone(Action action) {
330   // Invoking the callback can cause the download item state to change or cause
331   // the window to close, and |callback| refers to a member variable.
332   OnDone done = done_;
333   done_.Reset();
334   if (download_ != NULL) {
335     download_->RemoveObserver(this);
336     download_ = NULL;
337   }
338   if (!done.is_null())
339     done.Run(action);
340 }
341
342 }  // namespace
343
344 DownloadDangerPrompt* DownloadDangerPrompt::Create(
345     content::DownloadItem* item,
346     content::WebContents* web_contents,
347     bool show_context,
348     const OnDone& done) {
349   DownloadDangerPromptViews* download_danger_prompt =
350       new DownloadDangerPromptViews(item, web_contents, show_context, done);
351
352   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
353       WebContentsModalDialogManager::FromWebContents(web_contents);
354   WebContentsModalDialogManagerDelegate* modal_delegate =
355       web_contents_modal_dialog_manager->delegate();
356   CHECK(modal_delegate);
357   views::Widget* dialog = views::Widget::CreateWindowAsFramelessChild(
358       download_danger_prompt,
359       modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
360   web_contents_modal_dialog_manager->ShowDialog(dialog->GetNativeView());
361
362   return download_danger_prompt;
363 }