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/speech_recognition_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 { | 19 namespace speech { |
20 | 20 |
21 SpeechRecognitionBubbleController::SpeechRecognitionBubbleController( | 21 SpeechRecognitionBubbleController::SpeechRecognitionBubbleController( |
22 Delegate* delegate) | 22 Delegate* delegate) |
23 : delegate_(delegate), | 23 : delegate_(delegate), |
24 current_bubble_session_id_(0), | 24 current_bubble_session_id_(0), |
25 registrar_(new content::NotificationRegistrar) { | 25 registrar_(new content::NotificationRegistrar) { |
26 } | 26 } |
27 | 27 |
28 SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() { | |
29 DCHECK(bubbles_.empty()); | |
30 } | |
31 | |
32 void SpeechRecognitionBubbleController::CreateBubble( | 28 void SpeechRecognitionBubbleController::CreateBubble( |
33 int session_id, | 29 int session_id, |
34 int render_process_id, | 30 int render_process_id, |
35 int render_view_id, | 31 int render_view_id, |
36 const gfx::Rect& element_rect) { | 32 const gfx::Rect& element_rect) { |
37 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 33 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
38 BrowserThread::PostTask( | 34 BrowserThread::PostTask( |
39 BrowserThread::UI, FROM_HERE, | 35 BrowserThread::UI, FROM_HERE, |
40 base::Bind(&SpeechRecognitionBubbleController::CreateBubble, this, | 36 base::Bind(&SpeechRecognitionBubbleController::CreateBubble, this, |
41 session_id, render_process_id, render_view_id, | 37 session_id, render_process_id, render_view_id, |
(...skipping 16 matching lines...) Expand all Loading... |
58 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, | 54 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
59 this, session_id, SpeechRecognitionBubble::BUTTON_CANCEL)); | 55 this, session_id, SpeechRecognitionBubble::BUTTON_CANCEL)); |
60 return; | 56 return; |
61 } | 57 } |
62 | 58 |
63 bubbles_[session_id] = bubble; | 59 bubbles_[session_id] = bubble; |
64 | 60 |
65 UpdateTabContentsSubscription(session_id, BUBBLE_ADDED); | 61 UpdateTabContentsSubscription(session_id, BUBBLE_ADDED); |
66 } | 62 } |
67 | 63 |
68 void SpeechRecognitionBubbleController::CloseBubble(int session_id) { | |
69 ProcessRequestInUiThread(session_id, REQUEST_CLOSE, string16(), 0, 0); | |
70 } | |
71 | |
72 void SpeechRecognitionBubbleController::SetBubbleWarmUpMode(int session_id) { | 64 void SpeechRecognitionBubbleController::SetBubbleWarmUpMode(int session_id) { |
73 ProcessRequestInUiThread(session_id, REQUEST_SET_WARM_UP_MODE, | 65 ProcessRequestInUiThread(session_id, REQUEST_SET_WARM_UP_MODE, |
74 string16(), 0, 0); | 66 string16(), 0, 0); |
75 } | 67 } |
76 | 68 |
77 void SpeechRecognitionBubbleController::SetBubbleRecordingMode(int session_id) { | 69 void SpeechRecognitionBubbleController::SetBubbleRecordingMode(int session_id) { |
78 ProcessRequestInUiThread(session_id, REQUEST_SET_RECORDING_MODE, | 70 ProcessRequestInUiThread(session_id, REQUEST_SET_RECORDING_MODE, |
79 string16(), 0, 0); | 71 string16(), 0, 0); |
80 } | 72 } |
81 | 73 |
82 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode( | 74 void SpeechRecognitionBubbleController::SetBubbleRecognizingMode( |
83 int session_id) { | 75 int session_id) { |
84 ProcessRequestInUiThread(session_id, REQUEST_SET_RECOGNIZING_MODE, | 76 ProcessRequestInUiThread(session_id, REQUEST_SET_RECOGNIZING_MODE, |
85 string16(), 0, 0); | 77 string16(), 0, 0); |
86 } | 78 } |
87 | 79 |
| 80 void SpeechRecognitionBubbleController::SetBubbleMessage(int session_id, |
| 81 const string16& text) { |
| 82 ProcessRequestInUiThread(session_id, REQUEST_SET_MESSAGE, text, 0, 0); |
| 83 } |
| 84 |
88 void SpeechRecognitionBubbleController::SetBubbleInputVolume( | 85 void SpeechRecognitionBubbleController::SetBubbleInputVolume( |
89 int session_id, float volume, float noise_volume) { | 86 int session_id, float volume, float noise_volume) { |
90 ProcessRequestInUiThread(session_id, REQUEST_SET_INPUT_VOLUME, string16(), | 87 ProcessRequestInUiThread(session_id, REQUEST_SET_INPUT_VOLUME, string16(), |
91 volume, noise_volume); | 88 volume, noise_volume); |
92 } | 89 } |
93 | 90 |
94 void SpeechRecognitionBubbleController::SetBubbleMessage(int session_id, | 91 void SpeechRecognitionBubbleController::CloseBubble(int session_id) { |
95 const string16& text) { | 92 ProcessRequestInUiThread(session_id, REQUEST_CLOSE, string16(), 0, 0); |
96 ProcessRequestInUiThread(session_id, REQUEST_SET_MESSAGE, text, 0, 0); | |
97 } | 93 } |
98 | 94 |
99 void SpeechRecognitionBubbleController::UpdateTabContentsSubscription( | 95 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked( |
100 int session_id, ManageSubscriptionAction action) { | 96 SpeechRecognitionBubble::Button button) { |
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 98 DCHECK(current_bubble_session_id_); |
102 | 99 |
103 // If there are any other bubbles existing for the same WebContents, we would | 100 BrowserThread::PostTask( |
104 // have subscribed to tab close notifications on their behalf and we need to | 101 BrowserThread::IO, FROM_HERE, |
105 // stay registered. So we don't change the subscription in such cases. | 102 base::Bind( |
106 WebContents* web_contents = bubbles_[session_id]->GetWebContents(); | 103 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
107 for (BubbleSessionIdMap::iterator iter = bubbles_.begin(); | 104 this, current_bubble_session_id_, button)); |
108 iter != bubbles_.end(); ++iter) { | 105 } |
109 if (iter->second->GetWebContents() == web_contents && | |
110 iter->first != session_id) { | |
111 // At least one other bubble exists for the same WebContents. So don't | |
112 // make any change to the subscription. | |
113 return; | |
114 } | |
115 } | |
116 | 106 |
117 if (action == BUBBLE_ADDED) { | 107 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() { |
118 registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
119 content::Source<WebContents>(web_contents)); | 109 DCHECK(current_bubble_session_id_); |
120 } else { | 110 |
121 registrar_->Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 111 int old_bubble_session_id = current_bubble_session_id_; |
122 content::Source<WebContents>(web_contents)); | 112 current_bubble_session_id_ = 0; |
123 } | 113 |
| 114 BrowserThread::PostTask( |
| 115 BrowserThread::IO, FROM_HERE, |
| 116 base::Bind( |
| 117 &SpeechRecognitionBubbleController::InvokeDelegateFocusChanged, |
| 118 this, old_bubble_session_id)); |
124 } | 119 } |
125 | 120 |
126 void SpeechRecognitionBubbleController::Observe( | 121 void SpeechRecognitionBubbleController::Observe( |
127 int type, | 122 int type, |
128 const content::NotificationSource& source, | 123 const content::NotificationSource& source, |
129 const content::NotificationDetails& details) { | 124 const content::NotificationDetails& details) { |
130 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 125 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
131 // Cancel all bubbles and active recognition sessions for this tab. | 126 // Cancel all bubbles and active recognition sessions for this tab. |
132 WebContents* web_contents = content::Source<WebContents>(source).ptr(); | 127 WebContents* web_contents = content::Source<WebContents>(source).ptr(); |
133 BubbleSessionIdMap::iterator iter = bubbles_.begin(); | 128 BubbleSessionIdMap::iterator iter = bubbles_.begin(); |
134 while (iter != bubbles_.end()) { | 129 while (iter != bubbles_.end()) { |
135 if (iter->second->GetWebContents() == web_contents) { | 130 if (iter->second->GetWebContents() == web_contents) { |
136 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 131 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
137 base::Bind( | 132 base::Bind( |
138 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, | 133 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, |
139 this, iter->first, SpeechRecognitionBubble::BUTTON_CANCEL)); | 134 this, iter->first, SpeechRecognitionBubble::BUTTON_CANCEL)); |
140 CloseBubble(iter->first); | 135 CloseBubble(iter->first); |
141 // We expect to have a very small number of items in this map so | 136 // We expect to have a very small number of items in this map so |
142 // redo-ing from start is ok. | 137 // redo-ing from start is ok. |
143 iter = bubbles_.begin(); | 138 iter = bubbles_.begin(); |
144 } else { | 139 } else { |
145 ++iter; | 140 ++iter; |
146 } | 141 } |
147 } | 142 } |
148 } else { | 143 } else { |
149 NOTREACHED() << "Unknown notification"; | 144 NOTREACHED() << "Unknown notification"; |
150 } | 145 } |
151 } | 146 } |
152 | 147 |
| 148 SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() { |
| 149 DCHECK(bubbles_.empty()); |
| 150 } |
| 151 |
| 152 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked( |
| 153 int session_id, SpeechRecognitionBubble::Button button) { |
| 154 delegate_->InfoBubbleButtonClicked(session_id, button); |
| 155 } |
| 156 |
| 157 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged( |
| 158 int session_id) { |
| 159 delegate_->InfoBubbleFocusChanged(session_id); |
| 160 } |
| 161 |
153 void SpeechRecognitionBubbleController::ProcessRequestInUiThread( | 162 void SpeechRecognitionBubbleController::ProcessRequestInUiThread( |
154 int session_id, RequestType type, const string16& text, float volume, | 163 int session_id, RequestType type, const string16& text, float volume, |
155 float noise_volume) { | 164 float noise_volume) { |
156 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 165 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
157 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 166 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
158 &SpeechRecognitionBubbleController::ProcessRequestInUiThread, this, | 167 &SpeechRecognitionBubbleController::ProcessRequestInUiThread, this, |
159 session_id, type, text, volume, noise_volume)); | 168 session_id, type, text, volume, noise_volume)); |
160 return; | 169 return; |
161 } | 170 } |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 break; | 208 break; |
200 default: | 209 default: |
201 NOTREACHED(); | 210 NOTREACHED(); |
202 break; | 211 break; |
203 } | 212 } |
204 | 213 |
205 if (change_active_bubble) | 214 if (change_active_bubble) |
206 bubble->Show(); | 215 bubble->Show(); |
207 } | 216 } |
208 | 217 |
209 void SpeechRecognitionBubbleController::InfoBubbleButtonClicked( | 218 void SpeechRecognitionBubbleController::UpdateTabContentsSubscription( |
210 SpeechRecognitionBubble::Button button) { | 219 int session_id, ManageSubscriptionAction action) { |
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
212 DCHECK(current_bubble_session_id_); | |
213 | 221 |
214 BrowserThread::PostTask( | 222 // If there are any other bubbles existing for the same WebContents, we would |
215 BrowserThread::IO, FROM_HERE, | 223 // have subscribed to tab close notifications on their behalf and we need to |
216 base::Bind( | 224 // stay registered. So we don't change the subscription in such cases. |
217 &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked, | 225 WebContents* web_contents = bubbles_[session_id]->GetWebContents(); |
218 this, current_bubble_session_id_, button)); | 226 for (BubbleSessionIdMap::iterator iter = bubbles_.begin(); |
219 } | 227 iter != bubbles_.end(); ++iter) { |
| 228 if (iter->second->GetWebContents() == web_contents && |
| 229 iter->first != session_id) { |
| 230 // At least one other bubble exists for the same WebContents. So don't |
| 231 // make any change to the subscription. |
| 232 return; |
| 233 } |
| 234 } |
220 | 235 |
221 void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() { | 236 if (action == BUBBLE_ADDED) { |
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 237 registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
223 DCHECK(current_bubble_session_id_); | 238 content::Source<WebContents>(web_contents)); |
224 | 239 } else { |
225 int old_bubble_session_id = current_bubble_session_id_; | 240 registrar_->Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
226 current_bubble_session_id_ = 0; | 241 content::Source<WebContents>(web_contents)); |
227 | 242 } |
228 BrowserThread::PostTask( | |
229 BrowserThread::IO, FROM_HERE, | |
230 base::Bind( | |
231 &SpeechRecognitionBubbleController::InvokeDelegateFocusChanged, | |
232 this, old_bubble_session_id)); | |
233 } | |
234 | |
235 void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked( | |
236 int session_id, SpeechRecognitionBubble::Button button) { | |
237 delegate_->InfoBubbleButtonClicked(session_id, button); | |
238 } | |
239 | |
240 void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged( | |
241 int session_id) { | |
242 delegate_->InfoBubbleFocusChanged(session_id); | |
243 } | 243 } |
244 | 244 |
245 } // namespace speech | 245 } // namespace speech |
OLD | NEW |