root/content/browser/speech/input_tag_speech_dispatcher_host.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_factory_
  2. AsWeakPtr
  3. OnMessageReceived
  4. OverrideThreadForMessage
  5. OnChannelClosing
  6. OnStartRecognition
  7. StartRecognitionOnIO
  8. OnCancelRecognition
  9. OnStopRecording
  10. OnRecognitionResults
  11. OnAudioEnd
  12. OnRecognitionEnd
  13. OnRecognitionStart
  14. OnAudioStart
  15. OnSoundStart
  16. OnSoundEnd
  17. OnRecognitionError
  18. OnAudioLevelsChange
  19. OnEnvironmentEstimationComplete

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/speech/input_tag_speech_dispatcher_host.h"

#include "base/bind.h"
#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/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"

namespace {
const uint32 kMaxHypothesesForSpeechInputTag = 6;
}

namespace content {

InputTagSpeechDispatcherHost::InputTagSpeechDispatcherHost(
    bool is_guest,
    int render_process_id,
    net::URLRequestContextGetter* url_request_context_getter)
    : BrowserMessageFilter(SpeechRecognitionMsgStart),
      is_guest_(is_guest),
      render_process_id_(render_process_id),
      url_request_context_getter_(url_request_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
  // add an Init() method.
}

InputTagSpeechDispatcherHost::~InputTagSpeechDispatcherHost() {
  SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess(
      render_process_id_);
}

base::WeakPtr<InputTagSpeechDispatcherHost>
InputTagSpeechDispatcherHost::AsWeakPtr() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  return weak_factory_.GetWeakPtr();
}

bool InputTagSpeechDispatcherHost::OnMessageReceived(
    const IPC::Message& message, bool* message_was_ok) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP_EX(InputTagSpeechDispatcherHost, message,
                           *message_was_ok)
    IPC_MESSAGE_HANDLER(InputTagSpeechHostMsg_StartRecognition,
                        OnStartRecognition)
    IPC_MESSAGE_HANDLER(InputTagSpeechHostMsg_CancelRecognition,
                        OnCancelRecognition)
    IPC_MESSAGE_HANDLER(InputTagSpeechHostMsg_StopRecording,
                        OnStopRecording)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void InputTagSpeechDispatcherHost::OverrideThreadForMessage(
    const IPC::Message& message,
    BrowserThread::ID* thread) {
  if (message.type() == InputTagSpeechHostMsg_StartRecognition::ID)
    *thread = BrowserThread::UI;
}

void InputTagSpeechDispatcherHost::OnChannelClosing() {
  weak_factory_.InvalidateWeakPtrs();
}

void InputTagSpeechDispatcherHost::OnStartRecognition(
    const InputTagSpeechHostMsg_StartRecognition_Params& params) {
  InputTagSpeechHostMsg_StartRecognition_Params input_params(params);
  int render_process_id = render_process_id_;

  // 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))) {
    LOG(ERROR) << "ITSDH::OnStartRecognition, disallowed origin: "
               << params.origin_url;
    return;
  }

  // The chrome layer is mostly oblivious to BrowserPlugin guests and so it
  // cannot correctly place the speech bubble relative to a guest. Thus, we
  // set up the speech recognition context relative to the embedder.
  int guest_render_view_id = MSG_ROUTING_NONE;
  if (is_guest_) {
    RenderViewHostImpl* render_view_host =
        RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
    WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
        WebContents::FromRenderViewHost(render_view_host));
    BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest();
    input_params.element_rect.set_origin(
        guest->GetScreenCoordinates(input_params.element_rect.origin()));
    guest_render_view_id = params.render_view_id;
    render_process_id =
        guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
    input_params.render_view_id =
        guest->embedder_web_contents()->GetRoutingID();
  }
  bool filter_profanities =
      SpeechRecognitionManagerImpl::GetInstance() &&
      SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
      SpeechRecognitionManagerImpl::GetInstance()->delegate()->
          FilterProfanities(render_process_id_);

 BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(
          &InputTagSpeechDispatcherHost::StartRecognitionOnIO,
          this,
          render_process_id,
          guest_render_view_id,
          input_params,
          filter_profanities));
}

