Bug 1178738 - Implement dispatch of SpeechSynthesisErrorEvent. r=smaug
☠☠ backed out by 3756806c593a ☠ ☠
authorEitan Isaacson <eitan@monotonous.org>
Wed, 18 May 2016 10:14:45 -0700
changeset 300236 6fe5dd5c3f33486f3dddf6c363bd72d7f7687d6a
parent 300235 21944f25fbf079a6851cd9cc7b4a922bc3429c66
child 300237 4c66c0ddf56267ad34c5a3538a66d7f9fcfaafa2
push id30309
push usercbook@mozilla.com
push dateFri, 03 Jun 2016 10:00:40 +0000
treeherdermozilla-central@e27fe24a746f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1178738
milestone49.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 1178738 - Implement dispatch of SpeechSynthesisErrorEvent. r=smaug MozReview-Commit-ID: 77epkO1lh5c
dom/media/webspeech/synth/SpeechSynthesisUtterance.cpp
dom/media/webspeech/synth/SpeechSynthesisUtterance.h
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/nsSpeechTask.cpp
dom/media/webspeech/synth/test/common.js
dom/media/webspeech/synth/test/file_speech_queue.html
--- a/dom/media/webspeech/synth/SpeechSynthesisUtterance.cpp
+++ b/dom/media/webspeech/synth/SpeechSynthesisUtterance.cpp
@@ -4,16 +4,17 @@
  * 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 "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsGkAtoms.h"
 
 #include "mozilla/dom/SpeechSynthesisEvent.h"
