diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt index 1137e0dc74d74..c4b7a97792426 100644 --- a/Source/WebCore/CMakeLists.txt +++ b/Source/WebCore/CMakeLists.txt @@ -418,6 +418,7 @@ set(WebCore_NON_SVG_IDL_FILES Modules/speech/DOMWindowSpeechSynthesis.idl Modules/speech/SpeechSynthesis.idl Modules/speech/SpeechSynthesisEvent.idl + Modules/speech/SpeechSynthesisErrorEvent.idl Modules/speech/SpeechSynthesisUtterance.idl Modules/speech/SpeechSynthesisVoice.idl diff --git a/Source/WebCore/Modules/speech/SpeechSynthesis.cpp b/Source/WebCore/Modules/speech/SpeechSynthesis.cpp index 668d3cbfd419c..be1c66bcd124f 100644 --- a/Source/WebCore/Modules/speech/SpeechSynthesis.cpp +++ b/Source/WebCore/Modules/speech/SpeechSynthesis.cpp @@ -31,11 +31,32 @@ #include "EventNames.h" #include "PlatformSpeechSynthesisVoice.h" #include "PlatformSpeechSynthesizer.h" +#include "SpeechSynthesisErrorEvent.h" #include "SpeechSynthesisEvent.h" #include "SpeechSynthesisUtterance.h" #include "UserGestureIndicator.h" #include +namespace { +WebCore::SpeechSynthesisErrorEvent::Code toSpeechSynthesisErrorEventCode(WebCore::SpeechError error) { + switch(error) { + case WebCore::SpeechErrorCanceled: return WebCore::SpeechSynthesisErrorEvent::Code::Canceled; + case WebCore::SpeechErrorInterrupted: return WebCore::SpeechSynthesisErrorEvent::Code::Interrupted; + case WebCore::SpeechErrorAudioBusy: return WebCore::SpeechSynthesisErrorEvent::Code::AudioBusy; + case WebCore::SpeechErrorAudioHardware: return WebCore::SpeechSynthesisErrorEvent::Code::AudioHardware; + case WebCore::SpeechErrorNetwork: return WebCore::SpeechSynthesisErrorEvent::Code::Network; + case WebCore::SpeechErrorSynthesisUnavailable: return WebCore::SpeechSynthesisErrorEvent::Code::SynthesisUnavailable; + case WebCore::SpeechErrorSynthesisFailed: return WebCore::SpeechSynthesisErrorEvent::Code::SynthesisFailed; + case WebCore::SpeechErrorLanguageUnavailable: return WebCore::SpeechSynthesisErrorEvent::Code::LanguageUnavailable; + case WebCore::SpeechErrorVoiceUnavailable: return WebCore::SpeechSynthesisErrorEvent::Code::VoiceUnavailable; + case WebCore::SpeechErrorTextTooLong: return WebCore::SpeechSynthesisErrorEvent::Code::TextTooLong; + case WebCore::SpeechErrorInvalidArgument: return WebCore::SpeechSynthesisErrorEvent::Code::InvalidArgument; + case WebCore::SpeechErrorNotAllowed: return WebCore::SpeechSynthesisErrorEvent::Code::NotAllowed; + default: ASSERT(false, "Invalid SpeechError code"); return WebCore::SpeechSynthesisErrorEvent::Code::Interrupted; + } +} +} // namespace + namespace WebCore { Ref SpeechSynthesis::create(WeakPtr client) @@ -185,14 +206,24 @@ void SpeechSynthesis::fireEvent(const AtomString& type, SpeechSynthesisUtterance utterance.dispatchEvent(SpeechSynthesisEvent::create(type, charIndex, (MonotonicTime::now() - utterance.startTime()).seconds(), name)); } -void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance& utterance, bool errorOccurred) +void SpeechSynthesis::fireErrorEvent(SpeechSynthesisUtterance& utterance, SpeechError error) +{ + utterance.dispatchEvent(SpeechSynthesisErrorEvent::create(toSpeechSynthesisErrorEventCode(error))); +} + +void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance& utterance, bool errorOccurred, SpeechError error) { ASSERT(m_currentSpeechUtterance); Ref protect(utterance); - m_currentSpeechUtterance = nullptr; + if (m_currentSpeechUtterance == &utterance) + m_currentSpeechUtterance = nullptr; - fireEvent(errorOccurred ? eventNames().errorEvent : eventNames().endEvent, utterance, 0, String()); + // For older PlatformSpeechSynthesizers that doesn't support ErrorEvent yet + if (!errorOccurred || error == SpeechErrorNone) + fireEvent(errorOccurred ? eventNames().errorEvent : eventNames().endEvent, utterance, 0, String()); + else + fireErrorEvent(utterance, error); if (m_utteranceQueue.size()) { Ref firstUtterance = m_utteranceQueue.takeFirst(); @@ -255,7 +286,7 @@ void SpeechSynthesis::speakingErrorOccurred() { if (!m_currentSpeechUtterance) return; - speakingErrorOccurred(*m_currentSpeechUtterance->platformUtterance()); + speakingErrorOccurred(*m_currentSpeechUtterance->platformUtterance(), SpeechErrorNone); } void SpeechSynthesis::boundaryEventOccurred(bool wordBoundary, unsigned charIndex) @@ -296,10 +327,10 @@ void SpeechSynthesis::didFinishSpeaking(PlatformSpeechSynthesisUtterance& uttera handleSpeakingCompleted(static_cast(*utterance.client()), false); } -void SpeechSynthesis::speakingErrorOccurred(PlatformSpeechSynthesisUtterance& utterance) +void SpeechSynthesis::speakingErrorOccurred(PlatformSpeechSynthesisUtterance& utterance, SpeechError error) { if (utterance.client()) - handleSpeakingCompleted(static_cast(*utterance.client()), true); + handleSpeakingCompleted(static_cast(*utterance.client()), true, error); } } // namespace WebCore diff --git a/Source/WebCore/Modules/speech/SpeechSynthesis.h b/Source/WebCore/Modules/speech/SpeechSynthesis.h index 63cfc6549abe2..f44c458e27317 100644 --- a/Source/WebCore/Modules/speech/SpeechSynthesis.h +++ b/Source/WebCore/Modules/speech/SpeechSynthesis.h @@ -67,7 +67,7 @@ class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSyn void didPauseSpeaking(PlatformSpeechSynthesisUtterance&) override; void didResumeSpeaking(PlatformSpeechSynthesisUtterance&) override; void didFinishSpeaking(PlatformSpeechSynthesisUtterance&) override; - void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&) override; + void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&, SpeechError) override; void boundaryEventOccurred(PlatformSpeechSynthesisUtterance&, SpeechBoundary, unsigned charIndex) override; // SpeechSynthesisClient override methods @@ -80,8 +80,9 @@ class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSyn void voicesChanged() override; void startSpeakingImmediately(SpeechSynthesisUtterance&); - void handleSpeakingCompleted(SpeechSynthesisUtterance&, bool errorOccurred); + void handleSpeakingCompleted(SpeechSynthesisUtterance&, bool errorOccurred, SpeechError error = SpeechErrorNone); void fireEvent(const AtomString& type, SpeechSynthesisUtterance&, unsigned long charIndex, const String& name); + void fireErrorEvent(SpeechSynthesisUtterance&, SpeechError); #if PLATFORM(IOS_FAMILY) // Restrictions to change default behaviors. diff --git a/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.cpp b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.cpp new file mode 100644 index 0000000000000..3047833237100 --- /dev/null +++ b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.cpp @@ -0,0 +1,53 @@ +/* Copyright (C) 2019 RDK Management. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS. OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config.h" +#include "SpeechSynthesisErrorEvent.h" + +#if ENABLE(SPEECH_SYNTHESIS) + +#include "EventNames.h" +#include + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(SpeechSynthesisErrorEvent); + +Ref SpeechSynthesisErrorEvent::create(Code error) +{ + return adoptRef(*new SpeechSynthesisErrorEvent(error)); +} + +SpeechSynthesisErrorEvent::SpeechSynthesisErrorEvent(Code error) + : SpeechSynthesisEvent(eventNames().errorEvent, 0, 0.0, String()), m_error(error) +{ +} + +SpeechSynthesisErrorEvent::Code SpeechSynthesisErrorEvent::error() const { + return m_error; +} + +} // namespace WebCore + +#endif // ENABLE(SPEECH_SYNTHESIS) diff --git a/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.h b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.h new file mode 100644 index 0000000000000..28c8fcd3a3989 --- /dev/null +++ b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2019 RDK Management. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS. OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#if ENABLE(SPEECH_SYNTHESIS) + +#include "SpeechSynthesisEvent.h" + +namespace WebCore { + +class SpeechSynthesisErrorEvent final : public SpeechSynthesisEvent { + WTF_MAKE_ISO_ALLOCATED(SpeechSynthesisErrorEvent); +public: + enum class Code { + Canceled, + Interrupted, + AudioBusy, + AudioHardware, + Network, + SynthesisUnavailable, + SynthesisFailed, + LanguageUnavailable, + VoiceUnavailable, + TextTooLong, + InvalidArgument, + NotAllowed + }; + + static Ref create(const Code error); + virtual EventInterface eventInterface() const { return SpeechSynthesisErrorEventInterfaceType; } + Code error() const; + +private: + SpeechSynthesisErrorEvent(const Code error); + + Code m_error; +}; + +} // namespace WebCore + +#endif // ENABLE(SPEECH_SYNTHESIS) diff --git a/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.idl b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.idl new file mode 100644 index 0000000000000..7aa80d07d5d9c --- /dev/null +++ b/Source/WebCore/Modules/speech/SpeechSynthesisErrorEvent.idl @@ -0,0 +1,46 @@ +/* Copyright (C) 2019 RDK Management. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS. OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +// https://w3c.github.io/speech-api/#enumdef-speechsynthesiserrorcode +[ + Conditional=SPEECH_SYNTHESIS, +] enum SpeechSynthesisErrorCode { + "canceled", + "interrupted", + "audio-busy", + "audio-hardware", + "network", + "synthesis-unavailable", + "synthesis-failed", + "language-unavailable", + "voice-unavailable", + "text-too-long", + "invalid-argument", + "not-allowed" +}; + +[ + Conditional=SPEECH_SYNTHESIS +] interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent { + readonly attribute SpeechSynthesisErrorCode error; +}; diff --git a/Source/WebCore/Modules/speech/SpeechSynthesisEvent.h b/Source/WebCore/Modules/speech/SpeechSynthesisEvent.h index 3c16c3ef87672..bbc945cc9fedb 100644 --- a/Source/WebCore/Modules/speech/SpeechSynthesisEvent.h +++ b/Source/WebCore/Modules/speech/SpeechSynthesisEvent.h @@ -31,7 +31,7 @@ namespace WebCore { -class SpeechSynthesisEvent final : public Event { +class SpeechSynthesisEvent : public Event { WTF_MAKE_ISO_ALLOCATED(SpeechSynthesisEvent); public: static Ref create(const AtomString& type, unsigned charIndex, float elapsedTime, const String& name); @@ -42,9 +42,10 @@ class SpeechSynthesisEvent final : public Event { virtual EventInterface eventInterface() const { return SpeechSynthesisEventInterfaceType; } -private: +protected: SpeechSynthesisEvent(const AtomString& type, unsigned charIndex, float elapsedTime, const String& name); +private: unsigned long m_charIndex; float m_elapsedTime; String m_name; diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt index 35d8a3c9d3e59..59fb0a46a57ac 100644 --- a/Source/WebCore/Sources.txt +++ b/Source/WebCore/Sources.txt @@ -217,6 +217,7 @@ Modules/remoteplayback/RemotePlayback.cpp Modules/speech/DOMWindowSpeechSynthesis.cpp Modules/speech/SpeechSynthesis.cpp Modules/speech/SpeechSynthesisEvent.cpp +Modules/speech/SpeechSynthesisErrorEvent.cpp Modules/speech/SpeechSynthesisUtterance.cpp Modules/speech/SpeechSynthesisVoice.cpp @@ -3412,6 +3413,7 @@ JSSourceBuffer.cpp JSSourceBufferList.cpp JSSpeechSynthesis.cpp JSSpeechSynthesisEvent.cpp +JSSpeechSynthesisErrorEvent.cpp JSSpeechSynthesisUtterance.cpp JSSpeechSynthesisVoice.cpp JSStaticRange.cpp diff --git a/Source/WebCore/dom/EventNames.in b/Source/WebCore/dom/EventNames.in index 157f331c1ba73..c84b682e81bd0 100644 --- a/Source/WebCore/dom/EventNames.in +++ b/Source/WebCore/dom/EventNames.in @@ -62,6 +62,7 @@ RTCDTMFToneChangeEvent conditional=WEB_RTC RTCPeerConnectionIceEvent conditional=WEB_RTC RTCTrackEvent conditional=WEB_RTC SpeechSynthesisEvent conditional=SPEECH_SYNTHESIS +SpeechSynthesisErrorEvent conditional=SPEECH_SYNTHESIS WebGLContextEvent conditional=WEBGL StorageEvent SVGEvents interfaceName=Event diff --git a/Source/WebCore/platform/PlatformSpeechSynthesizer.h b/Source/WebCore/platform/PlatformSpeechSynthesizer.h index b4b8d08a0cc31..7e301e0ffa5a8 100644 --- a/Source/WebCore/platform/PlatformSpeechSynthesizer.h +++ b/Source/WebCore/platform/PlatformSpeechSynthesizer.h @@ -43,6 +43,22 @@ enum class SpeechBoundary : uint8_t { SpeechSentenceBoundary }; +enum SpeechError { + SpeechErrorNone, + SpeechErrorCanceled, + SpeechErrorInterrupted, + SpeechErrorAudioBusy, + SpeechErrorAudioHardware, + SpeechErrorNetwork, + SpeechErrorSynthesisUnavailable, + SpeechErrorSynthesisFailed, + SpeechErrorLanguageUnavailable, + SpeechErrorVoiceUnavailable, + SpeechErrorTextTooLong, + SpeechErrorInvalidArgument, + SpeechErrorNotAllowed +}; + class PlatformSpeechSynthesisUtterance; class PlatformSpeechSynthesizerClient { @@ -51,7 +67,7 @@ class PlatformSpeechSynthesizerClient { virtual void didFinishSpeaking(PlatformSpeechSynthesisUtterance&) = 0; virtual void didPauseSpeaking(PlatformSpeechSynthesisUtterance&) = 0; virtual void didResumeSpeaking(PlatformSpeechSynthesisUtterance&) = 0; - virtual void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&) = 0; + virtual void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&, SpeechError) = 0; virtual void boundaryEventOccurred(PlatformSpeechSynthesisUtterance&, SpeechBoundary, unsigned charIndex) = 0; virtual void voicesDidChange() = 0; protected: diff --git a/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm b/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm index 0faedf84bd567..2dfc785cb1d24 100644 --- a/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm +++ b/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm @@ -160,7 +160,7 @@ - (void)cancel return; [m_synthesizer stopSpeakingAtBoundary:NSSpeechImmediateBoundary]; - m_synthesizerObject->client()->speakingErrorOccurred(*m_utterance); + m_synthesizerObject->client()->speakingErrorOccurred(*m_utterance, WebCore::SpeechErrorNone); m_utterance = 0; } @@ -185,7 +185,7 @@ - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL) if (finishedSpeaking) m_synthesizerObject->client()->didFinishSpeaking(*utterance); else - m_synthesizerObject->client()->speakingErrorOccurred(*utterance); + m_synthesizerObject->client()->speakingErrorOccurred(*utterance, WebCore::SpeechErrorNone); } - (void)speechSynthesizer:(NSSpeechSynthesizer *)sender willSpeakWord:(NSRange)characterRange ofString:(NSString *)string diff --git a/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp b/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp index 69919cde9842f..c53ab29fb0aa8 100644 --- a/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp +++ b/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp @@ -75,7 +75,7 @@ void PlatformSpeechSynthesizerMock::cancel() return; m_speakingFinishedTimer.stop(); - client()->speakingErrorOccurred(*m_utterance); + client()->speakingErrorOccurred(*m_utterance, SpeechErrorCanceled); m_utterance = nullptr; } diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm index 7897e28e3c8ca..8934ee636ea62 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm @@ -285,7 +285,7 @@ speechSynthesisData().speakingResumedCompletionHandler(); } -void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&) +void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechError) { process().send(Messages::WebPage::SpeakingErrorOccurred(), m_webPageID); } diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h index dc833c9b9d16d..6f14ed7faee12 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.h +++ b/Source/WebKit/UIProcess/WebPageProxy.h @@ -2225,7 +2225,7 @@ class WebPageProxy : public API::ObjectImpl void didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override; void didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override; void didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override; - void speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&) override; + void speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechError) override; void boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary, unsigned charIndex) override; void voicesDidChange() override;