Title: [243002] trunk/Source
Revision
243002
Author
[email protected]
Date
2019-03-15 11:18:36 -0700 (Fri, 15 Mar 2019)

Log Message

[macOS] Broker access to Speech Synthesis
https://bugs.webkit.org/show_bug.cgi?id=195645
<rdar://problem/35369026>

Reviewed by Brent Fulgham.

To be able to close the connection to the speech synthesis daemon in the WebContent process,
speech synthesis should be performed in the UI process. This patch forwards speech synthesis
requests to the UI process by sending messages. On the UI process side, the speech synthesis
is performed by simply using the existing platform speech synthesizer. Speech synthesis
events are sent back to the WebContent process. All messages are async, except for the
message to get the list of available voices.

Source/WebCore:

No new tests, covered by existing tests.

* Modules/speech/DOMWindowSpeechSynthesis.cpp:
(WebCore::DOMWindowSpeechSynthesis::speechSynthesis):
* Modules/speech/SpeechSynthesis.cpp:
(WebCore::SpeechSynthesis::create):
(WebCore::SpeechSynthesis::SpeechSynthesis):
(WebCore::SpeechSynthesis::setPlatformSynthesizer):
(WebCore::SpeechSynthesis::getVoices):
(WebCore::SpeechSynthesis::startSpeakingImmediately):
(WebCore::SpeechSynthesis::cancel):
(WebCore::SpeechSynthesis::pause):
(WebCore::SpeechSynthesis::resume):
(WebCore::SpeechSynthesis::boundaryEventOccurred):
(WebCore::SpeechSynthesis::didStartSpeaking):
(WebCore::SpeechSynthesis::didFinishSpeaking):
(WebCore::SpeechSynthesis::didPauseSpeaking):
(WebCore::SpeechSynthesis::didResumeSpeaking):
(WebCore::SpeechSynthesis::speakingErrorOccurred):
(WebCore::SpeechSynthesis::voicesChanged):
* Modules/speech/SpeechSynthesis.h:
* WebCore.xcodeproj/project.pbxproj:
* page/Page.cpp:
(WebCore::Page::Page):
* page/Page.h:
(WebCore::Page::speechSynthesisClient const):
* page/PageConfiguration.cpp:
* page/PageConfiguration.h:
* page/SpeechSynthesisClient.h: Added.
* platform/PlatformSpeechSynthesisUtterance.h:
* platform/PlatformSpeechSynthesizer.h:
* platform/ios/PlatformSpeechSynthesizerIOS.mm:
(-[WebSpeechSynthesisWrapper speechSynthesizer:willSpeakRangeOfSpeechString:utterance:]):
* platform/mac/PlatformSpeechSynthesizerMac.mm:
(-[WebSpeechSynthesisWrapper speechSynthesizer:willSpeakWord:ofString:]):
* platform/mock/PlatformSpeechSynthesizerMock.cpp:
(WebCore::PlatformSpeechSynthesizerMock::speak):

Source/WebKit:

* Sources.txt:
* UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::WebPageProxy::didStartSpeaking):
(WebKit::WebPageProxy::didFinishSpeaking):
(WebKit::WebPageProxy::didPauseSpeaking):
(WebKit::WebPageProxy::didResumeSpeaking):
(WebKit::WebPageProxy::speakingErrorOccurred):
(WebKit::WebPageProxy::boundaryEventOccurred):
(WebKit::WebPageProxy::voicesDidChange):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::ensureSpeechSynthesisData):
(WebKit::WebPageProxy::speechSynthesisVoiceList):
(WebKit::WebPageProxy::speechSynthesisSpeak):
(WebKit::WebPageProxy::speechSynthesisCancel):
(WebKit::WebPageProxy::speechSynthesisPause):
(WebKit::WebPageProxy::speechSynthesisResume):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp: Added.
(WebKit::WebSpeechSynthesisClient::voiceList):
(WebKit::WebSpeechSynthesisClient::speak):
(WebKit::WebSpeechSynthesisClient::cancel):
(WebKit::WebSpeechSynthesisClient::pause):
(WebKit::WebSpeechSynthesisClient::resume):
* WebProcess/WebCoreSupport/WebSpeechSynthesisClient.h: Added.
(WebKit::WebSpeechSynthesisClient::WebSpeechSynthesisClient):
(WebKit::WebSpeechSynthesisClient::~WebSpeechSynthesisClient):
* WebProcess/WebCoreSupport/WebSpeechSynthesisVoice.h: Added.
(WebKit::WebSpeechSynthesisVoice::encode const):
(WebKit::WebSpeechSynthesisVoice::decode):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_hostFileDescriptor):
(WebKit::WebPage::speakingErrorOccurred):
(WebKit::WebPage::boundaryEventOccurred):
(WebKit::WebPage::voicesDidChange):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/com.apple.WebProcess.sb.in:
* WebProcess/glib/WebProcessGLib.cpp:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (243001 => 243002)


--- trunk/Source/WebCore/ChangeLog	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/ChangeLog	2019-03-15 18:18:36 UTC (rev 243002)
@@ -1,3 +1,56 @@
+2019-03-15  Per Arne Vollan  <[email protected]>
+
+        [macOS] Broker access to Speech Synthesis
+        https://bugs.webkit.org/show_bug.cgi?id=195645
+        <rdar://problem/35369026>
+
+        Reviewed by Brent Fulgham.
+
+        To be able to close the connection to the speech synthesis daemon in the WebContent process,
+        speech synthesis should be performed in the UI process. This patch forwards speech synthesis
+        requests to the UI process by sending messages. On the UI process side, the speech synthesis
+        is performed by simply using the existing platform speech synthesizer. Speech synthesis
+        events are sent back to the WebContent process. All messages are async, except for the
+        message to get the list of available voices.
+
+        No new tests, covered by existing tests.
+
+        * Modules/speech/DOMWindowSpeechSynthesis.cpp:
+        (WebCore::DOMWindowSpeechSynthesis::speechSynthesis):
+        * Modules/speech/SpeechSynthesis.cpp:
+        (WebCore::SpeechSynthesis::create):
+        (WebCore::SpeechSynthesis::SpeechSynthesis):
+        (WebCore::SpeechSynthesis::setPlatformSynthesizer):
+        (WebCore::SpeechSynthesis::getVoices):
+        (WebCore::SpeechSynthesis::startSpeakingImmediately):
+        (WebCore::SpeechSynthesis::cancel):
+        (WebCore::SpeechSynthesis::pause):
+        (WebCore::SpeechSynthesis::resume):
+        (WebCore::SpeechSynthesis::boundaryEventOccurred):
+        (WebCore::SpeechSynthesis::didStartSpeaking):
+        (WebCore::SpeechSynthesis::didFinishSpeaking):
+        (WebCore::SpeechSynthesis::didPauseSpeaking):
+        (WebCore::SpeechSynthesis::didResumeSpeaking):
+        (WebCore::SpeechSynthesis::speakingErrorOccurred):
+        (WebCore::SpeechSynthesis::voicesChanged):
+        * Modules/speech/SpeechSynthesis.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/Page.cpp:
+        (WebCore::Page::Page):
+        * page/Page.h:
+        (WebCore::Page::speechSynthesisClient const):
+        * page/PageConfiguration.cpp:
+        * page/PageConfiguration.h:
+        * page/SpeechSynthesisClient.h: Added.
+        * platform/PlatformSpeechSynthesisUtterance.h:
+        * platform/PlatformSpeechSynthesizer.h:
+        * platform/ios/PlatformSpeechSynthesizerIOS.mm:
+        (-[WebSpeechSynthesisWrapper speechSynthesizer:willSpeakRangeOfSpeechString:utterance:]):
+        * platform/mac/PlatformSpeechSynthesizerMac.mm:
+        (-[WebSpeechSynthesisWrapper speechSynthesizer:willSpeakWord:ofString:]):
+        * platform/mock/PlatformSpeechSynthesizerMock.cpp:
+        (WebCore::PlatformSpeechSynthesizerMock::speak):
+
 2019-03-15  Antti Koivisto  <[email protected]>
 
         Try to fix watchOS build.

