summaryrefslogtreecommitdiffstats
path: root/dom/media/webspeech/synth/ipc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/media/webspeech/synth/ipc
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/webspeech/synth/ipc')
-rw-r--r--dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl50
-rw-r--r--dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl48
-rw-r--r--dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp169
-rw-r--r--dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h107
-rw-r--r--dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp221
-rw-r--r--dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h102
6 files changed, 697 insertions, 0 deletions
diff --git a/dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl b/dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
new file mode 100644
index 0000000000..38e360bf4c
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
@@ -0,0 +1,50 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PContent;
+include protocol PSpeechSynthesisRequest;
+
+namespace mozilla {
+namespace dom {
+
+struct RemoteVoice {
+ nsString voiceURI;
+ nsString name;
+ nsString lang;
+ bool localService;
+ bool queued;
+};
+
+[ManualDealloc]
+sync protocol PSpeechSynthesis
+{
+ manager PContent;
+ manages PSpeechSynthesisRequest;
+
+child:
+
+ async VoiceAdded(RemoteVoice aVoice);
+
+ async VoiceRemoved(nsString aUri);
+
+ async SetDefaultVoice(nsString aUri, bool aIsDefault);
+
+ async IsSpeakingChanged(bool aIsSpeaking);
+
+ async NotifyVoicesChanged();
+
+ async InitialVoicesAndState(RemoteVoice[] aVoices, nsString[] aDefaults,
+ bool aIsSpeaking);
+
+parent:
+ async __delete__();
+
+ async PSpeechSynthesisRequest(nsString aText, nsString aUri, nsString aLang,
+ float aVolume, float aRate, float aPitch, bool aShouldResistFingerprinting);
+};
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
new file mode 100644
index 0000000000..8543eebc5b
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
@@ -0,0 +1,48 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PSpeechSynthesis;
+
+namespace mozilla {
+namespace dom {
+
+[ManualDealloc, ChildImpl=virtual, ParentImpl=virtual]
+async protocol PSpeechSynthesisRequest
+{
+ manager PSpeechSynthesis;
+
+ parent:
+
+ async __delete__();
+
+ async Pause();
+
+ async Resume();
+
+ async Cancel();
+
+ async ForceEnd();
+
+ async SetAudioOutputVolume(float aVolume);
+
+ child:
+
+ async OnEnd(bool aIsError, float aElapsedTime, uint32_t aCharIndex);
+
+ async OnStart(nsString aUri);
+
+ async OnPause(float aElapsedTime, uint32_t aCharIndex);
+
+ async OnResume(float aElapsedTime, uint32_t aCharIndex);
+
+ async OnBoundary(nsString aName, float aElapsedTime, uint32_t aCharIndex,
+ uint32_t aCharLength, uint8_t argc);
+
+ async OnMark(nsString aName, float aElapsedTime, uint32_t aCharIndex);
+};
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
new file mode 100644
index 0000000000..9a9e9b6fe2
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
@@ -0,0 +1,169 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SpeechSynthesisChild.h"
+#include "nsSynthVoiceRegistry.h"
+
+namespace mozilla::dom {
+
+SpeechSynthesisChild::SpeechSynthesisChild() {
+ MOZ_COUNT_CTOR(SpeechSynthesisChild);
+}
+
+SpeechSynthesisChild::~SpeechSynthesisChild() {
+ MOZ_COUNT_DTOR(SpeechSynthesisChild);
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvInitialVoicesAndState(
+ nsTArray<RemoteVoice>&& aVoices, nsTArray<nsString>&& aDefaults,
+ const bool& aIsSpeaking) {
+ nsSynthVoiceRegistry::RecvInitialVoicesAndState(aVoices, aDefaults,
+ aIsSpeaking);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvVoiceAdded(
+ const RemoteVoice& aVoice) {
+ nsSynthVoiceRegistry::RecvAddVoice(aVoice);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvVoiceRemoved(
+ const nsAString& aUri) {
+ nsSynthVoiceRegistry::RecvRemoveVoice(aUri);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvSetDefaultVoice(
+ const nsAString& aUri, const bool& aIsDefault) {
+ nsSynthVoiceRegistry::RecvSetDefaultVoice(aUri, aIsDefault);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvIsSpeakingChanged(
+ const bool& aIsSpeaking) {
+ nsSynthVoiceRegistry::RecvIsSpeakingChanged(aIsSpeaking);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisChild::RecvNotifyVoicesChanged() {
+ nsSynthVoiceRegistry::RecvNotifyVoicesChanged();
+ return IPC_OK();
+}
+
+PSpeechSynthesisRequestChild*
+SpeechSynthesisChild::AllocPSpeechSynthesisRequestChild(
+ const nsAString& aText, const nsAString& aLang, const nsAString& aUri,
+ const float& aVolume, const float& aRate, const float& aPitch,
+ const bool& aShouldResistFingerprinting) {
+ MOZ_CRASH("Caller is supposed to manually construct a request!");
+}
+
+bool SpeechSynthesisChild::DeallocPSpeechSynthesisRequestChild(
+ PSpeechSynthesisRequestChild* aActor) {
+ delete aActor;
+ return true;
+}
+
+// SpeechSynthesisRequestChild
+
+SpeechSynthesisRequestChild::SpeechSynthesisRequestChild(SpeechTaskChild* aTask)
+ : mTask(aTask) {
+ mTask->mActor = this;
+ MOZ_COUNT_CTOR(SpeechSynthesisRequestChild);
+}
+
+SpeechSynthesisRequestChild::~SpeechSynthesisRequestChild() {
+ MOZ_COUNT_DTOR(SpeechSynthesisRequestChild);
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnStart(
+ const nsAString& aUri) {
+ mTask->DispatchStartImpl(aUri);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnEnd(
+ const bool& aIsError, const float& aElapsedTime,
+ const uint32_t& aCharIndex) {
+ SpeechSynthesisRequestChild* actor = mTask->mActor;
+ mTask->mActor = nullptr;
+
+ if (aIsError) {
+ mTask->DispatchErrorImpl(aElapsedTime, aCharIndex);
+ } else {
+ mTask->DispatchEndImpl(aElapsedTime, aCharIndex);
+ }
+
+ SpeechSynthesisRequestChild::Send__delete__(actor);
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnPause(
+ const float& aElapsedTime, const uint32_t& aCharIndex) {
+ mTask->DispatchPauseImpl(aElapsedTime, aCharIndex);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnResume(
+ const float& aElapsedTime, const uint32_t& aCharIndex) {
+ mTask->DispatchResumeImpl(aElapsedTime, aCharIndex);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnBoundary(
+ const nsAString& aName, const float& aElapsedTime,
+ const uint32_t& aCharIndex, const uint32_t& aCharLength,
+ const uint8_t& argc) {
+ mTask->DispatchBoundaryImpl(aName, aElapsedTime, aCharIndex, aCharLength,
+ argc);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestChild::RecvOnMark(
+ const nsAString& aName, const float& aElapsedTime,
+ const uint32_t& aCharIndex) {
+ mTask->DispatchMarkImpl(aName, aElapsedTime, aCharIndex);
+ return IPC_OK();
+}
+
+// SpeechTaskChild
+
+SpeechTaskChild::SpeechTaskChild(SpeechSynthesisUtterance* aUtterance,
+ bool aShouldResistFingerprinting)
+ : nsSpeechTask(aUtterance, aShouldResistFingerprinting), mActor(nullptr) {}
+
+NS_IMETHODIMP
+SpeechTaskChild::Setup(nsISpeechTaskCallback* aCallback) {
+ MOZ_CRASH("Should never be called from child");
+}
+
+void SpeechTaskChild::Pause() {
+ MOZ_ASSERT(mActor);
+ mActor->SendPause();
+}
+
+void SpeechTaskChild::Resume() {
+ MOZ_ASSERT(mActor);
+ mActor->SendResume();
+}
+
+void SpeechTaskChild::Cancel() {
+ MOZ_ASSERT(mActor);
+ mActor->SendCancel();
+}
+
+void SpeechTaskChild::ForceEnd() {
+ MOZ_ASSERT(mActor);
+ mActor->SendForceEnd();
+}
+
+void SpeechTaskChild::SetAudioOutputVolume(float aVolume) {
+ if (mActor) {
+ mActor->SendSetAudioOutputVolume(aVolume);
+ }
+}
+
+} // namespace mozilla::dom
diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
new file mode 100644
index 0000000000..f57582932a
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
@@ -0,0 +1,107 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SpeechSynthesisChild_h
+#define mozilla_dom_SpeechSynthesisChild_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/PSpeechSynthesisChild.h"
+#include "mozilla/dom/PSpeechSynthesisRequestChild.h"
+#include "nsSpeechTask.h"
+
+namespace mozilla::dom {
+
+class nsSynthVoiceRegistry;
+class SpeechSynthesisRequestChild;
+class SpeechTaskChild;
+
+class SpeechSynthesisChild : public PSpeechSynthesisChild {
+ friend class nsSynthVoiceRegistry;
+ friend class PSpeechSynthesisChild;
+
+ public:
+ mozilla::ipc::IPCResult RecvInitialVoicesAndState(
+ nsTArray<RemoteVoice>&& aVoices, nsTArray<nsString>&& aDefaults,
+ const bool& aIsSpeaking);
+
+ mozilla::ipc::IPCResult RecvVoiceAdded(const RemoteVoice& aVoice);
+
+ mozilla::ipc::IPCResult RecvVoiceRemoved(const nsAString& aUri);
+
+ mozilla::ipc::IPCResult RecvSetDefaultVoice(const nsAString& aUri,
+ const bool& aIsDefault);
+
+ mozilla::ipc::IPCResult RecvIsSpeakingChanged(const bool& aIsSpeaking);
+
+ mozilla::ipc::IPCResult RecvNotifyVoicesChanged();
+
+ protected:
+ SpeechSynthesisChild();
+ virtual ~SpeechSynthesisChild();
+
+ PSpeechSynthesisRequestChild* AllocPSpeechSynthesisRequestChild(
+ const nsAString& aLang, const nsAString& aUri, const nsAString& aText,
+ const float& aVolume, const float& aPitch, const float& aRate,
+ const bool& aShouldResistFingerprinting);
+ bool DeallocPSpeechSynthesisRequestChild(
+ PSpeechSynthesisRequestChild* aActor);
+};
+
+class SpeechSynthesisRequestChild : public PSpeechSynthesisRequestChild {
+ public:
+ explicit SpeechSynthesisRequestChild(SpeechTaskChild* aTask);
+ virtual ~SpeechSynthesisRequestChild();
+
+ protected:
+ mozilla::ipc::IPCResult RecvOnStart(const nsAString& aUri) override;
+
+ mozilla::ipc::IPCResult RecvOnEnd(const bool& aIsError,
+ const float& aElapsedTime,
+ const uint32_t& aCharIndex) override;
+
+ mozilla::ipc::IPCResult RecvOnPause(const float& aElapsedTime,
+ const uint32_t& aCharIndex) override;
+
+ mozilla::ipc::IPCResult RecvOnResume(const float& aElapsedTime,
+ const uint32_t& aCharIndex) override;
+
+ mozilla::ipc::IPCResult RecvOnBoundary(const nsAString& aName,
+ const float& aElapsedTime,
+ const uint32_t& aCharIndex,
+ const uint32_t& aCharLength,
+ const uint8_t& argc) override;
+
+ mozilla::ipc::IPCResult RecvOnMark(const nsAString& aName,
+ const float& aElapsedTime,
+ const uint32_t& aCharIndex) override;
+
+ RefPtr<SpeechTaskChild> mTask;
+};
+
+class SpeechTaskChild : public nsSpeechTask {
+ friend class SpeechSynthesisRequestChild;
+
+ public:
+ explicit SpeechTaskChild(SpeechSynthesisUtterance* aUtterance,
+ bool aShouldResistFingerprinting);
+
+ NS_IMETHOD Setup(nsISpeechTaskCallback* aCallback) override;
+
+ void Pause() override;
+
+ void Resume() override;
+
+ void Cancel() override;
+
+ void ForceEnd() override;
+
+ void SetAudioOutputVolume(float aVolume) override;
+
+ private:
+ SpeechSynthesisRequestChild* mActor;
+};
+
+} // namespace mozilla::dom
+
+#endif
diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
new file mode 100644
index 0000000000..a9eb53c5b7
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
@@ -0,0 +1,221 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SpeechSynthesisParent.h"
+#include "nsSynthVoiceRegistry.h"
+
+namespace mozilla::dom {
+
+SpeechSynthesisParent::SpeechSynthesisParent() {
+ MOZ_COUNT_CTOR(SpeechSynthesisParent);
+}
+
+SpeechSynthesisParent::~SpeechSynthesisParent() {
+ MOZ_COUNT_DTOR(SpeechSynthesisParent);
+}
+
+void SpeechSynthesisParent::ActorDestroy(ActorDestroyReason aWhy) {
+ // Implement me! Bug 1005141
+}
+
+bool SpeechSynthesisParent::SendInit() {
+ return nsSynthVoiceRegistry::GetInstance()->SendInitialVoicesAndState(this);
+}
+
+PSpeechSynthesisRequestParent*
+SpeechSynthesisParent::AllocPSpeechSynthesisRequestParent(
+ const nsAString& aText, const nsAString& aLang, const nsAString& aUri,
+ const float& aVolume, const float& aRate, const float& aPitch,
+ const bool& aShouldResistFingerprinting) {
+ RefPtr<SpeechTaskParent> task =
+ new SpeechTaskParent(aVolume, aText, aShouldResistFingerprinting);
+ SpeechSynthesisRequestParent* actor = new SpeechSynthesisRequestParent(task);
+ return actor;
+}
+
+bool SpeechSynthesisParent::DeallocPSpeechSynthesisRequestParent(
+ PSpeechSynthesisRequestParent* aActor) {
+ delete aActor;
+ return true;
+}
+
+mozilla::ipc::IPCResult
+SpeechSynthesisParent::RecvPSpeechSynthesisRequestConstructor(
+ PSpeechSynthesisRequestParent* aActor, const nsAString& aText,
+ const nsAString& aLang, const nsAString& aUri, const float& aVolume,
+ const float& aRate, const float& aPitch,
+ const bool& aShouldResistFingerprinting) {
+ MOZ_ASSERT(aActor);
+ SpeechSynthesisRequestParent* actor =
+ static_cast<SpeechSynthesisRequestParent*>(aActor);
+ nsSynthVoiceRegistry::GetInstance()->Speak(aText, aLang, aUri, aVolume, aRate,
+ aPitch, actor->mTask);
+ return IPC_OK();
+}
+
+// SpeechSynthesisRequestParent
+
+SpeechSynthesisRequestParent::SpeechSynthesisRequestParent(
+ SpeechTaskParent* aTask)
+ : mTask(aTask) {
+ mTask->mActor = this;
+ MOZ_COUNT_CTOR(SpeechSynthesisRequestParent);
+}
+
+SpeechSynthesisRequestParent::~SpeechSynthesisRequestParent() {
+ if (mTask) {
+ mTask->mActor = nullptr;
+ // If we still have a task, cancel it.
+ mTask->Cancel();
+ }
+ MOZ_COUNT_DTOR(SpeechSynthesisRequestParent);
+}
+
+void SpeechSynthesisRequestParent::ActorDestroy(ActorDestroyReason aWhy) {
+ // Implement me! Bug 1005141
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::RecvPause() {
+ MOZ_ASSERT(mTask);
+ mTask->Pause();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::Recv__delete__() {
+ MOZ_ASSERT(mTask);
+ mTask->mActor = nullptr;
+ mTask = nullptr;
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::RecvResume() {
+ MOZ_ASSERT(mTask);
+ mTask->Resume();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::RecvCancel() {
+ MOZ_ASSERT(mTask);
+ mTask->Cancel();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::RecvForceEnd() {
+ MOZ_ASSERT(mTask);
+ mTask->ForceEnd();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SpeechSynthesisRequestParent::RecvSetAudioOutputVolume(
+ const float& aVolume) {
+ MOZ_ASSERT(mTask);
+ mTask->SetAudioOutputVolume(aVolume);
+ return IPC_OK();
+}
+
+// SpeechTaskParent
+
+nsresult SpeechTaskParent::DispatchStartImpl(const nsAString& aUri) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnStart(aUri)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchEndImpl(float aElapsedTime,
+ uint32_t aCharIndex) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnEnd(false, aElapsedTime, aCharIndex)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchPauseImpl(float aElapsedTime,
+ uint32_t aCharIndex) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnPause(aElapsedTime, aCharIndex)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchResumeImpl(float aElapsedTime,
+ uint32_t aCharIndex) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnResume(aElapsedTime, aCharIndex)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchErrorImpl(float aElapsedTime,
+ uint32_t aCharIndex) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnEnd(true, aElapsedTime, aCharIndex)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchBoundaryImpl(const nsAString& aName,
+ float aElapsedTime,
+ uint32_t aCharIndex,
+ uint32_t aCharLength,
+ uint8_t argc) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnBoundary(aName, aElapsedTime, aCharIndex,
+ aCharLength, argc)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult SpeechTaskParent::DispatchMarkImpl(const nsAString& aName,
+ float aElapsedTime,
+ uint32_t aCharIndex) {
+ if (!mActor) {
+ // Child is already gone.
+ return NS_OK;
+ }
+
+ if (NS_WARN_IF(!(mActor->SendOnMark(aName, aElapsedTime, aCharIndex)))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+} // namespace mozilla::dom
diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
new file mode 100644
index 0000000000..6ae4d38bbc
--- /dev/null
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
@@ -0,0 +1,102 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SpeechSynthesisParent_h
+#define mozilla_dom_SpeechSynthesisParent_h
+
+#include "mozilla/dom/PSpeechSynthesisParent.h"
+#include "mozilla/dom/PSpeechSynthesisRequestParent.h"
+#include "nsSpeechTask.h"
+
+namespace mozilla::dom {
+
+class ContentParent;
+class SpeechTaskParent;
+class SpeechSynthesisRequestParent;
+
+class SpeechSynthesisParent : public PSpeechSynthesisParent {
+ friend class ContentParent;
+ friend class SpeechSynthesisRequestParent;
+ friend class PSpeechSynthesisParent;
+
+ public:
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+
+ bool SendInit();
+
+ protected:
+ SpeechSynthesisParent();
+ virtual ~SpeechSynthesisParent();
+ PSpeechSynthesisRequestParent* AllocPSpeechSynthesisRequestParent(
+ const nsAString& aText, const nsAString& aLang, const nsAString& aUri,
+ const float& aVolume, const float& aRate, const float& aPitch,
+ const bool& aShouldResistFingerprinting);
+
+ bool DeallocPSpeechSynthesisRequestParent(
+ PSpeechSynthesisRequestParent* aActor);
+
+ mozilla::ipc::IPCResult RecvPSpeechSynthesisRequestConstructor(
+ PSpeechSynthesisRequestParent* aActor, const nsAString& aText,
+ const nsAString& aLang, const nsAString& aUri, const float& aVolume,
+ const float& aRate, const float& aPitch,
+ const bool& aShouldResistFingerprinting) override;
+};
+
+class SpeechSynthesisRequestParent : public PSpeechSynthesisRequestParent {
+ public:
+ explicit SpeechSynthesisRequestParent(SpeechTaskParent* aTask);
+ virtual ~SpeechSynthesisRequestParent();
+
+ RefPtr<SpeechTaskParent> mTask;
+
+ protected:
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+
+ mozilla::ipc::IPCResult RecvPause() override;
+
+ mozilla::ipc::IPCResult RecvResume() override;
+
+ mozilla::ipc::IPCResult RecvCancel() override;
+
+ mozilla::ipc::IPCResult RecvForceEnd() override;
+
+ mozilla::ipc::IPCResult RecvSetAudioOutputVolume(
+ const float& aVolume) override;
+
+ mozilla::ipc::IPCResult Recv__delete__() override;
+};
+
+class SpeechTaskParent : public nsSpeechTask {
+ friend class SpeechSynthesisRequestParent;
+
+ public:
+ SpeechTaskParent(float aVolume, const nsAString& aUtterance,
+ bool aShouldResistFingerprinting)
+ : nsSpeechTask(aVolume, aUtterance, aShouldResistFingerprinting),
+ mActor(nullptr) {}
+
+ nsresult DispatchStartImpl(const nsAString& aUri) override;
+
+ nsresult DispatchEndImpl(float aElapsedTime, uint32_t aCharIndex) override;
+
+ nsresult DispatchPauseImpl(float aElapsedTime, uint32_t aCharIndex) override;
+
+ nsresult DispatchResumeImpl(float aElapsedTime, uint32_t aCharIndex) override;
+
+ nsresult DispatchErrorImpl(float aElapsedTime, uint32_t aCharIndex) override;
+
+ nsresult DispatchBoundaryImpl(const nsAString& aName, float aElapsedTime,
+ uint32_t aCharIndex, uint32_t aCharLength,
+ uint8_t argc) override;
+
+ nsresult DispatchMarkImpl(const nsAString& aName, float aElapsedTime,
+ uint32_t aCharIndex) override;
+
+ private:
+ SpeechSynthesisRequestParent* mActor;
+};
+
+} // namespace mozilla::dom
+
+#endif