blob: 43fec59512a4600535f77a530d8e0ee32cf07f0f [file]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_ON_DEVICE_TRANSLATION_SERVICE_CONTROLLER_H_
#define COMPONENTS_ON_DEVICE_TRANSLATION_SERVICE_CONTROLLER_H_
#include <optional>
#include <set>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/no_destructor.h"
#include "base/task/sequenced_task_runner.h"
#include "base/types/expected.h"
#include "components/on_device_translation/installer.h"
#include "components/on_device_translation/public/mojom/on_device_translation_service.mojom.h"
#include "components/on_device_translation/public/mojom/translator.mojom.h"
#include "components/prefs/pref_change_registrar.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/on_device_translation/translation_manager.mojom-forward.h"
#include "url/origin.h"
class PrefService;
namespace on_device_translation {
class FileOperationProxyImpl;
enum class LanguagePackKey;
class ServiceControllerManager;
// This class is the controller that launches the on-device translation service
// and delegates the functionalities. It is designed to be shared by multiple
// `TranslationManagerImpl` instances. A single instance of this class is
// created for each pair of browser context and origin.
// TODO(crbug.com/364795294): This class does not support Android yet.
class OnDeviceTranslationServiceController
: public base::RefCounted<OnDeviceTranslationServiceController>,
public OnDeviceTranslationInstaller::Observer {
public:
OnDeviceTranslationServiceController(PrefService* local_state,
ServiceControllerManager* manager,
const url::Origin& origin);
OnDeviceTranslationServiceController(
const OnDeviceTranslationServiceController&) = delete;
OnDeviceTranslationServiceController& operator=(
const OnDeviceTranslationServiceController&) = delete;
// Creates a translator class that implements `mojom::Translator` for the
// given language pair.
void CreateTranslator(
const std::string& source_lang,
const std::string& target_lang,
base::OnceCallback<
void(base::expected<mojo::PendingRemote<mojom::Translator>,
blink::mojom::CreateTranslatorError>)> callback);
// Checks if the translate service can do translation from `source_lang` to
// `target_lang`.
void CanTranslate(
const std::string& source_lang,
const std::string& target_lang,
base::OnceCallback<void(blink::mojom::CanCreateTranslatorResult)>
callback);
// Sets the service idle timeout for testing. This must be called before the
// service is started.
void SetServiceIdleTimeoutForTesting(base::TimeDelta service_idle_timeout);
// Returns true if the service is running.
bool IsServiceRunning() const { return !!service_remote_; }
// OnDeviceTranslationInstaller::Observer
void OnLanguagePackInstalled(const LanguagePackKey lang_pack) override;
// OnDeviceTranslationInstaller::Observer
void OnLanguagePackInstallationChanged(
const LanguagePackKey lang_pack) override;
// OnDeviceTranslationInstaller::Observer
void OnInstallationChanged() override;
private:
friend base::RefCounted<OnDeviceTranslationServiceController>;
// The information of a pending task. This is used to keep the tasks that are
// waiting for the language packs to be installed.
class PendingTask {
public:
PendingTask(std::set<LanguagePackKey> required_packs,
base::OnceClosure once_closure);
~PendingTask();
PendingTask(const PendingTask&) = delete;
PendingTask& operator=(const PendingTask&) = delete;
PendingTask(PendingTask&&);
PendingTask& operator=(PendingTask&&);
std::set<LanguagePackKey> required_packs;
base::OnceClosure once_closure;
};
~OnDeviceTranslationServiceController() override;
// Checks if the translate service can do translation from `source_lang` to
// `target_lang`.
blink::mojom::CanCreateTranslatorResult CanTranslateImpl(
const std::string& source_lang,
const std::string& target_lang);
// Send the CreateTranslator IPC call to the OnDeviceTranslationService.
void CreateTranslatorImpl(
const std::string& source_lang,
const std::string& target_lang,
base::OnceCallback<
void(base::expected<mojo::PendingRemote<mojom::Translator>,
blink::mojom::CreateTranslatorError>)> callback);
// Called when the TranslateKitBinaryPath pref is changed.
void OnTranslateKitBinaryPathChanged(const std::string& pref_name);
// Called when the language pack key pref is changed.
void OnLanguagePackKeyPrefChanged(const std::string& pref_name);
// Tries to start the service if it is not already running. Returns true if
// the service is running or is started successfully.
bool MaybeStartService();
void MaybeRunPendingTasks();
// Called when the service is idle and the idle timeout is reached.
void OnServiceIdle();
// The manager that manages the service controller. This `manager_` is owned
// by the BrowserContext, and `this` is owned by the `TranslationManagerImpl`
// instances which are DocumentUserData. So `manager_` must outlive `this`.
const raw_ptr<ServiceControllerManager> manager_;
// The origin of the web page that created this service controller.
const url::Origin origin_;
// The idle timeout for the translation service. When the service is idle for
// this amount of time, the service will be terminated.
base::TimeDelta service_idle_timeout_;
mojo::Remote<mojom::OnDeviceTranslationService> service_remote_;
// The file operation proxy to access the files on disk. This is deleted on
// a background task runner.
std::unique_ptr<FileOperationProxyImpl, base::OnTaskRunnerDeleter>
file_operation_proxy_;
// The pending tasks that are waiting for the language packs to be installed.
std::vector<PendingTask> pending_tasks_;
};
} // namespace on_device_translation
#endif // COMPONENTS_ON_DEVICE_TRANSLATION_SERVICE_CONTROLLER_H_