Modified: trunk/Source/WebCore/Modules/speech/DOMWindowSpeechSynthesis.cpp (243001 => 243002)


--- trunk/Source/WebCore/Modules/speech/DOMWindowSpeechSynthesis.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/Modules/speech/DOMWindowSpeechSynthesis.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -70,7 +70,7 @@
 SpeechSynthesis* DOMWindowSpeechSynthesis::speechSynthesis()
 {
     if (!m_speechSynthesis && frame())
-        m_speechSynthesis = SpeechSynthesis::create();
+        m_speechSynthesis = SpeechSynthesis::create(makeWeakPtr(frame()->page()->speechSynthesisClient()));
     return m_speechSynthesis.get();
 }
 

Modified: trunk/Source/WebCore/Modules/speech/SpeechSynthesis.cpp (243001 => 243002)


--- trunk/Source/WebCore/Modules/speech/SpeechSynthesis.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/Modules/speech/SpeechSynthesis.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -38,18 +38,21 @@
 
 namespace WebCore {
 
-Ref<SpeechSynthesis> SpeechSynthesis::create()
+Ref<SpeechSynthesis> SpeechSynthesis::create(WeakPtr<SpeechSynthesisClient> client)
 {
-    return adoptRef(*new SpeechSynthesis);
+    return adoptRef(*new SpeechSynthesis(client));
 }
 
-SpeechSynthesis::SpeechSynthesis()
+SpeechSynthesis::SpeechSynthesis(WeakPtr<SpeechSynthesisClient> client)
     : m_currentSpeechUtterance(nullptr)
     , m_isPaused(false)
 #if PLATFORM(IOS_FAMILY)
     , m_restrictions(RequireUserGestureForSpeechStartRestriction)
 #endif
+    , m_speechSynthesisClient(client)
 {
+    if (m_speechSynthesisClient)
+        m_speechSynthesisClient->setObserver(makeWeakPtr(this));
 }
 
 void SpeechSynthesis::setPlatformSynthesizer(std::unique_ptr<PlatformSpeechSynthesizer> synthesizer)
@@ -59,6 +62,7 @@
     m_currentSpeechUtterance = nullptr;
     m_utteranceQueue.clear();
     m_isPaused = false;
+    m_speechSynthesisClient = nullptr;
 }
 
 void SpeechSynthesis::voicesDidChange()
@@ -66,16 +70,20 @@
     m_voiceList.clear();
 }
 
+PlatformSpeechSynthesizer& SpeechSynthesis::ensurePlatformSpeechSynthesizer()
+{
+    if (!m_platformSpeechSynthesizer)
+        m_platformSpeechSynthesizer = std::make_unique<PlatformSpeechSynthesizer>(this);
+    return *m_platformSpeechSynthesizer;
+}
+
 const Vector<Ref<SpeechSynthesisVoice>>& SpeechSynthesis::getVoices()
 {
-    if (m_voiceList.size())
+    if (!m_voiceList.isEmpty())
         return m_voiceList;
 
-    if (!m_platformSpeechSynthesizer)
-        m_platformSpeechSynthesizer = std::make_unique<PlatformSpeechSynthesizer>(this);
-
     // If the voiceList is empty, that's the cue to get the voices from the platform again.
-    for (auto& voice : m_platformSpeechSynthesizer->voiceList())
+    for (auto& voice : m_speechSynthesisClient ? m_speechSynthesisClient->voiceList() : ensurePlatformSpeechSynthesizer().voiceList())
         m_voiceList.append(SpeechSynthesisVoice::create(*voice));
 
     return m_voiceList;
@@ -113,9 +121,10 @@
         return;
     }
 
-    if (!m_platformSpeechSynthesizer)
-        m_platformSpeechSynthesizer = std::make_unique<PlatformSpeechSynthesizer>(this);
-    m_platformSpeechSynthesizer->speak(utterance.platformUtterance());
+    if (m_speechSynthesisClient)
+        m_speechSynthesisClient->speak(utterance.platformUtterance());
+    else
+        ensurePlatformSpeechSynthesizer().speak(utterance.platformUtterance());
 }
 
 void SpeechSynthesis::speak(SpeechSynthesisUtterance& utterance)
@@ -141,7 +150,9 @@
     // Hold on to the current utterance so the platform synthesizer can have a chance to clean up.
     RefPtr<SpeechSynthesisUtterance> current = m_currentSpeechUtterance;
     m_utteranceQueue.clear();
-    if (m_platformSpeechSynthesizer)
+    if (m_speechSynthesisClient)
+        m_speechSynthesisClient->cancel();
+    else if (m_platformSpeechSynthesizer)
         m_platformSpeechSynthesizer->cancel();
     current = nullptr;
 
@@ -151,14 +162,22 @@
 
 void SpeechSynthesis::pause()
 {
-    if (!m_isPaused && m_platformSpeechSynthesizer)
-        m_platformSpeechSynthesizer->pause();
+    if (!m_isPaused) {
+        if (m_speechSynthesisClient)
+            m_speechSynthesisClient->pause();
+        else if (m_platformSpeechSynthesizer)
+            m_platformSpeechSynthesizer->pause();
+    }
 }
 
 void SpeechSynthesis::resume()
 {
-    if (m_currentSpeechUtterance && m_platformSpeechSynthesizer)
-        m_platformSpeechSynthesizer->resume();
+    if (m_currentSpeechUtterance) {
+        if (m_speechSynthesisClient)
+            m_speechSynthesisClient->resume();
+        else if (m_platformSpeechSynthesizer)
+            m_platformSpeechSynthesizer->resume();
+    }
 }
 
 void SpeechSynthesis::fireEvent(const AtomicString& type, SpeechSynthesisUtterance& utterance, unsigned long charIndex, const String& name)
@@ -193,10 +212,10 @@
     ASSERT(utterance.client());
 
     switch (boundary) {
-    case SpeechWordBoundary:
+    case SpeechBoundary::SpeechWordBoundary:
         fireEvent(eventNames().boundaryEvent, static_cast<SpeechSynthesisUtterance&>(*utterance.client()), charIndex, wordBoundaryString);
         break;
-    case SpeechSentenceBoundary:
+    case SpeechBoundary::SpeechSentenceBoundary:
         fireEvent(eventNames().boundaryEvent, static_cast<SpeechSynthesisUtterance&>(*utterance.client()), charIndex, sentenceBoundaryString);
         break;
     default:
@@ -204,6 +223,41 @@
     }
 }
 
