- add sources.
[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/ui/views/constrained_window_views.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 "content/public/browser/web_contents_view.h"
16 #include "grit/chromium_strings.h"
17 #include "grit/generated_resources.h"
18 #include "ui/base/l10n/l10n_util.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 string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
53   virtual string16 GetWindowTitle() const OVERRIDE;
54   virtual void DeleteDelegate() OVERRIDE;
55   virtual ui::ModalType GetModalType() const OVERRIDE;
56   virtual bool Cancel() OVERRIDE;
57   virtual bool Accept() OVERRIDE;
58   virtual bool Close() OVERRIDE;
59   // TODO(wittman): Remove this override once we move to the new style frame
60   // view on all dialogs.
61   virtual views::NonClientFrameView* CreateNonClientFrameView(
62       views::Widget* widget) OVERRIDE;
63   virtual views::View* GetInitiallyFocusedView() OVERRIDE;
64   virtual views::View* GetContentsView() OVERRIDE;
65   virtual views::Widget* GetWidget() OVERRIDE;
66   virtual const views::Widget* GetWidget() const OVERRIDE;
67
68   // content::DownloadItem::Observer:
69   virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
70
71  private:
72   string16 GetAcceptButtonTitle() const;
73   string16 GetCancelButtonTitle() const;
74   // The message lead is separated from the main text and is bolded.
75   string16 GetMessageLead() const;
76   string16 GetMessageBody() const;
77   void RunDone(Action action);
78
79   content::DownloadItem* download_;
80   content::WebContents* web_contents_;
81   bool show_context_;
82   OnDone done_;
83
84   views::View* contents_view_;
85 };
86
87 DownloadDangerPromptViews::DownloadDangerPromptViews(
88     content::DownloadItem* item,
89     content::WebContents* web_contents,
90     bool show_context,
91     const OnDone& done)
92     : download_(item),
93       web_contents_(web_contents),
94       show_context_(show_context),
95       done_(done),
96       contents_view_(NULL) {
97   DCHECK(!done_.is_null());
98   download_->AddObserver(this);
99
100   contents_view_ = new views::View;
101
102   views::GridLayout* layout = views::GridLayout::CreatePanel(contents_view_);
103   contents_view_->SetLayoutManager(layout);
104
105   views::ColumnSet* column_set = layout->AddColumnSet(0);
106   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
107                         views::GridLayout::FIXED, kMessageWidth, 0);
108
109   const string16 message_lead = GetMessageLead();
110
111   if (!message_lead.empty()) {
112     views::Label* message_lead_label = new views::Label(message_lead);
113     message_lead_label->SetMultiLine(true);
114     message_lead_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
115     message_lead_label->SetAllowCharacterBreak(true);
116
117     gfx::FontList font_list(gfx::Font().DeriveFont(0, gfx::Font::BOLD));
118     message_lead_label->SetFontList(font_list);
119
120     layout->StartRow(0, 0);
121     layout->AddView(message_lead_label);
122
123     layout->AddPaddingRow(0, kParagraphPadding);
124   }
125
126   views::Label* message_body_label = new views::Label(GetMessageBody());
127   message_body_label->SetMultiLine(true);
128   message_body_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
129   message_body_label->SetAllowCharacterBreak(true);
130
131   layout->StartRow(0, 0);
132   layout->AddView(message_body_label);
133 }
134
135 // DownloadDangerPrompt methods:
136 void DownloadDangerPromptViews::InvokeActionForTesting(Action action) {
137   switch (action) {
138     case ACCEPT:
139       Accept();
140       break;
141
142     case CANCEL:
143     case DISMISS:
144       Cancel();
145       break;
146
147     default:
148       NOTREACHED();
149       break;
150   }
151 }
152
153 // views::DialogDelegate methods:
154 string16 DownloadDangerPromptViews::GetDialogButtonLabel(
155     ui::DialogButton button) const {
156   switch (button) {
157     case ui::DIALOG_BUTTON_OK:
158       return GetAcceptButtonTitle();
159
160     case ui::DIALOG_BUTTON_CANCEL:
161       return GetCancelButtonTitle();
162
163     default:
164       return DialogDelegate::GetDialogButtonLabel(button);
165   };
166 }
167
168 string16 DownloadDangerPromptViews::GetWindowTitle() const {
169   if (show_context_)
170     return l10n_util::GetStringUTF16(IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE);
171   else
172     return l10n_util::GetStringUTF16(IDS_RESTORE_KEEP_DANGEROUS_DOWNLOAD_TITLE);
173 }
174
175 void DownloadDangerPromptViews::DeleteDelegate() {
176   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
177
178   delete this;
179 }
180
181 ui::ModalType DownloadDangerPromptViews::GetModalType() const {
182 #if defined(USE_ASH)
183   return ui::MODAL_TYPE_CHILD;
184 #else
185   return views::WidgetDelegate::GetModalType();
186 #endif
187 }
188
189 bool DownloadDangerPromptViews::Cancel() {
190   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191
192   RunDone(CANCEL);
193   return true;
194 }
195
196 bool DownloadDangerPromptViews::Accept() {
197   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198
199   RunDone(ACCEPT);
200   return true;
201 }
202
203 bool DownloadDangerPromptViews::Close() {
204   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
205
206   RunDone(DISMISS);
207   return true;
208 }
209
210 // TODO(wittman): Remove this override once we move to the new style frame
211 // view on all dialogs.
212 views::NonClientFrameView* DownloadDangerPromptViews::CreateNonClientFrameView(
213     views::Widget* widget) {
214   return CreateConstrainedStyleNonClientFrameView(
215       widget,
216       web_contents_->GetBrowserContext());
217 }
218
219 views::View* DownloadDangerPromptViews::GetInitiallyFocusedView() {
220   return GetDialogClientView()->cancel_button();
221 }
222
223 views::View* DownloadDangerPromptViews::GetContentsView() {
224   return contents_view_;
225 }
226
227 views::Widget* DownloadDangerPromptViews::GetWidget() {
228   return contents_view_->GetWidget();
229 }
230
231 const views::Widget* DownloadDangerPromptViews::GetWidget() const {
232   return contents_view_->GetWidget();
233 }
234
235 // content::DownloadItem::Observer:
236 void DownloadDangerPromptViews::OnDownloadUpdated(
237     content::DownloadItem* download) {
238   // If the download is nolonger dangerous (accepted externally) or the download
239   // is in a terminal state, then the download danger prompt is no longer
240   // necessary.
241   if (!download_->IsDangerous() || download_->IsDone()) {
242     RunDone(DISMISS);
243     Cancel();
244   }
245 }
246
247 string16 DownloadDangerPromptViews::GetAcceptButtonTitle() const {
248   if (show_context_)
249     return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD);
250   switch (download_->GetDangerType()) {
251     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
252     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
253     case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
254       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN_MALICIOUS);
255     }
256     default:
257       return l10n_util::GetStringUTF16(IDS_CONFIRM_DOWNLOAD_AGAIN);
258   }
259 }
260
261 string16 DownloadDangerPromptViews::GetCancelButtonTitle() const {
262   if (show_context_)
263     return l10n_util::GetStringUTF16(IDS_CANCEL);
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(IDS_CONFIRM_CANCEL_AGAIN_MALICIOUS);
269     }
270     default:
271       return l10n_util::GetStringUTF16(IDS_CANCEL);
272   }
273 }
274
275 string16 DownloadDangerPromptViews::GetMessageLead() const {
276   if (!show_context_) {
277     switch (download_->GetDangerType()) {
278       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
279       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
280       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
281         return l10n_util::GetStringUTF16(
282             IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_LEAD);
283
284       default:
285         break;
286     }
287   }
288
289   return string16();
290 }
291
292 string16 DownloadDangerPromptViews::GetMessageBody() const {
293   if (show_context_) {
294     switch (download_->GetDangerType()) {
295       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
296         return l10n_util::GetStringFUTF16(
297             IDS_PROMPT_DANGEROUS_DOWNLOAD,
298             download_->GetFileNameToReportUser().LossyDisplayName());
299       }
300       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through
301       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
302       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
303         return l10n_util::GetStringFUTF16(
304             IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
305             download_->GetFileNameToReportUser().LossyDisplayName());
306       }
307       case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
308         return l10n_util::GetStringFUTF16(
309             IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
310             download_->GetFileNameToReportUser().LossyDisplayName());
311       }
312       case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
313         return l10n_util::GetStringFUTF16(
314             IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
315             download_->GetFileNameToReportUser().LossyDisplayName());
316       }
317       case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
318       case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
319       case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
320       case content::DOWNLOAD_DANGER_TYPE_MAX: {
321         break;
322       }
323     }
324   } else {
325     switch (download_->GetDangerType()) {
326       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
327       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
328       case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
329         return l10n_util::GetStringUTF16(
330             IDS_PROMPT_CONFIRM_KEEP_MALICIOUS_DOWNLOAD_BODY);
331       }
332       default: {
333         return l10n_util::GetStringUTF16(
334             IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
335       }
336     }
337   }
338   NOTREACHED();
339   return string16();
340 }
341
342 void DownloadDangerPromptViews::RunDone(Action action) {
343   // Invoking the callback can cause the download item state to change or cause
344   // the window to close, and |callback| refers to a member variable.
345   OnDone done = done_;
346   done_.Reset();
347   if (download_ != NULL) {
348     download_->RemoveObserver(this);
349     download_ = NULL;
350   }
351   if (!done.is_null())
352     done.Run(action);
353 }
354
355 }  // namespace
356
357 DownloadDangerPrompt* DownloadDangerPrompt::Create(
358     content::DownloadItem* item,
359     content::WebContents* web_contents,
360     bool show_context,
361     const OnDone& done) {
362   DownloadDangerPromptViews* download_danger_prompt =
363       new DownloadDangerPromptViews(item, web_contents, show_context, done);
364
365   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
366       WebContentsModalDialogManager::FromWebContents(web_contents);
367   WebContentsModalDialogManagerDelegate* modal_delegate =
368       web_contents_modal_dialog_manager->delegate();
369   CHECK(modal_delegate);
370   views::Widget* dialog = views::Widget::CreateWindowAsFramelessChild(
371       download_danger_prompt,
372       web_contents->GetView()->GetNativeView(),
373       modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
374   web_contents_modal_dialog_manager->ShowDialog(dialog->GetNativeView());
375
376   return download_danger_prompt;
377 }