Skip to content

Commit dc10130

Browse files
Allow PlatformSpeechSynthesiser to report error code on failure
Extend speakingErrorOccurred() of PlatformSpeechSynthesizerClient with SpeechError code that reflects the source of failure.
1 parent 05d16e8 commit dc10130

File tree

7 files changed

+58
-20
lines changed

7 files changed

+58
-20
lines changed

Source/WebCore/Modules/speech/SpeechSynthesis.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@
4141
#include <wtf/IsoMallocInlines.h>
4242
#include <wtf/NeverDestroyed.h>
4343

44+
namespace {
45+
WebCore::SpeechSynthesisErrorCode toSpeechSynthesisErrorEventCode(WebCore::SpeechError error) {
46+
switch(error) {
47+
case WebCore::SpeechError::Canceled: return WebCore::SpeechSynthesisErrorCode::Canceled;
48+
case WebCore::SpeechError::Interrupted: return WebCore::SpeechSynthesisErrorCode::Interrupted;
49+
case WebCore::SpeechError::AudioBusy: return WebCore::SpeechSynthesisErrorCode::AudioBusy;
50+
case WebCore::SpeechError::AudioHardware: return WebCore::SpeechSynthesisErrorCode::AudioHardware;
51+
case WebCore::SpeechError::Network: return WebCore::SpeechSynthesisErrorCode::Network;
52+
case WebCore::SpeechError::SynthesisUnavailable: return WebCore::SpeechSynthesisErrorCode::SynthesisUnavailable;
53+
case WebCore::SpeechError::SynthesisFailed: return WebCore::SpeechSynthesisErrorCode::SynthesisFailed;
54+
case WebCore::SpeechError::LanguageUnavailable: return WebCore::SpeechSynthesisErrorCode::LanguageUnavailable;
55+
case WebCore::SpeechError::VoiceUnavailable: return WebCore::SpeechSynthesisErrorCode::VoiceUnavailable;
56+
case WebCore::SpeechError::TextTooLong: return WebCore::SpeechSynthesisErrorCode::TextTooLong;
57+
case WebCore::SpeechError::InvalidArgument: return WebCore::SpeechSynthesisErrorCode::InvalidArgument;
58+
case WebCore::SpeechError::NotAllowed: return WebCore::SpeechSynthesisErrorCode::NotAllowed;
59+
default: ASSERT(false, "Invalid SpeechError code"); return WebCore::SpeechSynthesisErrorCode::Interrupted;
60+
}
61+
}
62+
} // namespace
63+
4464
namespace WebCore {
4565

4666
WTF_MAKE_ISO_ALLOCATED_IMPL(SpeechSynthesis);
@@ -207,18 +227,20 @@ void SpeechSynthesis::fireErrorEvent(const AtomString& type, SpeechSynthesisUtte
207227
utterance.dispatchEvent(SpeechSynthesisErrorEvent::create(type, { { &utterance, 0, 0, static_cast<float>((MonotonicTime::now() - utterance.startTime()).seconds()), { } }, errorCode }));
208228
}
209229

210-
void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance& utterance, bool errorOccurred)
230+
void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance& utterance, bool errorOccurred, SpeechError error)
211231
{
212232
ASSERT(m_currentSpeechUtterance);
213233
Ref<SpeechSynthesisUtterance> protect(utterance);
214234

215-
m_currentSpeechUtterance = nullptr;
235+
if (m_currentSpeechUtterance == &utterance)
236+
m_currentSpeechUtterance = nullptr;
216237

217-
if (errorOccurred)
218-
fireErrorEvent(eventNames().errorEvent, utterance, SpeechSynthesisErrorCode::Canceled);
238+
// For PlatformSpeechSynthesizer(s) that don't support ErrorEvent yet
239+
if (errorOccurred && error != SpeechError::None)
240+
fireErrorEvent(eventNames().errorEvent, utterance, toSpeechSynthesisErrorEventCode(error));
219241
else
220242
fireEvent(eventNames().endEvent, utterance, 0, 0, String());
221-
243+
222244
if (m_utteranceQueue.size()) {
223245
Ref<SpeechSynthesisUtterance> firstUtterance = m_utteranceQueue.takeFirst();
224246
ASSERT(&utterance == firstUtterance.ptr());
@@ -280,7 +302,7 @@ void SpeechSynthesis::speakingErrorOccurred()
280302
{
281303
if (!m_currentSpeechUtterance)
282304
return;
283-
speakingErrorOccurred(*m_currentSpeechUtterance->platformUtterance());
305+
speakingErrorOccurred(*m_currentSpeechUtterance->platformUtterance(), SpeechError::None);
284306
}
285307

286308
void SpeechSynthesis::boundaryEventOccurred(bool wordBoundary, unsigned charIndex, unsigned charLength)
@@ -321,10 +343,10 @@ void SpeechSynthesis::didFinishSpeaking(PlatformSpeechSynthesisUtterance& uttera
321343
handleSpeakingCompleted(static_cast<SpeechSynthesisUtterance&>(*utterance.client()), false);
322344
}
323345

324-
void SpeechSynthesis::speakingErrorOccurred(PlatformSpeechSynthesisUtterance& utterance)
346+
void SpeechSynthesis::speakingErrorOccurred(PlatformSpeechSynthesisUtterance& utterance, SpeechError error)
325347
{
326348
if (utterance.client())
327-
handleSpeakingCompleted(static_cast<SpeechSynthesisUtterance&>(*utterance.client()), true);
349+
handleSpeakingCompleted(static_cast<SpeechSynthesisUtterance&>(*utterance.client()), true, error);
328350
}
329351

330352
} // namespace WebCore

Source/WebCore/Modules/speech/SpeechSynthesis.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSyn
7373
void didPauseSpeaking(PlatformSpeechSynthesisUtterance&) override;
7474
void didResumeSpeaking(PlatformSpeechSynthesisUtterance&) override;
7575
void didFinishSpeaking(PlatformSpeechSynthesisUtterance&) override;
76-
void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&) override;
76+
void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&, SpeechError) override;
7777
void boundaryEventOccurred(PlatformSpeechSynthesisUtterance&, SpeechBoundary, unsigned charIndex, unsigned charLength) override;
7878

