diff options
author | hans@chromium.org <hans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 10:10:34 +0000 |
---|---|---|
committer | hans@chromium.org <hans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-25 10:10:34 +0000 |
commit | 64d09224049a393ad66c565299001beab3616c1e (patch) | |
tree | d7bb1d841856eaf297087711c6269e2f998057c3 /content/renderer | |
parent | c4205b9ed7bd1096500828e2893036c0f38a51df (diff) | |
download | chromium_src-64d09224049a393ad66c565299001beab3616c1e.zip chromium_src-64d09224049a393ad66c565299001beab3616c1e.tar.gz chromium_src-64d09224049a393ad66c565299001beab3616c1e.tar.bz2 |
Introduced SpeechRecognitionDispatcher(Host) classes, handling dispatch of IPC messages for continuous speech recognition. (Speech CL2.1)
BUG=116954
TEST=none
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=138801
Review URL: https://chromiumcodereview.appspot.com/10273006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139015 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-rw-r--r-- | content/renderer/input_tag_speech_dispatcher.cc | 2 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 10 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 7 | ||||
-rw-r--r-- | content/renderer/speech_recognition_dispatcher.cc | 193 | ||||
-rw-r--r-- | content/renderer/speech_recognition_dispatcher.h | 70 |
5 files changed, 281 insertions, 1 deletions
diff --git a/content/renderer/input_tag_speech_dispatcher.cc b/content/renderer/input_tag_speech_dispatcher.cc index 7aa6d9f..41f3dd7 100644 --- a/content/renderer/input_tag_speech_dispatcher.cc +++ b/content/renderer/input_tag_speech_dispatcher.cc @@ -81,7 +81,7 @@ void InputTagSpeechDispatcher::cancelRecognition(int request_id) { void InputTagSpeechDispatcher::stopRecording(int request_id) { VLOG(1) << "InputTagSpeechDispatcher::stopRecording enter"; Send(new InputTagSpeechHostMsg_StopRecording(routing_id(), - request_id)); + request_id)); VLOG(1) << "InputTagSpeechDispatcher::stopRecording exit"; } diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 271c3e7..7cc7ebe 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -89,6 +89,7 @@ #include "content/renderer/renderer_accessibility.h" #include "content/renderer/renderer_webapplicationcachehost_impl.h" #include "content/renderer/renderer_webcolorchooser_impl.h" +#include "content/renderer/speech_recognition_dispatcher.h" #include "content/renderer/text_input_client_observer.h" #include "content/renderer/v8_value_converter_impl.h" #include "content/renderer/web_intents_host.h" @@ -527,6 +528,7 @@ RenderViewImpl::RenderViewImpl( ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)), geolocation_dispatcher_(NULL), input_tag_speech_dispatcher_(NULL), + speech_recognition_dispatcher_(NULL), device_orientation_dispatcher_(NULL), media_stream_dispatcher_(NULL), media_stream_impl_(NULL), @@ -5386,6 +5388,14 @@ WebKit::WebSpeechInputController* RenderViewImpl::speechInputController( return input_tag_speech_dispatcher_; } +WebKit::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() { +#if defined(ENABLE_INPUT_SPEECH) + if (!speech_recognition_dispatcher_) + speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this); +#endif + return speech_recognition_dispatcher_; +} + WebKit::WebDeviceOrientationClient* RenderViewImpl::deviceOrientationClient() { if (!device_orientation_dispatcher_) device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this); diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 6345287..119ddad 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -81,6 +81,7 @@ class RendererAccessibility; class RendererWebColorChooserImpl; class SkBitmap; class InputTagSpeechDispatcher; +class SpeechRecognitionDispatcher; struct ViewMsg_Navigate_Params; struct ViewMsg_PostMessage_Params; struct ViewMsg_StopFinding_Params; @@ -140,6 +141,7 @@ class WebPeerConnectionHandlerClient; class WebSocketStreamHandle; class WebSpeechInputController; class WebSpeechInputListener; +class WebSpeechRecognizer; class WebStorageNamespace; class WebTouchEvent; class WebURLLoader; @@ -466,6 +468,7 @@ class RenderViewImpl : public RenderWidget, virtual WebKit::WebGeolocationClient* geolocationClient(); virtual WebKit::WebSpeechInputController* speechInputController( WebKit::WebSpeechInputListener* listener); + virtual WebKit::WebSpeechRecognizer* speechRecognizer(); virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient(); virtual void zoomLimitsChanged(double minimum_level, double maximum_level); virtual void zoomLevelChanged(); @@ -1269,6 +1272,10 @@ class RenderViewImpl : public RenderWidget, // The speech dispatcher attached to this view, lazily initialized. InputTagSpeechDispatcher* input_tag_speech_dispatcher_; + // The speech recognition dispatcher attached to this view, lazily + // initialized. + SpeechRecognitionDispatcher* speech_recognition_dispatcher_; + // Device orientation dispatcher attached to this view; lazily initialized. DeviceOrientationDispatcher* device_orientation_dispatcher_; diff --git a/content/renderer/speech_recognition_dispatcher.cc b/content/renderer/speech_recognition_dispatcher.cc new file mode 100644 index 0000000..90123dd --- /dev/null +++ b/content/renderer/speech_recognition_dispatcher.cc @@ -0,0 +1,193 @@ +// 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/renderer/speech_recognition_dispatcher.h" + +#include "base/basictypes.h" +#include "base/utf_string_conversions.h" +#include "content/common/speech_recognition_messages.h" +#include "content/renderer/render_view_impl.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechGrammar.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechRecognitionParams.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechRecognitionResult.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechRecognizerClient.h" + +using content::SpeechRecognitionError; +using content::SpeechRecognitionResult; +using WebKit::WebVector; +using WebKit::WebString; +using WebKit::WebSpeechGrammar; +using WebKit::WebSpeechRecognitionHandle; +using WebKit::WebSpeechRecognitionResult; +using WebKit::WebSpeechRecognitionParams; +using WebKit::WebSpeechRecognizerClient; + +SpeechRecognitionDispatcher::SpeechRecognitionDispatcher( + RenderViewImpl* render_view) + : content::RenderViewObserver(render_view), + recognizer_client_(NULL), + next_id_(1) { +} + +SpeechRecognitionDispatcher::~SpeechRecognitionDispatcher() { +} + +bool SpeechRecognitionDispatcher::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcher, message) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_Started, OnRecognitionStarted) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_AudioStarted, OnAudioStarted) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_SoundStarted, OnSoundStarted) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_SoundEnded, OnSoundEnded) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_AudioEnded, OnAudioEnded) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_ErrorOccurred, OnErrorOccurred) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_Ended, OnRecognitionEnded) + IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_ResultRetrieved, OnResultRetrieved) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void SpeechRecognitionDispatcher::start( + const WebSpeechRecognitionHandle& handle, + const WebSpeechRecognitionParams& params, + WebSpeechRecognizerClient* recognizer_client) { + //TODO(primiano) What to do if a start is issued to an already started object? + DCHECK(!recognizer_client_ || recognizer_client_ == recognizer_client); + recognizer_client_ = recognizer_client; + + SpeechRecognitionHostMsg_StartRequest_Params msg_params; + for (size_t i = 0; i < params.grammars().size(); ++i) { + const WebSpeechGrammar& grammar = params.grammars()[i]; + msg_params.grammars.push_back( + content::SpeechRecognitionGrammar(grammar.src().spec(), + grammar.weight())); + } + msg_params.language = UTF16ToUTF8(params.language()); + msg_params.is_one_shot = !params.continuous(); + msg_params.origin_url = ""; // TODO(primiano) we need an origin from WebKit. + msg_params.render_view_id = routing_id(); + msg_params.request_id = GetIDForHandle(handle); + Send(new SpeechRecognitionHostMsg_StartRequest(msg_params)); +} + +void SpeechRecognitionDispatcher::stop( + const WebSpeechRecognitionHandle& handle, + WebSpeechRecognizerClient* recognizer_client) { + DCHECK(recognizer_client_ == recognizer_client); + Send(new SpeechRecognitionHostMsg_StopCaptureRequest(routing_id(), + GetIDForHandle(handle))); +} + +void SpeechRecognitionDispatcher::abort( + const WebSpeechRecognitionHandle& handle, + WebSpeechRecognizerClient* recognizer_client) { + Send(new SpeechRecognitionHostMsg_AbortRequest(routing_id(), + GetIDForHandle(handle))); +} + +void SpeechRecognitionDispatcher::OnRecognitionStarted(int request_id) { + recognizer_client_->didStart(GetHandleFromID(request_id)); +} + +void SpeechRecognitionDispatcher::OnAudioStarted(int request_id) { + recognizer_client_->didStartAudio(GetHandleFromID(request_id)); +} + +void SpeechRecognitionDispatcher::OnSoundStarted(int request_id) { + recognizer_client_->didStartSound(GetHandleFromID(request_id)); +} + +void SpeechRecognitionDispatcher::OnSoundEnded(int request_id) { + recognizer_client_->didEndSound(GetHandleFromID(request_id)); +} + +void SpeechRecognitionDispatcher::OnAudioEnded(int request_id) { + recognizer_client_->didEndAudio(GetHandleFromID(request_id)); +} + +void SpeechRecognitionDispatcher::OnErrorOccurred( + int request_id, const SpeechRecognitionError& error) { + if (error.code == content::SPEECH_RECOGNITION_ERROR_NO_MATCH) { + recognizer_client_->didReceiveNoMatch(GetHandleFromID(request_id), + WebSpeechRecognitionResult()); + } else { + // TODO(primiano) speech_recognition_error.h must be updated with the new + // API specs soon. + WebSpeechRecognizerClient::ErrorCode wk_error_code; + switch (error.code) { + case content::SPEECH_RECOGNITION_ERROR_ABORTED: + wk_error_code = WebSpeechRecognizerClient::AbortedError; + break; + case content::SPEECH_RECOGNITION_ERROR_AUDIO: + wk_error_code = WebSpeechRecognizerClient::AudioCaptureError; + break; + case content::SPEECH_RECOGNITION_ERROR_NETWORK: + wk_error_code = WebSpeechRecognizerClient::NetworkError; + break; + case content::SPEECH_RECOGNITION_ERROR_NO_SPEECH: + wk_error_code = WebSpeechRecognizerClient::NoSpeechError; + break; + case content::SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR: + wk_error_code = WebSpeechRecognizerClient::BadGrammarError; + break; + default: + NOTREACHED(); + wk_error_code = WebSpeechRecognizerClient::OtherError; + } + recognizer_client_->didReceiveError(GetHandleFromID(request_id), + WebString(), // TODO(primiano) message? + wk_error_code); + } +} + +void SpeechRecognitionDispatcher::OnRecognitionEnded(int request_id) { + recognizer_client_->didEnd(GetHandleFromID(request_id)); + handle_map_.erase(request_id); +} + +void SpeechRecognitionDispatcher::OnResultRetrieved( + int request_id, const SpeechRecognitionResult& result) { + const size_t num_hypotheses = result.hypotheses.size(); + WebSpeechRecognitionResult webkit_result; + WebVector<WebString> transcripts(num_hypotheses); + WebVector<float> confidences(num_hypotheses); + for (size_t i = 0; i < num_hypotheses; ++i) { + transcripts[i] = result.hypotheses[i].utterance; + confidences[i] = static_cast<float>(result.hypotheses[i].confidence); + } + webkit_result.assign(transcripts, confidences, !result.provisional); + // TODO(primiano) Handle history, currently empty. + WebVector<WebSpeechRecognitionResult> empty_history; + recognizer_client_->didReceiveResult(GetHandleFromID(request_id), + webkit_result, + 0, // result_index + empty_history); +} + +int SpeechRecognitionDispatcher::GetIDForHandle( + const WebSpeechRecognitionHandle& handle) { + // Search first for an existing mapping. + for (HandleMap::iterator iter = handle_map_.begin(); + iter != handle_map_.end(); + ++iter) { + if (iter->second.equals(handle)) + return iter->first; + } + // If no existing mapping found, create a new one. + const int new_id = next_id_; + handle_map_[new_id] = handle; + ++next_id_; + return new_id; +} + +const WebSpeechRecognitionHandle& SpeechRecognitionDispatcher::GetHandleFromID( + int request_id) { + HandleMap::iterator iter = handle_map_.find(request_id); + DCHECK(iter != handle_map_.end()); + return iter->second; +} diff --git a/content/renderer/speech_recognition_dispatcher.h b/content/renderer/speech_recognition_dispatcher.h new file mode 100644 index 0000000..3e3b141 --- /dev/null +++ b/content/renderer/speech_recognition_dispatcher.h @@ -0,0 +1,70 @@ +// 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. + +#ifndef CONTENT_RENDERER_SPEECH_RECOGNITION_DISPATCHER_H_ +#define CONTENT_RENDERER_SPEECH_RECOGNITION_DISPATCHER_H_ +#pragma once + +#include <map> + +#include "base/basictypes.h" +#include "content/public/renderer/render_view_observer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechRecognitionHandle.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSpeechRecognizer.h" + +class RenderViewImpl; + +namespace content { +struct SpeechRecognitionError; +struct SpeechRecognitionResult; +} + +// SpeechRecognitionDispatcher is a delegate for methods used by WebKit for +// scripted JS speech APIs. It's the complement of +// SpeechRecognitionDispatcherHost (owned by RenderViewHost). +class SpeechRecognitionDispatcher : public content::RenderViewObserver, + public WebKit::WebSpeechRecognizer { + public: + explicit SpeechRecognitionDispatcher(RenderViewImpl* render_view); + virtual ~SpeechRecognitionDispatcher(); + + private: + // RenderViewObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // WebKit::WebSpeechRecognizer implementation. + virtual void start(const WebKit::WebSpeechRecognitionHandle&, + const WebKit::WebSpeechRecognitionParams&, + WebKit::WebSpeechRecognizerClient*) OVERRIDE; + virtual void stop(const WebKit::WebSpeechRecognitionHandle&, + WebKit::WebSpeechRecognizerClient*) OVERRIDE; + virtual void abort(const WebKit::WebSpeechRecognitionHandle&, + WebKit::WebSpeechRecognizerClient*) OVERRIDE; + + void OnRecognitionStarted(int request_id); + void OnAudioStarted(int request_id); + void OnSoundStarted(int request_id); + void OnSoundEnded(int request_id); + void OnAudioEnded(int request_id); + void OnErrorOccurred(int request_id, + const content::SpeechRecognitionError& error); + void OnRecognitionEnded(int request_id); + void OnResultRetrieved(int request_id, + const content::SpeechRecognitionResult& result); + + int GetIDForHandle(const WebKit::WebSpeechRecognitionHandle& handle); + const WebKit::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id); + + // The WebKit client class that we use to send events back to the JS world. + WebKit::WebSpeechRecognizerClient* recognizer_client_; + + typedef std::map<int, WebKit::WebSpeechRecognitionHandle> HandleMap; + HandleMap handle_map_; + int next_id_; + + DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcher); +}; + +#endif // CONTENT_RENDERER_SPEECH_RECOGNITION_DISPATCHER_H_ |