Add support for x-webkit-speech (issue #758).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1132 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-03-08 00:41:26 +00:00
parent 920ee60499
commit 63f6b6b09a
9 changed files with 316 additions and 2 deletions

View File

@ -894,6 +894,8 @@
'libcef/browser/scheme_impl.cc',
'libcef/browser/scheme_registration.cc',
'libcef/browser/scheme_registration.h',
'libcef/browser/speech_recognition_manager_delegate.cc',
'libcef/browser/speech_recognition_manager_delegate.h',
'libcef/browser/stream_impl.cc',
'libcef/browser/stream_impl.h',
'libcef/browser/trace_impl.cc',

View File

@ -11,8 +11,10 @@
#include "libcef/browser/download_manager_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/url_request_context_getter.h"
#include "libcef/common/cef_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/threading/thread.h"
#include "content/public/browser/download_manager.h"
@ -160,14 +162,19 @@ class CefSpeechRecognitionPreferences
: public content::SpeechRecognitionPreferences {
public:
CefSpeechRecognitionPreferences() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
filter_profanities_ =
command_line.HasSwitch(switches::kEnableProfanityFilter);
}
// Overridden from SpeechRecognitionPreferences:
virtual bool FilterProfanities() const OVERRIDE {
return false;
return filter_profanities_;
}
private:
bool filter_profanities_;
DISALLOW_COPY_AND_ASSIGN(CefSpeechRecognitionPreferences);
};

View File

@ -16,6 +16,7 @@
#include "libcef/browser/context.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/resource_dispatcher_host_delegate.h"
#include "libcef/browser/speech_recognition_manager_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/web_plugin_impl.h"
#include "libcef/common/cef_switches.h"
@ -435,6 +436,7 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
// any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
switches::kContextSafetyImplementation,
switches::kEnableSpeechInput,
switches::kProductVersion,
switches::kUncaughtExceptionStackSize,
};
@ -464,6 +466,17 @@ content::MediaObserver* CefContentBrowserClient::GetMediaObserver() {
return CefMediaCaptureDevicesDispatcher::GetInstance();
}
content::SpeechRecognitionManagerDelegate*
CefContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
#if defined(ENABLE_INPUT_SPEECH)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kEnableSpeechInput))
return new CefSpeechRecognitionManagerDelegate();
#endif
return NULL;
}
content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() {
return new CefAccessTokenStore;
}

View File

