#include "chrome/browser/chromeos/arc/start_smart_selection_action_menu.h"
#include <algorithm>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/intent_util.h"
#include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/ash/experiences/arc/intent_helper/arc_intent_helper_package.h"
#include "chromeos/ash/experiences/arc/metrics/arc_metrics_constants.h"
#include "components/renderer_context_menu/render_view_context_menu_proxy.h"
#include "components/services/app_service/public/cpp/app_launch_util.h"
#include "components/services/app_service/public/cpp/intent.h"
#include "content/public/browser/context_menu_params.h"
#include "ui/base/models/image_model.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/image/image_skia_operations.h"
namespace arc {
namespace {
apps::IntentPtr CreateIntent(
arc::ArcIntentHelperMojoDelegate::IntentInfo arc_intent,
arc::ArcIntentHelperMojoDelegate::ActivityName activity) {
auto intent = std::make_unique<apps::Intent>(arc_intent.action);
intent->data = std::move(arc_intent.data);
intent->mime_type = std::move(arc_intent.type);
if (arc_intent.categories.has_value())
intent->categories = std::move(arc_intent.categories.value());
intent->ui_bypassed = arc_intent.ui_bypassed;
if (arc_intent.extras.has_value())
intent->extras = std::move(arc_intent.extras.value());
intent->activity_name = std::move(activity.activity_name);
return intent;
}
}
constexpr size_t kMaxMainMenuCommands = 5;
StartSmartSelectionActionMenu::StartSmartSelectionActionMenu(
content::BrowserContext* context,
RenderViewContextMenuProxy* proxy,
std::unique_ptr<ArcIntentHelperMojoDelegate> delegate)
: context_(context), proxy_(proxy), delegate_(std::move(delegate)) {}
StartSmartSelectionActionMenu::~StartSmartSelectionActionMenu() = default;
void StartSmartSelectionActionMenu::InitMenu(
const content::ContextMenuParams& params) {
const std::string converted_text = base::UTF16ToUTF8(params.selection_text);
if (converted_text.empty())
return;
DCHECK(delegate_);
if (!delegate_->IsRequestTextSelectionActionsAvailable()) {
return;
}
if (!delegate_->RequestTextSelectionActions(
converted_text, ui::GetMaxSupportedResourceScaleFactor(),
base::BindOnce(
&StartSmartSelectionActionMenu::HandleTextSelectionActions,
weak_ptr_factory_.GetWeakPtr()))) {
return;
}
base::RecordAction(base::UserMetricsAction("Arc.SmartTextSelection.Request"));
for (size_t i = 0; i < kMaxMainMenuCommands; ++i) {
proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 + i,
std::u16string());
}
}
bool StartSmartSelectionActionMenu::IsCommandIdSupported(int command_id) {
return command_id >= IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 &&
command_id <= IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION_LAST;
}
bool StartSmartSelectionActionMenu::IsCommandIdChecked(int command_id) {
return false;
}
bool StartSmartSelectionActionMenu::IsCommandIdEnabled(int command_id) {
return true;
}
void StartSmartSelectionActionMenu::ExecuteCommand(int command_id) {
if (!IsCommandIdSupported(command_id))
return;
size_t index = command_id - IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1;
if (actions_.size() <= index)
return;
gfx::Point point = display::Screen::Get()->GetCursorScreenPoint();
display::Display display =
display::Screen::Get()->GetDisplayNearestPoint(point);
Profile* profile = Profile::FromBrowserContext(context_);
if (actions_[index].activity.package_name ==
arc::kArcIntentHelperPackageName) {
delegate_->HandleIntent(std::move(actions_[index].action_intent),
internal::ActivityIconLoader::ActivityName(
actions_[index].activity.package_name,
actions_[index].activity.activity_name));
return;
}
apps::AppServiceProxyFactory::GetForProfile(profile)->LaunchAppWithIntent(
actions_[index].app_id, ui::EF_NONE,
CreateIntent(std::move(actions_[index].action_intent),
std::move(actions_[index].activity)),
apps::LaunchSource::kFromSmartTextContextMenu,
std::make_unique<apps::WindowInfo>(display.id()), base::DoNothing());
}
void StartSmartSelectionActionMenu::OnContextMenuShown(
const content::ContextMenuParams& params,
const gfx::Rect& rect) {
for (size_t i = 0; i < kMaxMainMenuCommands; i++) {
proxy_->UpdateMenuItem(
IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 + i,
false,
true,
std::u16string());
}
}
void StartSmartSelectionActionMenu::HandleTextSelectionActions(
std::vector<ArcIntentHelperMojoDelegate::TextSelectionAction> actions) {
actions_ = std::move(actions);
for (size_t i = 0; i < actions_.size(); ++i) {
proxy_->UpdateMenuItem(
IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 + i,
true,
false,
base::UTF8ToUTF16(actions_[i].title));
proxy_->UpdateMenuIcon(
IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 + i,
ui::ImageModel::FromImageSkia(std::move(actions_[i].icon)));
}
for (size_t i = actions_.size(); i < kMaxMainMenuCommands; ++i) {
proxy_->RemoveMenuItem(IDC_CONTENT_CONTEXT_START_SMART_SELECTION_ACTION1 +
i);
}
proxy_->RemoveAdjacentSeparators();
}
}