+void SpeechSynthesis::didStartSpeaking()
+{
+    didStartSpeaking(*m_currentSpeechUtterance->platformUtterance());
+}
+
+void SpeechSynthesis::didFinishSpeaking()
+{
+    didFinishSpeaking(*m_currentSpeechUtterance->platformUtterance());
+}
+
+void SpeechSynthesis::didPauseSpeaking()
+{
+    didPauseSpeaking(*m_currentSpeechUtterance->platformUtterance());
+}
+
+void SpeechSynthesis::didResumeSpeaking()
+{
+    didResumeSpeaking(*m_currentSpeechUtterance->platformUtterance());
+}
+
+void SpeechSynthesis::speakingErrorOccurred()
+{
+    speakingErrorOccurred(*m_currentSpeechUtterance->platformUtterance());
+}
+
+void SpeechSynthesis::boundaryEventOccurred(bool wordBoundary, unsigned charIndex)
+{
+    boundaryEventOccurred(*m_currentSpeechUtterance->platformUtterance(), wordBoundary ? SpeechBoundary::SpeechWordBoundary : SpeechBoundary::SpeechSentenceBoundary, charIndex);
+}
+
+void SpeechSynthesis::voicesChanged()
+{
+    voicesDidChange();
+}
+
 void SpeechSynthesis::didStartSpeaking(PlatformSpeechSynthesisUtterance& utterance)
 {
     if (utterance.client())

Modified: trunk/Source/WebCore/Modules/speech/SpeechSynthesis.h (243001 => 243002)


--- trunk/Source/WebCore/Modules/speech/SpeechSynthesis.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/Modules/speech/SpeechSynthesis.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -29,6 +29,7 @@
 
 #include "PlatformSpeechSynthesisUtterance.h"
 #include "PlatformSpeechSynthesizer.h"
+#include "SpeechSynthesisClient.h"
 #include "SpeechSynthesisUtterance.h"
 #include "SpeechSynthesisVoice.h"
 #include <wtf/Deque.h>
@@ -39,9 +40,9 @@
 class PlatformSpeechSynthesizerClient;
 class SpeechSynthesisVoice;
 
-class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public RefCounted<SpeechSynthesis> {
+class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public SpeechSynthesisClientObserver, public RefCounted<SpeechSynthesis> {
 public:
-    static Ref<SpeechSynthesis> create();
+    static Ref<SpeechSynthesis> create(WeakPtr<SpeechSynthesisClient>);
 
     bool pending() const;
     bool speaking() const;
@@ -58,7 +59,7 @@
     WEBCORE_EXPORT void setPlatformSynthesizer(std::unique_ptr<PlatformSpeechSynthesizer>);
 
 private:
-    SpeechSynthesis();
+    SpeechSynthesis(WeakPtr<SpeechSynthesisClient>);
 
     // PlatformSpeechSynthesizerClient override methods.
     void voicesDidChange() override;
@@ -69,6 +70,15 @@
     void speakingErrorOccurred(PlatformSpeechSynthesisUtterance&) override;
     void boundaryEventOccurred(PlatformSpeechSynthesisUtterance&, SpeechBoundary, unsigned charIndex) override;
 
+    // SpeechSynthesisClient override methods
+    void didStartSpeaking() override;
+    void didFinishSpeaking() override;
+    void didPauseSpeaking() override;
+    void didResumeSpeaking() override;
+    void speakingErrorOccurred() override;
+    void boundaryEventOccurred(bool wordBoundary, unsigned charIndex) override;
+    void voicesChanged() override;
+    
     void startSpeakingImmediately(SpeechSynthesisUtterance&);
     void handleSpeakingCompleted(SpeechSynthesisUtterance&, bool errorOccurred);
     void fireEvent(const AtomicString& type, SpeechSynthesisUtterance&, unsigned long charIndex, const String& name);
@@ -84,6 +94,8 @@
     bool userGestureRequiredForSpeechStart() const { return m_restrictions & RequireUserGestureForSpeechStartRestriction; }
     void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
 #endif
+    PlatformSpeechSynthesizer& ensurePlatformSpeechSynthesizer();
+    
     std::unique_ptr<PlatformSpeechSynthesizer> m_platformSpeechSynthesizer;
     Vector<Ref<SpeechSynthesisVoice>> m_voiceList;
     SpeechSynthesisUtterance* m_currentSpeechUtterance;
@@ -92,6 +104,7 @@
 #if PLATFORM(IOS_FAMILY)
     BehaviorRestrictions m_restrictions;
 #endif
+    WeakPtr<SpeechSynthesisClient> m_speechSynthesisClient;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (243001 => 243002)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-03-15 18:18:36 UTC (rev 243002)
@@ -711,9 +711,9 @@
 		2936BF5C21D69E4B004A8FC9 /* AccessibilityObjectInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 2936BF5A21D6999E004A8FC9 /* AccessibilityObjectInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		293EAE1F1356B2FE0067ACF9 /* RuntimeApplicationChecks.h in Headers */ = {isa = PBXBuildFile; fileRef = 293EAE1E1356B2FE0067ACF9 /* RuntimeApplicationChecks.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		29489FC712C00F0300D83F0F /* AccessibilityScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 29489FC512C00F0300D83F0F /* AccessibilityScrollView.h */; };
-		297BE3D516C03C08003316BD /* PlatformSpeechSynthesisUtterance.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9116BF8BA1009DDAC0 /* PlatformSpeechSynthesisUtterance.h */; };
-		297BE3D616C03C0B003316BD /* PlatformSpeechSynthesisVoice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9216BF90B4009DDAC0 /* PlatformSpeechSynthesisVoice.h */; };
-		297BE3D716C03C0E003316BD /* PlatformSpeechSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */; };
+		297BE3D516C03C08003316BD /* PlatformSpeechSynthesisUtterance.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9116BF8BA1009DDAC0 /* PlatformSpeechSynthesisUtterance.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		297BE3D616C03C0B003316BD /* PlatformSpeechSynthesisVoice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2527CC9216BF90B4009DDAC0 /* PlatformSpeechSynthesisVoice.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		297BE3D716C03C0E003316BD /* PlatformSpeechSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		29A8122B0FBB9C1D00510293 /* AccessibilityTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 29A8120D0FBB9C1D00510293 /* AccessibilityTable.h */; };
 		29A8122C0FBB9C1D00510293 /* AccessibilityList.h in Headers */ = {isa = PBXBuildFile; fileRef = 29A8120E0FBB9C1D00510293 /* AccessibilityList.h */; };
 		29A8122E0FBB9C1D00510293 /* AccessibilityARIAGridCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 29A812100FBB9C1D00510293 /* AccessibilityARIAGridCell.h */; };
@@ -4002,6 +4002,7 @@
 		C0F2A44113869AAB0066C534 /* preprocessor.pm in Headers */ = {isa = PBXBuildFile; fileRef = C0F2A43F13869A280066C534 /* preprocessor.pm */; settings = {ATTRIBUTES = (Private, ); }; };
 		C105DA640F3AA6B8001DD44F /* TextEncodingDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = C105DA630F3AA6B8001DD44F /* TextEncodingDetector.h */; };
 		C11A9ECE21403A5C00CFB20A /* SwitchingGPUClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C11A9ECD21403A5C00CFB20A /* SwitchingGPUClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		C14938072234551A000CD707 /* SpeechSynthesisClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C149380522342719000CD707 /* SpeechSynthesisClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		C1E1D236203DF15400584665 /* ScreenProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = C1E1D235203DF15400584665 /* ScreenProperties.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		C2015C0A1BE6FEB200822389 /* FontVariantBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2015C091BE6FE2C00822389 /* FontVariantBuilder.h */; };
 		C21DF2EA1D9E4E9900F5B24C /* CSSFontVariationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = C21DF2E81D9E4E9900F5B24C /* CSSFontVariationValue.h */; };
