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 "chrome/browser/browser_process.h"
8 #include "chrome/browser/download/download_crx_util.h"
9 #include "chrome/browser/download/download_item_model.h"
10 #include "chrome/browser/download/download_prefs.h"
11 #include "chrome/browser/safe_browsing/download_protection_service.h"
12 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
13 #include "chrome/common/extensions/extension.h"
14 #include "chrome/common/url_constants.h"
15 #include "content/public/browser/download_item.h"
16 #include "content/public/browser/download_manager.h"
17 #include "content/public/browser/page_navigator.h"
18 #include "grit/generated_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
21 using content::DownloadItem
;
22 using extensions::Extension
;
24 DownloadShelfContextMenu::~DownloadShelfContextMenu() {
25 DetachFromDownloadItem();
28 DownloadShelfContextMenu::DownloadShelfContextMenu(
29 DownloadItem
* download_item
,
30 content::PageNavigator
* navigator
)
31 : download_item_(download_item
),
32 navigator_(navigator
) {
33 DCHECK(download_item_
);
34 download_item_
->AddObserver(this);
37 ui::SimpleMenuModel
* DownloadShelfContextMenu::GetMenuModel() {
38 ui::SimpleMenuModel
* model
= NULL
;
43 DownloadItemModel
download_model(download_item_
);
44 // We shouldn't be opening a context menu for a dangerous download, unless it
45 // is a malicious download.
46 DCHECK(!download_model
.IsDangerous() || download_model
.IsMalicious());
48 if (download_model
.IsMalicious())
49 model
= GetMaliciousMenuModel();
50 else if (download_item_
->IsComplete())
51 model
= GetFinishedMenuModel();
52 else if (download_item_
->IsInterrupted())
53 model
= GetInterruptedMenuModel();
55 model
= GetInProgressMenuModel();
59 bool DownloadShelfContextMenu::IsCommandIdEnabled(int command_id
) const {
63 switch (static_cast<ContextMenuCommands
>(command_id
)) {
65 return download_item_
->CanShowInFolder();
66 case OPEN_WHEN_COMPLETE
:
67 return download_item_
->CanOpenDownload() &&
68 !download_crx_util::IsExtensionDownload(*download_item_
);
69 case ALWAYS_OPEN_TYPE
:
70 // For temporary downloads, the target filename might be a temporary
71 // filename. Don't base an "Always open" decision based on it. Also
72 // exclude extensions.
73 return download_item_
->CanOpenDownload() &&
74 !download_crx_util::IsExtensionDownload(*download_item_
);
76 return download_item_
->IsPartialDownload();
78 return download_item_
->IsInProgress();
81 case LEARN_MORE_SCANNING
:
82 case LEARN_MORE_INTERRUPTED
:
88 bool DownloadShelfContextMenu::IsCommandIdChecked(int command_id
) const {
93 case OPEN_WHEN_COMPLETE
:
94 return download_item_
->GetOpenWhenComplete() ||
95 download_crx_util::IsExtensionDownload(*download_item_
);
96 case ALWAYS_OPEN_TYPE
:
97 return download_item_
->ShouldOpenFileBasedOnExtension();
99 return download_item_
->IsPaused();
104 void DownloadShelfContextMenu::ExecuteCommand(int command_id
, int event_flags
) {
108 switch (static_cast<ContextMenuCommands
>(command_id
)) {
110 download_item_
->ShowDownloadInShell();
112 case OPEN_WHEN_COMPLETE
:
113 download_item_
->OpenDownload();
115 case ALWAYS_OPEN_TYPE
: {
116 DownloadPrefs
* prefs
= DownloadPrefs::FromBrowserContext(
117 download_item_
->GetBrowserContext());
118 base::FilePath path
= download_item_
->GetUserVerifiedFilePath();
119 if (!IsCommandIdChecked(ALWAYS_OPEN_TYPE
))
120 prefs
->EnableAutoOpenBasedOnExtension(path
);
122 prefs
->DisableAutoOpenBasedOnExtension(path
);
126 download_item_
->Cancel(true /* Cancelled by user */);
129 // It is possible for the download to complete before the user clicks the
130 // menu item, recheck if the download is in progress state before toggling
132 if (download_item_
->IsPartialDownload()) {
133 if (download_item_
->IsPaused())
134 download_item_
->Resume();
136 download_item_
->Pause();
140 download_item_
->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD
);
143 download_item_
->DangerousDownloadValidated();
145 case LEARN_MORE_SCANNING
: {
146 #if defined(FULL_SAFE_BROWSING)
147 using safe_browsing::DownloadProtectionService
;
148 SafeBrowsingService
* sb_service
=
149 g_browser_process
->safe_browsing_service();
150 DownloadProtectionService
* protection_service
=
151 (sb_service
? sb_service
->download_protection_service() : NULL
);
152 if (protection_service
) {
153 protection_service
->ShowDetailsForDownload(*download_item_
, navigator_
);
156 // Should only be getting invoked if we are using safe browsing.
161 case LEARN_MORE_INTERRUPTED
:
163 content::OpenURLParams(GURL(chrome::kDownloadInterruptedLearnMoreURL
),
166 content::PAGE_TRANSITION_LINK
,
172 bool DownloadShelfContextMenu::GetAcceleratorForCommandId(
173 int command_id
, ui::Accelerator
* accelerator
) {
177 bool DownloadShelfContextMenu::IsItemForCommandIdDynamic(int command_id
) const {
178 return command_id
== TOGGLE_PAUSE
;
181 string16
DownloadShelfContextMenu::GetLabelForCommandId(int command_id
) const {
182 switch (static_cast<ContextMenuCommands
>(command_id
)) {
184 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_SHOW
);
185 case OPEN_WHEN_COMPLETE
:
186 if (download_item_
&& download_item_
->IsInProgress())
187 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE
);
188 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN
);
189 case ALWAYS_OPEN_TYPE
:
190 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE
);
192 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_CANCEL
);
194 if (download_item_
&& download_item_
->IsPaused())
195 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_RESUME_ITEM
);
196 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_PAUSE_ITEM
);
198 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_DISCARD
);
200 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_KEEP
);
201 case LEARN_MORE_SCANNING
:
202 return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING
);
203 case LEARN_MORE_INTERRUPTED
:
204 return l10n_util::GetStringUTF16(
205 IDS_DOWNLOAD_MENU_LEARN_MORE_INTERRUPTED
);
211 void DownloadShelfContextMenu::DetachFromDownloadItem() {
215 download_item_
->RemoveObserver(this);
216 download_item_
= NULL
;
219 void DownloadShelfContextMenu::OnDownloadDestroyed(DownloadItem
* download
) {
220 DCHECK(download_item_
== download
);
221 DetachFromDownloadItem();
224 ui::SimpleMenuModel
* DownloadShelfContextMenu::GetInProgressMenuModel() {
225 if (in_progress_download_menu_model_
)
226 return in_progress_download_menu_model_
.get();
228 in_progress_download_menu_model_
.reset(new ui::SimpleMenuModel(this));
230 in_progress_download_menu_model_
->AddCheckItemWithStringId(
231 OPEN_WHEN_COMPLETE
, IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE
);
232 in_progress_download_menu_model_
->AddCheckItemWithStringId(
233 ALWAYS_OPEN_TYPE
, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE
);
234 in_progress_download_menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
235 in_progress_download_menu_model_
->AddItemWithStringId(
236 TOGGLE_PAUSE
, IDS_DOWNLOAD_MENU_PAUSE_ITEM
);
237 in_progress_download_menu_model_
->AddItemWithStringId(
238 SHOW_IN_FOLDER
, IDS_DOWNLOAD_MENU_SHOW
);
239 in_progress_download_menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
240 in_progress_download_menu_model_
->AddItemWithStringId(
241 CANCEL
, IDS_DOWNLOAD_MENU_CANCEL
);
243 return in_progress_download_menu_model_
.get();
246 ui::SimpleMenuModel
* DownloadShelfContextMenu::GetFinishedMenuModel() {
247 if (finished_download_menu_model_
)
248 return finished_download_menu_model_
.get();
250 finished_download_menu_model_
.reset(new ui::SimpleMenuModel(this));
252 finished_download_menu_model_
->AddItemWithStringId(
253 OPEN_WHEN_COMPLETE
, IDS_DOWNLOAD_MENU_OPEN
);
254 finished_download_menu_model_
->AddCheckItemWithStringId(
255 ALWAYS_OPEN_TYPE
, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE
);
256 finished_download_menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
257 finished_download_menu_model_
->AddItemWithStringId(
258 SHOW_IN_FOLDER
, IDS_DOWNLOAD_MENU_SHOW
);
259 finished_download_menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
260 finished_download_menu_model_
->AddItemWithStringId(
261 CANCEL
, IDS_DOWNLOAD_MENU_CANCEL
);
263 return finished_download_menu_model_
.get();
266 ui::SimpleMenuModel
* DownloadShelfContextMenu::GetInterruptedMenuModel() {
268 // The Help Center article is currently Windows specific.
269 // TODO(asanka): Enable this for other platforms when the article is expanded
270 // for other platforms.
271 if (interrupted_download_menu_model_
)
272 return interrupted_download_menu_model_
.get();
274 interrupted_download_menu_model_
.reset(new ui::SimpleMenuModel(this));
276 interrupted_download_menu_model_
->AddItemWithStringId(
277 LEARN_MORE_INTERRUPTED
, IDS_DOWNLOAD_MENU_LEARN_MORE_INTERRUPTED
);
279 return interrupted_download_menu_model_
.get();
281 return GetInProgressMenuModel();
285 ui::SimpleMenuModel
* DownloadShelfContextMenu::GetMaliciousMenuModel() {
286 if (malicious_download_menu_model_
)
287 return malicious_download_menu_model_
.get();
289 malicious_download_menu_model_
.reset(new ui::SimpleMenuModel(this));
291 malicious_download_menu_model_
->AddItemWithStringId(
292 DISCARD
, IDS_DOWNLOAD_MENU_DISCARD
);
293 malicious_download_menu_model_
->AddItemWithStringId(
294 KEEP
, IDS_DOWNLOAD_MENU_KEEP
);
295 malicious_download_menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
296 malicious_download_menu_model_
->AddItemWithStringId(
297 LEARN_MORE_SCANNING
, IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING
);
299 return malicious_download_menu_model_
.get();