Chromium Code Reviews| Index: content/browser/speech/speech_recognition_dispatcher_host.cc |
| diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc |
| index f920c51e779d6632c6eab3f1c8ee304080c789aa..b4626b1f2f58edc295d61fb7387d8af4d9316b2b 100644 |
| --- a/content/browser/speech/speech_recognition_dispatcher_host.cc |
| +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc |
| @@ -9,23 +9,41 @@ |
| #include "base/lazy_instance.h" |
| #include "content/browser/browser_plugin/browser_plugin_guest.h" |
| #include "content/browser/child_process_security_policy_impl.h" |
| -#include "content/browser/renderer_host/render_view_host_impl.h" |
| #include "content/browser/speech/speech_recognition_manager_impl.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/common/speech_recognition_messages.h" |
| +#include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/speech_recognition_manager_delegate.h" |
| #include "content/public/browser/speech_recognition_session_config.h" |
| #include "content/public/browser/speech_recognition_session_context.h" |
| -#include "content/public/common/content_switches.h" |
| +#include "content/public/common/child_process_host.h" |
| namespace content { |
| +namespace { |
| + |
| +void SendMessageToFrame(int render_process_id, |
|
Charlie Reis
2014/12/01 23:49:43
Is this called from another thread? All the calle
mlamouri (slow - plz ping)
2014/12/08 17:41:04
Callers are on the IO thread. The method is thread
Charlie Reis
2014/12/08 20:02:57
Yeah, let's split it into two methods. That makes
mlamouri (slow - plz ping)
2014/12/08 21:08:00
Done.
|
| + int render_frame_id, |
| + IPC::Message* message) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&SendMessageToFrame, |
| + render_process_id, render_frame_id, message)); |
| + return; |
| + } |
| + |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + RenderFrameHost::FromID(render_process_id, render_frame_id)->Send(message); |
|
Charlie Reis
2014/12/01 23:49:43
We should be careful about FromID returning NULL,
mlamouri (slow - plz ping)
2014/12/08 17:41:04
Done.
|
| +} |
| + |
| +} // anonymous namespace |
| + |
| SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost( |
| - int render_process_id, |
| - net::URLRequestContextGetter* context_getter) |
| - : BrowserMessageFilter(SpeechRecognitionMsgStart), |
| - render_process_id_(render_process_id), |
| - context_getter_(context_getter), |
| + WebContents* web_contents) |
| + : WebContentsObserver(web_contents), |
| weak_factory_(this) { |
| // Do not add any non-trivial initialization here, instead do it lazily when |
| // required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or |
| @@ -33,8 +51,8 @@ SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost( |
| } |
| SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() { |
| - SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess( |
| - render_process_id_); |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + weak_factory_.InvalidateWeakPtrs(); |
| } |
| base::WeakPtr<SpeechRecognitionDispatcherHost> |
| @@ -42,14 +60,12 @@ SpeechRecognitionDispatcherHost::AsWeakPtr() { |
| return weak_factory_.GetWeakPtr(); |
| } |
| -void SpeechRecognitionDispatcherHost::OnDestruct() const { |
| - BrowserThread::DeleteOnIOThread::Destruct(this); |
| -} |
| - |
| bool SpeechRecognitionDispatcherHost::OnMessageReceived( |
| - const IPC::Message& message) { |
| + const IPC::Message& message, RenderFrameHost* render_frame_host) { |
| bool handled = true; |
| - IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcherHost, message) |
| + |
| + IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(SpeechRecognitionDispatcherHost, message, |
| + render_frame_host) |
| IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest, |
| OnStartRequest) |
| IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest, |
| @@ -60,100 +76,83 @@ bool SpeechRecognitionDispatcherHost::OnMessageReceived( |
| OnAbortAllRequests) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| + |
| return handled; |
| } |
| -void SpeechRecognitionDispatcherHost::OverrideThreadForMessage( |
| - const IPC::Message& message, |
| - BrowserThread::ID* thread) { |
| - if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID) |
| - *thread = BrowserThread::UI; |
| -} |
| - |
| -void SpeechRecognitionDispatcherHost::OnChannelClosing() { |
| - weak_factory_.InvalidateWeakPtrs(); |
| +void SpeechRecognitionDispatcherHost::RenderFrameDeleted( |
| + RenderFrameHost* render_frame_host) { |
| + OnAbortAllRequests(render_frame_host); |
| } |
| void SpeechRecognitionDispatcherHost::OnStartRequest( |
| + RenderFrameHost* render_frame_host, |
| const SpeechRecognitionHostMsg_StartRequest_Params& params) { |
| - SpeechRecognitionHostMsg_StartRequest_Params input_params(params); |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + int render_frame_id = render_frame_host->GetRoutingID(); |
| + int render_process_id = render_frame_host->GetProcess()->GetID(); |
| // Check that the origin specified by the renderer process is one |
| // that it is allowed to access. |
| if (params.origin_url != "null" && |
| !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( |
| - render_process_id_, GURL(params.origin_url))) { |
| + render_process_id, GURL(params.origin_url))) { |
| LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: " |
| << params.origin_url; |
| return; |
| } |
| int embedder_render_process_id = 0; |
| - int embedder_render_view_id = MSG_ROUTING_NONE; |
| - RenderViewHostImpl* render_view_host = |
| - RenderViewHostImpl::FromID(render_process_id_, params.render_view_id); |
| - if (!render_view_host) { |
| - // RVH can be null if the tab was closed while continuous mode speech |
| - // recognition was running. This seems to happen on mac. |
| - LOG(WARNING) << "SRDH::OnStartRequest, RenderViewHost does not exist"; |
| - return; |
| - } |
| - WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( |
| - WebContents::FromRenderViewHost(render_view_host)); |
| - BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest(); |
| + int embedder_render_frame_id = MSG_ROUTING_NONE; |
| + |
| + BrowserPluginGuest* guest = |
| + static_cast<WebContentsImpl*>(web_contents())->GetBrowserPluginGuest(); |
| + |
| if (guest) { |
| // If the speech API request was from a guest, save the context of the |
| // embedder since we will use it to decide permission. |
| embedder_render_process_id = |
| guest->embedder_web_contents()->GetRenderProcessHost()->GetID(); |
| DCHECK_NE(embedder_render_process_id, 0); |
| - embedder_render_view_id = |
| - guest->embedder_web_contents()->GetRenderViewHost()->GetRoutingID(); |
| - DCHECK_NE(embedder_render_view_id, MSG_ROUTING_NONE); |
| + embedder_render_frame_id = |
| + guest->embedder_web_contents()->GetMainFrame()->GetRoutingID(); |
| + DCHECK_NE(embedder_render_frame_id, MSG_ROUTING_NONE); |
| } |
| - // TODO(lazyboy): Check if filter_profanities should use |render_process_id| |
| - // instead of |render_process_id_|. |
| bool filter_profanities = |
| SpeechRecognitionManagerImpl::GetInstance() && |
| SpeechRecognitionManagerImpl::GetInstance()->delegate() && |
| SpeechRecognitionManagerImpl::GetInstance()->delegate()-> |
| - FilterProfanities(render_process_id_); |
| + FilterProfanities(render_process_id); |
| - // TODO(miu): This is a hack to allow SpeechRecognition to operate with the |
| - // MediaStreamManager, which partitions requests per RenderFrame, not per |
| - // RenderView. http://crbug.com/390749 |
| - const int params_render_frame_id = render_view_host ? |
| - render_view_host->GetMainFrame()->GetRoutingID() : MSG_ROUTING_NONE; |
| + SpeechRecognitionSessionContext context; |
| + context.context_name = params.origin_url; |
| + context.render_process_id = render_process_id; |
| + context.render_frame_id = render_frame_id; |
| + context.embedder_render_process_id = embedder_render_process_id; |
| + context.embedder_render_frame_id = embedder_render_frame_id; |
| + if (embedder_render_process_id) |
| + context.guest_render_frame_id = render_frame_id; |
| + context.request_id = params.request_id; |
| BrowserThread::PostTask( |
| - BrowserThread::IO, |
| - FROM_HERE, |
| - base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO, |
| - this, |
| - embedder_render_process_id, |
| - embedder_render_view_id, |
| - input_params, |
| - params_render_frame_id, |
| - filter_profanities)); |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&SpeechRecognitionDispatcherHost::StartSession, |
| + base::Unretained(this), |
| + params, |
| + context, |
| + base::Unretained(web_contents()->GetBrowserContext()-> |
| + GetRequestContextForRenderProcess(render_process_id)), |
| + filter_profanities)); |
| } |
| -void SpeechRecognitionDispatcherHost::OnStartRequestOnIO( |
| - int embedder_render_process_id, |
| - int embedder_render_view_id, |
| +void SpeechRecognitionDispatcherHost::StartSession( |
| const SpeechRecognitionHostMsg_StartRequest_Params& params, |
| - int params_render_frame_id, |
| + const SpeechRecognitionSessionContext& context, |
| + net::URLRequestContextGetter* url_request_context_getter, |
| bool filter_profanities) { |
| - SpeechRecognitionSessionContext context; |
| - context.context_name = params.origin_url; |
| - context.render_process_id = render_process_id_; |
| - context.render_view_id = params.render_view_id; |
| - context.render_frame_id = params_render_frame_id; |
| - context.embedder_render_process_id = embedder_render_process_id; |
| - context.embedder_render_view_id = embedder_render_view_id; |
| - if (embedder_render_process_id) |
| - context.guest_render_view_id = params.render_view_id; |
| - context.request_id = params.request_id; |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| SpeechRecognitionSessionConfig config; |
| config.is_legacy_api = false; |
| @@ -162,7 +161,7 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO( |
| config.max_hypotheses = params.max_hypotheses; |
| config.origin_url = params.origin_url; |
| config.initial_context = context; |
| - config.url_request_context_getter = context_getter_.get(); |
| + config.url_request_context_getter = url_request_context_getter; |
| config.filter_profanities = filter_profanities; |
| config.continuous = params.continuous; |
| config.interim_results = params.interim_results; |
| @@ -174,10 +173,25 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO( |
| SpeechRecognitionManager::GetInstance()->StartSession(session_id); |
| } |
| -void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id, |
| - int request_id) { |
| +void SpeechRecognitionDispatcherHost::OnAbortRequest( |
| + RenderFrameHost* render_frame_host, int request_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&SpeechRecognitionDispatcherHost::OnAbortRequestIO, |
| + base::Unretained(this), |
| + render_frame_host->GetProcess()->GetID(), |
| + render_frame_host->GetRoutingID(), |
| + request_id)); |
| +} |
| + |
| +void SpeechRecognitionDispatcherHost::OnAbortRequestIO( |
| + int render_process_id, int render_frame_id, int request_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| int session_id = SpeechRecognitionManager::GetInstance()->GetSession( |
| - render_process_id_, render_view_id, request_id); |
| + render_process_id, render_frame_id, request_id); |
| // The renderer might provide an invalid |request_id| if the session was not |
| // started as expected, e.g., due to unsatisfied security requirements. |
| @@ -185,15 +199,45 @@ void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id, |
| SpeechRecognitionManager::GetInstance()->AbortSession(session_id); |
| } |
| -void SpeechRecognitionDispatcherHost::OnAbortAllRequests(int render_view_id) { |
| - SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderView( |
| - render_process_id_, render_view_id); |
| +void SpeechRecognitionDispatcherHost::OnAbortAllRequests( |
| + RenderFrameHost* render_frame_host) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&SpeechRecognitionDispatcherHost::OnAbortAllRequestsIO, |
| + base::Unretained(this), |
| + render_frame_host->GetProcess()->GetID(), |
| + render_frame_host->GetRoutingID())); |
| +} |
| + |
| +void SpeechRecognitionDispatcherHost::OnAbortAllRequestsIO( |
| + int render_process_id, int render_frame_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderFrame( |
| + render_process_id, render_frame_id); |
| } |
| void SpeechRecognitionDispatcherHost::OnStopCaptureRequest( |
| - int render_view_id, int request_id) { |
| + RenderFrameHost* render_frame_host, int request_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&SpeechRecognitionDispatcherHost::OnStopCaptureRequestIO, |
| + base::Unretained(this), |
| + render_frame_host->GetProcess()->GetID(), |
| + render_frame_host->GetRoutingID(), |
| + request_id)); |
| +} |
| + |
| +void SpeechRecognitionDispatcherHost::OnStopCaptureRequestIO( |
| + int render_process_id, int render_frame_id, int request_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| int session_id = SpeechRecognitionManager::GetInstance()->GetSession( |
| - render_process_id_, render_view_id, request_id); |
| + render_process_id, render_frame_id, request_id); |
| // The renderer might provide an invalid |request_id| if the session was not |
| // started as expected, e.g., due to unsatisfied security requirements. |
| @@ -208,43 +252,55 @@ void SpeechRecognitionDispatcherHost::OnStopCaptureRequest( |
| void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_Started(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_Started(context.render_frame_id, |
| + context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_AudioStarted(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_AudioStarted( |
| + context.render_frame_id, context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_SoundStarted(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_SoundStarted( |
| + context.render_frame_id, context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_SoundEnded(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_SoundEnded( |
| + context.render_frame_id, context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_AudioEnded(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_AudioEnded( |
| + context.render_frame_id, context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_Ended(context.render_view_id, |
| - context.request_id)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_Ended( |
| + context.render_frame_id, context.request_id)); |
| } |
| void SpeechRecognitionDispatcherHost::OnRecognitionResults( |
| @@ -252,9 +308,10 @@ void SpeechRecognitionDispatcherHost::OnRecognitionResults( |
| const SpeechRecognitionResults& results) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_view_id, |
| - context.request_id, |
| - results)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_ResultRetrieved( |
| + context.render_frame_id, context.request_id, results)); |
| } |
| void SpeechRecognitionDispatcherHost::OnRecognitionError( |
| @@ -262,9 +319,10 @@ void SpeechRecognitionDispatcherHost::OnRecognitionError( |
| const SpeechRecognitionError& error) { |
| const SpeechRecognitionSessionContext& context = |
| SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| - Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_view_id, |
| - context.request_id, |
| - error)); |
| + |
| + SendMessageToFrame(context.render_process_id, context.render_frame_id, |
| + new SpeechRecognitionMsg_ErrorOccurred( |
| + context.render_frame_id, context.request_id, error)); |
| } |
| // The events below are currently not used by speech JS APIs implementation. |