@@ -13351,6 +13352,7 @@
 		C105DA630F3AA6B8001DD44F /* TextEncodingDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextEncodingDetector.h; sourceTree = "<group>"; };
 		C11A9ECD21403A5C00CFB20A /* SwitchingGPUClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwitchingGPUClient.h; sourceTree = "<group>"; };
 		C11A9ED22140578B00CFB20A /* SwitchingGPUClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SwitchingGPUClient.cpp; sourceTree = "<group>"; };
+		C149380522342719000CD707 /* SpeechSynthesisClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpeechSynthesisClient.h; sourceTree = "<group>"; };
 		C1E1D235203DF15400584665 /* ScreenProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScreenProperties.h; sourceTree = "<group>"; };
 		C2015C091BE6FE2C00822389 /* FontVariantBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontVariantBuilder.h; sourceTree = "<group>"; };
 		C20F4F6421DFBE5C0070C45A /* WHLSLTypeReference.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLTypeReference.cpp; sourceTree = "<group>"; };
@@ -20556,6 +20558,7 @@
 				5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */,
 				626CDE0C1140424C001E5A68 /* SpatialNavigation.cpp */,
 				626CDE0D1140424C001E5A68 /* SpatialNavigation.h */,
+				C149380522342719000CD707 /* SpeechSynthesisClient.h */,
 				62C1217A11AB9E76003C462C /* SuspendableTimer.cpp */,
 				62C1217B11AB9E77003C462C /* SuspendableTimer.h */,
 				2D4F96F11A1ECC240098BF88 /* TextIndicator.cpp */,
@@ -31709,6 +31712,7 @@
 				626CDE0F1140424C001E5A68 /* SpatialNavigation.h in Headers */,
 				657AFAFC20047A2900509464 /* SpectreGadget.h in Headers */,
 				AA2A5AD416A4861100975A25 /* SpeechSynthesis.h in Headers */,
+				C14938072234551A000CD707 /* SpeechSynthesisClient.h in Headers */,
 				AA2A5AD216A4860A00975A25 /* SpeechSynthesisEvent.h in Headers */,
 				AA2A5AD016A4860400975A25 /* SpeechSynthesisUtterance.h in Headers */,
 				AA2A5ACE16A485FD00975A25 /* SpeechSynthesisVoice.h in Headers */,

Modified: trunk/Source/WebCore/page/Page.cpp (243001 => 243002)


--- trunk/Source/WebCore/page/Page.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/page/Page.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -230,6 +230,9 @@
     , m_diagnosticLoggingClient(WTFMove(pageConfiguration.diagnosticLoggingClient))
     , m_performanceLoggingClient(WTFMove(pageConfiguration.performanceLoggingClient))
     , m_webGLStateTracker(WTFMove(pageConfiguration.webGLStateTracker))
+#if ENABLE(SPEECH_SYNTHESIS)
+    , m_speechSynthesisClient(WTFMove(pageConfiguration.speechSynthesisClient))
+#endif
     , m_libWebRTCProvider(WTFMove(pageConfiguration.libWebRTCProvider))
     , m_verticalScrollElasticity(ScrollElasticityAllowed)
     , m_horizontalScrollElasticity(ScrollElasticityAllowed)

Modified: trunk/Source/WebCore/page/Page.h (243001 => 243002)


--- trunk/Source/WebCore/page/Page.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/page/Page.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -145,6 +145,7 @@
 class ActivityStateChangeObserver;
 class VisitedLinkStore;
 class WebGLStateTracker;
+class SpeechSynthesisClient;
 class WheelEventDeltaFilter;
 
 typedef uint64_t SharedStringHash;
@@ -682,6 +683,10 @@
 
     WebGLStateTracker* webGLStateTracker() const { return m_webGLStateTracker.get(); }
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    SpeechSynthesisClient* speechSynthesisClient() const { return m_speechSynthesisClient.get(); }
+#endif
+
     bool isOnlyNonUtilityPage() const;
     bool isUtilityPage() const { return m_isUtilityPage; }
 
@@ -778,6 +783,10 @@
     
     std::unique_ptr<WebGLStateTracker> m_webGLStateTracker;
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    std::unique_ptr<SpeechSynthesisClient> m_speechSynthesisClient;
+#endif
+
     UniqueRef<LibWebRTCProvider> m_libWebRTCProvider;
     RTCController m_rtcController;
 

Modified: trunk/Source/WebCore/page/PageConfiguration.cpp (243001 => 243002)


--- trunk/Source/WebCore/page/PageConfiguration.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/page/PageConfiguration.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -36,6 +36,7 @@
 #include "PerformanceLoggingClient.h"
 #include "PluginInfoProvider.h"
 #include "SocketProvider.h"
+#include "SpeechSynthesisClient.h"
 #include "StorageNamespaceProvider.h"
 #include "UserContentController.h"
 #include "ValidationMessageClient.h"

Modified: trunk/Source/WebCore/page/PageConfiguration.h (243001 => 243002)


--- trunk/Source/WebCore/page/PageConfiguration.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/page/PageConfiguration.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -62,6 +62,7 @@
 class ValidationMessageClient;
 class VisitedLinkStore;
 class WebGLStateTracker;
+class SpeechSynthesisClient;
 
 class PageConfiguration {
     WTF_MAKE_NONCOPYABLE(PageConfiguration); WTF_MAKE_FAST_ALLOCATED;
@@ -102,6 +103,9 @@
     std::unique_ptr<DiagnosticLoggingClient> diagnosticLoggingClient;
     std::unique_ptr<PerformanceLoggingClient> performanceLoggingClient;
     std::unique_ptr<WebGLStateTracker> webGLStateTracker;
+#if ENABLE(SPEECH_SYNTHESIS)
+    std::unique_ptr<SpeechSynthesisClient> speechSynthesisClient;
+#endif
 
     RefPtr<ApplicationCacheStorage> applicationCacheStorage;
     RefPtr<DatabaseProvider> databaseProvider;

Added: trunk/Source/WebCore/page/SpeechSynthesisClient.h (0 => 243002)


--- trunk/Source/WebCore/page/SpeechSynthesisClient.h	                        (rev 0)
+++ trunk/Source/WebCore/page/SpeechSynthesisClient.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 Apple Inc. 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class PlatformSpeechSynthesisUtterance;
+class SpeechSynthesisClientObserver;
+class PlatformSpeechSynthesisVoice;
+    
+class SpeechSynthesisClient : public CanMakeWeakPtr<SpeechSynthesisClient> {
+public:
+    virtual ~SpeechSynthesisClient() = default;
+
+    virtual void setObserver(WeakPtr<SpeechSynthesisClientObserver>) = 0;
+    virtual WeakPtr<SpeechSynthesisClientObserver> observer() const = 0;
+    
+    virtual const Vector<RefPtr<PlatformSpeechSynthesisVoice>>& voiceList() = 0;
+    virtual void speak(RefPtr<PlatformSpeechSynthesisUtterance>) = 0;
+    virtual void cancel() = 0;
+    virtual void pause() = 0;
+    virtual void resume() = 0;
+
+};
+
+class SpeechSynthesisClientObserver : public CanMakeWeakPtr<SpeechSynthesisClientObserver>  {
+public:
+    virtual ~SpeechSynthesisClientObserver() = default;
+
+    virtual void didStartSpeaking() = 0;
+    virtual void didFinishSpeaking() = 0;
+    virtual void didPauseSpeaking() = 0;
+    virtual void didResumeSpeaking() = 0;
+    virtual void speakingErrorOccurred() = 0;
+    virtual void boundaryEventOccurred(bool wordBoundary, unsigned charIndex) = 0;
+    virtual void voicesChanged() = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SPEECH_SYNTHESIS)

Modified: trunk/Source/WebCore/platform/PlatformSpeechSynthesisUtterance.h (243001 => 243002)


--- trunk/Source/WebCore/platform/PlatformSpeechSynthesisUtterance.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/platform/PlatformSpeechSynthesisUtterance.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -37,7 +37,7 @@
     
 class PlatformSpeechSynthesisUtterance : public RefCounted<PlatformSpeechSynthesisUtterance> {
 public:
-    static Ref<PlatformSpeechSynthesisUtterance> create(PlatformSpeechSynthesisUtteranceClient&);
+    WEBCORE_EXPORT static Ref<PlatformSpeechSynthesisUtterance> create(PlatformSpeechSynthesisUtteranceClient&);
 
     const String& text() const { return m_text; }
     void setText(const String& text) { m_text = text; }

Modified: trunk/Source/WebCore/platform/PlatformSpeechSynthesizer.h (243001 => 243002)


--- trunk/Source/WebCore/platform/PlatformSpeechSynthesizer.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/platform/PlatformSpeechSynthesizer.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -38,7 +38,7 @@
 
 namespace WebCore {
 
-enum SpeechBoundary {
+enum class SpeechBoundary : uint8_t {
     SpeechWordBoundary,
     SpeechSentenceBoundary
 };

Modified: trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm (243001 => 243002)


--- trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm	2019-03-15 18:18:36 UTC (rev 243002)
@@ -225,7 +225,7 @@
         return;
 
     // iOS only supports word boundaries.
-    m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechWordBoundary, characterRange.location);
+    m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechBoundary::SpeechWordBoundary, characterRange.location);
 }
 
 @end

Modified: trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm (243001 => 243002)


--- trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm	2019-03-15 18:18:36 UTC (rev 243002)
@@ -197,7 +197,7 @@
         return;
 
     // Mac platform only supports word boundaries.
-    m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechWordBoundary, characterRange.location);
+    m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechBoundary::SpeechWordBoundary, characterRange.location);
 }
 
 @end

