OLD | NEW |
1 // Copyright (c) 2011 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/speech_input_bubble_controller.h" | 5 #include "chrome/browser/speech/speech_recognition_bubble_controller.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "chrome/browser/tab_contents/tab_util.h" | 8 #include "chrome/browser/tab_contents/tab_util.h" |
9 #include "content/public/browser/browser_thread.h" | 9 #include "content/public/browser/browser_thread.h" |
10 #include "content/public/browser/notification_registrar.h" | 10 #include "content/public/browser/notification_registrar.h" |
11 #include "content/public/browser/notification_source.h" | 11 #include "content/public/browser/notification_source.h" |
12 #include "content/public/browser/notification_types.h" | 12 #include "content/public/browser/notification_types.h" |
13 #include "content/public/browser/web_contents.h" | 13 #include "content/public/browser/web_contents.h" |
14 #include "ui/gfx/rect.h" | 14 #include "ui/gfx/rect.h" |
15 | 15 |
16 using content::BrowserThread; | 16 using content::BrowserThread; |
17 using content::WebContents; | 17 using content::WebContents; |
18 | 18 |
19 namespace speech_input { | 19 namespace speech { |
20 | 20 |
21 SpeechInputBubbleController::SpeechInputBubbleController(Delegate* delegate) | 21 SpeechRecognitionBubbleController::SpeechRecognitionBubbleController( |
| 22 Delegate* delegate) |
22 : delegate_(delegate), | 23 : delegate_(delegate), |
23 current_bubble_caller_id_(0), | 24 current_bubble_caller_id_(0), |
24 registrar_(new content::NotificationRegistrar) { | 25 registrar_(new content::NotificationRegistrar) { |
25 } | 26 } |
26 | 27 |
27 SpeechInputBubbleController::~SpeechInputBubbleController() { | 28 SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() { |
28 DCHECK(bubbles_.empty()); | 29 DCHECK(bubbles_.empty()); |
29 } | 30 } |
30 | 31 |
31 void SpeechInputBubbleController::CreateBubble(int caller_id, | 32 void SpeechRecognitionBubbleController::CreateBubble( |
32 int render_process_id, | 33 int caller_id, |
33 int render_view_id, | 34 int render_process_id, |
34 const gfx::Rect& element_rect) { | 35 int render_view_id, |
| 36 const gfx::Rect& element_rect) { |
35 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 37 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
36 BrowserThread::PostTask( | 38 BrowserThread::PostTask( |
37 BrowserThread::UI, FROM_HERE, | 39 BrowserThread::UI, FROM_HERE, |
38 base::Bind(&SpeechInputBubbleController::CreateBubble, this, | 40 base::Bind(&SpeechRecognitionBubbleController::CreateBubble, this, |
39 caller_id, render_process_id, render_view_id, | 41 caller_id, render_process_id, render_view_id, element_rect)); |
40 element_rect)); | |
41 return; | 42 return; |
42 } | 43 } |
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
44 WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, | 45 WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, |
45 render_view_id); | 46 render_view_id); |
46 | 47 |
47 DCHECK_EQ(0u, bubbles_.count(caller_id)); | 48 DCHECK_EQ(0u, bubbles_.count(caller_id)); |
48 SpeechInputBubble* bubble = SpeechInputBubble::Create(web_contents, this, | 49 SpeechRecognitionBubble* bubble = SpeechRecognitionBubble::Create( |
49 element_rect); | 50 web_contents, this, element_rect); |
50 if (!bubble) { | 51 if (!bubble) { |
51 // Could be null if tab or display rect were invalid. | 52 // Could be null if tab or display rect were invalid. |
52 // Simulate the cancel button being clicked to inform the delegate. | 53 // Simulate the cancel button being clicked to inform the delegate. |
53 BrowserThread::PostTask( | 54 BrowserThread::PostTask( |
54 BrowserThread::IO, FROM_HERE, | 55 BrowserThread::IO, FROM_HERE, |
55 base::Bind( | 56 base::Bind( |
56 &SpeechInputBubbleController::InvokeDelegateButtonClicked, | 57 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
57 this, caller_id, SpeechInputBubble::BUTTON_CANCEL)); | 58 this, caller_id, SpeechRecognitionBubble::BUTTON_CANCEL)); |
58 return; | 59 return; |
59 } | 60 } |
60 | 61 |
61 bubbles_[caller_id] = bubble; | 62 bubbles_[caller_id] = bubble; |
62 | 63 |
63 UpdateTabContentsSubscription(caller_id, BUBBLE_ADDED); | 64 UpdateTabContentsSubscription(caller_id, BUBBLE_ADDED); |
64 } | 65 } |
65 | 66 |
66 void SpeechInputBubbleController::CloseBubble(int caller_id) { | 67 void SpeechRecognitionBubbleController::CloseBubble(int caller_id) { |
67 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0, 0); | 68 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0, 0); |
68 } | 69 } |
69 | 70 |
70 void SpeechInputBubbleController::SetBubbleWarmUpMode(int caller_id) { | 71 void SpeechRecognitionBubbleController::SetBubbleWarmUpMode(int caller_id) { |
71 ProcessRequestInUiThread(caller_id, REQUEST_SET_WARM_UP_MODE, | 72 ProcessRequestInUiThread(caller_id, REQUEST_SET_WARM_UP_MODE, |
72 string16(), 0, 0); | 73 string16(), 0, 0); |
73 } | 74 } |
74 | 75 |
75 void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) { | 76 void SpeechRecognitionBubbleController::SetBubbleRecordingMode(int caller_id) { |
76 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE, | 77 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE, |
77 string16(), 0, 0); | 78 string16(), 0, 0); |
78 } | 79 } |
79 | 80 |
80 void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) { | 81 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode( |
| 82 int caller_id) { |
81 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE, | 83 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE, |
82 string16(), 0, 0); | 84 string16(), 0, 0); |
83 } | 85 } |
84 | 86 |
85 void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id, | 87 void SpeechRecognitionBubbleController::SetBubbleInputVolume( |
86 float volume, | 88 int caller_id, float volume, float noise_volume) { |
87 float noise_volume) { | |
88 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(), | 89 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(), |
89 volume, noise_volume); | 90 volume, noise_volume); |
90 } | 91 } |
91 | 92 |
92 void SpeechInputBubbleController::SetBubbleMessage(int caller_id, | 93 void SpeechRecognitionBubbleController::SetBubbleMessage(int caller_id, |
93 const string16& text) { | 94 const string16& text) { |
94 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0, 0); | 95 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0, 0); |
95 } | 96 } |
96 | 97 |
97 void SpeechInputBubbleController::UpdateTabContentsSubscription( | 98 void SpeechRecognitionBubbleController::UpdateTabContentsSubscription( |
98 int caller_id, ManageSubscriptionAction action) { | 99 int caller_id, ManageSubscriptionAction action) { |
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
100 | 101 |
101 // If there are any other bubbles existing for the same TabContents, we would | 102 // If there are any other bubbles existing for the same TabContents, we would |
102 // have subscribed to tab close notifications on their behalf and we need to | 103 // have subscribed to tab close notifications on their behalf and we need to |
103 // stay registered. So we don't change the subscription in such cases. | 104 // stay registered. So we don't change the subscription in such cases. |
104 WebContents* web_contents = bubbles_[caller_id]->web_contents(); | 105 WebContents* web_contents = bubbles_[caller_id]->web_contents(); |
105 for (BubbleCallerIdMap::iterator iter = bubbles_.begin(); | 106 for (BubbleCallerIdMap::iterator iter = bubbles_.begin(); |
106 iter != bubbles_.end(); ++iter) { | 107 iter != bubbles_.end(); ++iter) { |
107 if (iter->second->web_contents() == web_contents && | 108 if (iter->second->web_contents() == web_contents && |
108 iter->first != caller_id) { | 109 iter->first != caller_id) { |
109 // At least one other bubble exists for the same TabContents. So don't | 110 // At least one other bubble exists for the same TabContents. So don't |
110 // make any change to the subscription. | 111 // make any change to the subscription. |
111 return; | 112 return; |
112 } | 113 } |
113 } | 114 } |
114 | 115 |
115 if (action == BUBBLE_ADDED) { | 116 if (action == BUBBLE_ADDED) { |
116 registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 117 registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
117 content::Source<WebContents>(web_contents)); | 118 content::Source<WebContents>(web_contents)); |
118 } else { | 119 } else { |
119 registrar_->Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 120 registrar_->Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
120 content::Source<WebContents>(web_contents)); | 121 content::Source<WebContents>(web_contents)); |
121 } | 122 } |
122 } | 123 } |
123 | 124 |
124 void SpeechInputBubbleController::Observe( | 125 void SpeechRecognitionBubbleController::Observe( |
125 int type, | 126 int type, |
126 const content::NotificationSource& source, | 127 const content::NotificationSource& source, |
127 const content::NotificationDetails& details) { | 128 const content::NotificationDetails& details) { |
128 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 129 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
129 // Cancel all bubbles and active recognition sessions for this tab. | 130 // Cancel all bubbles and active recognition sessions for this tab. |
130 WebContents* web_contents = content::Source<WebContents>(source).ptr(); | 131 WebContents* web_contents = content::Source<WebContents>(source).ptr(); |
131 BubbleCallerIdMap::iterator iter = bubbles_.begin(); | 132 BubbleCallerIdMap::iterator iter = bubbles_.begin(); |
132 while (iter != bubbles_.end()) { | 133 while (iter != bubbles_.end()) { |
133 if (iter->second->web_contents() == web_contents) { | 134 if (iter->second->web_contents() == web_contents) { |
134 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 135 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
135 base::Bind( | 136 base::Bind( |
136 &SpeechInputBubbleController::InvokeDelegateButtonClicked, | 137 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
137 this, iter->first, SpeechInputBubble::BUTTON_CANCEL)); | 138 this, iter->first, SpeechRecognitionBubble::BUTTON_CANCEL)); |
138 CloseBubble(iter->first); | 139 CloseBubble(iter->first); |
139 // We expect to have a very small number of items in this map so | 140 // We expect to have a very small number of items in this map so |
140 // redo-ing from start is ok. | 141 // redo-ing from start is ok. |
141 iter = bubbles_.begin(); | 142 iter = bubbles_.begin(); |
142 } else { | 143 } else { |
143 ++iter; | 144 ++iter; |
144 } | 145 } |
145 } | 146 } |
146 } else { | 147 } else { |
147 NOTREACHED() << "Unknown notification"; | 148 NOTREACHED() << "Unknown notification"; |
148 } | 149 } |
149 } | 150 } |
150 | 151 |
151 void SpeechInputBubbleController::ProcessRequestInUiThread( | 152 void SpeechRecognitionBubbleController::ProcessRequestInUiThread( |
152 int caller_id, RequestType type, const string16& text, float volume, | 153 int caller_id, RequestType type, const string16& text, float volume, |
153 float noise_volume) { | 154 float noise_volume) { |
154 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 155 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
155 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 156 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
156 &SpeechInputBubbleController::ProcessRequestInUiThread, this, | 157 &SpeechRecognitionBubbleController::ProcessRequestInUiThread, this, |
157 caller_id, type, text, volume, noise_volume)); | 158 caller_id, type, text, volume, noise_volume)); |
158 return; | 159 return; |
159 } | 160 } |
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
161 // The bubble may have been closed before we got a chance to process this | 162 // The bubble may have been closed before we got a chance to process this |
162 // request. So check before proceeding. | 163 // request. So check before proceeding. |
163 if (!bubbles_.count(caller_id)) | 164 if (!bubbles_.count(caller_id)) |
164 return; | 165 return; |
165 | 166 |
166 bool change_active_bubble = (type == REQUEST_SET_WARM_UP_MODE || | 167 bool change_active_bubble = (type == REQUEST_SET_WARM_UP_MODE || |
167 type == REQUEST_SET_MESSAGE); | 168 type == REQUEST_SET_MESSAGE); |
168 if (change_active_bubble) { | 169 if (change_active_bubble) { |
169 if (current_bubble_caller_id_ && current_bubble_caller_id_ != caller_id) | 170 if (current_bubble_caller_id_ && current_bubble_caller_id_ != caller_id) |
170 bubbles_[current_bubble_caller_id_]->Hide(); | 171 bubbles_[current_bubble_caller_id_]->Hide(); |
171 current_bubble_caller_id_ = caller_id; | 172 current_bubble_caller_id_ = caller_id; |
172 } | 173 } |
173 | 174 |
174 SpeechInputBubble* bubble = bubbles_[caller_id]; | 175 SpeechRecognitionBubble* bubble = bubbles_[caller_id]; |
175 switch (type) { | 176 switch (type) { |
176 case REQUEST_SET_WARM_UP_MODE: | 177 case REQUEST_SET_WARM_UP_MODE: |
177 bubble->SetWarmUpMode(); | 178 bubble->SetWarmUpMode(); |
178 break; | 179 break; |
179 case REQUEST_SET_RECORDING_MODE: | 180 case REQUEST_SET_RECORDING_MODE: |
180 bubble->SetRecordingMode(); | 181 bubble->SetRecordingMode(); |
181 break; | 182 break; |
182 case REQUEST_SET_RECOGNIZING_MODE: | 183 case REQUEST_SET_RECOGNIZING_MODE: |
183 bubble->SetRecognizingMode(); | 184 bubble->SetRecognizingMode(); |
184 break; | 185 break; |
(...skipping 12 matching lines...) Expand all Loading... |
197 break; | 198 break; |
198 default: | 199 default: |
199 NOTREACHED(); | 200 NOTREACHED(); |
200 break; | 201 break; |
201 } | 202 } |
202 | 203 |
203 if (change_active_bubble) | 204 if (change_active_bubble) |
204 bubble->Show(); | 205 bubble->Show(); |
205 } | 206 } |
206 | 207 |
207 void SpeechInputBubbleController::InfoBubbleButtonClicked( | 208 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked( |
208 SpeechInputBubble::Button button) { | 209 SpeechRecognitionBubble::Button button) { |
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
210 DCHECK(current_bubble_caller_id_); | 211 DCHECK(current_bubble_caller_id_); |
211 | 212 |
212 BrowserThread::PostTask( | 213 BrowserThread::PostTask( |
213 BrowserThread::IO, FROM_HERE, | 214 BrowserThread::IO, FROM_HERE, |
214 base::Bind( | 215 base::Bind( |
215 &SpeechInputBubbleController::InvokeDelegateButtonClicked, | 216 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
216 this, current_bubble_caller_id_, button)); | 217 this, current_bubble_caller_id_, button)); |
217 } | 218 } |
218 | 219 |
219 void SpeechInputBubbleController::InfoBubbleFocusChanged() { | 220 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() { |
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
221 DCHECK(current_bubble_caller_id_); | 222 DCHECK(current_bubble_caller_id_); |
222 | 223 |
223 int old_bubble_caller_id = current_bubble_caller_id_; | 224 int old_bubble_caller_id = current_bubble_caller_id_; |
224 current_bubble_caller_id_ = 0; | 225 current_bubble_caller_id_ = 0; |
225 | 226 |
226 BrowserThread::PostTask( | 227 BrowserThread::PostTask( |
227 BrowserThread::IO, FROM_HERE, | 228 BrowserThread::IO, FROM_HERE, |
228 base::Bind( | 229 base::Bind( |
229 &SpeechInputBubbleController::InvokeDelegateFocusChanged, | 230 &SpeechRecognitionBubbleController::InvokeDelegateFocusChanged, |
230 this, old_bubble_caller_id)); | 231 this, old_bubble_caller_id)); |
231 } | 232 } |
232 | 233 |
233 void SpeechInputBubbleController::InvokeDelegateButtonClicked( | 234 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked( |
234 int caller_id, SpeechInputBubble::Button button) { | 235 int caller_id, SpeechRecognitionBubble::Button button) { |
235 delegate_->InfoBubbleButtonClicked(caller_id, button); | 236 delegate_->InfoBubbleButtonClicked(caller_id, button); |
236 } | 237 } |
237 | 238 |
238 void SpeechInputBubbleController::InvokeDelegateFocusChanged(int caller_id) { | 239 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged( |
| 240 int caller_id) { |
239 delegate_->InfoBubbleFocusChanged(caller_id); | 241 delegate_->InfoBubbleFocusChanged(caller_id); |
240 } | 242 } |
241 | 243 |
242 } // namespace speech_input | 244 } // namespace speech |
OLD | NEW |