1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/speech/tts_message_filter.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "content/public/browser/browser_context.h" 10 #include "content/public/browser/render_process_host.h" 11 12 using content::BrowserThread; 13 14 TtsMessageFilter::TtsMessageFilter(int render_process_id, 15 content::BrowserContext* browser_context) 16 : BrowserMessageFilter(TtsMsgStart), 17 render_process_id_(render_process_id), 18 browser_context_(browser_context), 19 weak_ptr_factory_(this) { 20 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 21 TtsController::GetInstance()->AddVoicesChangedDelegate(this); 22 23 // Balanced in OnChannelClosingInUIThread() to keep the ref-count be non-zero 24 // until all WeakPtr's are invalidated. 25 AddRef(); 26 } 27 28 void TtsMessageFilter::OverrideThreadForMessage( 29 const IPC::Message& message, BrowserThread::ID* thread) { 30 switch (message.type()) { 31 case TtsHostMsg_InitializeVoiceList::ID: 32 case TtsHostMsg_Speak::ID: 33 case TtsHostMsg_Pause::ID: 34 case TtsHostMsg_Resume::ID: 35 case TtsHostMsg_Cancel::ID: 36 *thread = BrowserThread::UI; 37 break; 38 } 39 } 40 41 bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message) { 42 bool handled = true; 43 IPC_BEGIN_MESSAGE_MAP(TtsMessageFilter, message) 44 IPC_MESSAGE_HANDLER(TtsHostMsg_InitializeVoiceList, OnInitializeVoiceList) 45 IPC_MESSAGE_HANDLER(TtsHostMsg_Speak, OnSpeak) 46 IPC_MESSAGE_HANDLER(TtsHostMsg_Pause, OnPause) 47 IPC_MESSAGE_HANDLER(TtsHostMsg_Resume, OnResume) 48 IPC_MESSAGE_HANDLER(TtsHostMsg_Cancel, OnCancel) 49 IPC_MESSAGE_UNHANDLED(handled = false) 50 IPC_END_MESSAGE_MAP() 51 return handled; 52 } 53 54 void TtsMessageFilter::OnChannelClosing() { 55 BrowserThread::PostTask( 56 BrowserThread::UI, FROM_HERE, 57 base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this)); 58 } 59 60 void TtsMessageFilter::OnDestruct() const { 61 BrowserThread::DeleteOnUIThread::Destruct(this); 62 } 63 64 void TtsMessageFilter::OnInitializeVoiceList() { 65 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 66 TtsController* tts_controller = TtsController::GetInstance(); 67 std::vector<VoiceData> voices; 68 tts_controller->GetVoices(browser_context_, &voices); 69 70 std::vector<TtsVoice> out_voices; 71 out_voices.resize(voices.size()); 72 for (size_t i = 0; i < voices.size(); ++i) { 73 TtsVoice& out_voice = out_voices[i]; 74 out_voice.voice_uri = voices[i].name; 75 out_voice.name = voices[i].name; 76 out_voice.lang = voices[i].lang; 77 out_voice.local_service = !voices[i].remote; 78 out_voice.is_default = (i == 0); 79 } 80 Send(new TtsMsg_SetVoiceList(out_voices)); 81 } 82 83 void TtsMessageFilter::OnSpeak(const TtsUtteranceRequest& request) { 84 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 85 86 scoped_ptr<Utterance> utterance(new Utterance(browser_context_)); 87 utterance->set_src_id(request.id); 88 utterance->set_text(request.text); 89 utterance->set_lang(request.lang); 90 utterance->set_voice_name(request.voice); 91 utterance->set_can_enqueue(true); 92 93 UtteranceContinuousParameters params; 94 params.rate = request.rate; 95 params.pitch = request.pitch; 96 params.volume = request.volume; 97 utterance->set_continuous_parameters(params); 98 99 utterance->set_event_delegate(weak_ptr_factory_.GetWeakPtr()); 100 101 TtsController::GetInstance()->SpeakOrEnqueue(utterance.release()); 102 } 103 104 void TtsMessageFilter::OnPause() { 105 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 106 TtsController::GetInstance()->Pause(); 107 } 108 109 void TtsMessageFilter::OnResume() { 110 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 TtsController::GetInstance()->Resume(); 112 } 113 114 void TtsMessageFilter::OnCancel() { 115 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 116 TtsController::GetInstance()->Stop(); 117 } 118 119 void TtsMessageFilter::OnTtsEvent(Utterance* utterance, 120 TtsEventType event_type, 121 int char_index, 122 const std::string& error_message) { 123 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 124 switch (event_type) { 125 case TTS_EVENT_START: 126 Send(new TtsMsg_DidStartSpeaking(utterance->src_id())); 127 break; 128 case TTS_EVENT_END: 129 Send(new TtsMsg_DidFinishSpeaking(utterance->src_id())); 130 break; 131 case TTS_EVENT_WORD: 132 Send(new TtsMsg_WordBoundary(utterance->src_id(), char_index)); 133 break; 134 case TTS_EVENT_SENTENCE: 135 Send(new TtsMsg_SentenceBoundary(utterance->src_id(), char_index)); 136 break; 137 case TTS_EVENT_MARKER: 138 Send(new TtsMsg_MarkerEvent(utterance->src_id(), char_index)); 139 break; 140 case TTS_EVENT_INTERRUPTED: 141 Send(new TtsMsg_WasInterrupted(utterance->src_id())); 142 break; 143 case TTS_EVENT_CANCELLED: 144 Send(new TtsMsg_WasCancelled(utterance->src_id())); 145 break; 146 case TTS_EVENT_ERROR: 147 Send(new TtsMsg_SpeakingErrorOccurred( 148 utterance->src_id(), error_message)); 149 break; 150 case TTS_EVENT_PAUSE: 151 Send(new TtsMsg_DidPauseSpeaking(utterance->src_id())); 152 break; 153 case TTS_EVENT_RESUME: 154 Send(new TtsMsg_DidResumeSpeaking(utterance->src_id())); 155 break; 156 } 157 } 158 159 void TtsMessageFilter::OnVoicesChanged() { 160 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 161 OnInitializeVoiceList(); 162 } 163 164 void TtsMessageFilter::OnChannelClosingInUIThread() { 165 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); 167 168 weak_ptr_factory_.InvalidateWeakPtrs(); 169 Release(); // Balanced in TtsMessageFilter(). 170 } 171 172 TtsMessageFilter::~TtsMessageFilter() { 173 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 174 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); 175 TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); 176 } 177