chromium/chrome/browser/speech/tts_ash.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_SPEECH_TTS_ASH_H_
#define CHROME_BROWSER_SPEECH_TTS_ASH_H_

#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/unguessable_token.h"
#include "chrome/browser/profiles/profile_manager_observer.h"
#include "chromeos/crosapi/mojom/tts.mojom.h"
#include "content/public/browser/tts_controller.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"

class GURL;
class ProfileManager;

namespace crosapi {
// Implements tts interface to allow Lacros to call ash to handle TTS
// requests, manages remote TtsClient objects registered by Lacros, and
// caches the voices from Lacros.
class TtsAsh : public mojom::Tts,
               public content::VoicesChangedDelegate,
               public ProfileManagerObserver {
 public:
  explicit TtsAsh(ProfileManager* profile_manager);
  TtsAsh(const TtsAsh&) = delete;
  TtsAsh& operator=(const TtsAsh&) = delete;
  ~TtsAsh() override;

  void BindReceiver(mojo::PendingReceiver<mojom::Tts> pending_receiver);

  // Returns true if there is any registered Tts Client.
  bool HasTtsClient() const;

  // Returns the browser context id for primary profile.
  base::UnguessableToken GetPrimaryProfileBrowserContextId() const;

  // Returns the cached lacros voices in |out_voices| for
  // |browser_context_id|.
  void GetCrosapiVoices(base::UnguessableToken browser_context_id,
                        std::vector<content::VoiceData>* out_voices);

  // Requests to the associated Lacros speech engine to speak the given
  // |utterance| with the given |voice|.
  void SpeakWithLacrosVoice(content::TtsUtterance* utterance,
                            const content::VoiceData& voice);

  // Requests the associated Lacros speech engine to stop speaking the
  // |utterance|.
  void StopRemoteEngine(content::TtsUtterance* utterance);

  // Requests the associated Lacros speech engine to pause speaking the
  // |utterance|.
  void PauseRemoteEngine(content::TtsUtterance* utterance);

  // Requests the associated Lacros speech engine to resume speaking the
  // |utterance|.
  void ResumeRemoteEngine(content::TtsUtterance* utterance);

  void DeletePendingAshUtteranceClient(int utterance_id);

  // crosapi::mojom::Tts:
  void RegisterTtsClient(mojo::PendingRemote<mojom::TtsClient> client,
                         const base::UnguessableToken& browser_context_id,
                         bool from_primary_profile) override;
  void VoicesChanged(const base::UnguessableToken& browser_context_id,
                     std::vector<mojom::TtsVoicePtr> lacros_voices) override;
  void SpeakOrEnqueue(
      mojom::TtsUtterancePtr utterance,
      mojo::PendingRemote<mojom::TtsUtteranceClient> utterance_client) override;
  void Stop(const GURL& source_url) override;
  void Pause() override;
  void Resume() override;
  void IsSpeaking(IsSpeakingCallback callback) override;

 private:
  class TtsUtteranceClient;
  // content::VoicesChangedDelegate:
  void OnVoicesChanged() override;

  // ProfileManagerObserver:
  void OnProfileAdded(Profile* profile) override;
  void OnProfileManagerDestroying() override;

  // Called when a Tts client is disconnected.
  void TtsClientDisconnected(const base::UnguessableToken& browser_context_id);

  // Owned by g_browser_process.
  raw_ptr<ProfileManager> profile_manager_;

  // Support any number of connections.
  mojo::ReceiverSet<mojom::Tts> receivers_;

  // Registered TtsClients from Lacros by browser_context_id.
  std::map<base::UnguessableToken, mojo::Remote<mojom::TtsClient>> tts_clients_;

  // Cached lacros voices by browser_context_id.
  std::map<base::UnguessableToken, std::vector<content::VoiceData>>
      crosapi_voices_;

  base::UnguessableToken primary_profile_browser_context_id_;

  // Pending Ash Utterance clients (for the Ash uttenrances to be spoken by
  // Lacros speech engine) by utterance id.
  // Note: The size of |pending_ash_utterance_clients_| should not be greater
  // that one, since Ash TtsController process the utterances one at a time in
  // sequence and  will not send more than 1 utterance to Lacros to be spoken.
  std::map<int, std::unique_ptr<TtsUtteranceClient>>
      pending_ash_utterance_clients_;

  base::ScopedObservation<content::TtsController,
                          content::VoicesChangedDelegate>
      voices_changed_observation_{this};

  base::ScopedObservation<ProfileManager, ProfileManagerObserver>
      profile_manager_observation_{this};

  base::WeakPtrFactory<TtsAsh> weak_ptr_factory_{this};
};

}  // namespace crosapi

#endif  // CHROME_BROWSER_SPEECH_TTS_ASH_H_