@ -97,6 +97,8 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
virtual content::QuotaPermissionContext*
CreateQuotaPermissionContext() OVERRIDE;
virtual content::MediaObserver* GetMediaObserver() OVERRIDE;
virtual content::SpeechRecognitionManagerDelegate*
GetSpeechRecognitionManagerDelegate() OVERRIDE;
virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE;
virtual bool CanCreateWindow(const GURL& opener_url,
const GURL& origin,

View File

@ -0,0 +1,217 @@
// 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 "libcef/browser/speech_recognition_manager_delegate.h"
#include <set>
#include <string>
#include "base/bind.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/speech_recognition_manager.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_result.h"
using content::BrowserThread;
using content::SpeechRecognitionManager;
using content::WebContents;
// Simple utility to get notified when a WebContents is closed or crashes.
// Both the callback site and the callback thread are passed by the caller in
// the constructor. There is no restriction on the constructor, however this
// class must be destroyed on the UI thread, due to the NotificationRegistrar
// dependency.
class CefSpeechRecognitionManagerDelegate::WebContentsWatcher
: public base::RefCountedThreadSafe<WebContentsWatcher>,
public content::NotificationObserver {
public:
typedef base::Callback<void(int render_process_id, int render_view_id)>
WebContentsClosedCallback;
WebContentsWatcher(WebContentsClosedCallback web_contents_closed_callback,
BrowserThread::ID callback_thread)
: web_contents_closed_callback_(web_contents_closed_callback),
callback_thread_(callback_thread) {
}
// Starts monitoring the WebContents corresponding to the given
// |render_process_id|, |render_view_id| pair, invoking
// |web_contents_closed_callback_| if closed/unloaded.
void Watch(int render_process_id, int render_view_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&WebContentsWatcher::Watch, this, render_process_id, render_view_id));
return;
}
WebContents* web_contents = NULL;
content::RenderViewHost* render_view_host =
content::RenderViewHost::FromID(render_process_id, render_view_id);
if (render_view_host)
web_contents = WebContents::FromRenderViewHost(render_view_host);
DCHECK(web_contents);
// Avoid multiple registrations on |registrar_| for the same |web_contents|.
if (registered_web_contents_.find(web_contents) !=
registered_web_contents_.end()) {
return;
}
registered_web_contents_.insert(web_contents);
// Lazy initialize the registrar.
if (!registrar_.get())
registrar_.reset(new content::NotificationRegistrar());
registrar_->Add(this,
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::Source<WebContents>(web_contents));
}
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, type);
WebContents* web_contents = content::Source<WebContents>(source).ptr();
int render_process_id = web_contents->GetRenderProcessHost()->GetID();
int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
registrar_->Remove(this,
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::Source<WebContents>(web_contents));
registered_web_contents_.erase(web_contents);
BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind(
web_contents_closed_callback_, render_process_id, render_view_id));
}
private:
friend class base::RefCountedThreadSafe<WebContentsWatcher>;
virtual ~WebContentsWatcher() {
// Must be destroyed on the UI thread due to |registrar_| non thread-safety.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
// Lazy-initialized and used on the UI thread to handle web contents
// notifications (tab closing).
scoped_ptr<content::NotificationRegistrar> registrar_;
// Keeps track of which WebContent(s) have been registered, in order to avoid
// double registrations on |registrar_|
std::set<content::WebContents*> registered_web_contents_;
// Callback used to notify, on the thread specified by |callback_thread_| the
// closure of a registered tab.
WebContentsClosedCallback web_contents_closed_callback_;
content::BrowserThread::ID callback_thread_;
DISALLOW_COPY_AND_ASSIGN(WebContentsWatcher);
};
CefSpeechRecognitionManagerDelegate
::CefSpeechRecognitionManagerDelegate() {
}
CefSpeechRecognitionManagerDelegate
::~CefSpeechRecognitionManagerDelegate() {
}
void CefSpeechRecognitionManagerDelegate::WebContentsClosedCallback(
int render_process_id, int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance();
// |manager| becomes NULL if a browser shutdown happens between the post of
// this task (from the UI thread) and this call (on the IO thread). In this
// case we just return.
if (!manager)
return;
manager->AbortAllSessionsForRenderView(render_process_id, render_view_id);
}
void CefSpeechRecognitionManagerDelegate::OnRecognitionStart(
int session_id) {
const content::SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
// Register callback to auto abort session on tab closure.
// |web_contents_watcher_| is lazyly istantiated on the first call.
if (!web_contents_watcher_.get()) {
web_contents_watcher_ = new WebContentsWatcher(
base::Bind(
&CefSpeechRecognitionManagerDelegate::WebContentsClosedCallback,
base::Unretained(this)),
BrowserThread::IO);
}
web_contents_watcher_->Watch(context.render_process_id,
context.render_view_id);
}
void CefSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
}
void CefSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete(
int session_id) {
}
void CefSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) {
}
void CefSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) {
}
void CefSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) {
}
void CefSpeechRecognitionManagerDelegate::OnRecognitionResults(
int session_id, const content::SpeechRecognitionResults& result) {
}
void CefSpeechRecognitionManagerDelegate::OnRecognitionError(
int session_id, const content::SpeechRecognitionError& error) {
}
void CefSpeechRecognitionManagerDelegate::OnAudioLevelsChange(
int session_id, float volume, float noise_volume) {
}
void CefSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) {
}
void CefSpeechRecognitionManagerDelegate::GetDiagnosticInformation(
bool* can_report_metrics,
std::string* hardware_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
void CefSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed(
int session_id,
base::Callback<void(bool ask_user, bool is_allowed)> callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
const content::SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
// Make sure that initiators properly set the |render_process_id| field.
DCHECK_NE(context.render_process_id, 0);
callback.Run(false, true);
}
content::SpeechRecognitionEventListener*
CefSpeechRecognitionManagerDelegate::GetEventListener() {
return this;
}

View File

@ -0,0 +1,61 @@
// 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 CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_
#define CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/browser/speech_recognition_manager_delegate.h"
// This is CEF's implementation of the SpeechRecognitionManagerDelegate
// interface. Based on chrome/browser/speech/
// chrome_speech_recognition_manager_delegate.[cc|h]
class CefSpeechRecognitionManagerDelegate
: NON_EXPORTED_BASE(public content::SpeechRecognitionManagerDelegate),
public content::SpeechRecognitionEventListener {
public:
CefSpeechRecognitionManagerDelegate();
virtual ~CefSpeechRecognitionManagerDelegate();
protected:
// SpeechRecognitionEventListener methods.
virtual void OnRecognitionStart(int session_id) OVERRIDE;
virtual void OnAudioStart(int session_id) OVERRIDE;
virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE;
virtual void OnSoundStart(int session_id) OVERRIDE;
virtual void OnSoundEnd(int session_id) OVERRIDE;
virtual void OnAudioEnd(int session_id) OVERRIDE;
virtual void OnRecognitionEnd(int session_id) OVERRIDE;
virtual void OnRecognitionResults(
int session_id, const content::SpeechRecognitionResults& result) OVERRIDE;
virtual void OnRecognitionError(
int session_id, const content::SpeechRecognitionError& error) OVERRIDE;
virtual void OnAudioLevelsChange(int session_id, float volume,
float noise_volume) OVERRIDE;
// SpeechRecognitionManagerDelegate methods.
virtual void GetDiagnosticInformation(bool* can_report_metrics,
std::string* hardware_info) OVERRIDE;
virtual void CheckRecognitionIsAllowed(
int session_id,
base::Callback<void(bool ask_user, bool is_allowed)> callback) OVERRIDE;
virtual content::SpeechRecognitionEventListener* GetEventListener() OVERRIDE;
private:
class WebContentsWatcher;
// Callback called by |web_contents_watcher_| on the IO thread to signal
// web contents closure.
void WebContentsClosedCallback(int render_process_id, int render_view_id);
scoped_refptr<WebContentsWatcher> web_contents_watcher_;
DISALLOW_COPY_AND_ASSIGN(CefSpeechRecognitionManagerDelegate);
};
#endif // CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_

View File

@ -89,4 +89,10 @@ const char kPersistSessionCookies[] = "persist-session-cookies";
// Enable media (WebRTC audio/video) streaming.
const char kEnableMediaStream[] = "enable-media-stream";
// Enable speech input (x-webkit-speech).
const char kEnableSpeechInput[] = "enable-speech-input";
// Enable the speech input profanity filter.
const char kEnableProfanityFilter[] = "enable-profanity-filter";
} // namespace switches

