Bug 1188099 - (Part 3) Introduce [ChromeOnly] SpeechSynthesis.forceEnd for tests. r=smaug r=kdavis
authorEitan Isaacson <eitan@monotonous.org>
Sat, 08 Aug 2015 10:30:46 -0700
changeset 288621 f83dae195fa43d99ed11bff30e9c3d81a7164b42
parent 288620 51b76297c3d33f0cc40ec95a887b141a7f89d678
child 288622 ae85c14a2bae38e65b9cfa04b7844574d9a31f86
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, kdavis
bugs1188099
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1188099 - (Part 3) Introduce [ChromeOnly] SpeechSynthesis.forceEnd for tests. r=smaug r=kdavis
dom/media/webspeech/synth/SpeechSynthesis.cpp
dom/media/webspeech/synth/SpeechSynthesis.h
dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
dom/media/webspeech/synth/nsSpeechTask.cpp
dom/media/webspeech/synth/nsSpeechTask.h
dom/media/webspeech/synth/nsSynthVoiceRegistry.cpp
dom/media/webspeech/synth/nsSynthVoiceRegistry.h
dom/webidl/SpeechSynthesis.webidl
--- a/dom/media/webspeech/synth/SpeechSynthesis.cpp
+++ b/dom/media/webspeech/synth/SpeechSynthesis.cpp
@@ -269,18 +269,20 @@ SpeechSynthesis::GetVoices(nsTArray< nsR
   mVoiceCache.Clear();
 
   for (uint32_t i = 0; i < aResult.Length(); i++) {
     SpeechSynthesisVoice* voice = aResult[i];
     mVoiceCache.Put(voice->mUri, voice);
   }
 }
 
-// For testing purposes, allows us to drop anything in the global queue from
-// content, and bring the browser to initial state.
+// For testing purposes, allows us to cancel the current task that is
+// misbehaving, and flush the queue.
 void
