| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" | 5 #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/synchronization/lock.h" | 10 #include "base/synchronization/lock.h" |
| 11 #include "base/threading/thread_restrictions.h" | 11 #include "base/threading/thread_restrictions.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/extensions/extension_service.h" |
| 14 #include "chrome/browser/prefs/pref_service.h" | 15 #include "chrome/browser/prefs/pref_service.h" |
| 15 #include "chrome/browser/profiles/profile_manager.h" | 16 #include "chrome/browser/profiles/profile_manager.h" |
| 17 #include "chrome/browser/speech/chrome_speech_recognition_preferences.h" |
| 16 #include "chrome/browser/speech/speech_recognition_tray_icon_controller.h" | 18 #include "chrome/browser/speech/speech_recognition_tray_icon_controller.h" |
| 17 #include "chrome/browser/tab_contents/tab_util.h" | 19 #include "chrome/browser/tab_contents/tab_util.h" |
| 18 #include "chrome/browser/view_type_utils.h" | 20 #include "chrome/browser/view_type_utils.h" |
| 19 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
| 20 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/browser/render_process_host.h" |
| 21 #include "content/public/browser/render_view_host.h" | 24 #include "content/public/browser/render_view_host.h" |
| 22 #include "content/public/browser/resource_context.h" | 25 #include "content/public/browser/resource_context.h" |
| 23 #include "content/public/browser/speech_recognition_manager.h" | 26 #include "content/public/browser/speech_recognition_manager.h" |
| 24 #include "content/public/browser/speech_recognition_session_config.h" | 27 #include "content/public/browser/speech_recognition_session_config.h" |
| 25 #include "content/public/browser/speech_recognition_session_context.h" | 28 #include "content/public/browser/speech_recognition_session_context.h" |
| 26 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 27 #include "content/public/common/speech_recognition_error.h" | 30 #include "content/public/common/speech_recognition_error.h" |
| 28 #include "content/public/common/speech_recognition_result.h" | 31 #include "content/public/common/speech_recognition_result.h" |
| 29 #include "grit/generated_resources.h" | 32 #include "grit/generated_resources.h" |
| 30 #include "net/url_request/url_request_context_getter.h" | 33 #include "net/url_request/url_request_context_getter.h" |
| 31 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 32 | 35 |
| 33 #if defined(OS_WIN) | 36 #if defined(OS_WIN) |
| 34 #include "chrome/installer/util/wmi.h" | 37 #include "chrome/installer/util/wmi.h" |
| 35 #endif | 38 #endif |
| 36 | 39 |
| 37 using content::BrowserThread; | 40 using content::BrowserThread; |
| 38 using content::SpeechRecognitionManager; | 41 using content::SpeechRecognitionManager; |
| 42 using content::SpeechRecognitionSessionContext; |
| 39 using content::WebContents; | 43 using content::WebContents; |
| 40 using content::SpeechRecognitionSessionContext; | |
| 41 | 44 |
| 42 namespace { | 45 namespace { |
| 43 const int kNoActiveBubble = | 46 const int kNoActiveBubble = |
| 44 content::SpeechRecognitionManager::kSessionIDInvalid; | 47 content::SpeechRecognitionManager::kSessionIDInvalid; |
| 45 | 48 |
| 49 const char kExtensionPrefix[] = "chrome-extension://"; |
| 50 |
| 46 bool RequiresBubble(int session_id) { | 51 bool RequiresBubble(int session_id) { |
| 47 return SpeechRecognitionManager::GetInstance()-> | 52 return SpeechRecognitionManager::GetInstance()-> |
| 48 GetSessionContext(session_id).requested_by_page_element; | 53 GetSessionContext(session_id).requested_by_page_element; |
| 49 } | 54 } |
| 50 | 55 |
| 51 bool RequiresTrayIcon(int session_id) { | 56 bool RequiresTrayIcon(int session_id) { |
| 52 return !RequiresBubble(session_id); | 57 return !RequiresBubble(session_id); |
| 53 } | 58 } |
| 54 } // namespace | 59 } // namespace |
| 55 | 60 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 | 208 |
| 204 // TODO(primiano) Why not creating directly the bubble in warmup mode? | 209 // TODO(primiano) Why not creating directly the bubble in warmup mode? |
| 205 GetBubbleController()->SetBubbleWarmUpMode(session_id); | 210 GetBubbleController()->SetBubbleWarmUpMode(session_id); |
| 206 } | 211 } |
| 207 } | 212 } |
| 208 | 213 |
| 209 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { | 214 void ChromeSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { |
| 210 if (RequiresBubble(session_id)) { | 215 if (RequiresBubble(session_id)) { |
| 211 GetBubbleController()->SetBubbleRecordingMode(session_id); | 216 GetBubbleController()->SetBubbleRecordingMode(session_id); |
| 212 } else if (RequiresTrayIcon(session_id)) { | 217 } else if (RequiresTrayIcon(session_id)) { |
| 218 // We post the action to the UI thread for sessions requiring a tray icon, |
| 219 // since ChromeSpeechRecognitionPreferences (which requires UI thread) is |
| 220 // involved for determining whether a security alert balloon is required. |
| 213 const content::SpeechRecognitionSessionContext& context = | 221 const content::SpeechRecognitionSessionContext& context = |
| 214 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); | 222 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| 215 GetTrayIconController()->Show(context.context_name, | 223 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| 216 context.is_first_request_for_context); | 224 &ChromeSpeechRecognitionManagerDelegate::ShowTrayIconOnUIThread, |
| 225 context.context_name, |
| 226 context.render_process_id, |
| 227 scoped_refptr<SpeechRecognitionTrayIconController>( |
| 228 GetTrayIconController()))); |
| 217 } | 229 } |
| 218 } | 230 } |
| 219 | 231 |
| 220 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( | 232 void ChromeSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( |
| 221 int session_id) { | 233 int session_id) { |
| 222 } | 234 } |
| 223 | 235 |
| 224 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { | 236 void ChromeSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { |
| 225 } | 237 } |
| 226 | 238 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 } | 340 } |
| 329 *can_report_metrics = optional_request_info_->can_report_metrics(); | 341 *can_report_metrics = optional_request_info_->can_report_metrics(); |
| 330 *hardware_info = optional_request_info_->value(); | 342 *hardware_info = optional_request_info_->value(); |
| 331 } | 343 } |
| 332 | 344 |
| 333 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( | 345 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( |
| 334 int session_id, | 346 int session_id, |
| 335 base::Callback<void(int session_id, bool is_allowed)> callback) { | 347 base::Callback<void(int session_id, bool is_allowed)> callback) { |
| 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 337 | 349 |
| 350 const content::SpeechRecognitionSessionContext& context = |
| 351 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| 352 |
| 353 // Make sure that initiators (extensions/web pages) properly set the |
| 354 // |render_process_id| field, which is needed later to retrieve the |
| 355 // ChromeSpeechRecognitionPreferences associated to their profile. |
| 356 DCHECK_NE(context.render_process_id, 0); |
| 357 |
| 338 // We don't need any particular check for sessions not using a bubble. In such | 358 // We don't need any particular check for sessions not using a bubble. In such |
| 339 // cases, we just notify it to the manager (calling-back synchronously, since | 359 // cases, we just notify it to the manager (calling-back synchronously, since |
| 340 // we remain in the IO thread). | 360 // we remain in the IO thread). |
| 341 if (RequiresTrayIcon(session_id)) { | 361 if (RequiresTrayIcon(session_id)) { |
| 342 callback.Run(session_id, true /* is_allowed */); | 362 callback.Run(session_id, true /* is_allowed */); |
| 343 return; | 363 return; |
| 344 } | 364 } |
| 345 | 365 |
| 346 // Sessions using bubbles, conversely, need a check on the renderer view type. | 366 // Sessions using bubbles, conversely, need a check on the renderer view type. |
| 347 // The check must be performed in the UI thread. We defer it posting to | 367 // The check must be performed in the UI thread. We defer it posting to |
| 348 // CheckRenderViewType, which will issue the callback on our behalf. | 368 // CheckRenderViewType, which will issue the callback on our behalf. |
| 349 const content::SpeechRecognitionSessionContext& context = | |
| 350 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); | |
| 351 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 369 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 352 base::Bind(&CheckRenderViewType, | 370 base::Bind(&CheckRenderViewType, |
| 353 session_id, | 371 session_id, |
| 354 callback, | 372 callback, |
| 355 context.render_process_id, | 373 context.render_process_id, |
| 356 context.render_view_id)); | 374 context.render_view_id)); |
| 357 } | 375 } |
| 358 | 376 |
| 359 content::SpeechRecognitionEventListener* | 377 content::SpeechRecognitionEventListener* |
| 360 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { | 378 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { |
| 361 return this; | 379 return this; |
| 362 } | 380 } |
| 363 | 381 |
| 382 void ChromeSpeechRecognitionManagerDelegate::ShowTrayIconOnUIThread( |
| 383 const std::string& context_name, |
| 384 int render_process_id, |
| 385 scoped_refptr<SpeechRecognitionTrayIconController> tray_icon_controller) { |
| 386 content::RenderProcessHost* render_process_host = |
| 387 content::RenderProcessHost::FromID(render_process_id); |
| 388 DCHECK(render_process_host); |
| 389 content::BrowserContext* browser_context = |
| 390 render_process_host->GetBrowserContext(); |
| 391 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 392 scoped_refptr<ChromeSpeechRecognitionPreferences> pref = |
| 393 ChromeSpeechRecognitionPreferences::GetForProfile(profile); |
| 394 bool show_notification = pref->ShouldShowSecurityNotification(context_name); |
| 395 if (show_notification) |
| 396 pref->SetHasShownSecurityNotification(context_name); |
| 397 |
| 398 // Speech recognitions initiated by JS APIs within an extension (so NOT by |
| 399 // extension API) will come with a context_name like "chrome-extension://id" |
| 400 // (that is, their origin as injected by WebKit). In such cases we try to |
| 401 // lookup the extension name, in order to show a more user-friendly balloon. |
| 402 string16 initiator_name = UTF8ToUTF16(context_name); |
| 403 if (context_name.find(kExtensionPrefix) == 0) { |
| 404 const std::string extension_id = |
| 405 context_name.substr(sizeof(kExtensionPrefix) - 1); |
| 406 const extensions::Extension* extension = |
| 407 profile->GetExtensionService()->GetExtensionById(extension_id, true); |
| 408 DCHECK(extension); |
| 409 initiator_name = UTF8ToUTF16(extension->name()); |
| 410 } |
| 411 |
| 412 tray_icon_controller->Show(initiator_name, show_notification); |
| 413 } |
| 414 |
| 364 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType( | 415 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType( |
| 365 int session_id, | 416 int session_id, |
| 366 base::Callback<void(int session_id, bool is_allowed)> callback, | 417 base::Callback<void(int session_id, bool is_allowed)> callback, |
| 367 int render_process_id, | 418 int render_process_id, |
| 368 int render_view_id) { | 419 int render_view_id) { |
| 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 370 const content::RenderViewHost* render_view_host = | 421 const content::RenderViewHost* render_view_host = |
| 371 content::RenderViewHost::FromID(render_process_id, render_view_id); | 422 content::RenderViewHost::FromID(render_process_id, render_view_id); |
| 372 bool allowed = false; | 423 bool allowed = false; |
| 373 if (render_view_host) { | 424 if (render_view_host) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 396 | 447 |
| 397 SpeechRecognitionTrayIconController* | 448 SpeechRecognitionTrayIconController* |
| 398 ChromeSpeechRecognitionManagerDelegate::GetTrayIconController() { | 449 ChromeSpeechRecognitionManagerDelegate::GetTrayIconController() { |
| 399 if (!tray_icon_controller_.get()) | 450 if (!tray_icon_controller_.get()) |
| 400 tray_icon_controller_ = new SpeechRecognitionTrayIconController(); | 451 tray_icon_controller_ = new SpeechRecognitionTrayIconController(); |
| 401 return tray_icon_controller_.get(); | 452 return tray_icon_controller_.get(); |
| 402 } | 453 } |
| 403 | 454 |
| 404 | 455 |
| 405 } // namespace speech | 456 } // namespace speech |
| OLD | NEW |