View File

@ -40,6 +40,8 @@ extern const char kDisableAuthorAndUserStyles[];
extern const char kDisableDeveloperTools[];
extern const char kPersistSessionCookies[];
extern const char kEnableMediaStream[];
extern const char kEnableSpeechInput[];
extern const char kEnableProfanityFilter[];
} // namespace switches

View File

@ -272,12 +272,17 @@ void CefContentRendererClient::AddCustomScheme(
}
void CefContentRendererClient::WebKitInitialized() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
WebKit::WebRuntimeFeatures::enableMediaPlayer(
media::IsMediaLibraryInitialized());
// TODO(cef): Enable these once the implementation supports it.
WebKit::WebRuntimeFeatures::enableNotifications(false);
WebKit::WebRuntimeFeatures::enableSpeechInput(
command_line.HasSwitch(switches::kEnableSpeechInput));
worker_script_observer_.reset(new CefWebWorkerScriptObserver());
WebKit::WebWorkerInfo::addScriptObserver(worker_script_observer_.get());
@ -313,7 +318,6 @@ void CefContentRendererClient::WebKitInitialized() {
}
// The number of stack trace frames to capture for uncaught exceptions.
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kUncaughtExceptionStackSize)) {
int uncaught_exception_stack_size = 0;
base::StringToInt(