-SpeechSynthesis::DropGlobalQueue()
+SpeechSynthesis::ForceEnd()
 {
-  nsSynthVoiceRegistry::GetInstance()->DropGlobalQueue();
+  if (mCurrentTask) {
+    mCurrentTask->ForceEnd();
+  }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webspeech/synth/SpeechSynthesis.h
+++ b/dom/media/webspeech/synth/SpeechSynthesis.h
@@ -49,17 +49,17 @@ public:
   void Pause();
 
   void Resume();
 
   void OnEnd(const nsSpeechTask* aTask);
 
   void GetVoices(nsTArray< nsRefPtr<SpeechSynthesisVoice> >& aResult);
 
-  void DropGlobalQueue();
+  void ForceEnd();
 
 private:
   virtual ~SpeechSynthesis();
 
   void AdvanceQueue();
 
   nsCOMPtr<nsPIDOMWindow> mParent;
 
--- a/dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
+++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
@@ -36,14 +36,12 @@ child:
 parent:
     __delete__();
 
     PSpeechSynthesisRequest(nsString aText, nsString aUri, nsString aLang,
                             float aVolume, float aRate, float aPitch);
 
     sync ReadVoicesAndState() returns (RemoteVoice[] aVoices,
                                        nsString[] aDefaults, bool aIsSpeaking);
-
-    DropGlobalQueue();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
+++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
@@ -16,16 +16,18 @@ async protocol PSpeechSynthesisRequest
  parent:
 
   Pause();
 
   Resume();
 
   Cancel();
 
+  ForceEnd();
+
  child:
 
   __delete__(bool aIsError, float aElapsedTime, uint32_t aCharIndex);
 
   OnStart(nsString aUri);
 
   OnPause(float aElapsedTime, uint32_t aCharIndex);
 
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
@@ -179,10 +179,17 @@ SpeechTaskChild::Resume()
 
 void
 SpeechTaskChild::Cancel()
 {
   MOZ_ASSERT(mActor);
   mActor->SendCancel();
 }
 
+void
+SpeechTaskChild::ForceEnd()
+{
+  MOZ_ASSERT(mActor);
+  mActor->SendForceEnd();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
@@ -85,16 +85,18 @@ public:
   NS_IMETHOD SendAudioNative(int16_t* aData, uint32_t aDataLen) override;
 
   virtual void Pause() override;
 
   virtual void Resume() override;
 
   virtual void Cancel() override;
 
+  virtual void ForceEnd() override;
+
 private:
   SpeechSynthesisRequestChild* mActor;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
@@ -29,24 +29,16 @@ SpeechSynthesisParent::RecvReadVoicesAnd
                                               InfallibleTArray<nsString>* aDefaults,
                                               bool* aIsSpeaking)
 {
   nsSynthVoiceRegistry::GetInstance()->SendVoicesAndState(aVoices, aDefaults,
                                                           aIsSpeaking);
   return true;
 }
 
-bool
-SpeechSynthesisParent::RecvDropGlobalQueue()
-{
-  nsSynthVoiceRegistry::GetInstance()->DropGlobalQueue();
-
-  return true;
-}
-
 PSpeechSynthesisRequestParent*
 SpeechSynthesisParent::AllocPSpeechSynthesisRequestParent(const nsString& aText,
                                                           const nsString& aLang,
                                                           const nsString& aUri,
                                                           const float& aVolume,
                                                           const float& aRate,
                                                           const float& aPitch)
 {
@@ -122,16 +114,24 @@ SpeechSynthesisRequestParent::RecvResume
 bool
 SpeechSynthesisRequestParent::RecvCancel()
 {
   MOZ_ASSERT(mTask);
   mTask->Cancel();
   return true;
 }
 
+bool
+SpeechSynthesisRequestParent::RecvForceEnd()
+{
+  MOZ_ASSERT(mTask);
+  mTask->ForceEnd();
+  return true;
+}
+
 // SpeechTaskParent
 
 nsresult
 SpeechTaskParent::DispatchStartImpl(const nsAString& aUri)
 {
   MOZ_ASSERT(mActor);
   if(NS_WARN_IF(!(mActor->SendOnStart(nsString(aUri))))) {
     return NS_ERROR_FAILURE;
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
@@ -23,18 +23,16 @@ class SpeechSynthesisParent : public PSp
 
 public:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   bool RecvReadVoicesAndState(InfallibleTArray<RemoteVoice>* aVoices,
                               InfallibleTArray<nsString>* aDefaults,
                               bool* aIsSpeaking) override;
 
-  bool RecvDropGlobalQueue() override;
-
 protected:
   SpeechSynthesisParent();
   virtual ~SpeechSynthesisParent();
   PSpeechSynthesisRequestParent* AllocPSpeechSynthesisRequestParent(const nsString& aText,
                                                                     const nsString& aLang,
                                                                     const nsString& aUri,
                                                                     const float& aVolume,
                                                                     const float& aRate,
@@ -64,16 +62,18 @@ protected:
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual bool RecvPause() override;
 
   virtual bool RecvResume() override;
 
   virtual bool RecvCancel() override;
+
+  virtual bool RecvForceEnd() override;
 };
 
 class SpeechTaskParent : public nsSpeechTask
 {
   friend class SpeechSynthesisRequestParent;
 public:
   SpeechTaskParent(float aVolume, const nsAString& aUtterance)
     : nsSpeechTask(aVolume, aUtterance) {}
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -608,16 +608,30 @@ nsSpeechTask::Cancel()
     mPreCanceled = true;
   }
 
   if (!mIndirectAudio) {
     DispatchEndInner(GetCurrentTime(), GetCurrentCharOffset());
   }
 }
 
+void
+nsSpeechTask::ForceEnd()
+{
+  if (mStream) {
+    mStream->ChangeExplicitBlockerCount(1);
+  }
+
+  if (!mInited) {
+    mPreCanceled = true;
+  }
+
+  DispatchEndInner(GetCurrentTime(), GetCurrentCharOffset());
+}
+
 float
 nsSpeechTask::GetCurrentTime()
 {
   return mStream ? (float)(mStream->GetCurrentTime() / 1000000.0) : 0;
 }
 
 uint32_t
 nsSpeechTask::GetCurrentCharOffset()
--- a/dom/media/webspeech/synth/nsSpeechTask.h
+++ b/dom/media/webspeech/synth/nsSpeechTask.h
@@ -32,16 +32,18 @@ public:
   nsSpeechTask(float aVolume, const nsAString& aText);
 
   virtual void Pause();
 
   virtual void Resume();
 
   virtual void Cancel();
 
+  virtual void ForceEnd();
+
   float GetCurrentTime();
 
   uint32_t GetCurrentCharOffset();
 
   void SetSpeechSynthesis(SpeechSynthesis* aSpeechSynthesis);
 
   void Init(ProcessedMediaStream* aStream);
 
--- a/dom/media/webspeech/synth/nsSynthVoiceRegistry.cpp
+++ b/dom/media/webspeech/synth/nsSynthVoiceRegistry.cpp
@@ -752,27 +752,16 @@ nsSynthVoiceRegistry::SetIsSpeaking(bool
   nsTArray<SpeechSynthesisParent*> ssplist;
   GetAllSpeechSynthActors(ssplist);
   for (uint32_t i = 0; i < ssplist.Length(); ++i) {
     unused << ssplist[i]->SendIsSpeakingChanged(aIsSpeaking);
   }
 }
 
 void
-nsSynthVoiceRegistry::DropGlobalQueue()
-{
-  if (XRE_IsParentProcess()) {
-    mGlobalQueue.Clear();
-    SetIsSpeaking(false);
-  } else {
-    mSpeechSynthChild->SendDropGlobalQueue();
-  }
-}
-
-void
 nsSynthVoiceRegistry::SpeakImpl(VoiceData* aVoice,
                                 nsSpeechTask* aTask,
                                 const nsAString& aText,
                                 const float& aVolume,
                                 const float& aRate,
                                 const float& aPitch)
 {
   LOG(LogLevel::Debug,
--- a/dom/media/webspeech/synth/nsSynthVoiceRegistry.h
+++ b/dom/media/webspeech/synth/nsSynthVoiceRegistry.h
@@ -47,18 +47,16 @@ public:
   void SpeakNext();
 
   void ResumeQueue();
 
   bool IsSpeaking();
 
   void SetIsSpeaking(bool aIsSpeaking);
 
-  void DropGlobalQueue();
-
   static nsSynthVoiceRegistry* GetInstance();
 
   static already_AddRefed<nsSynthVoiceRegistry> GetInstanceForService();
 
   static void RecvRemoveVoice(const nsAString& aUri);
 
   static void RecvAddVoice(const RemoteVoice& aVoice);
 
--- a/dom/webidl/SpeechSynthesis.webidl
+++ b/dom/webidl/SpeechSynthesis.webidl
@@ -20,10 +20,11 @@ interface SpeechSynthesis {
   void speak(SpeechSynthesisUtterance utterance);
   void cancel();
   void pause();
   [UnsafeInPrerendering]
   void resume();
   sequence<SpeechSynthesisVoice> getVoices();
 
   [ChromeOnly]
-  void dropGlobalQueue();
+  // Force an utterance to end. Circumvents bad speech service implementations.
+  void forceEnd();
 };