blob: 8a6df465eb3fb60992089c4eb6bcdb81a2164022 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/download/download_shelf_context_menu.h"
#include <memory>
#include "build/build_config.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_commands.h"
#include "chrome/grit/generated_resources.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/common/content_features.h"
#include "extensions/common/extension.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/gfx/color_palette.h"
#if defined(OS_WIN)
#include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
#endif
using MixedContentStatus = download::DownloadItem::MixedContentStatus;
bool DownloadShelfContextMenu::WantsContextMenu(
DownloadUIModel* download_model) {
return !download_model->IsDangerous() || download_model->MightBeMalicious() ||
download_model->IsMixedContent();
}
DownloadShelfContextMenu::~DownloadShelfContextMenu() {
DetachFromDownloadItem();
}
DownloadShelfContextMenu::DownloadShelfContextMenu(
base::WeakPtr<DownloadUIModel> download)
: download_(download), download_commands_(new DownloadCommands(download)) {
DCHECK(download_);
download_->AddObserver(this);
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetMenuModel() {
ui::SimpleMenuModel* model = nullptr;
if (!download_)
return nullptr;
DCHECK(WantsContextMenu(download_.get()));
bool is_download = download_->download() != nullptr;
if (download_->IsMixedContent()) {
model = GetMixedContentDownloadMenuModel();
} else if (ChromeDownloadManagerDelegate::IsDangerTypeBlocked(
download_->GetDangerType())) {
model = GetInterruptedMenuModel(is_download);
} else if (download_->GetDangerType() ==
download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING) {
model = GetDeepScanningMenuModel(is_download);
} else if (download_->IsMalicious()) {
model = GetMaliciousMenuModel(is_download);
} else if (download_->MightBeMalicious()) {
model = GetMaybeMaliciousMenuModel(is_download);
} else if (download_->GetState() == download::DownloadItem::COMPLETE) {
model = GetFinishedMenuModel(is_download);
} else if (download_->GetState() == download::DownloadItem::INTERRUPTED) {
model = GetInterruptedMenuModel(is_download);
} else if (download_->IsPaused()) {
model = GetInProgressPausedMenuModel(is_download);
} else {
model = GetInProgressMenuModel(is_download);
}
return model;
}
bool DownloadShelfContextMenu::IsCommandIdEnabled(int command_id) const {
if (!download_commands_)
return false;
return download_commands_->IsCommandEnabled(
static_cast<DownloadCommands::Command>(command_id));
}
bool DownloadShelfContextMenu::IsCommandIdChecked(int command_id) const {
if (!download_commands_)
return false;
return download_commands_->IsCommandChecked(
static_cast<DownloadCommands::Command>(command_id));
}
bool DownloadShelfContextMenu::IsCommandIdVisible(int command_id) const {
if (!download_commands_)
return false;
return download_commands_->IsCommandVisible(
static_cast<DownloadCommands::Command>(command_id));
}
void DownloadShelfContextMenu::ExecuteCommand(int command_id, int event_flags) {
if (!download_commands_)
return;
download_commands_->ExecuteCommand(
static_cast<DownloadCommands::Command>(command_id));
}
bool DownloadShelfContextMenu::IsItemForCommandIdDynamic(int command_id) const {
return false;
}
std::u16string DownloadShelfContextMenu::GetLabelForCommandId(
int command_id) const {
int id = -1;
switch (static_cast<DownloadCommands::Command>(command_id)) {
case DownloadCommands::OPEN_WHEN_COMPLETE:
if (download_ && !download_->IsDone())
id = IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE;
else
id = IDS_DOWNLOAD_MENU_OPEN;
break;
case DownloadCommands::PAUSE:
id = IDS_DOWNLOAD_MENU_PAUSE_ITEM;
break;
case DownloadCommands::RESUME:
id = IDS_DOWNLOAD_MENU_RESUME_ITEM;
break;
case DownloadCommands::SHOW_IN_FOLDER:
id = IDS_DOWNLOAD_MENU_SHOW;
break;
case DownloadCommands::DISCARD:
id = IDS_DOWNLOAD_MENU_DISCARD;
break;
case DownloadCommands::KEEP:
id = IDS_DOWNLOAD_MENU_KEEP;
break;
case DownloadCommands::ALWAYS_OPEN_TYPE: {
if (download_commands_) {
bool can_open_pdf_in_system_viewer =
download_commands_->CanOpenPdfInSystemViewer();
if (can_open_pdf_in_system_viewer) {
id = IDS_DOWNLOAD_MENU_PLATFORM_OPEN_ALWAYS;
#if defined(OS_WIN)
if (IsAdobeReaderDefaultPDFViewer())
id = IDS_DOWNLOAD_MENU_ALWAYS_OPEN_PDF_IN_READER;
#endif // defined(_OS_WIN)
break;
}
}
id = IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE;
break;
}
case DownloadCommands::PLATFORM_OPEN:
id = IDS_DOWNLOAD_MENU_PLATFORM_OPEN;
break;
case DownloadCommands::CANCEL:
id = IDS_DOWNLOAD_MENU_CANCEL;
break;
case DownloadCommands::LEARN_MORE_SCANNING:
id = IDS_DOWNLOAD_MENU_LEARN_MORE_SCANNING;
break;
case DownloadCommands::LEARN_MORE_INTERRUPTED:
id = IDS_DOWNLOAD_MENU_LEARN_MORE_INTERRUPTED;
break;
case DownloadCommands::LEARN_MORE_MIXED_CONTENT:
id = IDS_DOWNLOAD_MENU_LEARN_MORE_MIXED_CONTENT;
break;
case DownloadCommands::COPY_TO_CLIPBOARD:
case DownloadCommands::ANNOTATE:
// These commands are implemented only for the Download notification.
NOTREACHED();
break;
case DownloadCommands::DEEP_SCAN:
id = IDS_DOWNLOAD_MENU_DEEP_SCAN;
break;
case DownloadCommands::BYPASS_DEEP_SCANNING:
id = IDS_OPEN_DOWNLOAD_NOW;
break;
}
CHECK(id != -1);
return l10n_util::GetStringUTF16(id);
}
void DownloadShelfContextMenu::DetachFromDownloadItem() {
if (!download_)
return;
download_commands_.reset();
download_->RemoveObserver(this);
download_ = nullptr;
}
void DownloadShelfContextMenu::OnDownloadDestroyed() {
DetachFromDownloadItem();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressMenuModel(
bool is_download) {
if (in_progress_download_menu_model_)
return in_progress_download_menu_model_.get();
in_progress_download_menu_model_ =
std::make_unique<ui::SimpleMenuModel>(this);
if (is_download) {
in_progress_download_menu_model_->AddCheckItem(
DownloadCommands::OPEN_WHEN_COMPLETE,
GetLabelForCommandId(DownloadCommands::OPEN_WHEN_COMPLETE));
AddAutoOpenToMenu(in_progress_download_menu_model_.get());
in_progress_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
}
in_progress_download_menu_model_->AddItem(
DownloadCommands::PAUSE, GetLabelForCommandId(DownloadCommands::PAUSE));
if (is_download) {
in_progress_download_menu_model_->AddItem(
DownloadCommands::SHOW_IN_FOLDER,
GetLabelForCommandId(DownloadCommands::SHOW_IN_FOLDER));
}
in_progress_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
in_progress_download_menu_model_->AddItem(
DownloadCommands::CANCEL, GetLabelForCommandId(DownloadCommands::CANCEL));
return in_progress_download_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressPausedMenuModel(
bool is_download) {
if (in_progress_download_paused_menu_model_)
return in_progress_download_paused_menu_model_.get();
in_progress_download_paused_menu_model_ =
std::make_unique<ui::SimpleMenuModel>(this);
if (is_download) {
in_progress_download_paused_menu_model_->AddCheckItem(
DownloadCommands::OPEN_WHEN_COMPLETE,
GetLabelForCommandId(DownloadCommands::OPEN_WHEN_COMPLETE));
AddAutoOpenToMenu(in_progress_download_paused_menu_model_.get());
in_progress_download_paused_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
}
in_progress_download_paused_menu_model_->AddItem(
DownloadCommands::RESUME, GetLabelForCommandId(DownloadCommands::RESUME));
if (is_download) {
in_progress_download_paused_menu_model_->AddItem(
DownloadCommands::SHOW_IN_FOLDER,
GetLabelForCommandId(DownloadCommands::SHOW_IN_FOLDER));
}
in_progress_download_paused_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
in_progress_download_paused_menu_model_->AddItem(
DownloadCommands::CANCEL, GetLabelForCommandId(DownloadCommands::CANCEL));
return in_progress_download_paused_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetFinishedMenuModel(
bool is_download) {
if (finished_download_menu_model_)
return finished_download_menu_model_.get();
finished_download_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
if (is_download) {
finished_download_menu_model_->AddItem(
DownloadCommands::OPEN_WHEN_COMPLETE,
GetLabelForCommandId(DownloadCommands::OPEN_WHEN_COMPLETE));
}
finished_download_menu_model_->AddItem(
DownloadCommands::PLATFORM_OPEN,
GetLabelForCommandId(DownloadCommands::PLATFORM_OPEN));
if (is_download) {
AddAutoOpenToMenu(finished_download_menu_model_.get());
}
finished_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
if (is_download) {
finished_download_menu_model_->AddItem(
DownloadCommands::SHOW_IN_FOLDER,
GetLabelForCommandId(DownloadCommands::SHOW_IN_FOLDER));
finished_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
}
finished_download_menu_model_->AddItem(
DownloadCommands::CANCEL, GetLabelForCommandId(DownloadCommands::CANCEL));
return finished_download_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetInterruptedMenuModel(
bool is_download) {
if (interrupted_download_menu_model_)
return interrupted_download_menu_model_.get();
interrupted_download_menu_model_ =
std::make_unique<ui::SimpleMenuModel>(this);
interrupted_download_menu_model_->AddItem(
DownloadCommands::RESUME, GetLabelForCommandId(DownloadCommands::RESUME));
#if defined(OS_WIN)
// The Help Center article is currently Windows specific.
// TODO(asanka): Enable this for other platforms when the article is expanded
// for other platforms.
interrupted_download_menu_model_->AddItem(
DownloadCommands::LEARN_MORE_INTERRUPTED,
GetLabelForCommandId(DownloadCommands::LEARN_MORE_INTERRUPTED));
#endif
interrupted_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
interrupted_download_menu_model_->AddItem(
DownloadCommands::CANCEL, GetLabelForCommandId(DownloadCommands::CANCEL));
return interrupted_download_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetMaybeMaliciousMenuModel(
bool is_download) {
if (maybe_malicious_download_menu_model_)
return maybe_malicious_download_menu_model_.get();
maybe_malicious_download_menu_model_ =
std::make_unique<ui::SimpleMenuModel>(this);
maybe_malicious_download_menu_model_->AddItem(
DownloadCommands::KEEP, GetLabelForCommandId(DownloadCommands::KEEP));
maybe_malicious_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
maybe_malicious_download_menu_model_->AddItem(
DownloadCommands::LEARN_MORE_SCANNING,
GetLabelForCommandId(DownloadCommands::LEARN_MORE_SCANNING));
return maybe_malicious_download_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetMaliciousMenuModel(
bool is_download) {
if (malicious_download_menu_model_)
return malicious_download_menu_model_.get();
malicious_download_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
malicious_download_menu_model_->AddItem(
DownloadCommands::LEARN_MORE_SCANNING,
GetLabelForCommandId(DownloadCommands::LEARN_MORE_SCANNING));
return malicious_download_menu_model_.get();
}
ui::SimpleMenuModel* DownloadShelfContextMenu::GetDeepScanningMenuModel(
bool is_download) {
if (deep_scanning_menu_model_)
return deep_scanning_menu_model_.get();
deep_scanning_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
deep_scanning_menu_model_->AddItem(
DownloadCommands::DEEP_SCAN,
GetLabelForCommandId(DownloadCommands::DEEP_SCAN));
deep_scanning_menu_model_->AddItem(
DownloadCommands::DISCARD,
GetLabelForCommandId(DownloadCommands::DISCARD));
deep_scanning_menu_model_->AddItem(
DownloadCommands::BYPASS_DEEP_SCANNING,
GetLabelForCommandId(DownloadCommands::BYPASS_DEEP_SCANNING));
deep_scanning_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
if (is_download) {
deep_scanning_menu_model_->AddItem(
DownloadCommands::SHOW_IN_FOLDER,
GetLabelForCommandId(DownloadCommands::SHOW_IN_FOLDER));
deep_scanning_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
}
deep_scanning_menu_model_->AddItem(
DownloadCommands::CANCEL, GetLabelForCommandId(DownloadCommands::CANCEL));
return deep_scanning_menu_model_.get();
}
ui::SimpleMenuModel*
DownloadShelfContextMenu::GetMixedContentDownloadMenuModel() {
if (mixed_content_download_menu_model_)
return mixed_content_download_menu_model_.get();
mixed_content_download_menu_model_ =
std::make_unique<ui::SimpleMenuModel>(this);
if (download_->GetMixedContentStatus() == MixedContentStatus::WARN) {
mixed_content_download_menu_model_->AddItem(
DownloadCommands::DISCARD,
GetLabelForCommandId(DownloadCommands::DISCARD));
} else {
mixed_content_download_menu_model_->AddItem(
DownloadCommands::KEEP, GetLabelForCommandId(DownloadCommands::KEEP));
}
mixed_content_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
mixed_content_download_menu_model_->AddItem(
DownloadCommands::LEARN_MORE_MIXED_CONTENT,
GetLabelForCommandId(DownloadCommands::LEARN_MORE_MIXED_CONTENT));
return mixed_content_download_menu_model_.get();
}
void DownloadShelfContextMenu::AddAutoOpenToMenu(ui::SimpleMenuModel* menu) {
if (!download_)
return;
if (download_->IsOpenWhenCompleteByPolicy()) {
menu->AddItemWithIcon(
DownloadCommands::ALWAYS_OPEN_TYPE,
GetLabelForCommandId(DownloadCommands::ALWAYS_OPEN_TYPE),
ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon,
gfx::kChromeIconGrey,
ui::SimpleMenuModel::kDefaultIconSize));
} else {
menu->AddCheckItem(
DownloadCommands::ALWAYS_OPEN_TYPE,
GetLabelForCommandId(DownloadCommands::ALWAYS_OPEN_TYPE));
}
}