Modified: trunk/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp (243001 => 243002)


--- trunk/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -62,8 +62,8 @@
     client()->didStartSpeaking(*m_utterance);
 
     // Fire a fake word and then sentence boundary event.
-    client()->boundaryEventOccurred(*m_utterance, SpeechWordBoundary, 0);
-    client()->boundaryEventOccurred(*m_utterance, SpeechSentenceBoundary, m_utterance->text().length());
+    client()->boundaryEventOccurred(*m_utterance, SpeechBoundary::SpeechWordBoundary, 0);
+    client()->boundaryEventOccurred(*m_utterance, SpeechBoundary::SpeechSentenceBoundary, m_utterance->text().length());
 
     // Give the fake speech job some time so that pause and other functions have time to be called.
     m_speakingFinishedTimer.startOneShot(100_ms);

Modified: trunk/Source/WebKit/ChangeLog (243001 => 243002)


--- trunk/Source/WebKit/ChangeLog	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/ChangeLog	2019-03-15 18:18:36 UTC (rev 243002)
@@ -1,3 +1,59 @@
+2019-03-15  Per Arne Vollan  <[email protected]>
+
+        [macOS] Broker access to Speech Synthesis
+        https://bugs.webkit.org/show_bug.cgi?id=195645
+        <rdar://problem/35369026>
+
+        Reviewed by Brent Fulgham.
+
+        To be able to close the connection to the speech synthesis daemon in the WebContent process,
+        speech synthesis should be performed in the UI process. This patch forwards speech synthesis
+        requests to the UI process by sending messages. On the UI process side, the speech synthesis
+        is performed by simply using the existing platform speech synthesizer. Speech synthesis
+        events are sent back to the WebContent process. All messages are async, except for the
+        message to get the list of available voices.
+
+        * Sources.txt:
+        * UIProcess/Cocoa/WebPageProxyCocoa.mm:
+        (WebKit::WebPageProxy::didStartSpeaking):
+        (WebKit::WebPageProxy::didFinishSpeaking):
+        (WebKit::WebPageProxy::didPauseSpeaking):
+        (WebKit::WebPageProxy::didResumeSpeaking):
+        (WebKit::WebPageProxy::speakingErrorOccurred):
+        (WebKit::WebPageProxy::boundaryEventOccurred):
+        (WebKit::WebPageProxy::voicesDidChange):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::ensureSpeechSynthesisData):
+        (WebKit::WebPageProxy::speechSynthesisVoiceList):
+        (WebKit::WebPageProxy::speechSynthesisSpeak):
+        (WebKit::WebPageProxy::speechSynthesisCancel):
+        (WebKit::WebPageProxy::speechSynthesisPause):
+        (WebKit::WebPageProxy::speechSynthesisResume):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp: Added.
+        (WebKit::WebSpeechSynthesisClient::voiceList):
+        (WebKit::WebSpeechSynthesisClient::speak):
+        (WebKit::WebSpeechSynthesisClient::cancel):
+        (WebKit::WebSpeechSynthesisClient::pause):
+        (WebKit::WebSpeechSynthesisClient::resume):
+        * WebProcess/WebCoreSupport/WebSpeechSynthesisClient.h: Added.
+        (WebKit::WebSpeechSynthesisClient::WebSpeechSynthesisClient):
+        (WebKit::WebSpeechSynthesisClient::~WebSpeechSynthesisClient):
+        * WebProcess/WebCoreSupport/WebSpeechSynthesisVoice.h: Added.
+        (WebKit::WebSpeechSynthesisVoice::encode const):
+        (WebKit::WebSpeechSynthesisVoice::decode):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::m_hostFileDescriptor):
+        (WebKit::WebPage::speakingErrorOccurred):
+        (WebKit::WebPage::boundaryEventOccurred):
+        (WebKit::WebPage::voicesDidChange):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/com.apple.WebProcess.sb.in:
+        * WebProcess/glib/WebProcessGLib.cpp:
+
 2019-03-15  Antti Koivisto  <[email protected]>
 
         Optimize Region for single rectangle case

Modified: trunk/Source/WebKit/Sources.txt (243001 => 243002)


--- trunk/Source/WebKit/Sources.txt	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/Sources.txt	2019-03-15 18:18:36 UTC (rev 243002)
@@ -540,6 +540,7 @@
 WebProcess/WebCoreSupport/WebProgressTrackerClient.cpp
 WebProcess/WebCoreSupport/WebSearchPopupMenu.cpp
 WebProcess/WebCoreSupport/WebUserMediaClient.cpp
+WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp
 
 WebProcess/WebPage/DrawingArea.cpp
 WebProcess/WebPage/EventDispatcher.cpp

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm (243001 => 243002)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm	2019-03-15 18:18:36 UTC (rev 243002)
@@ -244,4 +244,40 @@
 
 #endif
 
+#if ENABLE(SPEECH_SYNTHESIS)
+void WebPageProxy::didStartSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+}
+
+void WebPageProxy::didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+    m_speechSynthesisData->speakingFinishedCompletionHandler();
+}
+
+void WebPageProxy::didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+    m_speechSynthesisData->speakingPausedCompletionHandler();
+}
+
+void WebPageProxy::didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+    m_speechSynthesisData->speakingResumedCompletionHandler();
+}
+
+void WebPageProxy::speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&)
+{
+    process().send(Messages::WebPage::SpeakingErrorOccurred(), m_pageID);
+}
+
+void WebPageProxy::boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary speechBoundary, unsigned charIndex)
+{
+    process().send(Messages::WebPage::BoundaryEventOccurred(speechBoundary == WebCore::SpeechBoundary::SpeechWordBoundary, charIndex), m_pageID);
+}
+
+void WebPageProxy::voicesDidChange()
+{
+    process().send(Messages::WebPage::VoicesDidChange(), m_pageID);
+}
+#endif // ENABLE(SPEECH_SYNTHESIS)
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (243001 => 243002)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -8812,6 +8812,57 @@
     m_process->processPool().clearAdClickAttribution(m_websiteDataStore->sessionID(), WTFMove(completionHandler));
 }
 