7979
// SpeechSynthesisClient override methods
@@ -84,9 +84,9 @@ class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSyn
8484
void speakingErrorOccurred() override;
8585
void boundaryEventOccurred(bool wordBoundary, unsigned charIndex, unsigned charLength) override;
8686
void voicesChanged() override;
87-
87+
8888
void startSpeakingImmediately(SpeechSynthesisUtterance&);
89-
void handleSpeakingCompleted(SpeechSynthesisUtterance&, bool errorOccurred);
89+
void handleSpeakingCompleted(SpeechSynthesisUtterance&, bool errorOccurred, SpeechError error = SpeechError::None);
9090
void fireEvent(const AtomString& type, SpeechSynthesisUtterance&, unsigned long charIndex, unsigned long charLength, const String& name) const;
9191
void fireErrorEvent(const AtomString& type, SpeechSynthesisUtterance&, SpeechSynthesisErrorCode) const;
9292

@@ -99,14 +99,14 @@ class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSyn
9999

100100
bool userGestureRequiredForSpeechStart() const { return m_restrictions & RequireUserGestureForSpeechStartRestriction; }
101101
void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
102-
102+
103103
ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); }
104104
EventTargetInterface eventTargetInterface() const final { return SpeechSynthesisEventTargetInterfaceType; }
105105
void refEventTarget() final { ref(); }
106106
void derefEventTarget() final { deref(); }
107-
107+
108108
PlatformSpeechSynthesizer& ensurePlatformSpeechSynthesizer();
109-
109+
110110
std::unique_ptr<PlatformSpeechSynthesizer> m_platformSpeechSynthesizer;
111111
Vector<Ref<SpeechSynthesisVoice>> m_voiceList;
112112
RefPtr<SpeechSynthesisUtterance> m_currentSpeechUtterance;

