Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: chrome/browser/speech/speech_input_extension_manager.cc

Issue 8386074: Add a tray notification UI for speech input recording in the extension API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: creating the notification object dynamically on first use. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/extensions/speech_input/extension_speech_input_manager. h" 5 #include "chrome/browser/speech/speech_input_extension_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_writer.h" 8 #include "base/json/json_writer.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_event_router.h" 11 #include "chrome/browser/extensions/extension_event_router.h"
12 #include "chrome/browser/extensions/speech_input/extension_speech_input_api_cons tants.h" 12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/profiles/profile_dependency_manager.h" 15 #include "chrome/browser/profiles/profile_dependency_manager.h"
15 #include "chrome/browser/profiles/profile_keyed_service.h" 16 #include "chrome/browser/profiles/profile_keyed_service.h"
16 #include "chrome/browser/profiles/profile_keyed_service_factory.h" 17 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
18 #include "chrome/browser/speech/speech_input_extension_notification.h"
17 #include "chrome/common/chrome_notification_types.h" 19 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/extensions/extension.h" 20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/pref_names.h"
19 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_service.h" 23 #include "content/public/browser/notification_service.h"
21 24
22 using content::BrowserThread; 25 using content::BrowserThread;
23
24 using namespace speech_input; 26 using namespace speech_input;
25 27
26 namespace constants = extension_speech_input_api_constants; 28 namespace {
27 29
28 namespace { 30 const char kErrorNoRecordingDeviceFound[] = "noRecordingDeviceFound";
31 const char kErrorRecordingDeviceInUse[] = "recordingDeviceInUse";
32 const char kErrorUnableToStart[] = "unableToStart";
33 const char kErrorRequestDenied[] = "requestDenied";
34 const char kErrorRequestInProgress[] = "requestInProgress";
35 const char kErrorInvalidOperation[] = "invalidOperation";
36
37 const char kErrorCodeKey[] = "code";
38 const char kErrorCaptureError[] = "captureError";
39 const char kErrorNetworkError[] = "networkError";
40 const char kErrorNoSpeechHeard[] = "noSpeechHeard";
41 const char kErrorNoResults[] = "noResults";
42
43 const char kUtteranceKey[] = "utterance";
44 const char kConfidenceKey[] = "confidence";
45 const char kHypothesesKey[] = "hypotheses";
46
47 const char kOnErrorEvent[] = "experimental.speechInput.onError";
48 const char kOnResultEvent[] = "experimental.speechInput.onResult";
49 const char kOnSoundStartEvent[] = "experimental.speechInput.onSoundStart";
50 const char kOnSoundEndEvent[] = "experimental.speechInput.onSoundEnd";
29 51
30 // Caller id provided to the speech recognizer. Since only one extension can 52 // Caller id provided to the speech recognizer. Since only one extension can
31 // be recording on the same time a constant value is enough as id. 53 // be recording on the same time a constant value is enough as id.
32 static const int kSpeechCallerId = 1; 54 static const int kSpeechCallerId = 1;
33 55
34 // Wrap an ExtensionSpeechInputManager using scoped_refptr to avoid 56 // Wrap an SpeechInputExtensionManager using scoped_refptr to avoid
35 // assertion failures on destruction because of not using release(). 57 // assertion failures on destruction because of not using release().
36 class ExtensionSpeechInputManagerWrapper : public ProfileKeyedService { 58 class SpeechInputExtensionManagerWrapper : public ProfileKeyedService {
37 public: 59 public:
38 explicit ExtensionSpeechInputManagerWrapper( 60 explicit SpeechInputExtensionManagerWrapper(
39 ExtensionSpeechInputManager* manager) 61 SpeechInputExtensionManager* manager)
40 : manager_(manager) {} 62 : manager_(manager) {}
41 63
42 virtual ~ExtensionSpeechInputManagerWrapper() {} 64 virtual ~SpeechInputExtensionManagerWrapper() {}
43 65
44 ExtensionSpeechInputManager* manager() const { return manager_.get(); } 66 SpeechInputExtensionManager* manager() const { return manager_.get(); }
45 67
46 private: 68 private:
47 // Methods from ProfileKeyedService. 69 // Methods from ProfileKeyedService.
48 virtual void Shutdown() OVERRIDE { 70 virtual void Shutdown() OVERRIDE {
49 manager()->ShutdownOnUIThread(); 71 manager()->ShutdownOnUIThread();
50 } 72 }
51 73
52 scoped_refptr<ExtensionSpeechInputManager> manager_; 74 scoped_refptr<SpeechInputExtensionManager> manager_;
53 }; 75 };
54 76
55 } 77 }
56 78
57 // Factory for ExtensionSpeechInputManagers as profile keyed services. 79 // Factory for SpeechInputExtensionManagers as profile keyed services.
58 class ExtensionSpeechInputManager::Factory : public ProfileKeyedServiceFactory { 80 class SpeechInputExtensionManager::Factory : public ProfileKeyedServiceFactory {
59 public: 81 public:
60 static void Initialize(); 82 static void Initialize();
61 static Factory* GetInstance(); 83 static Factory* GetInstance();
62 84
63 ExtensionSpeechInputManagerWrapper* GetForProfile(Profile* profile); 85 SpeechInputExtensionManagerWrapper* GetForProfile(Profile* profile);
64 86
65 private: 87 private:
66 friend struct DefaultSingletonTraits<Factory>; 88 friend struct DefaultSingletonTraits<Factory>;
67 89
68 Factory(); 90 Factory();
69 virtual ~Factory(); 91 virtual ~Factory();
70 92
71 // ProfileKeyedServiceFactory methods: 93 // ProfileKeyedServiceFactory methods:
72 virtual ProfileKeyedService* BuildServiceInstanceFor( 94 virtual ProfileKeyedService* BuildServiceInstanceFor(
73 Profile* profile) const OVERRIDE; 95 Profile* profile) const OVERRIDE;
74 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return false; } 96 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return false; }
75 virtual bool ServiceIsNULLWhileTesting() OVERRIDE { return true; } 97 virtual bool ServiceIsNULLWhileTesting() OVERRIDE { return true; }
76 virtual bool ServiceIsCreatedWithProfile() OVERRIDE { return true; } 98 virtual bool ServiceIsCreatedWithProfile() OVERRIDE { return true; }
77 99
78 DISALLOW_COPY_AND_ASSIGN(Factory); 100 DISALLOW_COPY_AND_ASSIGN(Factory);
79 }; 101 };
80 102
81 void ExtensionSpeechInputManager::Factory::Initialize() { 103 void SpeechInputExtensionManager::Factory::Initialize() {
82 GetInstance(); 104 GetInstance();
83 } 105 }
84 106
85 ExtensionSpeechInputManager::Factory* 107 SpeechInputExtensionManager::Factory*
86 ExtensionSpeechInputManager::Factory::GetInstance() { 108 SpeechInputExtensionManager::Factory::GetInstance() {
87 return Singleton<ExtensionSpeechInputManager::Factory>::get(); 109 return Singleton<SpeechInputExtensionManager::Factory>::get();
88 } 110 }
89 111
90 ExtensionSpeechInputManagerWrapper* 112 SpeechInputExtensionManagerWrapper*
91 ExtensionSpeechInputManager::Factory::GetForProfile( 113 SpeechInputExtensionManager::Factory::GetForProfile(
92 Profile* profile) { 114 Profile* profile) {
93 return static_cast<ExtensionSpeechInputManagerWrapper*>( 115 return static_cast<SpeechInputExtensionManagerWrapper*>(
94 GetServiceForProfile(profile, true)); 116 GetServiceForProfile(profile, true));
95 } 117 }
96 118
97 ExtensionSpeechInputManager::Factory::Factory() 119 SpeechInputExtensionManager::Factory::Factory()
98 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { 120 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) {
99 } 121 }
100 122
101 ExtensionSpeechInputManager::Factory::~Factory() { 123 SpeechInputExtensionManager::Factory::~Factory() {
102 } 124 }
103 125
104 ProfileKeyedService* 126 ProfileKeyedService*
105 ExtensionSpeechInputManager::Factory::BuildServiceInstanceFor( 127 SpeechInputExtensionManager::Factory::BuildServiceInstanceFor(
106 Profile* profile) const { 128 Profile* profile) const {
107 scoped_refptr<ExtensionSpeechInputManager> manager( 129 scoped_refptr<SpeechInputExtensionManager> manager(
108 new ExtensionSpeechInputManager(profile)); 130 new SpeechInputExtensionManager(profile));
109 return new ExtensionSpeechInputManagerWrapper(manager); 131 return new SpeechInputExtensionManagerWrapper(manager);
110 } 132 }
111 133
112 ExtensionSpeechInterface::ExtensionSpeechInterface() { 134 SpeechInputExtensionInterface::SpeechInputExtensionInterface() {
113 } 135 }
114 136
115 ExtensionSpeechInterface::~ExtensionSpeechInterface() { 137 SpeechInputExtensionInterface::~SpeechInputExtensionInterface() {
116 } 138 }
117 139
118 ExtensionSpeechInputManager::ExtensionSpeechInputManager(Profile* profile) 140 SpeechInputExtensionManager::SpeechInputExtensionManager(Profile* profile)
119 : profile_(profile), 141 : profile_(profile),
120 state_(kIdle), 142 state_(kIdle),
121 speech_interface_(NULL) { 143 speech_interface_(NULL) {
122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 144 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
123 content::Source<Profile>(profile_)); 145 content::Source<Profile>(profile_));
124 } 146 }
125 147
126 ExtensionSpeechInputManager::~ExtensionSpeechInputManager() { 148 SpeechInputExtensionManager::~SpeechInputExtensionManager() {
127 } 149 }
128 150
129 ExtensionSpeechInputManager* ExtensionSpeechInputManager::GetForProfile( 151 SpeechInputExtensionManager* SpeechInputExtensionManager::GetForProfile(
130 Profile* profile) { 152 Profile* profile) {
131 ExtensionSpeechInputManagerWrapper *wrapper = 153 SpeechInputExtensionManagerWrapper *wrapper =
132 Factory::GetInstance()->GetForProfile(profile); 154 Factory::GetInstance()->GetForProfile(profile);
133 if (!wrapper) 155 if (!wrapper)
134 return NULL; 156 return NULL;
135 return wrapper->manager(); 157 return wrapper->manager();
136 } 158 }
137 159
138 void ExtensionSpeechInputManager::InitializeFactory() { 160 void SpeechInputExtensionManager::InitializeFactory() {
139 Factory::Initialize(); 161 Factory::Initialize();
140 } 162 }
141 163
142 void ExtensionSpeechInputManager::Observe(int type, 164 void SpeechInputExtensionManager::Observe(int type,
143 const content::NotificationSource& source, 165 const content::NotificationSource& source,
144 const content::NotificationDetails& details) { 166 const content::NotificationDetails& details) {
145 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 167 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
146 ExtensionUnloaded( 168 ExtensionUnloaded(
147 content::Details<UnloadedExtensionInfo>(details)->extension->id()); 169 content::Details<UnloadedExtensionInfo>(details)->extension->id());
148 } else { 170 } else {
149 NOTREACHED(); 171 NOTREACHED();
150 } 172 }
151 } 173 }
152 174
153 void ExtensionSpeechInputManager::ShutdownOnUIThread() { 175 void SpeechInputExtensionManager::ShutdownOnUIThread() {
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
155 VLOG(1) << "Profile shutting down."; 177 VLOG(1) << "Profile shutting down.";
156 178
157 base::AutoLock auto_lock(state_lock_); 179 base::AutoLock auto_lock(state_lock_);
158 DCHECK(state_ != kShutdown); 180 DCHECK(state_ != kShutdown);
159 if (state_ != kIdle) { 181 if (state_ != kIdle) {
182 DCHECK(notification_.get());
183 notification_->Hide();
160 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 184 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
161 base::Bind(&ExtensionSpeechInputManager::ForceStopOnIOThread, this)); 185 base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this));
162 } 186 }
163 state_ = kShutdown; 187 state_ = kShutdown;
164 VLOG(1) << "Entering the shutdown sink state."; 188 VLOG(1) << "Entering the shutdown sink state.";
165 registrar_.RemoveAll(); 189 registrar_.RemoveAll();
166 profile_ = NULL; 190 profile_ = NULL;
167 } 191 }
168 192
169 void ExtensionSpeechInputManager::ExtensionUnloaded( 193 void SpeechInputExtensionManager::ExtensionUnloaded(
170 const std::string& extension_id) { 194 const std::string& extension_id) {
171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
172 196
173 base::AutoLock auto_lock(state_lock_); 197 base::AutoLock auto_lock(state_lock_);
174 if (state_ == kShutdown) 198 if (state_ == kShutdown)
175 return; 199 return;
176 200
177 VLOG(1) << "Extension unloaded. Requesting to enforce stop..."; 201 VLOG(1) << "Extension unloaded. Requesting to enforce stop...";
178 if (extension_id_in_use_ == extension_id) { 202 if (extension_id_in_use_ == extension_id) {
179 if (state_ != kIdle) { 203 if (state_ != kIdle) {
180 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 204 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
181 base::Bind(&ExtensionSpeechInputManager::ForceStopOnIOThread, this)); 205 base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this));
182 } 206 }
183 } 207 }
184 } 208 }
185 209
186 void ExtensionSpeechInputManager::SetExtensionSpeechInterface( 210 void SpeechInputExtensionManager::SetSpeechInputExtensionInterface(
187 ExtensionSpeechInterface* interface) { 211 SpeechInputExtensionInterface* interface) {
188 speech_interface_ = interface; 212 speech_interface_ = interface;
189 } 213 }
190 214
191 ExtensionSpeechInterface* 215 SpeechInputExtensionInterface*
192 ExtensionSpeechInputManager::GetExtensionSpeechInterface() { 216 SpeechInputExtensionManager::GetSpeechInputExtensionInterface() {
193 return speech_interface_ ? speech_interface_ : this; 217 return speech_interface_ ? speech_interface_ : this;
194 } 218 }
195 219
196 void ExtensionSpeechInputManager::ResetToIdleState() { 220 void SpeechInputExtensionManager::ResetToIdleState() {
197 VLOG(1) << "State changed to idle. Deassociating any extensions."; 221 VLOG(1) << "State changed to idle. Deassociating any extensions.";
198 state_ = kIdle; 222 state_ = kIdle;
199 extension_id_in_use_.clear(); 223 extension_id_in_use_.clear();
200 } 224 }
201 225
202 void ExtensionSpeechInputManager::SetRecognitionResult( 226 void SpeechInputExtensionManager::SetRecognitionResult(
203 int caller_id, 227 int caller_id,
204 const SpeechInputResult& result) { 228 const SpeechInputResult& result) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
206 DCHECK_EQ(caller_id, kSpeechCallerId); 230 DCHECK_EQ(caller_id, kSpeechCallerId);
207 231
208 // Stopping will start the disassociation with the extension. 232 // Stopping will start the disassociation with the extension.
209 // Make a copy to report the results to the proper one. 233 // Make a copy to report the results to the proper one.
210 std::string extension_id = extension_id_in_use_; 234 std::string extension_id = extension_id_in_use_;
211 ForceStopOnIOThread(); 235 ForceStopOnIOThread();
212 236
213 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 237 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
214 base::Bind(&ExtensionSpeechInputManager::SetRecognitionResultOnUIThread, 238 base::Bind(&SpeechInputExtensionManager::SetRecognitionResultOnUIThread,
215 this, result, extension_id)); 239 this, result, extension_id));
216 } 240 }
217 241
218 void ExtensionSpeechInputManager::SetRecognitionResultOnUIThread( 242 void SpeechInputExtensionManager::SetRecognitionResultOnUIThread(
219 const SpeechInputResult& result, const std::string& extension_id) { 243 const SpeechInputResult& result, const std::string& extension_id) {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
221 245
222 ListValue args; 246 ListValue args;
223 DictionaryValue* js_event = new DictionaryValue(); 247 DictionaryValue* js_event = new DictionaryValue();
224 args.Append(js_event); 248 args.Append(js_event);
225 249
226 ListValue* js_hypothesis_array = new ListValue(); 250 ListValue* js_hypothesis_array = new ListValue();
227 js_event->Set(constants::kHypothesesKey, js_hypothesis_array); 251 js_event->Set(kHypothesesKey, js_hypothesis_array);
228 252
229 for (size_t i = 0; i < result.hypotheses.size(); ++i) { 253 for (size_t i = 0; i < result.hypotheses.size(); ++i) {
230 const SpeechInputHypothesis& hypothesis = result.hypotheses[i]; 254 const SpeechInputHypothesis& hypothesis = result.hypotheses[i];
231 255
232 DictionaryValue* js_hypothesis_object = new DictionaryValue(); 256 DictionaryValue* js_hypothesis_object = new DictionaryValue();
233 js_hypothesis_array->Append(js_hypothesis_object); 257 js_hypothesis_array->Append(js_hypothesis_object);
234 258
235 js_hypothesis_object->SetString(constants::kUtteranceKey, 259 js_hypothesis_object->SetString(kUtteranceKey,
236 UTF16ToUTF8(hypothesis.utterance)); 260 UTF16ToUTF8(hypothesis.utterance));
237 js_hypothesis_object->SetDouble(constants::kConfidenceKey, 261 js_hypothesis_object->SetDouble(kConfidenceKey,
238 hypothesis.confidence); 262 hypothesis.confidence);
239 } 263 }
240 264
241 std::string json_args; 265 std::string json_args;
242 base::JSONWriter::Write(&args, false, &json_args); 266 base::JSONWriter::Write(&args, false, &json_args);
243 VLOG(1) << "Results: " << json_args; 267 VLOG(1) << "Results: " << json_args;
244 DispatchEventToExtension(extension_id, constants::kOnResultEvent, json_args); 268 DispatchEventToExtension(extension_id, kOnResultEvent, json_args);
245 } 269 }
246 270
247 void ExtensionSpeechInputManager::DidStartReceivingAudio(int caller_id) { 271 void SpeechInputExtensionManager::DidStartReceivingAudio(int caller_id) {
248 VLOG(1) << "DidStartReceivingAudio"; 272 VLOG(1) << "DidStartReceivingAudio";
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
250 DCHECK_EQ(caller_id, kSpeechCallerId); 274 DCHECK_EQ(caller_id, kSpeechCallerId);
251 275
252 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 276 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
253 base::Bind(&ExtensionSpeechInputManager::DidStartReceivingAudioOnUIThread, 277 base::Bind(&SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread,
254 this)); 278 this));
255 } 279 }
256 280
257 void ExtensionSpeechInputManager::DidCompleteRecording(int caller_id) { 281 void SpeechInputExtensionManager::DidCompleteRecording(int caller_id) {
258 DCHECK_EQ(caller_id, kSpeechCallerId); 282 DCHECK_EQ(caller_id, kSpeechCallerId);
259 } 283 }
260 284
261 void ExtensionSpeechInputManager::DidCompleteRecognition(int caller_id) { 285 void SpeechInputExtensionManager::DidCompleteRecognition(int caller_id) {
262 DCHECK_EQ(caller_id, kSpeechCallerId); 286 DCHECK_EQ(caller_id, kSpeechCallerId);
263 } 287 }
264 288
265 void ExtensionSpeechInputManager::DidStartReceivingAudioOnUIThread() { 289 void SpeechInputExtensionManager::DidStartReceivingAudioOnUIThread() {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
267 291
268 base::AutoLock auto_lock(state_lock_); 292 base::AutoLock auto_lock(state_lock_);
269 if (state_ == kShutdown) 293 if (state_ == kShutdown)
270 return; 294 return;
271 295
272 DCHECK_EQ(state_, kStarting); 296 DCHECK_EQ(state_, kStarting);
273 VLOG(1) << "State changed to recording"; 297 VLOG(1) << "State changed to recording";
274 state_ = kRecording; 298 state_ = kRecording;
275 299
300 const Extension* extension = profile_->GetExtensionService()->
301 GetExtensionById(extension_id_in_use_, true);
302 DCHECK(extension);
303
304 bool show_notification = !profile_->GetPrefs()->GetBoolean(
305 prefs::kSpeechInputTrayNotificationShown);
306
307 if (!notification_.get())
308 notification_.reset(new SpeechInputExtensionNotification(profile_));
309 notification_->Show(extension, show_notification);
310
311 if (show_notification) {
312 profile_->GetPrefs()->SetBoolean(
313 prefs::kSpeechInputTrayNotificationShown, true);
314 }
315
276 VLOG(1) << "Sending start notification"; 316 VLOG(1) << "Sending start notification";
277 content::NotificationService::current()->Notify( 317 content::NotificationService::current()->Notify(
278 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED, 318 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED,
279 content::Source<Profile>(profile_), 319 content::Source<Profile>(profile_),
280 content::Details<std::string>(&extension_id_in_use_)); 320 content::Details<std::string>(&extension_id_in_use_));
281 } 321 }
282 322
283 void ExtensionSpeechInputManager::OnRecognizerError( 323 void SpeechInputExtensionManager::OnRecognizerError(
284 int caller_id, SpeechInputError error) { 324 int caller_id, SpeechInputError error) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
286 DCHECK_EQ(caller_id, kSpeechCallerId); 326 DCHECK_EQ(caller_id, kSpeechCallerId);
287 VLOG(1) << "OnRecognizerError: " << error; 327 VLOG(1) << "OnRecognizerError: " << error;
288 328
289 base::AutoLock auto_lock(state_lock_); 329 base::AutoLock auto_lock(state_lock_);
290 if (state_ == kShutdown) 330 if (state_ == kShutdown)
291 return; 331 return;
292 332
293 // Release the recognizer object. 333 // Release the recognizer object.
294 GetExtensionSpeechInterface()->StopRecording(true); 334 GetSpeechInputExtensionInterface()->StopRecording(true);
295 335
296 std::string event_error_code; 336 std::string event_error_code;
297 bool report_to_event = true; 337 bool report_to_event = true;
298 338
299 switch (error) { 339 switch (error) {
300 case kErrorNone: 340 case kErrorNone:
301 break; 341 break;
302 342
303 case kErrorAudio: 343 case kErrorAudio:
304 if (state_ == kStarting) { 344 if (state_ == kStarting) {
305 event_error_code = constants::kErrorUnableToStart; 345 event_error_code = kErrorUnableToStart;
306 report_to_event = false; 346 report_to_event = false;
307 } else { 347 } else {
308 event_error_code = constants::kErrorCaptureError; 348 event_error_code = kErrorCaptureError;
309 } 349 }
310 break; 350 break;
311 351
312 case kErrorNetwork: 352 case kErrorNetwork:
313 event_error_code = constants::kErrorNetworkError; 353 event_error_code = kErrorNetworkError;
314 break; 354 break;
315 355
316 case kErrorBadGrammar: 356 case kErrorBadGrammar:
317 // No error is returned on invalid language, for example. 357 // No error is returned on invalid language, for example.
318 // To avoid confusion about when this is would be fired, the invalid 358 // To avoid confusion about when this is would be fired, the invalid
319 // params error is not being exposed to the onError event. 359 // params error is not being exposed to the onError event.
320 event_error_code = constants::kErrorUnableToStart; 360 event_error_code = kErrorUnableToStart;
321 break; 361 break;
322 362
323 case kErrorNoSpeech: 363 case kErrorNoSpeech:
324 event_error_code = constants::kErrorNoSpeechHeard; 364 event_error_code = kErrorNoSpeechHeard;
325 break; 365 break;
326 366
327 case kErrorNoMatch: 367 case kErrorNoMatch:
328 event_error_code = constants::kErrorNoResults; 368 event_error_code = kErrorNoResults;
329 break; 369 break;
330 370
331 // The remaining kErrorAborted case should never be returned by the server. 371 // The remaining kErrorAborted case should never be returned by the server.
332 default: 372 default:
333 NOTREACHED(); 373 NOTREACHED();
334 } 374 }
335 375
336 if (!event_error_code.empty()) { 376 if (!event_error_code.empty()) {
337 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 377 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
338 base::Bind(&ExtensionSpeechInputManager::DispatchError, 378 base::Bind(&SpeechInputExtensionManager::DispatchError,
339 this, event_error_code, report_to_event)); 379 this, event_error_code, report_to_event));
340 } 380 }
341 } 381 }
342 382
343 void ExtensionSpeechInputManager::DidCompleteEnvironmentEstimation( 383 void SpeechInputExtensionManager::DidCompleteEnvironmentEstimation(
344 int caller_id) { 384 int caller_id) {
345 DCHECK_EQ(caller_id, kSpeechCallerId); 385 DCHECK_EQ(caller_id, kSpeechCallerId);
346 } 386 }
347 387
348 void ExtensionSpeechInputManager::DidStartReceivingSpeech(int caller_id) { 388 void SpeechInputExtensionManager::DidStartReceivingSpeech(int caller_id) {
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
350 DCHECK_EQ(caller_id, kSpeechCallerId); 390 DCHECK_EQ(caller_id, kSpeechCallerId);
351 VLOG(1) << "DidStartReceivingSpeech"; 391 VLOG(1) << "DidStartReceivingSpeech";
352 392
353 std::string json_args; 393 std::string json_args;
354 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 394 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
355 base::Bind(&ExtensionSpeechInputManager::DispatchEventToExtension, 395 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension,
356 this, extension_id_in_use_, std::string(constants::kOnSoundStartEvent), 396 this, extension_id_in_use_, std::string(kOnSoundStartEvent),
357 json_args)); 397 json_args));
358 } 398 }
359 399
360 void ExtensionSpeechInputManager::DidStopReceivingSpeech(int caller_id) { 400 void SpeechInputExtensionManager::DidStopReceivingSpeech(int caller_id) {
361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
362 DCHECK_EQ(caller_id, kSpeechCallerId); 402 DCHECK_EQ(caller_id, kSpeechCallerId);
363 VLOG(1) << "DidStopReceivingSpeech"; 403 VLOG(1) << "DidStopReceivingSpeech";
364 404
365 std::string json_args; 405 std::string json_args;
366 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 406 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
367 base::Bind(&ExtensionSpeechInputManager::DispatchEventToExtension, 407 base::Bind(&SpeechInputExtensionManager::DispatchEventToExtension,
368 this, extension_id_in_use_, std::string(constants::kOnSoundEndEvent), 408 this, extension_id_in_use_, std::string(kOnSoundEndEvent),
369 json_args)); 409 json_args));
370 } 410 }
371 411
372 void ExtensionSpeechInputManager::DispatchEventToExtension( 412 void SpeechInputExtensionManager::DispatchEventToExtension(
373 const std::string& extension_id, const std::string& event, 413 const std::string& extension_id, const std::string& event,
374 const std::string& json_args) { 414 const std::string& json_args) {
375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376 416
377 base::AutoLock auto_lock(state_lock_); 417 base::AutoLock auto_lock(state_lock_);
378 if (state_ == kShutdown) 418 if (state_ == kShutdown)
379 return; 419 return;
380 420
381 if (profile_ && profile_->GetExtensionEventRouter()) { 421 if (profile_ && profile_->GetExtensionEventRouter()) {
382 std::string final_args; 422 std::string final_args;
383 if (json_args.empty()) { 423 if (json_args.empty()) {
384 ListValue args; 424 ListValue args;
385 base::JSONWriter::Write(&args, false, &final_args); 425 base::JSONWriter::Write(&args, false, &final_args);
386 } else { 426 } else {
387 final_args = json_args; 427 final_args = json_args;
388 } 428 }
389 429
390 profile_->GetExtensionEventRouter()->DispatchEventToExtension( 430 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
391 extension_id, event, final_args, profile_, GURL()); 431 extension_id, event, final_args, profile_, GURL());
392 } 432 }
393 } 433 }
394 434
395 void ExtensionSpeechInputManager::DispatchError( 435 void SpeechInputExtensionManager::DispatchError(
396 const std::string& error, bool dispatch_event) { 436 const std::string& error, bool dispatch_event) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 438
399 std::string extension_id; 439 std::string extension_id;
400 { 440 {
401 base::AutoLock auto_lock(state_lock_); 441 base::AutoLock auto_lock(state_lock_);
402 if (state_ == kShutdown) 442 if (state_ == kShutdown)
403 return; 443 return;
404 444
445 if (state_ == kRecording) {
446 DCHECK(notification_.get());
447 notification_->Hide();
448 }
449
405 extension_id = extension_id_in_use_; 450 extension_id = extension_id_in_use_;
406 ResetToIdleState(); 451 ResetToIdleState();
407 452
408 // Will set the error property in the ongoing extension function calls. 453 // Will set the error property in the ongoing extension function calls.
409 ExtensionError details(extension_id, error); 454 ExtensionError details(extension_id, error);
410 content::NotificationService::current()->Notify( 455 content::NotificationService::current()->Notify(
411 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED, 456 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED,
412 content::Source<Profile>(profile_), 457 content::Source<Profile>(profile_),
413 content::Details<ExtensionError>(&details)); 458 content::Details<ExtensionError>(&details));
414 } 459 }
415 460
416 // Used for errors that are also reported via the onError event. 461 // Used for errors that are also reported via the onError event.
417 if (dispatch_event) { 462 if (dispatch_event) {
418 ListValue args; 463 ListValue args;
419 DictionaryValue *js_error = new DictionaryValue(); 464 DictionaryValue *js_error = new DictionaryValue();
420 args.Append(js_error); 465 args.Append(js_error);
421 js_error->SetString(constants::kErrorCodeKey, error); 466 js_error->SetString(kErrorCodeKey, error);
422 std::string json_args; 467 std::string json_args;
423 base::JSONWriter::Write(&args, false, &json_args); 468 base::JSONWriter::Write(&args, false, &json_args);
424 DispatchEventToExtension(extension_id, 469 DispatchEventToExtension(extension_id,
425 constants::kOnErrorEvent, json_args); 470 kOnErrorEvent, json_args);
426 } 471 }
427 } 472 }
428 473
429 bool ExtensionSpeechInputManager::Start(const std::string& extension_id, 474 bool SpeechInputExtensionManager::Start(const std::string& extension_id,
430 const std::string& language, const std::string& grammar, 475 const std::string& language, const std::string& grammar,
431 bool filter_profanities, std::string* error) { 476 bool filter_profanities, std::string* error) {
432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
433 DCHECK(error); 478 DCHECK(error);
434 VLOG(1) << "Requesting start (UI thread)"; 479 VLOG(1) << "Requesting start (UI thread)";
435 480
436 base::AutoLock auto_lock(state_lock_); 481 base::AutoLock auto_lock(state_lock_);
437 if (state_ == kShutdown || 482 if (state_ == kShutdown ||
438 (!extension_id_in_use_.empty() && extension_id_in_use_ != extension_id)) { 483 (!extension_id_in_use_.empty() && extension_id_in_use_ != extension_id)) {
439 *error = constants::kErrorRequestDenied; 484 *error = kErrorRequestDenied;
440 return false; 485 return false;
441 } 486 }
442 487
443 switch (state_) { 488 switch (state_) {
444 case kIdle: 489 case kIdle:
445 break; 490 break;
446 491
447 case kStarting: 492 case kStarting:
448 *error = constants::kErrorRequestInProgress; 493 *error = kErrorRequestInProgress;
449 return false; 494 return false;
450 495
451 case kRecording: 496 case kRecording:
452 case kStopping: 497 case kStopping:
453 *error = constants::kErrorInvalidOperation; 498 *error = kErrorInvalidOperation;
454 return false; 499 return false;
455 500
456 default: 501 default:
457 NOTREACHED(); 502 NOTREACHED();
458 } 503 }
459 504
460 extension_id_in_use_ = extension_id; 505 extension_id_in_use_ = extension_id;
461 VLOG(1) << "State changed to starting"; 506 VLOG(1) << "State changed to starting";
462 state_ = kStarting; 507 state_ = kStarting;
463 508
464 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 509 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
465 base::Bind(&ExtensionSpeechInputManager::StartOnIOThread, this, 510 base::Bind(&SpeechInputExtensionManager::StartOnIOThread, this,
466 profile_->GetRequestContext(), language, grammar, filter_profanities)); 511 profile_->GetRequestContext(), language, grammar, filter_profanities));
467 return true; 512 return true;
468 } 513 }
469 514
470 void ExtensionSpeechInputManager::StartOnIOThread( 515 void SpeechInputExtensionManager::StartOnIOThread(
471 net::URLRequestContextGetter* context_getter, 516 net::URLRequestContextGetter* context_getter,
472 const std::string& language, const std::string& grammar, 517 const std::string& language, const std::string& grammar,
473 bool filter_profanities) { 518 bool filter_profanities) {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
475 VLOG(1) << "Requesting start (IO thread)"; 520 VLOG(1) << "Requesting start (IO thread)";
476 521
477 // Everything put inside the lock to ensure the validity of context_getter, 522 // Everything put inside the lock to ensure the validity of context_getter,
478 // guaranteed while not in the shutdown state. Any ongoing or recognition 523 // guaranteed while not in the shutdown state. Any ongoing or recognition
479 // request will be requested to be aborted when entering the shutdown state. 524 // request will be requested to be aborted when entering the shutdown state.
480 base::AutoLock auto_lock(state_lock_); 525 base::AutoLock auto_lock(state_lock_);
481 if (state_ == kShutdown) 526 if (state_ == kShutdown)
482 return; 527 return;
483 528
484 if (!GetExtensionSpeechInterface()->HasAudioInputDevices()) { 529 if (!GetSpeechInputExtensionInterface()->HasAudioInputDevices()) {
485 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 530 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
486 base::Bind(&ExtensionSpeechInputManager::DispatchError, this, 531 base::Bind(&SpeechInputExtensionManager::DispatchError, this,
487 std::string(constants::kErrorNoRecordingDeviceFound), false)); 532 std::string(kErrorNoRecordingDeviceFound), false));
488 return; 533 return;
489 } 534 }
490 535
491 if (GetExtensionSpeechInterface()->IsRecordingInProcess()) { 536 if (GetSpeechInputExtensionInterface()->IsRecordingInProcess()) {
492 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 537 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
493 base::Bind(&ExtensionSpeechInputManager::DispatchError, this, 538 base::Bind(&SpeechInputExtensionManager::DispatchError, this,
494 std::string(constants::kErrorRecordingDeviceInUse), false)); 539 std::string(kErrorRecordingDeviceInUse), false));
495 return; 540 return;
496 } 541 }
497 542
498 GetExtensionSpeechInterface()->StartRecording(this, context_getter, 543 GetSpeechInputExtensionInterface()->StartRecording(this, context_getter,
499 kSpeechCallerId, language, grammar, filter_profanities); 544 kSpeechCallerId, language, grammar, filter_profanities);
500 } 545 }
501 546
502 bool ExtensionSpeechInputManager::HasAudioInputDevices() { 547 bool SpeechInputExtensionManager::HasAudioInputDevices() {
503 return AudioManager::GetAudioManager()->HasAudioInputDevices(); 548 return AudioManager::GetAudioManager()->HasAudioInputDevices();
504 } 549 }
505 550
506 bool ExtensionSpeechInputManager::IsRecordingInProcess() { 551 bool SpeechInputExtensionManager::IsRecordingInProcess() {
507 // Thread-safe query. 552 // Thread-safe query.
508 return AudioManager::GetAudioManager()->IsRecordingInProcess(); 553 return AudioManager::GetAudioManager()->IsRecordingInProcess();
509 } 554 }
510 555
511 bool ExtensionSpeechInputManager::IsRecording() { 556 bool SpeechInputExtensionManager::IsRecording() {
512 return GetExtensionSpeechInterface()->IsRecordingInProcess(); 557 return GetSpeechInputExtensionInterface()->IsRecordingInProcess();
513 } 558 }
514 559
515 void ExtensionSpeechInputManager::StartRecording( 560 void SpeechInputExtensionManager::StartRecording(
516 speech_input::SpeechRecognizerDelegate* delegate, 561 speech_input::SpeechRecognizerDelegate* delegate,
517 net::URLRequestContextGetter* context_getter, int caller_id, 562 net::URLRequestContextGetter* context_getter, int caller_id,
518 const std::string& language, const std::string& grammar, 563 const std::string& language, const std::string& grammar,
519 bool filter_profanities) { 564 bool filter_profanities) {
520 DCHECK(!recognizer_); 565 DCHECK(!recognizer_);
521 recognizer_ = new SpeechRecognizer(delegate, caller_id, language, grammar, 566 recognizer_ = new SpeechRecognizer(delegate, caller_id, language, grammar,
522 context_getter, filter_profanities, "", ""); 567 context_getter, filter_profanities, "", "");
523 recognizer_->StartRecording(); 568 recognizer_->StartRecording();
524 } 569 }
525 570
526 bool ExtensionSpeechInputManager::HasValidRecognizer() { 571 bool SpeechInputExtensionManager::HasValidRecognizer() {
527 // Conditional expression used to avoid a performance warning on windows. 572 // Conditional expression used to avoid a performance warning on windows.
528 return recognizer_ ? true : false; 573 return recognizer_ ? true : false;
529 } 574 }
530 575
531 bool ExtensionSpeechInputManager::Stop(const std::string& extension_id, 576 bool SpeechInputExtensionManager::Stop(const std::string& extension_id,
532 std::string* error) { 577 std::string* error) {
533 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
534 DCHECK(error); 579 DCHECK(error);
535 VLOG(1) << "Requesting stop (UI thread)"; 580 VLOG(1) << "Requesting stop (UI thread)";
536 581
537 base::AutoLock auto_lock(state_lock_); 582 base::AutoLock auto_lock(state_lock_);
538 if (state_ == kShutdown || 583 if (state_ == kShutdown ||
539 (!extension_id_in_use_.empty() && extension_id_in_use_ != extension_id)) { 584 (!extension_id_in_use_.empty() && extension_id_in_use_ != extension_id)) {
540 *error = constants::kErrorRequestDenied; 585 *error = kErrorRequestDenied;
541 return false; 586 return false;
542 } 587 }
543 588
544 switch (state_) { 589 switch (state_) {
545 case kRecording: 590 case kRecording:
546 break; 591 break;
547 592
548 case kStopping: 593 case kStopping:
549 *error = constants::kErrorRequestInProgress; 594 *error = kErrorRequestInProgress;
550 return false; 595 return false;
551 596
552 case kIdle: 597 case kIdle:
553 case kStarting: 598 case kStarting:
554 *error = constants::kErrorInvalidOperation; 599 *error = kErrorInvalidOperation;
555 return false; 600 return false;
556 601
557 default: 602 default:
558 NOTREACHED(); 603 NOTREACHED();
559 } 604 }
560 605
561 // Guarded by the state lock. 606 // Guarded by the state lock.
562 DCHECK(GetExtensionSpeechInterface()->HasValidRecognizer()); 607 DCHECK(GetSpeechInputExtensionInterface()->HasValidRecognizer());
563 608
564 VLOG(1) << "State changed to stopping"; 609 VLOG(1) << "State changed to stopping";
565 state_ = kStopping; 610 state_ = kStopping;
566 611
567 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 612 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
568 base::Bind(&ExtensionSpeechInputManager::ForceStopOnIOThread, this)); 613 base::Bind(&SpeechInputExtensionManager::ForceStopOnIOThread, this));
569 return true; 614 return true;
570 } 615 }
571 616
572 void ExtensionSpeechInputManager::ForceStopOnIOThread() { 617 void SpeechInputExtensionManager::ForceStopOnIOThread() {
573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
574 VLOG(1) << "Requesting forced stop (IO thread)"; 619 VLOG(1) << "Requesting forced stop (IO thread)";
575 620
576 base::AutoLock auto_lock(state_lock_); 621 base::AutoLock auto_lock(state_lock_);
577 DCHECK(state_ != kIdle); 622 DCHECK(state_ != kIdle);
578 623
579 GetExtensionSpeechInterface()->StopRecording(false); 624 GetSpeechInputExtensionInterface()->StopRecording(false);
580 625
581 if (state_ == kShutdown) 626 if (state_ == kShutdown)
582 return; 627 return;
583 628
584 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 629 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
585 base::Bind(&ExtensionSpeechInputManager::StopSucceededOnUIThread, this)); 630 base::Bind(&SpeechInputExtensionManager::StopSucceededOnUIThread, this));
586 } 631 }
587 632
588 void ExtensionSpeechInputManager::StopRecording(bool recognition_failed) { 633 void SpeechInputExtensionManager::StopRecording(bool recognition_failed) {
589 if (recognizer_) { 634 if (recognizer_) {
590 // Recognition is already cancelled in case of failure. 635 // Recognition is already cancelled in case of failure.
591 // Double-cancelling leads to assertion failures. 636 // Double-cancelling leads to assertion failures.
592 if (!recognition_failed) 637 if (!recognition_failed)
593 recognizer_->CancelRecognition(); 638 recognizer_->CancelRecognition();
594 recognizer_.release(); 639 recognizer_.release();
595 } 640 }
596 } 641 }
597 642
598 void ExtensionSpeechInputManager::StopSucceededOnUIThread() { 643 void SpeechInputExtensionManager::StopSucceededOnUIThread() {
599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 644 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
600 VLOG(1) << "Stop succeeded (UI thread)"; 645 VLOG(1) << "Stop succeeded (UI thread)";
601 646
602 base::AutoLock auto_lock(state_lock_); 647 base::AutoLock auto_lock(state_lock_);
603 if (state_ == kShutdown) 648 if (state_ == kShutdown)
604 return; 649 return;
605 650
606 std::string extension_id = extension_id_in_use_; 651 std::string extension_id = extension_id_in_use_;
607 ResetToIdleState(); 652 ResetToIdleState();
608 653
654 DCHECK(notification_.get());
655 notification_->Hide();
656
609 content::NotificationService::current()->Notify( 657 content::NotificationService::current()->Notify(
610 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED, 658 chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED,
611 // Guarded by the state_ == kShutdown check. 659 // Guarded by the state_ == kShutdown check.
612 content::Source<Profile>(profile_), 660 content::Source<Profile>(profile_),
613 content::Details<std::string>(&extension_id)); 661 content::Details<std::string>(&extension_id));
614 } 662 }
663
664 void SpeechInputExtensionManager::SetInputVolume(int caller_id,
665 float volume,
666 float noise_volume) {
667 DCHECK_EQ(caller_id, kSpeechCallerId);
668 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
669 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
670 base::Bind(&SpeechInputExtensionManager::SetInputVolumeOnUIThread,
671 this, volume));
672 }
673
674 void SpeechInputExtensionManager::SetInputVolumeOnUIThread(
675 float volume) {
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
677 DCHECK(notification_.get());
678 notification_->SetVUMeterVolume(volume);
679 }
OLDNEW
« no previous file with comments | « chrome/browser/speech/speech_input_extension_manager.h ('k') | chrome/browser/speech/speech_input_extension_notification.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698