+#if ENABLE(SPEECH_SYNTHESIS)
+WebPageProxy::SpeechSynthesisData& WebPageProxy::speechSynthesisData()
+{
+    if (!m_speechSynthesisData)
+        m_speechSynthesisData = SpeechSynthesisData { std::make_unique<PlatformSpeechSynthesizer>(this), nullptr, nullptr, nullptr, nullptr };
+    return *m_speechSynthesisData;
+}
+
+void WebPageProxy::speechSynthesisVoiceList(Vector<WebSpeechSynthesisVoice>& result)
+{
+    auto& voiceList = speechSynthesisData().synthesizer->voiceList();
+    for (auto& voice : voiceList) {
+        WebSpeechSynthesisVoice v { voice->voiceURI(), voice->name(), voice->lang(), voice->localService(), voice->isDefault() };
+        result.append(WTFMove(v));
+    }
+}
+
+void WebPageProxy::speechSynthesisSpeak(const String& text, const String& lang, float volume, float rate, float pitch, MonotonicTime startTime, const String& voiceURI, const String& voiceName, const String& voiceLang, bool localService, bool defaultVoice, CompletionHandler<void()>&& completionHandler)
+{
+    auto voice = WebCore::PlatformSpeechSynthesisVoice::create(voiceURI, voiceName, voiceLang, localService, defaultVoice);
+    auto utterance = WebCore::PlatformSpeechSynthesisUtterance::create(*this);
+    utterance->setText(text);
+    utterance->setLang(lang);
+    utterance->setVolume(volume);
+    utterance->setRate(rate);
+    utterance->setPitch(pitch);
+    utterance->setVoice(&voice.get());
+
+    speechSynthesisData().utterance = WTFMove(utterance);
+    speechSynthesisData().speakingFinishedCompletionHandler = WTFMove(completionHandler);
+    speechSynthesisData().synthesizer->speak(m_speechSynthesisData->utterance.get());
+}
+
+void WebPageProxy::speechSynthesisCancel()
+{
+    speechSynthesisData().synthesizer->cancel();
+}
+
+void WebPageProxy::speechSynthesisPause(CompletionHandler<void()>&& completionHandler)
+{
+    speechSynthesisData().speakingPausedCompletionHandler = WTFMove(completionHandler);
+    speechSynthesisData().synthesizer->pause();
+}
+
+void WebPageProxy::speechSynthesisResume(CompletionHandler<void()>&& completionHandler)
+{
+    speechSynthesisData().speakingResumedCompletionHandler = WTFMove(completionHandler);
+    speechSynthesisData().synthesizer->resume();
+}
+#endif // ENABLE(SPEECH_SYNTHESIS)
+
 void WebPageProxy::addObserver(WebViewDidMoveToWindowObserver& observer)
 {
     auto result = m_webViewDidMoveToWindowObservers.add(&observer, makeWeakPtr(observer));

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (243001 => 243002)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -82,6 +82,8 @@
 #include <WebCore/MediaProducer.h>
 #include <WebCore/PlatformEvent.h>
 #include <WebCore/PlatformScreen.h>
+#include <WebCore/PlatformSpeechSynthesisUtterance.h>
+#include <WebCore/PlatformSpeechSynthesizer.h>
 #include <WebCore/PointerID.h>
 #include <WebCore/RegistrableDomain.h>
 #include <WebCore/ScrollTypes.h>
@@ -361,6 +363,10 @@
     , public WebPopupMenuProxy::Client
     , public IPC::MessageReceiver
     , public IPC::MessageSender
+#if ENABLE(SPEECH_SYNTHESIS)
+    , public WebCore::PlatformSpeechSynthesisUtteranceClient
+    , public WebCore::PlatformSpeechSynthesizerClient
+#endif
     , public CanMakeWeakPtr<WebPageProxy> {
 public:
     static Ref<WebPageProxy> create(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
@@ -1485,6 +1491,14 @@
     void dumpAdClickAttribution(CompletionHandler<void(const String&)>&&);
     void clearAdClickAttribution(CompletionHandler<void()>&&);
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    void speechSynthesisVoiceList(Vector<WebSpeechSynthesisVoice>& result);
+    void speechSynthesisSpeak(const String&, const String&, float volume, float rate, float pitch, MonotonicTime startTime, const String& voiceURI, const String& voiceName, const String& voiceLang, bool localService, bool defaultVoice, CompletionHandler<void()>&&);
+    void speechSynthesisCancel();
+    void speechSynthesisPause(CompletionHandler<void()>&&);
+    void speechSynthesisResume(CompletionHandler<void()>&&);
+#endif
+
     void addObserver(WebViewDidMoveToWindowObserver&);
     void removeObserver(WebViewDidMoveToWindowObserver&);
     void webViewDidMoveToWindow();
@@ -2013,6 +2027,19 @@
     NSWindow *paymentCoordinatorPresentingWindow(const WebPaymentCoordinatorProxy&) final;
 #endif
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    void didStartSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
+    void didFinishSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
+    void didPauseSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
+    void didResumeSpeaking(WebCore::PlatformSpeechSynthesisUtterance&) override;
+    void speakingErrorOccurred(WebCore::PlatformSpeechSynthesisUtterance&) override;
+    void boundaryEventOccurred(WebCore::PlatformSpeechSynthesisUtterance&, WebCore::SpeechBoundary, unsigned charIndex) override;
+    void voicesDidChange() override;
+
+    struct SpeechSynthesisData;
+    SpeechSynthesisData& speechSynthesisData();
+#endif
+
     WeakPtr<PageClient> m_pageClient;
     Ref<API::PageConfiguration> m_configuration;
 
@@ -2432,6 +2459,17 @@
 #endif
 
     HashMap<WebViewDidMoveToWindowObserver*, WeakPtr<WebViewDidMoveToWindowObserver>> m_webViewDidMoveToWindowObservers;
+    
+#if ENABLE(SPEECH_SYNTHESIS)
+    struct SpeechSynthesisData {
+        std::unique_ptr<WebCore::PlatformSpeechSynthesizer> synthesizer;
+        RefPtr<WebCore::PlatformSpeechSynthesisUtterance> utterance;
+        CompletionHandler<void()> speakingFinishedCompletionHandler;
+        CompletionHandler<void()> speakingPausedCompletionHandler;
+        CompletionHandler<void()> speakingResumedCompletionHandler;
+    };
+    Optional<SpeechSynthesisData> m_speechSynthesisData;
+#endif
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (243001 => 243002)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-03-15 18:18:36 UTC (rev 243002)
@@ -551,4 +551,11 @@
 
     SignedPublicKeyAndChallengeString(unsigned keySizeIndex, String challengeString, URL url) -> (String result) LegacySync
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    SpeechSynthesisVoiceList() -> (Vector<WebKit::WebSpeechSynthesisVoice> voiceList) LegacySync
+    SpeechSynthesisSpeak(String text, String lang, float volume, float rate, float pitch, MonotonicTime startTime, String voiceURI, String voiceName, String voiceLang, bool localService, bool defaultVoice) -> () Async
+    SpeechSynthesisCancel()
+    SpeechSynthesisPause() -> () Async
+    SpeechSynthesisResume() -> () Async
+#endif
 }

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (243001 => 243002)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2019-03-15 18:18:36 UTC (rev 243002)
@@ -1531,6 +1531,7 @@
 		C0E3AA7C1209E83C00A49D01 /* Module.h in Headers */ = {isa = PBXBuildFile; fileRef = C0E3AA441209E2BA00A49D01 /* Module.h */; };
 		C11A9ECC214035F800CFB20A /* WebSwitchingGPUClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C11A9ECB214035F800CFB20A /* WebSwitchingGPUClient.h */; };
 		C11E1694212B87C500985FF6 /* WKMockDisplay.h in Headers */ = {isa = PBXBuildFile; fileRef = C11E1692212B87C500985FF6 /* WKMockDisplay.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		C149380922347104000CD707 /* WebSpeechSynthesisClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C149380222341C60000CD707 /* WebSpeechSynthesisClient.h */; };
 		C18173612058424700DFDA65 /* DisplayLink.h in Headers */ = {isa = PBXBuildFile; fileRef = C18173602058424700DFDA65 /* DisplayLink.h */; };
 		C1E123BA20A11573002646F4 /* PDFContextMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = C1E123B920A11572002646F4 /* PDFContextMenu.h */; };
 		C517388112DF8F4F00EE3F47 /* DragControllerAction.h in Headers */ = {isa = PBXBuildFile; fileRef = C517388012DF8F4F00EE3F47 /* DragControllerAction.h */; };