Source/WebCore/platform/PlatformSpeechSynthesizer.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ OBJC_CLASS WebSpeechSynthesisWrapper;
3838

3939
namespace WebCore {
4040

41+
enum class SpeechError : uint8_t {
42+
None,
43+
Canceled,
44+
Interrupted,
45+
AudioBusy,
46+
AudioHardware,
47+
Network,
48+
SynthesisUnavailable,
49+
SynthesisFailed,
50+
LanguageUnavailable,
51+
VoiceUnavailable,
52+
TextTooLong,
53+
InvalidArgument,
54+
NotAllowed
55+
};
56+
4157
enum class SpeechBoundary : uint8_t {
4258
SpeechWordBoundary,
4359
SpeechSentenceBoundary
@@ -51,7 +67,7 @@ class PlatformSpeechSynthesizerClient {
5167
virtual void didFinishSpeaking(PlatformSpeechSynthesisUtterance&) = 0;
5268
virtual void didPauseSpeaking(PlatformSpeechSynthesisUtterance&) = 0;
5369
virtual void didResumeSpeaking(PlatformSpeechSynthesisUtterance&) = 0;
54-
virtual void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&) = 0;
70+
virtual void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&, SpeechError) = 0;
5571
virtual void boundaryEventOccurred(PlatformSpeechSynthesisUtterance&, SpeechBoundary, unsigned charIndex, unsigned charLength) = 0;
5672
virtual void voicesDidChange() = 0;
5773
protected:

Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ - (void)cancel
160160
return;
161161

162162
[m_synthesizer stopSpeakingAtBoundary:NSSpeechImmediateBoundary];
163-
m_synthesizerObject->client()->speakingErrorOccurred(*m_utterance);
163+
m_synthesizerObject->client()->speakingErrorOccurred(*m_utterance, WebCore::SpeechError::None);
164164
m_utterance = 0;
165165
}
166166

@@ -185,7 +185,7 @@ - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)
185185
if (finishedSpeaking)
186186
m_synthesizerObject->client()->didFinishSpeaking(*utterance);
187187
else
188-
m_synthesizerObject->client()->speakingErrorOccurred(*utterance);
188+
m_synthesizerObject->client()->speakingErrorOccurred(*utterance, WebCore::SpeechError::None);
189189
}
190190

191191
- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender willSpeakWord:(NSRange)characterRange ofString:(NSString *)string

Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void PlatformSpeechSynthesizerMock::cancel()
7575
return;
7676

7777
m_speakingFinishedTimer.stop();
78-
client()->speakingErrorOccurred(*m_utterance);
78+
client()->speakingErrorOccurred(*m_utterance, WebCore::SpeechError::Canceled);
7979
m_utterance = nullptr;
8080
}
8181

Source/WebKit/UIProcess/WebPageProxy.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9715,7 +9715,7 @@ void WebPageProxy::didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
97159715
speechSynthesisData().speakingResumedCompletionHandler();
97169716
}
97179717

9718-
void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&)
9718+
void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechError)
97199719
{
97209720
send(Messages::WebPage::SpeakingErrorOccurred());
97219721
}

Source/WebKit/UIProcess/WebPageProxy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2225,7 +2225,7 @@ class WebPageProxy : public API::ObjectImpl<API::Object::Type::Page>
22252225
void didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
22262226
void didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
22272227
void didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
2228-
void speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&) override;
2228+
void speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechError) override;
22292229
void boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary, unsigned charIndex, unsigned charLength) override;
22302230
void voicesDidChange() override;
22312231

0 commit comments

Comments
 (0)