#include "base/bind.h"
#include "base/logging.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/speech/tts_controller.h"
-#include "chrome/browser/speech/tts_message_filter.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
using content::BrowserThread;
-TtsMessageFilter::TtsMessageFilter(int render_process_id, Profile* profile)
- : render_process_id_(render_process_id),
- profile_(profile) {
+TtsMessageFilter::TtsMessageFilter(int render_process_id,
+ content::BrowserContext* browser_context)
+ : BrowserMessageFilter(TtsMsgStart),
+ render_process_id_(render_process_id),
+ browser_context_(browser_context),
+ valid_(true) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TtsController::GetInstance()->AddVoicesChangedDelegate(this);
+
+ // Balanced in OnChannelClosingInUIThread() to keep the ref-count be non-zero
+ // until all pointers to this class are invalidated.
+ AddRef();
}
void TtsMessageFilter::OverrideThreadForMessage(
}
}
-bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message,
- bool* message_was_ok) {
+bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(TtsMessageFilter, message, *message_was_ok)
+ IPC_BEGIN_MESSAGE_MAP(TtsMessageFilter, message)
IPC_MESSAGE_HANDLER(TtsHostMsg_InitializeVoiceList, OnInitializeVoiceList)
IPC_MESSAGE_HANDLER(TtsHostMsg_Speak, OnSpeak)
IPC_MESSAGE_HANDLER(TtsHostMsg_Pause, OnPause)
}
void TtsMessageFilter::OnChannelClosing() {
+ base::AutoLock lock(mutex_);
+ valid_ = false;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this));
}
+bool TtsMessageFilter::Valid() {
+ base::AutoLock lock(mutex_);
+ return valid_;
+}
+
+void TtsMessageFilter::OnDestruct() const {
+ {
+ base::AutoLock lock(mutex_);
+ valid_ = false;
+ }
+ BrowserThread::DeleteOnUIThread::Destruct(this);
+}
+
+TtsMessageFilter::~TtsMessageFilter() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Cleanup();
+}
+
void TtsMessageFilter::OnInitializeVoiceList() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TtsController* tts_controller = TtsController::GetInstance();
std::vector<VoiceData> voices;
- tts_controller->GetVoices(profile_, &voices);
+ tts_controller->GetVoices(browser_context_, &voices);
std::vector<TtsVoice> out_voices;
out_voices.resize(voices.size());
void TtsMessageFilter::OnSpeak(const TtsUtteranceRequest& request) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_ptr<Utterance> utterance(new Utterance(profile_));
+
+ scoped_ptr<Utterance> utterance(new Utterance(browser_context_));
utterance->set_src_id(request.id);
utterance->set_text(request.text);
utterance->set_lang(request.lang);
TtsEventType event_type,
int char_index,
const std::string& error_message) {
+ if (!Valid())
+ return;
+
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
switch (event_type) {
case TTS_EVENT_START:
}
void TtsMessageFilter::OnVoicesChanged() {
+ if (!Valid())
+ return;
+
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
OnInitializeVoiceList();
}
void TtsMessageFilter::OnChannelClosingInUIThread() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
+ Cleanup();
+ Release(); // Balanced in TtsMessageFilter().
}
-TtsMessageFilter::~TtsMessageFilter() {
+void TtsMessageFilter::Cleanup() {
+ TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
+ TtsController::GetInstance()->RemoveUtteranceEventDelegate(this);
}