Home | History | Annotate | Download | only in speech
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/speech/speech_recognition_bubble_controller.h"
      6 
      7 #include "base/bind.h"
      8 #include "chrome/browser/tab_contents/tab_util.h"
      9 #include "content/public/browser/browser_thread.h"
     10 #include "content/public/browser/notification_registrar.h"
     11 #include "content/public/browser/notification_source.h"
     12 #include "content/public/browser/notification_types.h"
     13 #include "content/public/browser/render_process_host.h"
     14 #include "content/public/browser/render_view_host.h"
     15 #include "content/public/browser/web_contents.h"
     16 
     17 using content::BrowserThread;
     18 using content::WebContents;
     19 
     20 namespace {
     21 const int kInvalidSessionId = 0;
     22 }
     23 
     24 namespace speech {
     25 
     26 SpeechRecognitionBubbleController::SpeechRecognitionBubbleController(
     27     Delegate* delegate)
     28     : delegate_(delegate),
     29       current_bubble_session_id_(kInvalidSessionId),
     30       current_bubble_render_process_id_(0),
     31       current_bubble_render_view_id_(0),
     32       last_request_issued_(REQUEST_CLOSE) {
     33 }
     34 
     35 SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() {
     36   DCHECK_EQ(kInvalidSessionId, current_bubble_session_id_);
     37 }
     38 
     39 void SpeechRecognitionBubbleController::CreateBubble(
     40     int session_id,
     41     int render_process_id,
     42     int render_view_id,
     43     const gfx::Rect& element_rect) {
     44   current_bubble_session_id_ = session_id;
     45   current_bubble_render_process_id_ = render_process_id;
     46   current_bubble_render_view_id_ = render_view_id;
     47 
     48   UIRequest request(REQUEST_CREATE);
     49   request.render_process_id = render_process_id;
     50   request.render_view_id = render_view_id;
     51   request.element_rect = element_rect;
     52   ProcessRequestInUiThread(request);
     53 }
     54 
     55 void SpeechRecognitionBubbleController::SetBubbleRecordingMode() {
     56   ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECORDING_MODE));
     57 }
     58 
     59 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode() {
     60   ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECOGNIZING_MODE));
     61 }
     62 
     63 void SpeechRecognitionBubbleController::SetBubbleMessage(const string16& text) {
     64   UIRequest request(REQUEST_SET_MESSAGE);
     65   request.message = text;
     66   ProcessRequestInUiThread(request);
     67 }
     68 
     69 bool SpeechRecognitionBubbleController::IsShowingMessage() const {
     70   return last_request_issued_ == REQUEST_SET_MESSAGE;
     71 }
     72 
     73 void SpeechRecognitionBubbleController::SetBubbleInputVolume(
     74     float volume,
     75     float noise_volume) {
     76   UIRequest request(REQUEST_SET_INPUT_VOLUME);
     77   request.volume = volume;
     78   request.noise_volume = noise_volume;
     79   ProcessRequestInUiThread(request);
     80 }
     81 
     82 void SpeechRecognitionBubbleController::CloseBubble() {
     83   current_bubble_session_id_ = kInvalidSessionId;
     84   ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE));
     85 }
     86 
     87 int SpeechRecognitionBubbleController::GetActiveSessionID() const {
     88   return current_bubble_session_id_;
     89 }
     90 
     91 bool SpeechRecognitionBubbleController::IsShowingBubbleForRenderView(
     92     int render_process_id,
     93     int render_view_id) {
     94   return (current_bubble_session_id_ != kInvalidSessionId) &&
     95       (current_bubble_render_process_id_ == render_process_id) &&
     96       (current_bubble_render_view_id_ == render_view_id);
     97 }
     98 
     99 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked(
    100     SpeechRecognitionBubble::Button button) {
    101   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    102   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    103       base::Bind(
    104           &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, this,
    105           button));
    106 }
    107 
    108 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() {
    109   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    110   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    111       base::Bind(&SpeechRecognitionBubbleController::InvokeDelegateFocusChanged,
    112                  this));
    113 }
    114 
    115 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked(
    116     SpeechRecognitionBubble::Button button) {
    117   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    118   DCHECK_NE(kInvalidSessionId, current_bubble_session_id_);
    119   delegate_->InfoBubbleButtonClicked(current_bubble_session_id_, button);
    120 }
    121 
    122 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged() {
    123   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    124   DCHECK_NE(kInvalidSessionId, current_bubble_session_id_);
    125   delegate_->InfoBubbleFocusChanged(current_bubble_session_id_);
    126 }
    127 
    128 void SpeechRecognitionBubbleController::ProcessRequestInUiThread(
    129     const UIRequest& request) {
    130   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    131     last_request_issued_ = request.type;
    132     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    133         base::Bind(&SpeechRecognitionBubbleController::ProcessRequestInUiThread,
    134                    this, request));
    135     return;
    136   }
    137 
    138   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    139 
    140   switch (request.type) {
    141     case REQUEST_CREATE:
    142       bubble_.reset(SpeechRecognitionBubble::Create(
    143           tab_util::GetWebContentsByID(request.render_process_id,
    144                                        request.render_view_id),
    145           this, request.element_rect));
    146 
    147       if (!bubble_.get()) {
    148         // Could be null if tab or display rect were invalid.
    149         // Simulate the cancel button being clicked to inform the delegate.
    150         BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    151             base::Bind(
    152                 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
    153                 this, SpeechRecognitionBubble::BUTTON_CANCEL));
    154         return;
    155       }
    156       bubble_->Show();
    157       bubble_->SetWarmUpMode();
    158       break;
    159     case REQUEST_SET_RECORDING_MODE:
    160       if (!bubble_.get()) {
    161         // We've seen this on crash/ but don't yet understand why this happen.
    162         // TODO(tommi): It would be nice to figure this out properly and fix
    163         // but since this feature is being deprecated, removing the code
    164         // altogether is probably a simpler and more permanent fix :)
    165         DLOG(ERROR) << "NULL bubble in REQUEST_SET_RECORDING_MODE!";
    166       } else {
    167         bubble_->SetRecordingMode();
    168       }
    169       break;
    170     case REQUEST_SET_RECOGNIZING_MODE:
    171       DCHECK(bubble_.get());
    172       bubble_->SetRecognizingMode();
    173       break;
    174     case REQUEST_SET_MESSAGE:
    175       DCHECK(bubble_.get());
    176       bubble_->SetMessage(request.message);
    177       break;
    178     case REQUEST_SET_INPUT_VOLUME:
    179       DCHECK(bubble_.get());
    180       bubble_->SetInputVolume(request.volume, request.noise_volume);
    181       break;
    182     case REQUEST_CLOSE:
    183       bubble_.reset();
    184       break;
    185     default:
    186       NOTREACHED();
    187       break;
    188   }
    189 }
    190 
    191 SpeechRecognitionBubbleController::UIRequest::UIRequest(RequestType type_value)
    192     : type(type_value),
    193       volume(0.0F),
    194       noise_volume(0.0F),
    195       render_process_id(0),
    196       render_view_id(0) {
    197 }
    198 
    199 SpeechRecognitionBubbleController::UIRequest::~UIRequest() {
    200 }
    201 
    202 }  // namespace speech
    203