This source file includes following definitions.
- TabClosedCallbackOnIOThread
- OptionalRequestInfo
- Refresh
- CheckUMAAndGetHardwareInfo
- GetHardwareInfo
- value
- can_report_metrics
- TabWatcher
- Watch
- Observe
- FindWebContents
- ChromeSpeechRecognitionManagerDelegate
- ChromeSpeechRecognitionManagerDelegate
- TabClosedCallback
- OnRecognitionStart
- OnAudioStart
- OnEnvironmentEstimationComplete
- OnSoundStart
- OnSoundEnd
- OnAudioEnd
- OnRecognitionResults
- OnRecognitionError
- OnAudioLevelsChange
- OnRecognitionEnd
- GetDiagnosticInformation
- CheckRecognitionIsAllowed
- GetEventListener
- FilterProfanities
- CheckRenderViewType
#include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h"
#include <set>
#include <string>
#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.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/resource_context.h"
#include "content/public/browser/speech_recognition_manager.h"
#include "content/public/browser/speech_recognition_session_config.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"
#include "extensions/browser/view_type_utils.h"
#include "net/url_request/url_request_context_getter.h"
#if defined(OS_WIN)
#include "chrome/installer/util/wmi.h"
#endif
using content::BrowserThread;
using content::SpeechRecognitionManager;
using content::WebContents;
namespace speech {
namespace {
void TabClosedCallbackOnIOThread(int render_process_id, int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance();
if (!manager)
return;
manager->AbortAllSessionsForRenderView(render_process_id, render_view_id);
}
}
class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo
: public base::RefCountedThreadSafe<OptionalRequestInfo> {
public:
OptionalRequestInfo() : can_report_metrics_(false) {
}
void Refresh() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&OptionalRequestInfo::CheckUMAAndGetHardwareInfo, this));
}
void CheckUMAAndGetHardwareInfo() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
#if !defined(OS_CHROMEOS)
if (g_browser_process->local_state()->GetBoolean(
prefs::kMetricsReportingEnabled)) {
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&OptionalRequestInfo::GetHardwareInfo, this));
}
#endif
}
void GetHardwareInfo() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::AutoLock lock(lock_);
can_report_metrics_ = true;
base::string16 device_model =
SpeechRecognitionManager::GetInstance()->GetAudioInputDeviceModel();
#if defined(OS_WIN)
value_ = base::UTF16ToUTF8(
installer::WMIComputerSystem::GetModel() + L"|" + device_model);
#else
value_ = base::UTF16ToUTF8(device_model);
#endif
}
std::string value() {
base::AutoLock lock(lock_);
return value_;
}
bool can_report_metrics() {
base::AutoLock lock(lock_);
return can_report_metrics_;
}
private:
friend class base::RefCountedThreadSafe<OptionalRequestInfo>;
~OptionalRequestInfo() {}
base::Lock lock_;
std::string value_;
bool can_report_metrics_;
DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo);
};
class ChromeSpeechRecognitionManagerDelegate::TabWatcher
: public base::RefCountedThreadSafe<TabWatcher>,
public content::NotificationObserver {
public:
typedef base::Callback<void(int render_process_id, int render_view_id)>
TabClosedCallback;
explicit TabWatcher(TabClosedCallback tab_closed_callback)
: tab_closed_callback_(tab_closed_callback) {
}
void Watch(int render_process_id, int render_view_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&TabWatcher::Watch, this, render_process_id, render_view_id));
return;
}
WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id,
render_view_id);
if (!web_contents)
return;
if (FindWebContents(web_contents) != registered_web_contents_.end()) {
return;
}
registered_web_contents_.push_back(
WebContentsInfo(web_contents, render_process_id, render_view_id));
if (!registrar_.get())
registrar_.reset(new content::NotificationRegistrar());
registrar_->Add(this,
content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
content::Source<WebContents>(web_contents));
registrar_->Add(this,
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::Source<WebContents>(web_contents));
}
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED ||
type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED);
WebContents* web_contents = content::Source<WebContents>(source).ptr();
std::vector<WebContentsInfo>::iterator iter = FindWebContents(web_contents);
DCHECK(iter != registered_web_contents_.end());
int render_process_id = iter->render_process_id;
int render_view_id = iter->render_view_id;
registered_web_contents_.erase(iter);
registrar_->Remove(this,
content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
content::Source<WebContents>(web_contents));
registrar_->Remove(this,
content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::Source<WebContents>(web_contents));
tab_closed_callback_.Run(render_process_id, render_view_id);
}
private:
struct WebContentsInfo {
WebContentsInfo(content::WebContents* web_contents,
int render_process_id,
int render_view_id)
: web_contents(web_contents),
render_process_id(render_process_id),
render_view_id(render_view_id) {}
~WebContentsInfo() {}
content::WebContents* web_contents;
int render_process_id;
int render_view_id;
};
friend class base::RefCountedThreadSafe<TabWatcher>;
virtual ~TabWatcher() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
std::vector<WebContentsInfo>::iterator FindWebContents(
content::WebContents* web_contents) {
for (std::vector<WebContentsInfo>::iterator i(
registered_web_contents_.begin());
i != registered_web_contents_.end(); ++i) {
if (i->web_contents == web_contents)
return i;
}
return registered_web_contents_.end();
}
scoped_ptr<content::NotificationRegistrar> registrar_;
std::vector<WebContentsInfo> registered_web_contents_;
TabClosedCallback tab_closed_callback_;
DISALLOW_COPY_AND_ASSIGN(TabWatcher);
};
ChromeSpeechRecognitionManagerDelegate
::ChromeSpeechRecognitionManagerDelegate() {
}
ChromeSpeechRecognitionManagerDelegate
::~ChromeSpeechRecognitionManagerDelegate() {
}
void ChromeSpeechRecognitionManagerDelegate::TabClosedCallback(
int render_process_id, int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&TabClosedCallbackOnIOThread, render_process_id, render_view_id));
}
void ChromeSpeechRecognitionManagerDelegate::OnRecognitionStart(
int session_id) {
const content::SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
if (!tab_watcher_.get()) {
tab_watcher_ = new TabWatcher(
base::Bind(&ChromeSpeechRecognitionManagerDelegate::TabClosedCallback,
base::Unretained(this)));
}
tab_watcher_->Watch(context.render_process_id, context.render_view_id);
}
void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete(
int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::OnRecognitionResults(
int session_id, const content::SpeechRecognitionResults& result) {
}
void ChromeSpeechRecognitionManagerDelegate::OnRecognitionError(
int session_id, const content::SpeechRecognitionError& error) {
}
void ChromeSpeechRecognitionManagerDelegate::OnAudioLevelsChange(
int session_id, float volume, float noise_volume) {
}
void ChromeSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) {
}
void ChromeSpeechRecognitionManagerDelegate::GetDiagnosticInformation(
bool* can_report_metrics,
std::string* hardware_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!optional_request_info_.get()) {
optional_request_info_ = new OptionalRequestInfo();
optional_request_info_->Refresh();
}
*can_report_metrics = optional_request_info_->can_report_metrics();
*hardware_info = optional_request_info_->value();
}
void ChromeSpeechRecognitionManagerDelegate::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);
DCHECK_NE(context.render_process_id, 0);
int render_process_id = context.render_process_id;
int render_view_id = context.render_view_id;
if (context.embedder_render_process_id) {
render_process_id = context.embedder_render_process_id;
render_view_id = context.embedder_render_view_id;
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&CheckRenderViewType,
callback,
render_process_id,
render_view_id,
!context.requested_by_page_element));
}
content::SpeechRecognitionEventListener*
ChromeSpeechRecognitionManagerDelegate::GetEventListener() {
return this;
}
bool ChromeSpeechRecognitionManagerDelegate::FilterProfanities(
int render_process_id) {
content::RenderProcessHost* rph =
content::RenderProcessHost::FromID(render_process_id);
if (!rph)
return true;
return Profile::FromBrowserContext(rph->GetBrowserContext())->GetPrefs()->
GetBoolean(prefs::kSpeechRecognitionFilterProfanities);
}
void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType(
base::Callback<void(bool ask_user, bool is_allowed)> callback,
int render_process_id,
int render_view_id,
bool js_api) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const content::RenderViewHost* render_view_host =
content::RenderViewHost::FromID(render_process_id, render_view_id);
bool allowed = false;
bool check_permission = false;
if (!render_view_host) {
if (!js_api) {
allowed = false;
check_permission = false;
} else {
allowed = true;
check_permission = false;
}
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(callback, check_permission, allowed));
return;
}
WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
if (web_contents->GetCommittedWebUI() &&
web_contents->GetLastCommittedURL().spec() ==
chrome::kChromeUIAppListStartPageURL) {
allowed = true;
check_permission = false;
}
extensions::ViewType view_type = extensions::GetViewType(web_contents);
if (view_type == extensions::VIEW_TYPE_TAB_CONTENTS ||
view_type == extensions::VIEW_TYPE_APP_WINDOW ||
view_type == extensions::VIEW_TYPE_VIRTUAL_KEYBOARD ||
(view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE &&
js_api)) {
allowed = true;
if (js_api)
check_permission = true;
}
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(callback, check_permission, allowed));
}
}