Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / speech / speech_recognition_bubble_controller.cc
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       last_request_issued_(REQUEST_CLOSE),
30       current_bubble_session_id_(kInvalidSessionId),
31       current_bubble_render_process_id_(0),
32       current_bubble_render_view_id_(0) {
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   {
45     base::AutoLock auto_lock(lock_);
46     current_bubble_session_id_ = session_id;
47     current_bubble_render_process_id_ = render_process_id;
48     current_bubble_render_view_id_ = render_view_id;
49   }
50
51   UIRequest request(REQUEST_CREATE);
52   request.render_process_id = render_process_id;
53   request.render_view_id = render_view_id;
54   request.element_rect = element_rect;
55   ProcessRequestInUiThread(request);
56 }
57
58 void SpeechRecognitionBubbleController::SetBubbleRecordingMode() {
59   ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECORDING_MODE));
60 }
61
62 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode() {
63   ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECOGNIZING_MODE));
64 }
65
66 void SpeechRecognitionBubbleController::SetBubbleMessage(
67     const base::string16& text) {
68   UIRequest request(REQUEST_SET_MESSAGE);
69   request.message = text;
70   ProcessRequestInUiThread(request);
71 }
72
73 bool SpeechRecognitionBubbleController::IsShowingMessage() const {
74   return last_request_issued_ == REQUEST_SET_MESSAGE;
75 }
76
77 void SpeechRecognitionBubbleController::SetBubbleInputVolume(
78     float volume,
79     float noise_volume) {
80   UIRequest request(REQUEST_SET_INPUT_VOLUME);
81   request.volume = volume;
82   request.noise_volume = noise_volume;
83   ProcessRequestInUiThread(request);
84 }
85
86 void SpeechRecognitionBubbleController::CloseBubble() {
87   {
88     base::AutoLock auto_lock(lock_);
89     current_bubble_session_id_ = kInvalidSessionId;
90   }
91   ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE));
92 }
93
94 void SpeechRecognitionBubbleController::CloseBubbleForRenderViewOnUIThread(
95     int render_process_id, int render_view_id) {
96   {
97     base::AutoLock auto_lock(lock_);
98     if (current_bubble_session_id_ == kInvalidSessionId ||
99         current_bubble_render_process_id_ != render_process_id ||
100         current_bubble_render_view_id_ != render_view_id) {
101       return;
102     }
103     current_bubble_session_id_ = kInvalidSessionId;
104   }
105   ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE));
106 }
107
108 int SpeechRecognitionBubbleController::GetActiveSessionID() {
109   base::AutoLock auto_lock(lock_);
110   return current_bubble_session_id_;
111 }
112
113 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked(
114     SpeechRecognitionBubble::Button button) {
115   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
117       base::Bind(
118           &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, this,
119           button));
120 }
121
122 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() {
123   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
124   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
125       base::Bind(&SpeechRecognitionBubbleController::InvokeDelegateFocusChanged,
126                  this));
127 }
128
129 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked(
130     SpeechRecognitionBubble::Button button) {
131   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
132   {
133     base::AutoLock auto_lock(lock_);
134     if (kInvalidSessionId == current_bubble_session_id_)
135       return;
136   }
137   delegate_->InfoBubbleButtonClicked(current_bubble_session_id_, button);
138 }
139
140 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged() {
141   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
142   {
143     base::AutoLock auto_lock(lock_);
144     if (kInvalidSessionId == current_bubble_session_id_)
145       return;
146   }
147   delegate_->InfoBubbleFocusChanged(current_bubble_session_id_);
148 }
149
150 void SpeechRecognitionBubbleController::ProcessRequestInUiThread(
151     const UIRequest& request) {
152   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
153     last_request_issued_ = request.type;
154     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
155         base::Bind(&SpeechRecognitionBubbleController::ProcessRequestInUiThread,
156                    this, request));
157     return;
158   }
159
160   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161
162   // In the case of a tab closed or crashed, the bubble can have been destroyed
163   // earlier on the UI thread, while other tasks were being enqueued from the IO
164   // to the UI thread. Simply return in such cases.
165   if (request.type != REQUEST_CREATE && !bubble_.get())
166     return;
167
168   switch (request.type) {
169     case REQUEST_CREATE:
170       bubble_.reset(SpeechRecognitionBubble::Create(
171           request.render_process_id, request.render_view_id,
172           this, request.element_rect));
173
174       if (!bubble_.get()) {
175         // Could be null if tab or display rect were invalid.
176         // Simulate the cancel button being clicked to inform the delegate.
177         BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
178             base::Bind(
179                 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
180                 this, SpeechRecognitionBubble::BUTTON_CANCEL));
181         return;
182       }
183       bubble_->Show();
184       bubble_->SetWarmUpMode();
185       break;
186     case REQUEST_SET_RECORDING_MODE:
187       bubble_->SetRecordingMode();
188       break;
189     case REQUEST_SET_RECOGNIZING_MODE:
190       bubble_->SetRecognizingMode();
191       break;
192     case REQUEST_SET_MESSAGE:
193       bubble_->SetMessage(request.message);
194       break;
195     case REQUEST_SET_INPUT_VOLUME:
196       bubble_->SetInputVolume(request.volume, request.noise_volume);
197       break;
198     case REQUEST_CLOSE:
199       bubble_.reset();
200       break;
201     default:
202       NOTREACHED();
203       break;
204   }
205 }
206
207 SpeechRecognitionBubbleController::UIRequest::UIRequest(RequestType type_value)
208     : type(type_value),
209       volume(0.0F),
210       noise_volume(0.0F),
211       render_process_id(0),
212       render_view_id(0) {
213 }
214
215 SpeechRecognitionBubbleController::UIRequest::~UIRequest() {
216 }
217
218 }  // namespace speech