| 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..737a610f48fad5ebb29e65e67e27db11b4dbfed6 100644
|
| --- a/content/browser/speech/speech_recognition_dispatcher_host.cc
|
| +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
|
| @@ -9,23 +9,77 @@
|
| #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 SendMessageToFrameOnUI(int render_process_id,
|
| + int render_frame_id,
|
| + IPC::Message* message) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + RenderFrameHost* render_frame_host =
|
| + RenderFrameHost::FromID(render_process_id, render_frame_id);
|
| + if (render_frame_host)
|
| + render_frame_host->Send(message);
|
| +}
|
| +
|
| +void SendMessageToFrame(int render_process_id,
|
| + int render_frame_id,
|
| + IPC::Message* message) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&SendMessageToFrameOnUI,
|
| + render_process_id, render_frame_id, message));
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +using FrameDeletedCallback = base::Callback<void(int)>;
|
| +using WebContentsDeletedCallback = base::Callback<void(WebContents*)>;
|
| +
|
| +class SpeechRecognitionDispatcherHost::FrameDeletedObserver
|
| + : public WebContentsObserver {
|
| + public:
|
| + FrameDeletedObserver(WebContents* web_contents,
|
| + FrameDeletedCallback frame_deleted_cb,
|
| + WebContentsDeletedCallback web_contents_deleted_cb)
|
| + : WebContentsObserver(web_contents) {
|
| + }
|
| +
|
| + ~FrameDeletedObserver() override {
|
| + }
|
| +
|
| + private:
|
| + void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
|
| + frame_deleted_cb_.Run(render_frame_host->GetRoutingID());
|
| + }
|
| +
|
| + void WebContentsDestroyed() override {
|
| + web_contents_deleted_cb_.Run(web_contents());
|
| + }
|
| +
|
| + const FrameDeletedCallback frame_deleted_cb_;
|
| + const WebContentsDeletedCallback web_contents_deleted_cb_;
|
| +};
|
| +
|
| SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
|
| - int render_process_id,
|
| - net::URLRequestContextGetter* context_getter)
|
| + int render_process_id)
|
| : BrowserMessageFilter(SpeechRecognitionMsgStart),
|
| render_process_id_(render_process_id),
|
| - context_getter_(context_getter),
|
| 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 +87,11 @@ SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
|
| }
|
|
|
| SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
|
| - SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess(
|
| - render_process_id_);
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + weak_factory_.InvalidateWeakPtrs();
|
| +
|
| + STLDeleteContainerPairSecondPointers(frame_deleted_observers_.begin(),
|
| + frame_deleted_observers_.end());
|
| }
|
|
|
| base::WeakPtr<SpeechRecognitionDispatcherHost>
|
| @@ -46,9 +103,20 @@ void SpeechRecognitionDispatcherHost::OnDestruct() const {
|
| BrowserThread::DeleteOnIOThread::Destruct(this);
|
| }
|
|
|
| +void SpeechRecognitionDispatcherHost::OnChannelClosing() {
|
| + weak_factory_.InvalidateWeakPtrs();
|
| +}
|
| +
|
| +void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
|
| + const IPC::Message& message, BrowserThread::ID* thread) {
|
| + if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID)
|
| + *thread = BrowserThread::UI;
|
| +}
|
| +
|
| bool SpeechRecognitionDispatcherHost::OnMessageReceived(
|
| const IPC::Message& message) {
|
| bool handled = true;
|
| +
|
| IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcherHost, message)
|
| IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest,
|
| OnStartRequest)
|
| @@ -60,23 +128,13 @@ 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();
|
| + return handled;
|
| }
|
|
|
| void SpeechRecognitionDispatcherHost::OnStartRequest(
|
| const SpeechRecognitionHostMsg_StartRequest_Params& params) {
|
| - SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| // Check that the origin specified by the renderer process is one
|
| // that it is allowed to access.
|
| @@ -89,72 +147,60 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
|
| }
|
|
|
| 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;
|
| +
|
| + WebContents* web_contents = WebContents::FromRenderFrameHost(
|
| + RenderFrameHost::FromID(render_process_id_, params.render_frame_id));
|
| + DCHECK(web_contents);
|
| +
|
| + 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_);
|
|
|
| - // 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;
|
| -
|
| - 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));
|
| -}
|
| -
|
| -void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
|
| - int embedder_render_process_id,
|
| - int embedder_render_view_id,
|
| - const SpeechRecognitionHostMsg_StartRequest_Params& params,
|
| - int params_render_frame_id,
|
| - 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.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;
|
| + context.embedder_render_frame_id = embedder_render_frame_id;
|
| if (embedder_render_process_id)
|
| - context.guest_render_view_id = params.render_view_id;
|
| + context.guest_render_frame_id = params.render_frame_id;
|
| context.request_id = params.request_id;
|
|
|
| + BrowserThread::PostTask(
|
| + 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::StartSession(
|
| + const SpeechRecognitionHostMsg_StartRequest_Params& params,
|
| + const SpeechRecognitionSessionContext& context,
|
| + net::URLRequestContextGetter* url_request_context_getter,
|
| + bool filter_profanities) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| SpeechRecognitionSessionConfig config;
|
| config.is_legacy_api = false;
|
| config.language = params.language;
|
| @@ -162,7 +208,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 +220,12 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
|
| SpeechRecognitionManager::GetInstance()->StartSession(session_id);
|
| }
|
|
|
| -void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_view_id,
|
| +void SpeechRecognitionDispatcherHost::OnAbortRequest(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 +233,19 @@ 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(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) {
|
| + 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.
|
| @@ -203,48 +255,103 @@ void SpeechRecognitionDispatcherHost::OnStopCaptureRequest(
|
| }
|
| }
|
|
|
| +void SpeechRecognitionDispatcherHost::CreateObserverFor(
|
| + WebContents* web_contents) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + if (frame_deleted_observers_.find(web_contents) !=
|
| + frame_deleted_observers_.end()) {
|
| + return;
|
| + }
|
| +
|
| + frame_deleted_observers_.emplace(
|
| + web_contents,
|
| + new FrameDeletedObserver(
|
| + web_contents,
|
| + base::Bind(&SpeechRecognitionDispatcherHost::AbortAllRequestsFromUI,
|
| + AsWeakPtr()),
|
| + base::Bind(&SpeechRecognitionDispatcherHost::RemoveObserverFor,
|
| + AsWeakPtr())));
|
| +}
|
| +
|
| +void SpeechRecognitionDispatcherHost::RemoveObserverFor(
|
| + WebContents* web_contents) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + FrameDeletedObservers::iterator it =
|
| + frame_deleted_observers_.find(web_contents);
|
| + if (it == frame_deleted_observers_.end())
|
| + return;
|
| +
|
| + delete it->second;
|
| + frame_deleted_observers_.erase(web_contents);
|
| +}
|
| +
|
| +void SpeechRecognitionDispatcherHost::AbortAllRequestsFromUI(
|
| + int render_frame_id) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&SpeechRecognitionDispatcherHost::OnAbortAllRequests,
|
| + this,
|
| + render_frame_id));
|
| +}
|
| +
|
| // -------- SpeechRecognitionEventListener interface implementation -----------
|
|
|
| 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 +359,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 +370,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.
|
|
|