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