#ifndef CONTENT_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_
#define CONTENT_BROWSER_SPEECH_TTS_CONTROLLER_IMPL_H_
#include <list>
#include <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/json/json_reader.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/singleton.h"
#include "base/metrics/user_metrics.h"
#include "base/observer_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/tts_controller.h"
#include "content/public/browser/tts_platform.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/base/network_change_notifier.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
#if BUILDFLAG(IS_CHROMEOS)
class TtsControllerDelegate;
#endif
class CONTENT_EXPORT TtsControllerImpl
: public TtsController,
public WebContentsObserver,
public net::NetworkChangeNotifier::NetworkChangeObserver {
public:
static TtsControllerImpl* GetInstance();
TtsControllerImpl(const TtsControllerImpl&) = delete;
TtsControllerImpl& operator=(const TtsControllerImpl&) = delete;
static void SkipAddNetworkChangeObserverForTests(bool enabled);
void SetStopSpeakingWhenHidden(bool value);
bool IsSpeaking() override;
void SpeakOrEnqueue(std::unique_ptr<TtsUtterance> utterance) override;
void Stop() override;
void Stop(const GURL& source_url) override;
void Pause() override;
void Resume() override;
void UpdateLanguageStatus(BrowserContext* browser_context,
const std::string& lang,
LanguageInstallStatus install_status,
const std::string& error) override;
void AddUpdateLanguageStatusDelegate(
UpdateLanguageStatusDelegate* delegate) override;
void RemoveUpdateLanguageStatusDelegate(
UpdateLanguageStatusDelegate* delegate) override;
void UninstallLanguageRequest(content::BrowserContext* browser_context,
const std::string& lang,
const std::string& client_id,
int source,
bool uninstall_immediately) override;
void InstallLanguageRequest(BrowserContext* browser_context,
const std::string& lang,
const std::string& client_id,
int source) override;
void LanguageStatusRequest(BrowserContext* browser_context,
const std::string& lang,
const std::string& client_id,
int source) override;
void OnTtsEvent(int utterance_id,
TtsEventType event_type,
int char_index,
int length,
const std::string& error_message) override;
void OnTtsUtteranceBecameInvalid(int utterance_id) override;
void GetVoices(BrowserContext* browser_context,
const GURL& source_url,
std::vector<VoiceData>* out_voices) override;
void VoicesChanged() override;
void AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) override;
void RemoveVoicesChangedDelegate(VoicesChangedDelegate* delegate) override;
void RemoveUtteranceEventDelegate(UtteranceEventDelegate* delegate) override;
void SetTtsEngineDelegate(TtsEngineDelegate* delegate) override;
TtsEngineDelegate* GetTtsEngineDelegate() override;
void RefreshVoices() override;
void Shutdown();
void OnBrowserContextDestroyed(BrowserContext* browser_context);
void SetTtsPlatform(TtsPlatform* tts_platform) override;
int QueueSize() override;
void StripSSML(
const std::string& utterance,
base::OnceCallback<void(const std::string&)> callback) override;
protected:
TtsControllerImpl();
~TtsControllerImpl() override;
bool IsPausedForTesting() const { return paused_; }
private:
friend class TestTtsControllerImpl;
friend struct base::DefaultSingletonTraits<TtsControllerImpl>;
TtsPlatform* GetTtsPlatform();
bool TtsPlatformReady();
bool TtsPlatformLoading();
void SpeakNow(std::unique_ptr<TtsUtterance> utterance);
void StopAndClearQueue(const GURL& source_url);
bool StopCurrentUtteranceIfMatches(const GURL& source_url);
void StopCurrentUtterance();
void RemoveUtteranceAndStopIfNeeded(int utterance_id);
bool StopCurrentUtteranceIfMatches(int utterance_id);
void ClearUtteranceQueue(bool send_events);
void FinishCurrentUtterance();
void SpeakNextUtterance();
void UpdateUtteranceDefaults(TtsUtterance* utterance);
void OnSpeakFinished(int utterance_id, bool success);
static void StripSSMLHelper(
const std::string& utterance,
base::OnceCallback<void(const std::string&)> on_ssml_parsed,
data_decoder::DataDecoder::ValueOrError result);
static void PopulateParsedText(std::string* parsed_text,
const base::Value* element);
int GetMatchingVoice(TtsUtterance* utterance,
const std::vector<VoiceData>& voices);
void SetCurrentUtterance(std::unique_ptr<TtsUtterance> utterance);
void StopCurrentUtteranceAndRemoveUtterancesMatching(WebContents* wc);
bool ShouldSpeakUtterance(TtsUtterance* utterance);
void WebContentsDestroyed() override;
void OnVisibilityChanged(Visibility visibility) override;
void OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) override;
#if BUILDFLAG(IS_CHROMEOS)
TtsControllerDelegate* GetTtsControllerDelegate();
void SetTtsControllerDelegateForTesting(TtsControllerDelegate* delegate);
raw_ptr<TtsControllerDelegate, DanglingUntriaged> delegate_ = nullptr;
#endif
raw_ptr<TtsEngineDelegate, DanglingUntriaged> engine_delegate_ = nullptr;
bool stop_speaking_when_hidden_ = false;
base::ObserverList<VoicesChangedDelegate> voices_changed_delegates_;
base::ObserverList<UpdateLanguageStatusDelegate>
update_language_status_delegates_;
std::unique_ptr<TtsUtterance> current_utterance_;
bool paused_ = false;
raw_ptr<TtsPlatform, DanglingUntriaged> tts_platform_ = nullptr;
std::list<std::unique_ptr<TtsUtterance>> utterance_list_;
bool allow_remote_voices_ = false;
static bool skip_add_network_change_observer_for_tests_;
};
}
#endif