+#include "mozilla/dom/SpeechSynthesisErrorEvent.h"
 #include "mozilla/dom/SpeechSynthesisUtteranceBinding.h"
 #include "SpeechSynthesisUtterance.h"
 #include "SpeechSynthesisVoice.h"
 
 #include <stdlib.h>
 
 namespace mozilla {
 namespace dom {
@@ -169,10 +170,29 @@ SpeechSynthesisUtterance::DispatchSpeech
   init.mElapsedTime = aElapsedTime;
   init.mName = aName;
 
   RefPtr<SpeechSynthesisEvent> event =
     SpeechSynthesisEvent::Constructor(this, aEventType, init);
   DispatchTrustedEvent(event);
 }
 
+void
+SpeechSynthesisUtterance::DispatchSpeechSynthesisErrorEvent(uint32_t aCharIndex,
+                                                            float aElapsedTime,
+                                                            SpeechSynthesisErrorCode aError)
+{
+  SpeechSynthesisErrorEventInit init;
+  init.mBubbles = false;
+  init.mCancelable = false;
+  init.mUtterance = this;
+  init.mCharIndex = aCharIndex;
+  init.mElapsedTime = aElapsedTime;
+  init.mName = NS_LITERAL_STRING("");
+  init.mError = aError;
+
+  RefPtr<SpeechSynthesisErrorEvent> event =
+    SpeechSynthesisErrorEvent::Constructor(this, NS_LITERAL_STRING("error"), init);
+  DispatchTrustedEvent(event);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webspeech/synth/SpeechSynthesisUtterance.h
+++ b/dom/media/webspeech/synth/SpeechSynthesisUtterance.h
@@ -15,16 +15,17 @@
 #include "nsSpeechTask.h"
 
 namespace mozilla {
 namespace dom {
 
 class SpeechSynthesisVoice;
 class SpeechSynthesis;
 class nsSynthVoiceRegistry;
+enum class SpeechSynthesisErrorCode : uint32_t;
 
 class SpeechSynthesisUtterance final : public DOMEventTargetHelper
 {
   friend class SpeechSynthesis;
   friend class nsSpeechTask;
   friend class nsSynthVoiceRegistry;
 
 public:
@@ -94,16 +95,20 @@ public:
 
 private:
   virtual ~SpeechSynthesisUtterance();
 
   void DispatchSpeechSynthesisEvent(const nsAString& aEventType,
                                     uint32_t aCharIndex,
                                     float aElapsedTime, const nsAString& aName);
 
+  void DispatchSpeechSynthesisErrorEvent(uint32_t aCharIndex,
+                                         float aElapsedTime,
+                                         SpeechSynthesisErrorCode aError);
+
   nsString mText;
 
   nsString mLang;
 
   float mVolume;
 
   float mRate;
 
--- a/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
+++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
@@ -24,17 +24,17 @@ async protocol PSpeechSynthesisRequest
   async Cancel();
 
   async ForceEnd();
 
   async SetAudioOutputVolume(float aVolume);
 
  child:
 
-  async OnEnd(bool aIsError, float aElapsedTime, uint32_t aCharIndex);
+  async OnEnd(bool aIsError, float aElapsedTime, uint32_t aCharIndex, uint32_t aError);
 
   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);
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
@@ -91,23 +91,24 @@ SpeechSynthesisRequestChild::RecvOnStart
 {
   mTask->DispatchStartImpl(aUri);
   return true;
 }
 
 bool
 SpeechSynthesisRequestChild::RecvOnEnd(const bool& aIsError,
                                        const float& aElapsedTime,
-                                       const uint32_t& aCharIndex)
+                                       const uint32_t& aCharIndex,
+                                       const uint32_t& aError)
 {
   SpeechSynthesisRequestChild* actor = mTask->mActor;
   mTask->mActor = nullptr;
 
   if (aIsError) {
-    mTask->DispatchErrorImpl(aElapsedTime, aCharIndex, 0);
+    mTask->DispatchErrorImpl(aElapsedTime, aCharIndex, aError);
   } else {
     mTask->DispatchEndImpl(aElapsedTime, aCharIndex);
   }
 
   actor->Send__delete__(actor);
 
   return true;
 }
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
@@ -51,17 +51,18 @@ public:
   explicit SpeechSynthesisRequestChild(SpeechTaskChild* aTask);
   virtual ~SpeechSynthesisRequestChild();
 
 protected:
   bool RecvOnStart(const nsString& aUri) override;
 
   bool RecvOnEnd(const bool& aIsError,
                  const float& aElapsedTime,
-                 const uint32_t& aCharIndex) override;
+                 const uint32_t& aCharIndex,
+                 const uint32_t& aError) override;
 
   bool RecvOnPause(const float& aElapsedTime, const uint32_t& aCharIndex) override;
 
   bool RecvOnResume(const float& aElapsedTime, const uint32_t& aCharIndex) override;
 
   bool RecvOnBoundary(const nsString& aName, const float& aElapsedTime,
                       const uint32_t& aCharIndex) override;
 
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp
@@ -161,17 +161,17 @@ SpeechTaskParent::DispatchStartImpl(cons
 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)))) {
+  if(NS_WARN_IF(!(mActor->SendOnEnd(false, aElapsedTime, aCharIndex, 0)))) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 SpeechTaskParent::DispatchPauseImpl(float aElapsedTime, uint32_t aCharIndex)
@@ -194,17 +194,17 @@ SpeechTaskParent::DispatchResumeImpl(flo
 
   return NS_OK;
 }
 
 nsresult
 SpeechTaskParent::DispatchErrorImpl(float aElapsedTime, uint32_t aCharIndex, uint32_t aError)
 {
   MOZ_ASSERT(mActor);
-  if(NS_WARN_IF(!(mActor->SendOnEnd(true, aElapsedTime, aCharIndex)))) {
+  if(NS_WARN_IF(!(mActor->SendOnEnd(true, aElapsedTime, aCharIndex, aError)))) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 SpeechTaskParent::DispatchBoundaryImpl(const nsAString& aName,
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -528,19 +528,18 @@ nsSpeechTask::DispatchErrorImpl(float aE
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (mSpeechSynthesis) {
     mSpeechSynthesis->OnEnd(this);
   }
 
   mUtterance->mState = SpeechSynthesisUtterance::STATE_ENDED;
-  mUtterance->DispatchSpeechSynthesisEvent(NS_LITERAL_STRING("error"),
-                                           aCharIndex, aElapsedTime,
-                                           EmptyString());
+  mUtterance->DispatchSpeechSynthesisErrorEvent(aCharIndex, aElapsedTime,
+                                                SpeechSynthesisErrorCode(aError));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSpeechTask::DispatchBoundary(const nsAString& aName,
                                float aElapsedTime, uint32_t aCharIndex)
 {
   if (!mIndirectAudio) {
--- a/dom/media/webspeech/synth/test/common.js
+++ b/dom/media/webspeech/synth/test/common.js
@@ -34,17 +34,18 @@ function synthTestQueue(aTestArgs, aEndF
       })(aTestArgs[i][1] ? aTestArgs[i][1].uri : null));
 
     u.addEventListener('end', onend_handler);
     u.addEventListener('error', onend_handler);
 
     u.addEventListener('error',
       (function (expectedError) {
         return function onerror_handler(e) {
-          ok(expectedError, "Error in speech utterance '" + e.target.text + "'");
+          ok(e instanceof SpeechSynthesisErrorEvent, "error event is of right type");
+          is(expectedError, e.error, "Matched error type");
         };
       })(aTestArgs[i][1] ? aTestArgs[i][1].err : false));
 
     utterances.push(u);
     win.speechSynthesis.speak(u);
   }
 
   ok(!speechSynthesis.speaking, "speechSynthesis is not speaking yet.");
--- a/dom/media/webspeech/synth/test/file_speech_queue.html
+++ b/dom/media/webspeech/synth/test/file_speech_queue.html
@@ -47,17 +47,17 @@ function testFunc(done_cb) {
     [[{text: "Hello, world."},
       { uri: langUriMap['en-JM'] }],
      [{text: "Bonjour tout le monde .",
        args: { lang: "fr", rate: 0.5, pitch: 0.75 }},
       { uri: langUriMap['fr-CA'], rate: 0.5, pitch: 0.75}],
      [{text: "How are you doing?", args: { lang: "en-GB" } },
       { rate: 1, pitch: 1, uri: langUriMap['en-GB']}],
      [{text: "Come stai?", args: { lang: "it-IT-fail" } },
-      { rate: 1, pitch: 1, uri: langUriMap['it-IT-fail'], err: true }],
+      { rate: 1, pitch: 1, uri: langUriMap['it-IT-fail'], err: "synthesis-failed" }],
      [{text: "¡hasta mañana!", args: { lang: "es-MX" } },
       { uri: langUriMap['es-MX'] }]],
     function () {
       var test_data = [];
       var voices = speechSynthesis.getVoices();
       for (var voice of voices) {
         if (voice.voiceURI.indexOf('urn:moz-tts:fake-direct') < 0) {
           continue;