blob: 8d16682c885994b9313dd13406a859f903d2867b [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/input_method/editor_panel_manager.h"
#include <string_view>
#include <utility>
#include "ash/constants/ash_features.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/notreached.h"
#include "chrome/browser/ash/input_method/editor_consent_enums.h"
#include "chrome/browser/ash/input_method/editor_metrics_enums.h"
#include "chrome/browser/ash/input_method/editor_metrics_recorder.h"
#include "chromeos/crosapi/mojom/editor_panel.mojom.h"
namespace ash::input_method {
namespace {
crosapi::mojom::EditorPanelPresetQueryCategory ToEditorPanelQueryCategory(
const orca::mojom::PresetTextQueryType query_type) {
switch (query_type) {
case orca::mojom::PresetTextQueryType::kUnknown:
return crosapi::mojom::EditorPanelPresetQueryCategory::kUnknown;
case orca::mojom::PresetTextQueryType::kShorten:
return crosapi::mojom::EditorPanelPresetQueryCategory::kShorten;
case orca::mojom::PresetTextQueryType::kElaborate:
return crosapi::mojom::EditorPanelPresetQueryCategory::kElaborate;
case orca::mojom::PresetTextQueryType::kRephrase:
return crosapi::mojom::EditorPanelPresetQueryCategory::kRephrase;
case orca::mojom::PresetTextQueryType::kFormalize:
return crosapi::mojom::EditorPanelPresetQueryCategory::kFormalize;
case orca::mojom::PresetTextQueryType::kEmojify:
return crosapi::mojom::EditorPanelPresetQueryCategory::kEmojify;
case orca::mojom::PresetTextQueryType::kProofread:
return crosapi::mojom::EditorPanelPresetQueryCategory::kProofread;
}
}
crosapi::mojom::EditorPanelMode GetEditorPanelMode(EditorMode editor_mode) {
switch (editor_mode) {
case EditorMode::kBlocked:
return crosapi::mojom::EditorPanelMode::kBlocked;
case EditorMode::kConsentNeeded:
return crosapi::mojom::EditorPanelMode::kPromoCard;
case EditorMode::kRewrite:
return crosapi::mojom::EditorPanelMode::kRewrite;
case EditorMode::kWrite:
return crosapi::mojom::EditorPanelMode::kWrite;
}
}
crosapi::mojom::EditorPanelPresetTextQueryPtr ToEditorPanelQuery(
const orca::mojom::PresetTextQueryPtr& orca_query) {
auto editor_panel_query = crosapi::mojom::EditorPanelPresetTextQuery::New();
editor_panel_query->text_query_id = orca_query->id;
editor_panel_query->name = orca_query->label;
editor_panel_query->description = orca_query->description;
editor_panel_query->category = ToEditorPanelQueryCategory(orca_query->type);
return editor_panel_query;
}
} // namespace
EditorPanelManager::EditorPanelManager(Delegate* delegate)
: delegate_(delegate) {}
EditorPanelManager::~EditorPanelManager() = default;
void EditorPanelManager::BindReceiver(
mojo::PendingReceiver<crosapi::mojom::EditorPanelManager>
pending_receiver) {
receivers_.Add(this, std::move(pending_receiver));
}
void EditorPanelManager::BindEditorClient() {
if (!editor_client_remote_.is_bound()) {
delegate_->BindEditorClient(
editor_client_remote_.BindNewPipeAndPassReceiver());
editor_client_remote_.reset_on_disconnect();
}
}
void EditorPanelManager::GetEditorPanelContext(
GetEditorPanelContextCallback callback) {
// Force fetching and updating the input context.
// TODO: b:332605855 - Remove this hack after input context is fetched within
// GetEditorPanelMode / GetEditorMode.
if (base::FeatureList::IsEnabled(
ash::features::kOrcaForceFetchContextOnGetEditorPanelContext)) {
delegate_->FetchAndUpdateInputContext();
}
// Cache the current text context, so that any input fields that are part of
// the editor panel do not interfere with the context.
delegate_->CacheContext();
// TODO(b/295059934): Get the panel mode from the editor mediator.
const auto editor_panel_mode = GetEditorPanelMode(delegate_->GetEditorMode());
// TODO(b/295059934): Bind the editor client before getting the preset text
// queries.
if (editor_panel_mode == crosapi::mojom::EditorPanelMode::kRewrite &&
editor_client_remote_.is_bound()) {
editor_client_remote_->GetPresetTextQueries(
base::BindOnce(&EditorPanelManager::OnGetPresetTextQueriesResult,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} else {
auto context = crosapi::mojom::EditorPanelContext::New();
context->editor_panel_mode = editor_panel_mode;
std::move(callback).Run(std::move(context));
}
}
void EditorPanelManager::OnPromoCardDismissed() {
}
void EditorPanelManager::OnPromoCardDeclined() {
delegate_->OnPromoCardDeclined();
delegate_->GetMetricsRecorder()->LogEditorState(
EditorStates::kPromoCardExplicitDismissal);
}
void EditorPanelManager::StartEditingFlow() {
delegate_->HandleTrigger(/*preset_query_id=*/std::nullopt,
/*freeform_text=*/std::nullopt);
}
void EditorPanelManager::StartEditingFlowWithPreset(
const std::string& text_query_id) {
delegate_->HandleTrigger(/*preset_query_id=*/text_query_id,
/*freeform_text=*/std::nullopt);
}
void EditorPanelManager::StartEditingFlowWithFreeform(const std::string& text) {
delegate_->HandleTrigger(/*preset_query_id=*/std::nullopt,
/*freeform_text=*/text);
}
void EditorPanelManager::OnGetPresetTextQueriesResult(
GetEditorPanelContextCallback callback,
std::vector<orca::mojom::PresetTextQueryPtr> queries) {
auto context = crosapi::mojom::EditorPanelContext::New();
context->editor_panel_mode = crosapi::mojom::EditorPanelMode::kRewrite;
for (const auto& query : queries) {
context->preset_text_queries.push_back(ToEditorPanelQuery(query));
}
std::move(callback).Run(std::move(context));
}
void EditorPanelManager::OnEditorMenuVisibilityChanged(bool visible) {
is_editor_menu_visible_ = visible;
}
bool EditorPanelManager::IsEditorMenuVisible() const {
return is_editor_menu_visible_;
}
void EditorPanelManager::LogEditorMode(
crosapi::mojom::EditorPanelMode mode) {
EditorOpportunityMode opportunity_mode =
delegate_->GetEditorOpportunityMode();
EditorMetricsRecorder* logger = delegate_->GetMetricsRecorder();
logger->SetMode(opportunity_mode);
logger->SetTone(EditorTone::kUnset);
if (opportunity_mode == EditorOpportunityMode::kRewrite ||
opportunity_mode == EditorOpportunityMode::kWrite) {
logger->LogEditorState(EditorStates::kNativeUIShowOpportunity);
}
if (mode == crosapi::mojom::EditorPanelMode::kRewrite ||
mode == crosapi::mojom::EditorPanelMode::kWrite) {
logger->LogEditorState(EditorStates::kNativeUIShown);
}
if (mode == crosapi::mojom::EditorPanelMode::kBlocked) {
logger->LogEditorState(EditorStates::kBlocked);
for (EditorBlockedReason blocked_reason : delegate_->GetBlockedReasons()) {
logger->LogEditorState(ToEditorStatesMetric(blocked_reason));
}
}
if (mode == crosapi::mojom::EditorPanelMode::kPromoCard) {
logger->LogEditorState(EditorStates::kPromoCardImpression);
}
}
void EditorPanelManager::BindEditorObserver(
mojo::PendingRemote<crosapi::mojom::EditorObserver>
pending_observer_remote) {
observer_remotes_.Add(std::move(pending_observer_remote));
}
void EditorPanelManager::AddObserver(EditorPanelManager::Observer* observer) {
observers_.AddObserver(observer);
}
void EditorPanelManager::RemoveObserver(
EditorPanelManager::Observer* observer) {
observers_.RemoveObserver(observer);
}
void EditorPanelManager::NotifyEditorModeChanged(const EditorMode& mode) {
for (const mojo::Remote<crosapi::mojom::EditorObserver>& obs :
observer_remotes_) {
obs->OnEditorPanelModeChanged(GetEditorPanelMode(mode));
}
for (EditorPanelManager::Observer& obs : observers_) {
obs.OnEditorModeChanged(mode);
}
}
} // namespace ash::input_method