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.
5 #include "chrome/browser/speech/speech_recognition_bubble_controller.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"
17 using content::BrowserThread
;
18 using content::WebContents
;
21 const int kInvalidSessionId
= 0;
26 SpeechRecognitionBubbleController::SpeechRecognitionBubbleController(
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) {
35 SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() {
36 DCHECK_EQ(kInvalidSessionId
, current_bubble_session_id_
);
39 void SpeechRecognitionBubbleController::CreateBubble(
41 int render_process_id
,
43 const gfx::Rect
& element_rect
) {
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
;
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
);
58 void SpeechRecognitionBubbleController::SetBubbleRecordingMode() {
59 ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECORDING_MODE
));
62 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode() {
63 ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECOGNIZING_MODE
));
66 void SpeechRecognitionBubbleController::SetBubbleMessage(
67 const base::string16
& text
) {
68 UIRequest
request(REQUEST_SET_MESSAGE
);
69 request
.message
= text
;
70 ProcessRequestInUiThread(request
);
73 bool SpeechRecognitionBubbleController::IsShowingMessage() const {
74 return last_request_issued_
== REQUEST_SET_MESSAGE
;
77 void SpeechRecognitionBubbleController::SetBubbleInputVolume(
80 UIRequest
request(REQUEST_SET_INPUT_VOLUME
);
81 request
.volume
= volume
;
82 request
.noise_volume
= noise_volume
;
83 ProcessRequestInUiThread(request
);
86 void SpeechRecognitionBubbleController::CloseBubble() {
88 base::AutoLock
auto_lock(lock_
);
89 current_bubble_session_id_
= kInvalidSessionId
;
91 ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE
));
94 void SpeechRecognitionBubbleController::CloseBubbleForRenderViewOnUIThread(
95 int render_process_id
, int render_view_id
) {
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
) {
103 current_bubble_session_id_
= kInvalidSessionId
;
105 ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE
));
108 int SpeechRecognitionBubbleController::GetActiveSessionID() {
109 base::AutoLock
auto_lock(lock_
);
110 return current_bubble_session_id_
;
113 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked(
114 SpeechRecognitionBubble::Button button
) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
116 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
118 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked
, this,
122 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
124 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
125 base::Bind(&SpeechRecognitionBubbleController::InvokeDelegateFocusChanged
,
129 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked(
130 SpeechRecognitionBubble::Button button
) {
131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
133 base::AutoLock
auto_lock(lock_
);
134 if (kInvalidSessionId
== current_bubble_session_id_
)
137 delegate_
->InfoBubbleButtonClicked(current_bubble_session_id_
, button
);
140 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged() {
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
143 base::AutoLock
auto_lock(lock_
);
144 if (kInvalidSessionId
== current_bubble_session_id_
)
147 delegate_
->InfoBubbleFocusChanged(current_bubble_session_id_
);
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
,
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
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())
168 switch (request
.type
) {
170 bubble_
.reset(SpeechRecognitionBubble::Create(
171 tab_util::GetWebContentsByID(request
.render_process_id
,
172 request
.render_view_id
),
173 this, request
.element_rect
));
175 if (!bubble_
.get()) {
176 // Could be null if tab or display rect were invalid.
177 // Simulate the cancel button being clicked to inform the delegate.
178 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
180 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked
,
181 this, SpeechRecognitionBubble::BUTTON_CANCEL
));
185 bubble_
->SetWarmUpMode();
187 case REQUEST_SET_RECORDING_MODE
:
188 bubble_
->SetRecordingMode();
190 case REQUEST_SET_RECOGNIZING_MODE
:
191 bubble_
->SetRecognizingMode();
193 case REQUEST_SET_MESSAGE
:
194 bubble_
->SetMessage(request
.message
);
196 case REQUEST_SET_INPUT_VOLUME
:
197 bubble_
->SetInputVolume(request
.volume
, request
.noise_volume
);
208 SpeechRecognitionBubbleController::UIRequest::UIRequest(RequestType type_value
)
212 render_process_id(0),
216 SpeechRecognitionBubbleController::UIRequest::~UIRequest() {
219 } // namespace speech