void InputTagSpeechDispatcherHost::StartRecognitionOnIO(
    int render_process_id,
    int guest_render_view_id,
    const InputTagSpeechHostMsg_StartRecognition_Params& params,
    bool filter_profanities) {
  SpeechRecognitionSessionContext context;
  context.render_process_id = render_process_id;
  context.render_view_id = params.render_view_id;
  context.guest_render_view_id = guest_render_view_id;
  // Keep context.embedder_render_process_id and context.embedder_render_view_id
  // unset.
  context.request_id = params.request_id;
  context.element_rect = params.element_rect;

  SpeechRecognitionSessionConfig config;
  config.language = params.language;
  if (!params.grammar.empty()) {
    config.grammars.push_back(SpeechRecognitionGrammar(params.grammar));
  }
  config.max_hypotheses = kMaxHypothesesForSpeechInputTag;
  config.origin_url = params.origin_url;
  config.initial_context = context;
  config.url_request_context_getter = url_request_context_getter_.get();
  config.filter_profanities = filter_profanities;
  config.event_listener = AsWeakPtr();

  int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
      config);
  DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid);
  SpeechRecognitionManager::GetInstance()->StartSession(session_id);
}

void InputTagSpeechDispatcherHost::OnCancelRecognition(int render_view_id,
                                                       int request_id) {
  int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
      render_process_id_, render_view_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.
  if (session_id != SpeechRecognitionManager::kSessionIDInvalid)
    SpeechRecognitionManager::GetInstance()->AbortSession(session_id);
}

void InputTagSpeechDispatcherHost::OnStopRecording(int render_view_id,
                                                   int request_id) {
  int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
      render_process_id_, render_view_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.
  if (session_id != SpeechRecognitionManager::kSessionIDInvalid) {
    SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
        session_id);
  }
}

// -------- SpeechRecognitionEventListener interface implementation -----------
void InputTagSpeechDispatcherHost::OnRecognitionResults(
    int session_id,
    const SpeechRecognitionResults& results) {
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionResults enter";

  const SpeechRecognitionSessionContext& context =
      SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);

  int render_view_id =
      context.guest_render_view_id == MSG_ROUTING_NONE ?
          context.render_view_id : context.guest_render_view_id;
  Send(new InputTagSpeechMsg_SetRecognitionResults(
      render_view_id,
      context.request_id,
      results));
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionResults exit";
}

void InputTagSpeechDispatcherHost::OnAudioEnd(int session_id) {
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnAudioEnd enter";

  const SpeechRecognitionSessionContext& context =
      SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
  int render_view_id =
      context.guest_render_view_id == MSG_ROUTING_NONE ?
          context.render_view_id : context.guest_render_view_id;
  Send(new InputTagSpeechMsg_RecordingComplete(render_view_id,
                                               context.request_id));
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnAudioEnd exit";
}

void InputTagSpeechDispatcherHost::OnRecognitionEnd(int session_id) {
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionEnd enter";
  const SpeechRecognitionSessionContext& context =
      SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
  int render_view_id =
      context.guest_render_view_id == MSG_ROUTING_NONE ?
          context.render_view_id : context.guest_render_view_id;
  Send(new InputTagSpeechMsg_RecognitionComplete(render_view_id,
                                                 context.request_id));
  DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionEnd exit";
}

// The events below are currently not used by x-webkit-speech implementation.
void InputTagSpeechDispatcherHost::OnRecognitionStart(int session_id) {}
void InputTagSpeechDispatcherHost::OnAudioStart(int session_id) {}
void InputTagSpeechDispatcherHost::OnSoundStart(int session_id) {}
void InputTagSpeechDispatcherHost::OnSoundEnd(int session_id) {}
void InputTagSpeechDispatcherHost::OnRecognitionError(
    int session_id,
    const SpeechRecognitionError& error) {}
void InputTagSpeechDispatcherHost::OnAudioLevelsChange(
    int session_id, float volume, float noise_volume) {}
void InputTagSpeechDispatcherHost::OnEnvironmentEstimationComplete(
    int session_id) {}

}  // namespace content

/* [<][>][^][v][top][bottom][index][help] */