| 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 <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 const char kExtensionPrefix[] = "chrome-extension://"; | 50 const char kExtensionPrefix[] = "chrome-extension://"; |
| 51 | 51 |
| 52 bool RequiresBubble(int session_id) { | 52 bool RequiresBubble(int session_id) { |
| 53 return SpeechRecognitionManager::GetInstance()-> | 53 return SpeechRecognitionManager::GetInstance()-> |
| 54 GetSessionContext(session_id).requested_by_page_element; | 54 GetSessionContext(session_id).requested_by_page_element; |
| 55 } | 55 } |
| 56 | 56 |
| 57 bool RequiresTrayIcon(int session_id) { | 57 bool RequiresTrayIcon(int session_id) { |
| 58 return !RequiresBubble(session_id); | 58 return !RequiresBubble(session_id); |
| 59 } | 59 } |
| 60 |
| 60 } // namespace | 61 } // namespace |
| 61 | 62 |
| 62 namespace speech { | 63 namespace speech { |
| 63 | 64 |
| 64 // Asynchronously fetches the PC and audio hardware/driver info if | 65 // Asynchronously fetches the PC and audio hardware/driver info if |
| 65 // the user has opted into UMA. This information is sent with speech input | 66 // the user has opted into UMA. This information is sent with speech input |
| 66 // requests to the server for identifying and improving quality issues with | 67 // requests to the server for identifying and improving quality issues with |
| 67 // specific device configurations. | 68 // specific device configurations. |
| 68 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo | 69 class ChromeSpeechRecognitionManagerDelegate::OptionalRequestInfo |
| 69 : public base::RefCountedThreadSafe<OptionalRequestInfo> { | 70 : public base::RefCountedThreadSafe<OptionalRequestInfo> { |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 // a long wait and disk seeks when they click on a UI element and start | 461 // a long wait and disk seeks when they click on a UI element and start |
| 461 // speaking. | 462 // speaking. |
| 462 optional_request_info_->Refresh(); | 463 optional_request_info_->Refresh(); |
| 463 } | 464 } |
| 464 *can_report_metrics = optional_request_info_->can_report_metrics(); | 465 *can_report_metrics = optional_request_info_->can_report_metrics(); |
| 465 *hardware_info = optional_request_info_->value(); | 466 *hardware_info = optional_request_info_->value(); |
| 466 } | 467 } |
| 467 | 468 |
| 468 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( | 469 void ChromeSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( |
| 469 int session_id, | 470 int session_id, |
| 470 base::Callback<void(int session_id, bool is_allowed)> callback) { | 471 base::Callback<void(bool ask_user, bool is_allowed)> callback) { |
| 471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 472 | 473 |
| 473 const content::SpeechRecognitionSessionContext& context = | 474 const content::SpeechRecognitionSessionContext& context = |
| 474 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); | 475 SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); |
| 475 | 476 |
| 476 // Make sure that initiators (extensions/web pages) properly set the | 477 // Make sure that initiators (extensions/web pages) properly set the |
| 477 // |render_process_id| field, which is needed later to retrieve the | 478 // |render_process_id| field, which is needed later to retrieve the |
| 478 // ChromeSpeechRecognitionPreferences associated to their profile. | 479 // ChromeSpeechRecognitionPreferences associated to their profile. |
| 479 DCHECK_NE(context.render_process_id, 0); | 480 DCHECK_NE(context.render_process_id, 0); |
| 480 | 481 |
| 481 // We don't need any particular check for sessions not using a bubble. In such | 482 // Check that the render view type is appropriate, and whether or not we |
| 482 // cases, we just notify it to the manager (calling-back synchronously, since | 483 // need to request permission from the user. |
| 483 // we remain in the IO thread). | |
| 484 if (RequiresTrayIcon(session_id)) { | |
| 485 callback.Run(session_id, true /* is_allowed */); | |
| 486 return; | |
| 487 } | |
| 488 | |
| 489 // Sessions using bubbles, conversely, need a check on the renderer view type. | |
| 490 // The check must be performed in the UI thread. We defer it posting to | |
| 491 // CheckRenderViewType, which will issue the callback on our behalf. | |
| 492 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 484 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 493 base::Bind(&CheckRenderViewType, | 485 base::Bind(&CheckRenderViewType, |
| 494 session_id, | |
| 495 callback, | 486 callback, |
| 496 context.render_process_id, | 487 context.render_process_id, |
| 497 context.render_view_id)); | 488 context.render_view_id, |
| 489 RequiresTrayIcon(session_id))); |
| 498 } | 490 } |
| 499 | 491 |
| 500 content::SpeechRecognitionEventListener* | 492 content::SpeechRecognitionEventListener* |
| 501 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { | 493 ChromeSpeechRecognitionManagerDelegate::GetEventListener() { |
| 502 return this; | 494 return this; |
| 503 } | 495 } |
| 504 | 496 |
| 505 void ChromeSpeechRecognitionManagerDelegate::ShowTrayIconOnUIThread( | 497 void ChromeSpeechRecognitionManagerDelegate::ShowTrayIconOnUIThread( |
| 506 const std::string& context_name, | 498 const std::string& context_name, |
| 507 int render_process_id, | 499 int render_process_id, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 529 const extensions::Extension* extension = | 521 const extensions::Extension* extension = |
| 530 profile->GetExtensionService()->GetExtensionById(extension_id, true); | 522 profile->GetExtensionService()->GetExtensionById(extension_id, true); |
| 531 DCHECK(extension); | 523 DCHECK(extension); |
| 532 initiator_name = UTF8ToUTF16(extension->name()); | 524 initiator_name = UTF8ToUTF16(extension->name()); |
| 533 } | 525 } |
| 534 | 526 |
| 535 tray_icon_controller->Show(initiator_name, show_notification); | 527 tray_icon_controller->Show(initiator_name, show_notification); |
| 536 } | 528 } |
| 537 | 529 |
| 538 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType( | 530 void ChromeSpeechRecognitionManagerDelegate::CheckRenderViewType( |
| 539 int session_id, | 531 base::Callback<void(bool ask_user, bool is_allowed)> callback, |
| 540 base::Callback<void(int session_id, bool is_allowed)> callback, | |
| 541 int render_process_id, | 532 int render_process_id, |
| 542 int render_view_id) { | 533 int render_view_id, |
| 534 bool js_api) { |
| 543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 544 const content::RenderViewHost* render_view_host = | 536 const content::RenderViewHost* render_view_host = |
| 545 content::RenderViewHost::FromID(render_process_id, render_view_id); | 537 content::RenderViewHost::FromID(render_process_id, render_view_id); |
| 538 |
| 546 bool allowed = false; | 539 bool allowed = false; |
| 547 if (render_view_host) { | 540 bool ask_permission = false; |
| 548 // For host delegates other than VIEW_TYPE_TAB_CONTENTS we can't reliably | 541 |
| 549 // show a popup, including the speech input bubble. In these cases for | 542 if (!render_view_host) { |
| 550 // privacy reasons we don't want to start recording if the user can't be | 543 if (!js_api) { |
| 551 // properly notified. An example of this is trying to show the speech input | 544 // If there is no render view, we cannot show the speech bubble, so this |
| 552 // bubble within an extension popup: http://crbug.com/92083. In these | 545 // is not allowed. |
| 553 // situations the speech input extension API should be used instead. | 546 allowed = false; |
| 554 WebContents* web_contents = | 547 ask_permission = false; |
| 555 WebContents::FromRenderViewHost(render_view_host); | 548 } else { |
| 556 chrome::ViewType view_type = chrome::GetViewType(web_contents); | 549 // This happens for extensions. Manifest should be checked for permission. |
| 557 if (view_type == chrome::VIEW_TYPE_TAB_CONTENTS) | |
| 558 allowed = true; | 550 allowed = true; |
| 551 ask_permission = false; |
| 552 } |
| 553 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 554 base::Bind(callback, ask_permission, allowed)); |
| 555 return; |
| 559 } | 556 } |
| 557 |
| 558 WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host); |
| 559 chrome::ViewType view_type = chrome::GetViewType(web_contents); |
| 560 |
| 561 if (view_type == chrome::VIEW_TYPE_TAB_CONTENTS) { |
| 562 // If it is a tab, we can show the speech input bubble or ask for |
| 563 // permission. |
| 564 |
| 565 allowed = true; |
| 566 if (js_api) |
| 567 ask_permission = true; |
| 568 } |
| 569 |
| 560 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 570 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 561 base::Bind(callback, session_id, allowed)); | 571 base::Bind(callback, ask_permission, allowed)); |
| 562 } | 572 } |
| 563 | 573 |
| 564 SpeechRecognitionBubbleController* | 574 SpeechRecognitionBubbleController* |
| 565 ChromeSpeechRecognitionManagerDelegate::GetBubbleController() { | 575 ChromeSpeechRecognitionManagerDelegate::GetBubbleController() { |
| 566 if (!bubble_controller_.get()) | 576 if (!bubble_controller_.get()) |
| 567 bubble_controller_ = new SpeechRecognitionBubbleController(this); | 577 bubble_controller_ = new SpeechRecognitionBubbleController(this); |
| 568 return bubble_controller_.get(); | 578 return bubble_controller_.get(); |
| 569 } | 579 } |
| 570 | 580 |
| 571 SpeechRecognitionTrayIconController* | 581 SpeechRecognitionTrayIconController* |
| 572 ChromeSpeechRecognitionManagerDelegate::GetTrayIconController() { | 582 ChromeSpeechRecognitionManagerDelegate::GetTrayIconController() { |
| 573 if (!tray_icon_controller_.get()) | 583 if (!tray_icon_controller_.get()) |
| 574 tray_icon_controller_ = new SpeechRecognitionTrayIconController(); | 584 tray_icon_controller_ = new SpeechRecognitionTrayIconController(); |
| 575 return tray_icon_controller_.get(); | 585 return tray_icon_controller_.get(); |
| 576 } | 586 } |
| 577 | 587 |
| 578 | 588 |
| 579 } // namespace speech | 589 } // namespace speech |
| OLD | NEW |