Bug 1178738 - Implement dispatch of SpeechSynthesisErrorEvent. r?smaug
MozReview-Commit-ID: 77epkO1lh5c
--- 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;