@@ -4347,6 +4348,9 @@
 		C11A9ED021403B4000CFB20A /* WebSwitchingGPUClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebSwitchingGPUClient.cpp; sourceTree = "<group>"; };
 		C11E1692212B87C500985FF6 /* WKMockDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMockDisplay.h; sourceTree = "<group>"; };
 		C11E1693212B87C500985FF6 /* WKMockDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKMockDisplay.cpp; sourceTree = "<group>"; };
+		C149380222341C60000CD707 /* WebSpeechSynthesisClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebSpeechSynthesisClient.h; sourceTree = "<group>"; };
+		C149380322341DF7000CD707 /* WebSpeechSynthesisClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebSpeechSynthesisClient.cpp; sourceTree = "<group>"; };
+		C149380A223853BE000CD707 /* WebSpeechSynthesisVoice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebSpeechSynthesisVoice.h; sourceTree = "<group>"; };
 		C181735E205839F600DFDA65 /* DrawingAreaMac.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DrawingAreaMac.cpp; sourceTree = "<group>"; };
 		C18173602058424700DFDA65 /* DisplayLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayLink.h; sourceTree = "<group>"; };
 		C1817362205844A900DFDA65 /* DisplayLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayLink.cpp; sourceTree = "<group>"; };
@@ -7297,6 +7301,9 @@
 				1A1E093218861D3800D2DC49 /* WebProgressTrackerClient.h */,
 				D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */,
 				D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */,
+				C149380322341DF7000CD707 /* WebSpeechSynthesisClient.cpp */,
+				C149380222341C60000CD707 /* WebSpeechSynthesisClient.h */,
+				C149380A223853BE000CD707 /* WebSpeechSynthesisVoice.h */,
 				4A410F4819AF7B80002EBAB5 /* WebUserMediaClient.cpp */,
 				4A410F4919AF7B80002EBAB5 /* WebUserMediaClient.h */,
 				83EE57591DB7D60600C74C50 /* WebValidationMessageClient.cpp */,
@@ -9645,6 +9652,7 @@
 				1A53C2AA1A325730004E8C70 /* WebsiteDataStore.h in Headers */,
 				511F7D411EB1BCF500E47B83 /* WebsiteDataStoreParameters.h in Headers */,
 				0EDE85032004E75D00030560 /* WebsitePopUpPolicy.h in Headers */,
+				C149380922347104000CD707 /* WebSpeechSynthesisClient.h in Headers */,
 				836034A01ACB34D600626549 /* WebSQLiteDatabaseTracker.h in Headers */,
 				1A52C0F81A38CDC70016160A /* WebStorageNamespaceProvider.h in Headers */,
 				9356F2DC2152B6B500E6D5DF /* WebSWClientConnection.h in Headers */,

