summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc6
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rw-r--r--chrome/browser/speech/speech_input_browsertest.cc103
-rw-r--r--chrome/browser/speech/speech_input_dispatcher_host.cc101
-rw-r--r--chrome/browser/speech/speech_input_dispatcher_host.h63
-rw-r--r--chrome/browser/speech/speech_input_manager.cc14
-rw-r--r--chrome/browser/speech/speech_input_manager.h44
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/render_messages_internal.h31
-rw-r--r--chrome/renderer/render_view.cc12
-rw-r--r--chrome/renderer/render_view.h8
-rw-r--r--chrome/renderer/speech_input_dispatcher.cc61
-rw-r--r--chrome/renderer/speech_input_dispatcher.h46
-rw-r--r--chrome/test/data/speech/basic_recognition.html30
16 files changed, 533 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index a8253e6..0c5fc51 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -50,6 +50,7 @@
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
+#include "chrome/browser/speech/speech_input_dispatcher_host.h"
#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/task_manager.h"
#include "chrome/browser/worker_host/message_port_dispatcher.h"
@@ -230,6 +231,8 @@ ResourceMessageFilter::ResourceMessageFilter(
off_the_record_(profile->IsOffTheRecord()),
next_route_id_callback_(NewCallbackWithReturnValue(
render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(speech_input_dispatcher_host_(
+ new speech_input::SpeechInputDispatcherHost(this->id()))),
ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_dispatcher_host_(
GeolocationDispatcherHost::New(
this->id(), profile->GetGeolocationPermissionContext()))) {
@@ -332,7 +335,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
db_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) ||
mp_dispatcher->OnMessageReceived(
msg, this, next_route_id_callback(), &msg_is_ok) ||
- geolocation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok);
+ geolocation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) ||
+ speech_input_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok);
if (!handled) {
DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK.
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index d5cd9d9..317f55e 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -62,6 +62,10 @@ class PrinterQuery;
class PrintJobManager;
}
+namespace speech_input {
+class SpeechInputDispatcherHost;
+}
+
namespace webkit_glue {
struct WebCookie;
}
@@ -441,6 +445,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// A callback to create a routing id for the associated renderer process.
scoped_ptr<CallbackWithReturnValue<int>::Type> next_route_id_callback_;
+ // Used to handle speech input related messages.
+ scoped_refptr<speech_input::SpeechInputDispatcherHost>
+ speech_input_dispatcher_host_;
+
// Used to handle geolocation-related messages.
scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher_host_;
diff --git a/chrome/browser/speech/speech_input_browsertest.cc b/chrome/browser/speech/speech_input_browsertest.cc
new file mode 100644
index 0000000..b451934
--- /dev/null
+++ b/chrome/browser/speech/speech_input_browsertest.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2010 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 "base/command_line.h"
+#include "base/file_path.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/speech/speech_input_dispatcher_host.h"
+#include "chrome/browser/speech/speech_input_manager.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace speech_input {
+class FakeSpeechInputManager;
+}
+
+// This class does not need to be refcounted (typically done by PostTask) since
+// it will outlive the test and gets released only when the test shuts down.
+// Disabling refcounting here saves a bit of unnecessary code and the factory
+// method can return a plain pointer below as required by the real code.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(speech_input::FakeSpeechInputManager);
+
+namespace speech_input {
+
+const char* kTestResult = "Pictures of the moon";
+
+class FakeSpeechInputManager : public SpeechInputManager {
+ public:
+ explicit FakeSpeechInputManager(Listener* listener)
+ : render_view_id_(0),
+ listener_(listener) {
+ }
+
+ // SpeechInputManager methods.
+ void StartRecognition(int render_view_id) {
+ EXPECT_EQ(0, render_view_id_);
+ render_view_id_ = render_view_id;
+ // Give the fake result in a short while.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &FakeSpeechInputManager::SetFakeRecognitionResult));
+ }
+ void CancelRecognition(int render_view_id) {
+ EXPECT_EQ(render_view_id_, render_view_id);
+ render_view_id_ = 0;
+ }
+ void StopRecording(int render_view_id) {
+ EXPECT_EQ(render_view_id_, render_view_id);
+ // Nothing to do here since we aren't really recording.
+ }
+
+ private:
+ void SetFakeRecognitionResult() {
+ if (render_view_id_) { // Do a check in case we were cancelled..
+ listener_->DidCompleteRecording(render_view_id_);
+ listener_->SetRecognitionResult(render_view_id_,
+ ASCIIToUTF16(kTestResult));
+ listener_->DidCompleteRecognition(render_view_id_);
+ render_view_id_ = 0;
+ }
+ }
+
+ int render_view_id_;
+ Listener* listener_;
+};
+
+// Factory method.
+SpeechInputManager* fakeManagerFactory(SpeechInputManager::Listener* listener) {
+ return new FakeSpeechInputManager(listener);
+}
+
+class SpeechInputBrowserTest : public InProcessBrowserTest {
+ public:
+ // InProcessBrowserTest methods
+ virtual void SetUpCommandLine(CommandLine* command_line) {
+ command_line->AppendSwitch(switches::kEnableSpeechInput);
+ }
+
+ GURL testUrl(const FilePath::CharType* filename) {
+ const FilePath kTestDir(FILE_PATH_LITERAL("speech"));
+ return ui_test_utils::GetTestUrl(kTestDir, FilePath(filename));
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SpeechInputBrowserTest, TestBasicRecognition) {
+ // Inject the fake manager factory so that the test result is returned to the
+ // web page.
+ SpeechInputDispatcherHost::set_manager_factory(&fakeManagerFactory);
+
+ // The test page starts speech recognition and waits to receive the above
+ // defined test string as the result. Once it receives the result it either
+ // navigates to #pass or #fail depending on the result.
+ GURL test_url = testUrl(FILE_PATH_LITERAL("basic_recognition.html"));
+ ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(),
+ test_url,
+ 2);
+
+ // Check that the page got the result it expected.
+ EXPECT_EQ("pass", browser()->GetSelectedTabContents()->GetURL().ref());
+}
+
+} // namespace speech_input
diff --git a/chrome/browser/speech/speech_input_dispatcher_host.cc b/chrome/browser/speech/speech_input_dispatcher_host.cc
new file mode 100644
index 0000000..8346cbe
--- /dev/null
+++ b/chrome/browser/speech/speech_input_dispatcher_host.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 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 "chrome/browser/speech/speech_input_dispatcher_host.h"
+
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
+#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/common/render_messages.h"
+
+namespace speech_input {
+
+SpeechInputManager::FactoryMethod*
+ SpeechInputDispatcherHost::manager_factory_ = &SpeechInputManager::Create;
+
+SpeechInputDispatcherHost::SpeechInputDispatcherHost(
+ int resource_message_filter_process_id)
+ : resource_message_filter_process_id_(resource_message_filter_process_id) {
+ // This is initialized by ResourceMessageFilter. Do not add any non-trivial
+ // initialization here, instead do it lazily when required (e.g. see the
+ // method |manager()|) or add an Init() method.
+}
+
+SpeechInputDispatcherHost::~SpeechInputDispatcherHost() {
+}
+
+SpeechInputManager* SpeechInputDispatcherHost::manager() {
+ if (!manager_.get()) {
+ manager_.reset((*manager_factory_)(this));
+ DCHECK(manager_.get());
+ }
+ return manager_.get();
+}
+
+bool SpeechInputDispatcherHost::OnMessageReceived(
+ const IPC::Message& msg, bool* msg_was_ok) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, msg, *msg_was_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StartRecognition,
+ OnStartRecognition)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_CancelRecognition,
+ OnCancelRecognition)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StopRecording,
+ OnStopRecording)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void SpeechInputDispatcherHost::OnStartRecognition(int render_view_id) {
+ LOG(INFO) << "SpeechInputDispatcherHost: start recognition"
+ << render_view_id;
+ manager()->StartRecognition(render_view_id);
+}
+
+void SpeechInputDispatcherHost::OnCancelRecognition(int render_view_id) {
+ LOG(INFO) << "SpeechInputDispatcherHost: cancel recognition"
+ << render_view_id;
+ manager()->CancelRecognition(render_view_id);
+}
+
+void SpeechInputDispatcherHost::OnStopRecording(int render_view_id) {
+ LOG(INFO) << "SpeechInputDispatcherHost: stop recording"
+ << render_view_id;
+ manager()->StopRecording(render_view_id);
+}
+
+void SpeechInputDispatcherHost::SendMessageToRenderView(IPC::Message* message,
+ int render_view_id) {
+ CallRenderViewHost(
+ resource_message_filter_process_id_, render_view_id,
+ &RenderViewHost::Send, message);
+}
+
+
+void SpeechInputDispatcherHost::SetRecognitionResult(int render_view_id,
+ const string16& result) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ SendMessageToRenderView(
+ new ViewMsg_SpeechInput_SetRecognitionResult(render_view_id, result),
+ render_view_id);
+}
+
+void SpeechInputDispatcherHost::DidCompleteRecording(int render_view_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ SendMessageToRenderView(
+ new ViewMsg_SpeechInput_RecordingComplete(render_view_id),
+ render_view_id);
+}
+
+void SpeechInputDispatcherHost::DidCompleteRecognition(int render_view_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ SendMessageToRenderView(
+ new ViewMsg_SpeechInput_RecognitionComplete(render_view_id),
+ render_view_id);
+}
+
+} // namespace speech_input
diff --git a/chrome/browser/speech/speech_input_dispatcher_host.h b/chrome/browser/speech/speech_input_dispatcher_host.h
new file mode 100644
index 0000000..45f9c98
--- /dev/null
+++ b/chrome/browser/speech/speech_input_dispatcher_host.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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 CHROME_BROWSER_SPEECH_SPEECH_INPUT_DISPATCHER_HOST_H_
+#define CHROME_BROWSER_SPEECH_SPEECH_INPUT_DISPATCHER_HOST_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "ipc/ipc_message.h"
+#include "speech_input_manager.h"
+
+namespace speech_input {
+
+// SpeechInputDispatcherHost is a delegate for Speech API messages used by
+// ResourceMessageFilter.
+// It's the complement of SpeechInputDispatcher (owned by RenderView).
+class SpeechInputDispatcherHost
+ : public base::RefCountedThreadSafe<SpeechInputDispatcherHost>,
+ public SpeechInputManager::Listener {
+ public:
+ explicit SpeechInputDispatcherHost(int resource_message_filter_process_id);
+
+ // SpeechInputManager::Listener methods.
+ void SetRecognitionResult(int render_view_id, const string16& result);
+ void DidCompleteRecording(int render_view_id);
+ void DidCompleteRecognition(int render_view_id);
+
+ // Called to possibly handle the incoming IPC message. Returns true if
+ // handled.
+ bool OnMessageReceived(const IPC::Message& msg, bool* msg_was_ok);
+
+ // Factory setter useful for tests.
+ static void set_manager_factory(SpeechInputManager::FactoryMethod* factory) {
+ manager_factory_ = factory;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<SpeechInputDispatcherHost>;
+ virtual ~SpeechInputDispatcherHost();
+ void SendMessageToRenderView(IPC::Message* message, int render_view_id);
+
+ void OnStartRecognition(int render_view_id);
+ void OnCancelRecognition(int render_view_id);
+ void OnStopRecording(int render_view_id);
+
+ // Returns the speech input manager to forward events to, creating one if
+ // needed.
+ SpeechInputManager* manager();
+
+ int resource_message_filter_process_id_;
+
+ scoped_ptr<SpeechInputManager> manager_;
+
+ static SpeechInputManager::FactoryMethod* manager_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechInputDispatcherHost);
+};
+
+} // namespace speech_input
+
+#endif // CHROME_BROWSER_SPEECH_SPEECH_INPUT_DISPATCHER_HOST_H_
diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc
new file mode 100644
index 0000000..f75a839
--- /dev/null
+++ b/chrome/browser/speech/speech_input_manager.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2010 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 "chrome/browser/speech/speech_input_manager.h"
+
+namespace speech_input {
+
+SpeechInputManager* SpeechInputManager::Create(Listener* listener) {
+ // TODO(satish): Implement a real speech input manager.
+ return NULL;
+}
+
+} // namespace speech_input
diff --git a/chrome/browser/speech/speech_input_manager.h b/chrome/browser/speech/speech_input_manager.h
new file mode 100644
index 0000000..39f0d89
--- /dev/null
+++ b/chrome/browser/speech/speech_input_manager.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2010 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 CHROME_BROWSER_SPEECH_SPEECH_INPUT_MANAGER_H_
+#define CHROME_BROWSER_SPEECH_SPEECH_INPUT_MANAGER_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ipc/ipc_message.h"
+
+namespace speech_input {
+
+// This is the gatekeeper for speech recognition in the browser process. It
+// handles requests received from various render views and makes sure only one
+// of them can use speech recognition at a time. It also sends recognition
+// results and status events to the render views when required.
+class SpeechInputManager {
+ public:
+ // Implemented by the dispatcher host to relay events to the render views.
+ class Listener {
+ public:
+ virtual void SetRecognitionResult(int render_view_id,
+ const string16& value) = 0;
+ virtual void DidCompleteRecording(int render_view_id) = 0;
+ virtual void DidCompleteRecognition(int render_view_id) = 0;
+ };
+
+ // Factory method to create new instances.
+ static SpeechInputManager* Create(Listener* listener);
+ // Factory method definition useful for tests.
+ typedef SpeechInputManager* (FactoryMethod)(Listener*);
+
+ virtual ~SpeechInputManager() {}
+
+ // Handlers for requests from render views.
+ virtual void StartRecognition(int render_view_id) = 0;
+ virtual void CancelRecognition(int render_view_id) = 0;
+ virtual void StopRecording(int render_view_id) = 0;
+};
+
+} // namespace speech_input
+
+#endif // CHROME_BROWSER_SPEECH_SPEECH_INPUT_MANAGER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a96d688..5780bd3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2316,6 +2316,10 @@
'browser/shell_integration_mac.mm',
'browser/shell_integration_linux.cc',
'browser/shell_integration_win.cc',
+ 'browser/speech/speech_input_dispatcher_host.cc',
+ 'browser/speech/speech_input_dispatcher_host.h',
+ 'browser/speech/speech_input_manager.cc',
+ 'browser/speech/speech_input_manager.h',
'browser/spellcheck_host.cc',
'browser/spellcheck_host.h',
'browser/spellchecker_linux.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index cb2b417..a775909 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -172,6 +172,8 @@
'renderer/safe_browsing/phishing_dom_feature_extractor.h',
'renderer/safe_browsing/phishing_url_feature_extractor.cc',
'renderer/safe_browsing/phishing_url_feature_extractor.h',
+ 'renderer/speech_input_dispatcher.cc',
+ 'renderer/speech_input_dispatcher.h',
'renderer/spellchecker/spellcheck.cc',
'renderer/spellchecker/spellcheck.h',
'renderer/spellchecker/spellcheck_worditerator.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index c33e615..a547fac 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1613,6 +1613,7 @@
'browser/safe_browsing/safe_browsing_browsertest.cc',
'browser/sessions/session_restore_browsertest.cc',
'browser/speech/enable_speech_input_switch_browsertest.cc',
+ 'browser/speech/speech_input_browsertest.cc',
'browser/ssl/ssl_browser_tests.cc',
'browser/task_manager_browsertest.cc',
'browser/views/browser_actions_container_browsertest.cc',
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 76d2585..66ce013 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -976,6 +976,19 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_ROUTED1(ViewMsg_AccessibilityDoDefaultAction,
int /* object id */)
+ // Relay a speech recognition result, either partial or final.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SpeechInput_SetRecognitionResult,
+ string16 /* result */)
+
+ // Indicate that speech recognizer has stopped recording and started
+ // recognition.
+ IPC_MESSAGE_ROUTED0(ViewMsg_SpeechInput_RecordingComplete)
+
+ // Indicate that speech recognizer has completed recognition. This will be
+ // the last message sent in response to a
+ // ViewHostMsg_SpeechInput_StartRecognition.
+ IPC_MESSAGE_ROUTED0(ViewMsg_SpeechInput_RecognitionComplete)
+
IPC_END_MESSAGES(View)
@@ -2539,4 +2552,22 @@ IPC_BEGIN_MESSAGES(ViewHost)
// This allows the browser to handle things such as zooming differently.
IPC_MESSAGE_ROUTED0(ViewHostMsg_SetDisplayingPDFContent)
+ // Requests the speech input service to start speech recognition on behalf of
+ // the given |render_view_id|.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SpeechInput_StartRecognition,
+ int /* render_view_id */)
+
+ // Requests the speech input service to cancel speech recognition on behalf of
+ // the given |render_view_id|. If speech recognition is not happening nor or
+ // is happening on behalf of some other render view, this call does nothing.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SpeechInput_CancelRecognition,
+ int /* render_view_id */)
+
+ // Requests the speech input service to stop audio recording on behalf of
+ // the given |render_view_id|. Any audio recorded so far will be fed to the
+ // speech recognizer. If speech recognition is not happening nor or is
+ // happening on behalf of some other render view, this call does nothing.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_SpeechInput_StopRecording,
+ int /* render_view_id */)
+
IPC_END_MESSAGES(ViewHost)
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 39c4193..9d97ee2 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -61,6 +61,7 @@
#include "chrome/renderer/render_view_visitor.h"
#include "chrome/renderer/renderer_webapplicationcachehost_impl.h"
#include "chrome/renderer/renderer_webstoragenamespace_impl.h"
+#include "chrome/renderer/speech_input_dispatcher.h"
#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/renderer/user_script_slave.h"
#include "chrome/renderer/visitedlink_slave.h"
@@ -628,6 +629,10 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
geolocation_dispatcher_->OnMessageReceived(message)) {
return;
}
+ if (speech_input_dispatcher_.get() &&
+ speech_input_dispatcher_->OnMessageReceived(message)) {
+ return;
+ }
IPC_BEGIN_MESSAGE_MAP(RenderView, message)
IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, OnCaptureThumbnail)
@@ -5258,6 +5263,13 @@ WebKit::WebGeolocationService* RenderView::geolocationService() {
return geolocation_dispatcher_.get();
}
+WebKit::WebSpeechInputController* RenderView::speechInputController(
+ WebKit::WebSpeechInputListener* listener) {
+ if (!speech_input_dispatcher_.get())
+ speech_input_dispatcher_.reset(new SpeechInputDispatcher(this, listener));
+ return speech_input_dispatcher_.get();
+}
+
bool RenderView::IsNonLocalTopLevelNavigation(
const GURL& url, WebKit::WebFrame* frame, WebKit::WebNavigationType type) {
// Must be a top level frame.
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 3d3cdbd..18f5fe2 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -67,6 +67,7 @@ class PepperDeviceTest;
class PrintWebViewHelper;
class RenderViewVisitor;
class SkBitmap;
+class SpeechInputDispatcher;
class WebPluginDelegatePepper;
class WebPluginDelegateProxy;
struct ContextMenuMediaParams;
@@ -107,6 +108,8 @@ class WebMediaPlayer;
class WebMediaPlayerClient;
class WebNode;
class WebPlugin;
+class WebSpeechInputController;
+class WebSpeechInputListener;
class WebStorageNamespace;
class WebURLRequest;
class WebView;
@@ -414,6 +417,8 @@ class RenderView : public RenderWidget,
virtual void didAcceptAutocompleteSuggestion(
const WebKit::WebInputElement& element);
virtual WebKit::WebGeolocationService* geolocationService();
+ virtual WebKit::WebSpeechInputController* speechInputController(
+ WebKit::WebSpeechInputListener* listener);
// WebKit::WebFrameClient implementation -------------------------------------
@@ -1207,6 +1212,9 @@ class RenderView : public RenderWidget,
// maintains the cache and other features of the accessibility tree.
scoped_ptr<WebKit::WebAccessibilityCache> accessibility_;
+ // The speech dispatcher attached to this view, lazily initialized.
+ scoped_ptr<SpeechInputDispatcher> speech_input_dispatcher_;
+
// Misc ----------------------------------------------------------------------
// The current and pending file chooser completion objects. If the queue is
diff --git a/chrome/renderer/speech_input_dispatcher.cc b/chrome/renderer/speech_input_dispatcher.cc
new file mode 100644
index 0000000..70989d6
--- /dev/null
+++ b/chrome/renderer/speech_input_dispatcher.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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 "chrome/renderer/speech_input_dispatcher.h"
+
+#include "chrome/renderer/render_view.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSpeechInputListener.h"
+
+using WebKit::WebFrame;
+
+SpeechInputDispatcher::SpeechInputDispatcher(
+ RenderView* render_view, WebKit::WebSpeechInputListener* listener)
+ : render_view_(render_view),
+ listener_(listener) {
+}
+
+bool SpeechInputDispatcher::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(SpeechInputDispatcher, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_SpeechInput_SetRecognitionResult,
+ OnSpeechRecognitionResult)
+ IPC_MESSAGE_HANDLER(ViewMsg_SpeechInput_RecordingComplete,
+ OnSpeechRecordingComplete)
+ IPC_MESSAGE_HANDLER(ViewMsg_SpeechInput_RecognitionComplete,
+ OnSpeechRecognitionComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool SpeechInputDispatcher::startRecognition() {
+ render_view_->Send(new ViewHostMsg_SpeechInput_StartRecognition(
+ render_view_->routing_id()));
+ return true;
+}
+
+void SpeechInputDispatcher::cancelRecognition() {
+ render_view_->Send(new ViewHostMsg_SpeechInput_CancelRecognition(
+ render_view_->routing_id()));
+}
+
+void SpeechInputDispatcher::stopRecording() {
+ render_view_->Send(new ViewHostMsg_SpeechInput_StopRecording(
+ render_view_->routing_id()));
+}
+
+void SpeechInputDispatcher::OnSpeechRecognitionResult(
+ const string16& result) {
+ listener_->setRecognitionResult(result);
+}
+
+void SpeechInputDispatcher::OnSpeechRecordingComplete() {
+ listener_->didCompleteRecording();
+}
+
+void SpeechInputDispatcher::OnSpeechRecognitionComplete() {
+ listener_->didCompleteRecognition();
+}
diff --git a/chrome/renderer/speech_input_dispatcher.h b/chrome/renderer/speech_input_dispatcher.h
new file mode 100644
index 0000000..ccb69a9
--- /dev/null
+++ b/chrome/renderer/speech_input_dispatcher.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2010 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 CHROME_RENDERER_SPEECH_INPUT_DISPATCHER_H_
+#define CHROME_RENDERER_SPEECH_INPUT_DISPATCHER_H_
+
+#include "base/basictypes.h"
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSpeechInputController.h"
+
+class GURL;
+class RenderView;
+
+namespace WebKit {
+class WebSpeechInputListener;
+}
+
+// SpeechInputDispatcher is a delegate for speech input messages used by WebKit.
+// It's the complement of SpeechInputDispatcherHost (owned by RenderViewHost).
+class SpeechInputDispatcher : public WebKit::WebSpeechInputController {
+ public:
+ SpeechInputDispatcher(RenderView* render_view,
+ WebKit::WebSpeechInputListener* listener);
+
+ // Called to possibly handle the incoming IPC message. Returns true if
+ // handled. Called in render thread.
+ bool OnMessageReceived(const IPC::Message& msg);
+
+ // WebKit::WebSpeechInputController.
+ bool startRecognition();
+ void cancelRecognition();
+ void stopRecording();
+
+ private:
+ void OnSpeechRecognitionResult(const string16& result);
+ void OnSpeechRecordingComplete();
+ void OnSpeechRecognitionComplete();
+
+ RenderView* render_view_;
+ WebKit::WebSpeechInputListener* listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechInputDispatcher);
+};
+
+#endif // CHROME_RENDERER_SPEECH_INPUT_DISPATCHER_H_
diff --git a/chrome/test/data/speech/basic_recognition.html b/chrome/test/data/speech/basic_recognition.html
new file mode 100644
index 0000000..ef0ccb1
--- /dev/null
+++ b/chrome/test/data/speech/basic_recognition.html
@@ -0,0 +1,30 @@
+<html>
+ <head>
+ <title>Speech input test</title>
+ <script type="text/javascript">
+ function onspeechresult(value) {
+ if (value == "Pictures of the moon") {
+ document.getElementById('status').innerHTML = 'PASS';
+ document.location = '#pass';
+ } else {
+ document.location = '#fail';
+ }
+ }
+ function run() {
+ // Send a click to the right corner of the input field where the speech
+ // button is rendered.
+ var inputField = document.getElementById('inputField');
+ var evt = document.createEvent('MouseEvents');
+ evt.initMouseEvent('click', true, true, window,
+ 0, 0, 0,
+ inputField.offsetWidth - 4, 4,
+ false, false, false, false, 0, null);
+ inputField.dispatchEvent(evt);
+ }
+ </script>
+ </head>
+ <body onLoad="run()">
+ <input id='inputField' speech onchange="onspeechresult(this.value);"><br>
+ <div id="status">FAIL</div>
+ </body>
+</html>