Implement new dangerous download reporting dialog for UNCOMMON_DOWNLOAD, in Views
[chromium-blink-merge.git] / chrome / browser / download / download_shelf_context_menu.cc
blob2d772f47ea0167692d45202de03c181d5a78c3bd
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.
5 #include "chrome/browser/download/download_shelf_context_menu.h"
7 #include "base/command_line.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/download/download_crx_util.h"
10 #include "chrome/browser/download/download_item_model.h"
11 #include "chrome/browser/download/download_prefs.h"
12 #include "chrome/browser/safe_browsing/download_feedback_service.h"
13 #include "chrome/browser/safe_browsing/download_protection_service.h"
14 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/download_item.h"
17 #include "content/public/browser/download_manager.h"
18 #include "content/public/browser/page_navigator.h"
19 #include "content/public/common/content_switches.h"
20 #include "extensions/common/extension.h"
21 #include "grit/generated_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
24 using content::DownloadItem;
25 using extensions::Extension;
27 namespace {
29 // Returns true if downloads resumption is enabled.
30 bool IsDownloadResumptionEnabled() {
31 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
32 return command_line.HasSwitch(switches::kEnableDownloadResumption);
35 } // namespace
37 DownloadShelfContextMenu::~DownloadShelfContextMenu() {
38 DetachFromDownloadItem();
41 DownloadShelfContextMenu::DownloadShelfContextMenu(
42 DownloadItem* download_item,
43 content::PageNavigator* navigator)
44 : download_item_(download_item),
45 navigator_(navigator) {
46 DCHECK(download_item_);
47 download_item_->AddObserver(this);
50 ui::SimpleMenuModel* DownloadShelfContextMenu::GetMenuModel() {
51 ui::SimpleMenuModel* model = NULL;
53 if (!download_item_)
54 return NULL;
56 DownloadItemModel download_model(download_item_);
57 // We shouldn't be opening a context menu for a dangerous download, unless it
58 // is a malicious download.
59 DCHECK(!download_model.IsDangerous() || download_model.MightBeMalicious());
61 if (download_model.IsMalicious())
62 model = GetMaliciousMenuModel();
63 else if (download_model.MightBeMalicious())
64 model = GetMaybeMaliciousMenuModel();
65 else if (download_item_->GetState() == DownloadItem::COMPLETE)
66 model = GetFinishedMenuModel();
67 else if (download_item_->GetState() == DownloadItem::INTERRUPTED)
68 model = GetInterruptedMenuModel();
69 else
70 model = GetInProgressMenuModel();
71 return model;
74 bool DownloadShelfContextMenu::IsCommandIdEnabled(int command_id) const {
75 if (!download_item_)
76 return false;
78 switch (static_cast<ContextMenuCommands>(command_id)) {
79 case SHOW_IN_FOLDER:
80 return download_item_->CanShowInFolder();
81 case OPEN_WHEN_COMPLETE:
82 case PLATFORM_OPEN:
83 return download_item_->CanOpenDownload() &&
84 !download_crx_util::IsExtensionDownload(*download_item_);
85 case ALWAYS_OPEN_TYPE:
86 // For temporary downloads, the target filename might be a temporary
87 // filename. Don't base an "Always open" decision based on it. Also
88 // exclude extensions.
89 return download_item_->CanOpenDownload() &&
90 !download_crx_util::IsExtensionDownload(*download_item_);
91 case CANCEL:
92 return !download_item_->IsDone();
93 case TOGGLE_PAUSE:
94 return !download_item_->IsDone();
95 case DISCARD:
96 case KEEP:
97 case REPORT:
98 case LEARN_MORE_SCANNING:
99 case LEARN_MORE_INTERRUPTED:
100 return true;
102 return false;
105 bool DownloadShelfContextMenu::IsCommandIdChecked(int command_id) const {
106 if (!download_item_)
107 return false;
109 switch (command_id) {
110 case OPEN_WHEN_COMPLETE:
111 return download_item_->GetOpenWhenComplete() ||
112 download_crx_util::IsExtensionDownload(*download_item_);
113 case ALWAYS_OPEN_TYPE:
114 return download_item_->ShouldOpenFileBasedOnExtension();
115 case TOGGLE_PAUSE:
116 return download_item_->IsPaused();
118 return false;
121 void DownloadShelfContextMenu::ExecuteCommand(int command_id, int event_flags) {
122 if (!download_item_)
123 return;
125 switch (static_cast<ContextMenuCommands>(command_id)) {
126 case SHOW_IN_FOLDER:
127 download_item_->ShowDownloadInShell();
128 break;
129 case OPEN_WHEN_COMPLETE:
130 download_item_->OpenDownload();
131 break;
132 case ALWAYS_OPEN_TYPE: {
133 DownloadPrefs* prefs = DownloadPrefs::FromBrowserContext(
134 download_item_->GetBrowserContext());
135 base::FilePath path = download_item_->GetTargetFilePath();
136 if (!IsCommandIdChecked(ALWAYS_OPEN_TYPE))
137 prefs->EnableAutoOpenBasedOnExtension(path);
138 else
139 prefs->DisableAutoOpenBasedOnExtension(path);
140 break;
142 case PLATFORM_OPEN:
143 DownloadItemModel(download_item_).OpenUsingPlatformHandler();
144 break;
145 case CANCEL:
146 download_item_->Cancel(true /* Cancelled by user */);
147 break;
148 case TOGGLE_PAUSE:
149 if (download_item_->GetState() == DownloadItem::IN_PROGRESS &&
150 !download_item_->IsPaused()) {
151 download_item_->Pause();
152 } else {
153 download_item_->Resume();
155 break;
156 case DISCARD:
157 download_item_->Remove();
158 break;
159 case KEEP:
160 download_item_->ValidateDangerousDownload();
161 break;
162 case REPORT: {
163 #if defined(FULL_SAFE_BROWSING)
164 using safe_browsing::DownloadProtectionService;
165 DownloadItemModel download_model(download_item_);
166 if (!download_model.ShouldAllowDownloadFeedback())
167 break;
168 SafeBrowsingService* sb_service =
169 g_browser_process->safe_browsing_service();
170 DownloadProtectionService* protection_service =
171 (sb_service ? sb_service->download_protection_service() : NULL);
172 if (protection_service) {
173 protection_service->feedback_service()->BeginFeedbackForDownload(
174 download_item_);
176 #else
177 // Should only be getting invoked if we are using safe browsing.
178 NOTREACHED();
179 #endif
180 break;
182 case LEARN_MORE_SCANNING: {
183 #if defined(FULL_SAFE_BROWSING)
184 using safe_browsing::DownloadProtectionService;
185 SafeBrowsingService* sb_service =
186 g_browser_process->safe_browsing_service();
187 DownloadProtectionService* protection_service =
188 (sb_service ? sb_service->download_protection_service() : NULL);
189 if (protection_service) {
190 protection_service->ShowDetailsForDownload(*download_item_, navigator_);
192 #else
193 // Should only be getting invoked if we are using safe browsing.
194 NOTREACHED();
195 #endif
196 break;
198 case LEARN_MORE_INTERRUPTED:
199 navigator_->OpenURL(
200 content::OpenURLParams(GURL(chrome::kDownloadInterruptedLearnMoreURL),
201 content::Referrer(),
202 NEW_FOREGROUND_TAB,
203 content::PAGE_TRANSITION_LINK,
204 false));
205 break;
209 bool DownloadShelfContextMenu::GetAcceleratorForCommandId(
210 int command_id, ui::Accelerator* accelerator) {
211 return false;
214 bool DownloadShelfContextMenu::IsItemForCommandIdDynamic(int command_id) const {
215 return command_id == TOGGLE_PAUSE;
218 base::string16 DownloadShelfContextMenu::GetLabelForCommandId(
219 int command_id) const {
220 switch (static_cast<ContextMenuCommands>(command_id)) {
221 case SHOW_IN_FOLDER:
222 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_SHOW);
223 case OPEN_WHEN_COMPLETE:
224 if (download_item_ && !download_item_->IsDone())
225 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
226 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN);
227 case ALWAYS_OPEN_TYPE:
228 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
229 case PLATFORM_OPEN:
230 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_PLATFORM_OPEN);
231 case CANCEL:
232 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_CANCEL);
233 case TOGGLE_PAUSE:
234 if (download_item_ &&
235 download_item_->GetState() == DownloadItem::IN_PROGRESS &&
236 !download_item_->IsPaused())
237 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_PAUSE_ITEM);
238 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_RESUME_ITEM);
239 case DISCARD:
240 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_DISCARD);
241 case REPORT:
242 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_REPORT);
243 case KEEP:
244 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_KEEP);
245 case LEARN_MORE_SCANNING:
246 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING);
247 case LEARN_MORE_INTERRUPTED:
248 return l10n_util::GetStringUTF16(
249 IDS_DOWNLOAD_MENU_LEARN_MORE_INTERRUPTED);
251 NOTREACHED();
252 return base::string16();
255 void DownloadShelfContextMenu::DetachFromDownloadItem() {
256 if (!download_item_)
257 return;
259 download_item_->RemoveObserver(this);
260 download_item_ = NULL;
263 void DownloadShelfContextMenu::OnDownloadDestroyed(DownloadItem* download) {
264 DCHECK(download_item_ == download);
265 DetachFromDownloadItem();
268 ui::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressMenuModel() {
269 if (in_progress_download_menu_model_)
270 return in_progress_download_menu_model_.get();
272 in_progress_download_menu_model_.reset(new ui::SimpleMenuModel(this));
274 in_progress_download_menu_model_->AddCheckItemWithStringId(
275 OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
276 in_progress_download_menu_model_->AddCheckItemWithStringId(
277 ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
278 in_progress_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
279 in_progress_download_menu_model_->AddItemWithStringId(
280 TOGGLE_PAUSE, IDS_DOWNLOAD_MENU_PAUSE_ITEM);
281 in_progress_download_menu_model_->AddItemWithStringId(
282 SHOW_IN_FOLDER, IDS_DOWNLOAD_MENU_SHOW);
283 in_progress_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
284 in_progress_download_menu_model_->AddItemWithStringId(
285 CANCEL, IDS_DOWNLOAD_MENU_CANCEL);
287 return in_progress_download_menu_model_.get();
290 ui::SimpleMenuModel* DownloadShelfContextMenu::GetFinishedMenuModel() {
291 if (finished_download_menu_model_)
292 return finished_download_menu_model_.get();
294 finished_download_menu_model_.reset(new ui::SimpleMenuModel(this));
296 finished_download_menu_model_->AddItemWithStringId(
297 OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN);
298 finished_download_menu_model_->AddCheckItemWithStringId(
299 ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
300 if (DownloadItemModel(download_item_).ShouldPreferOpeningInBrowser())
301 finished_download_menu_model_->AddItemWithStringId(
302 PLATFORM_OPEN, IDS_DOWNLOAD_MENU_PLATFORM_OPEN);
303 finished_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
304 finished_download_menu_model_->AddItemWithStringId(
305 SHOW_IN_FOLDER, IDS_DOWNLOAD_MENU_SHOW);
306 finished_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
307 finished_download_menu_model_->AddItemWithStringId(
308 CANCEL, IDS_DOWNLOAD_MENU_CANCEL);
310 return finished_download_menu_model_.get();
313 ui::SimpleMenuModel* DownloadShelfContextMenu::GetInterruptedMenuModel() {
314 #if !defined(OS_WIN)
315 // If resumption isn't enabled and we aren't on Windows, then none of the
316 // options here are applicable.
317 if (!IsDownloadResumptionEnabled())
318 return GetInProgressMenuModel();
319 #endif
321 if (interrupted_download_menu_model_)
322 return interrupted_download_menu_model_.get();
324 interrupted_download_menu_model_.reset(new ui::SimpleMenuModel(this));
326 if (IsDownloadResumptionEnabled()) {
327 interrupted_download_menu_model_->AddItemWithStringId(
328 TOGGLE_PAUSE, IDS_DOWNLOAD_MENU_RESUME_ITEM);
330 #if defined(OS_WIN)
331 // The Help Center article is currently Windows specific.
332 // TODO(asanka): Enable this for other platforms when the article is expanded
333 // for other platforms.
334 interrupted_download_menu_model_->AddItemWithStringId(
335 LEARN_MORE_INTERRUPTED, IDS_DOWNLOAD_MENU_LEARN_MORE_INTERRUPTED);
336 #endif
337 if (IsDownloadResumptionEnabled()) {
338 interrupted_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
339 interrupted_download_menu_model_->AddItemWithStringId(
340 CANCEL, IDS_DOWNLOAD_MENU_CANCEL);
343 return interrupted_download_menu_model_.get();
346 ui::SimpleMenuModel* DownloadShelfContextMenu::GetMaybeMaliciousMenuModel() {
347 if (maybe_malicious_download_menu_model_)
348 return maybe_malicious_download_menu_model_.get();
350 maybe_malicious_download_menu_model_.reset(new ui::SimpleMenuModel(this));
352 maybe_malicious_download_menu_model_->AddItemWithStringId(
353 KEEP, IDS_DOWNLOAD_MENU_KEEP);
354 maybe_malicious_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
355 maybe_malicious_download_menu_model_->AddItemWithStringId(
356 LEARN_MORE_SCANNING, IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING);
357 return maybe_malicious_download_menu_model_.get();
360 ui::SimpleMenuModel*
361 DownloadShelfContextMenu::GetMaliciousMenuModel() {
362 if (malicious_download_menu_model_)
363 return malicious_download_menu_model_.get();
365 malicious_download_menu_model_.reset(new ui::SimpleMenuModel(this));
367 DownloadItemModel download_model(download_item_);
368 if (download_model.ShouldAllowDownloadFeedback()) {
369 malicious_download_menu_model_->AddItemWithStringId(
370 REPORT, IDS_DOWNLOAD_MENU_REPORT);
372 malicious_download_menu_model_->AddItemWithStringId(
373 LEARN_MORE_SCANNING, IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING);
375 return malicious_download_menu_model_.get();