Added: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp (0 => 243002)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp	                        (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 Apple Inc. 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 APPLE INC. ``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 APPLE INC. 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 "WebSpeechSynthesisClient.h"
+
+#include "WebPage.h"
+#include "WebPageProxyMessages.h"
+#include "WebSpeechSynthesisVoice.h"
+
+#if ENABLE(SPEECH_SYNTHESIS)
+
+namespace WebKit {
+
+const Vector<RefPtr<WebCore::PlatformSpeechSynthesisVoice>>& WebSpeechSynthesisClient::voiceList()
+{
+    // FIXME: this message should not be sent synchronously. Instead, the UI process should
+    // get the list of voices and pass it on to the WebContent processes, see
+    // https://bugs.webkit.org/show_bug.cgi?id=195723
+    Vector<WebSpeechSynthesisVoice> voiceList;
+    m_page.sendSync(Messages::WebPageProxy::SpeechSynthesisVoiceList(), voiceList);
+
+    m_voices.clear();
+    for (auto& voice : voiceList) {
+        m_voices.append(WebCore::PlatformSpeechSynthesisVoice::create(voice.voiceURI, voice.name, voice.lang, voice.localService, voice.defaultLang));
+        
+    }
+    return m_voices;
+}
+
+void WebSpeechSynthesisClient::speak(RefPtr<WebCore::PlatformSpeechSynthesisUtterance> utterance)
+{
+    WTF::CompletionHandler<void()> completionHandler = [this, weakThis = makeWeakPtr(*this)]() mutable {
+        if (weakThis)
+            m_page.corePage()->speechSynthesisClient()->observer()->didFinishSpeaking();
+    };
+
+    auto voice = utterance->voice();
+    m_page.sendWithAsyncReply(Messages::WebPageProxy::SpeechSynthesisSpeak(utterance->text(), utterance->lang(), utterance->volume(), utterance->rate(), utterance->pitch(), utterance->startTime(), voice->voiceURI(), voice->name(), voice->lang(), voice->localService(), voice->isDefault()), WTFMove(completionHandler));
+
+    m_page.corePage()->speechSynthesisClient()->observer()->didStartSpeaking();
+}
+
+void WebSpeechSynthesisClient::cancel()
+{
+    m_page.send(Messages::WebPageProxy::SpeechSynthesisCancel());
+}
+
+void WebSpeechSynthesisClient::pause()
+{
+    WTF::CompletionHandler<void()> completionHandler = [this, weakThis = makeWeakPtr(*this)]() mutable {
+        if (weakThis)
+            m_page.corePage()->speechSynthesisClient()->observer()->didPauseSpeaking();
+    };
+    
+    m_page.sendWithAsyncReply(Messages::WebPageProxy::SpeechSynthesisPause(), WTFMove(completionHandler));
+}
+
+void WebSpeechSynthesisClient::resume()
+{
+    WTF::CompletionHandler<void()> completionHandler = [this, weakThis = makeWeakPtr(*this)]() mutable {
+        if (weakThis)
+            m_page.corePage()->speechSynthesisClient()->observer()->didResumeSpeaking();
+    };
+    
+    m_page.sendWithAsyncReply(Messages::WebPageProxy::SpeechSynthesisResume(), WTFMove(completionHandler));
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SPEECH_SYNTHESIS)

Added: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.h (0 => 243002)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.h	                        (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisClient.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 Apple Inc. 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 APPLE INC. ``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 APPLE INC. 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 <WebCore/PlatformSpeechSynthesisUtterance.h>
+#include <WebCore/PlatformSpeechSynthesisVoice.h>
+#include <WebCore/SpeechSynthesisClient.h>
+
+namespace WebKit {
+
+class WebPage;
+    
+class WebSpeechSynthesisClient : public WebCore::SpeechSynthesisClient {
+public:
+    WebSpeechSynthesisClient(WebPage& page)
+        : m_page(page)
+    {
+    }
+    
+    virtual ~WebSpeechSynthesisClient() { }
+    
+    const Vector<RefPtr<WebCore::PlatformSpeechSynthesisVoice>>& voiceList() override;
+    void speak(RefPtr<WebCore::PlatformSpeechSynthesisUtterance>) override;
+    void cancel() override;
+    void pause() override;
+    void resume() override;
+    
+    void setObserver(WeakPtr<WebCore::SpeechSynthesisClientObserver> observer) override { m_observer = observer; }
+    WeakPtr<WebCore::SpeechSynthesisClientObserver> observer() const override { return m_observer; }
+    
+
+private:
+    WebPage& m_page;
+    WeakPtr<WebCore::SpeechSynthesisClientObserver> m_observer;
+    Vector<RefPtr<WebCore::PlatformSpeechSynthesisVoice>> m_voices;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SPEECH_SYNTHESIS)

Added: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisVoice.h (0 => 243002)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisVoice.h	                        (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebSpeechSynthesisVoice.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 Apple Inc. 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 APPLE INC. ``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 APPLE INC. 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)
+
+namespace WebKit {
+    
+struct WebSpeechSynthesisVoice {
+    String voiceURI;
+    String name;
+    String lang;
+    bool localService { false };
+    bool defaultLang { false };
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<WebSpeechSynthesisVoice> decode(Decoder&);
+};
+
+template<class Encoder>
+void WebSpeechSynthesisVoice::encode(Encoder& encoder) const
+{
+    encoder << voiceURI
+    << name
+    << lang
+    << localService
+    << defaultLang;
+}
+
+template<class Decoder>
+Optional<WebSpeechSynthesisVoice> WebSpeechSynthesisVoice::decode(Decoder& decoder)
+{
+    Optional<String> voiceURI;
+    decoder >> voiceURI;
+    if (!voiceURI)
+        return WTF::nullopt;
+
+    Optional<String> name;
+    decoder >> name;
+    if (!name)
+        return WTF::nullopt;
+
+    Optional<String> lang;
+    decoder >> lang;
+    if (!lang)
+        return WTF::nullopt;
+
+    Optional<bool> localService;
+    decoder >> localService;
+    if (!localService)
+        return WTF::nullopt;
+
+    Optional<bool> defaultLang;
+    decoder >> defaultLang;
+    if (!defaultLang)
+        return WTF::nullopt;
+
+    return {{ WTFMove(*voiceURI), WTFMove(*name), WTFMove(*lang), WTFMove(*localService), WTFMove(*defaultLang) }};}
+
+} // namespace WebKit
+
+#endif // ENABLE(SPEECH_SYNTHESIS)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (243001 => 243002)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -120,6 +120,7 @@
 #include "WebProcessProxyMessages.h"
 #include "WebProgressTrackerClient.h"
 #include "WebSocketProvider.h"
+#include "WebSpeechSynthesisClient.h"
 #include "WebStorageNamespaceProvider.h"
 #include "WebURLSchemeHandlerProxy.h"
 #include "WebUndoStep.h"
@@ -452,6 +453,10 @@
         send(Messages::WebPageProxy::SetIsUsingHighPerformanceWebGL(isUsingHighPerformanceWebGL));
     });
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    pageConfiguration.speechSynthesisClient = std::make_unique<WebSpeechSynthesisClient>(*this);
+#endif
+
 #if PLATFORM(COCOA)
     pageConfiguration.validationMessageClient = std::make_unique<WebValidationMessageClient>(*this);
 #endif
@@ -6406,6 +6411,23 @@
 #endif
 }
 
+#if ENABLE(SPEECH_SYNTHESIS)
+void WebPage::speakingErrorOccurred()
+{
+    corePage()->speechSynthesisClient()->observer()->speakingErrorOccurred();
+}
+
+void WebPage::boundaryEventOccurred(bool wordBoundary, unsigned charIndex)
+{
+    corePage()->speechSynthesisClient()->observer()->boundaryEventOccurred(wordBoundary, charIndex);
+}
+
+void WebPage::voicesDidChange()
+{
+    corePage()->speechSynthesisClient()->observer()->voicesChanged();
+}
+#endif
+
 #if ENABLE(ATTACHMENT_ELEMENT)
 
 void WebPage::insertAttachment(const String& identifier, Optional<uint64_t>&& fileSize, const String& fileName, const String& contentType, CallbackID callbackID)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (243001 => 243002)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-03-15 18:18:36 UTC (rev 243002)
@@ -1504,6 +1504,12 @@
 
     void simulateDeviceOrientationChange(double alpha, double beta, double gamma);
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    void speakingErrorOccurred();
+    void boundaryEventOccurred(bool wordBoundary, unsigned charIndex);
+    void voicesDidChange();
+#endif
+
     void frameBecameRemote(uint64_t frameID, WebCore::GlobalFrameIdentifier&& remoteFrameIdentifier, WebCore::GlobalWindowIdentifier&& remoteWindowIdentifier);
 
     void registerURLSchemeHandler(uint64_t identifier, const String& scheme);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (243001 => 243002)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-03-15 18:18:36 UTC (rev 243002)
@@ -549,6 +549,12 @@
     UpdateCurrentModifierState(OptionSet<WebCore::PlatformEvent::Modifier> modifiers)
     SimulateDeviceOrientationChange(double alpha, double beta, double gamma)
 
+#if ENABLE(SPEECH_SYNTHESIS)
+    SpeakingErrorOccurred()
+    BoundaryEventOccurred(bool wordBoundary, unsigned charIndex)
+    VoicesDidChange()
+#endif
+
     TextInputContextsInRect(WebCore::FloatRect rect) -> (Vector<struct WebKit::TextInputContext> contexts) Async
     FocusTextInputContext(struct WebKit::TextInputContext context) -> (bool success) Async
 }

Modified: trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in (243001 => 243002)


--- trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in	2019-03-15 18:18:36 UTC (rev 243002)
@@ -603,7 +603,6 @@
        (global-name "com.apple.lsd.mapdb")
        (global-name "com.apple.mobileassetd")
        (global-name "com.apple.powerlog.plxpclogger.xpc")
-       (global-name "com.apple.speech.speechsynthesisd")
        (global-name "com.apple.system.logger")
        (global-name "com.apple.tccd")
        (global-name "com.apple.tccd.system")

Modified: trunk/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp (243001 => 243002)


--- trunk/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp	2019-03-15 18:07:32 UTC (rev 243001)
+++ trunk/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp	2019-03-15 18:18:36 UTC (rev 243002)
@@ -42,6 +42,8 @@
 
 namespace WebKit {
 
+using namespace WebCore;
+
 void WebProcess::platformSetCacheModel(CacheModel cacheModel)
 {
     WebCore::MemoryCache::singleton().setDisabled(cacheModel == CacheModel::DocumentViewer);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to