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

Side by Side Diff: content/browser/speech/google_one_shot_remote_engine.cc

Issue 9972011: Speech refactoring: Reimplemented SpeechRecognitionManagerImpl as a FSM. (CL1.7) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed according to Satish review. Created 8 years, 8 months 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) 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 "content/browser/speech/google_one_shot_remote_engine.h" 5 #include "content/browser/speech/google_one_shot_remote_engine.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 GoogleOneShotRemoteEngineConfig::GoogleOneShotRemoteEngineConfig() 159 GoogleOneShotRemoteEngineConfig::GoogleOneShotRemoteEngineConfig()
160 : filter_profanities(false), 160 : filter_profanities(false),
161 audio_sample_rate(kDefaultConfigSampleRate), 161 audio_sample_rate(kDefaultConfigSampleRate),
162 audio_num_bits_per_sample(kDefaultConfigBitsPerSample) { 162 audio_num_bits_per_sample(kDefaultConfigBitsPerSample) {
163 } 163 }
164 164
165 GoogleOneShotRemoteEngineConfig::~GoogleOneShotRemoteEngineConfig() {} 165 GoogleOneShotRemoteEngineConfig::~GoogleOneShotRemoteEngineConfig() {}
166 166
167 GoogleOneShotRemoteEngine::GoogleOneShotRemoteEngine( 167 GoogleOneShotRemoteEngine::GoogleOneShotRemoteEngine(
168 net::URLRequestContextGetter* context) 168 net::URLRequestContextGetter* context)
169 : url_context_(context) { 169 : url_context_(context),
170 url_fetcher_destroyed_(false) {
170 } 171 }
171 172
172 GoogleOneShotRemoteEngine::~GoogleOneShotRemoteEngine() {} 173 GoogleOneShotRemoteEngine::~GoogleOneShotRemoteEngine() {}
173 174
174 void GoogleOneShotRemoteEngine::SetConfig( 175 void GoogleOneShotRemoteEngine::SetConfig(
175 const GoogleOneShotRemoteEngineConfig& config) { 176 const GoogleOneShotRemoteEngineConfig& config) {
176 config_ = config; 177 config_ = config;
177 } 178 }
178 179
179 void GoogleOneShotRemoteEngine::StartRecognition() { 180 void GoogleOneShotRemoteEngine::StartRecognition() {
180 DCHECK(delegate()); 181 DCHECK(delegate());
181 DCHECK(!url_fetcher_.get()); 182 DCHECK(!url_fetcher_.get() || url_fetcher_destroyed_);
182 std::string lang_param = config_.language; 183 std::string lang_param = config_.language;
183 184
184 if (lang_param.empty() && url_context_) { 185 if (lang_param.empty() && url_context_) {
185 // If no language is provided then we use the first from the accepted 186 // If no language is provided then we use the first from the accepted
186 // language list. If this list is empty then it defaults to "en-US". 187 // language list. If this list is empty then it defaults to "en-US".
187 // Example of the contents of this list: "es,en-GB;q=0.8", "" 188 // Example of the contents of this list: "es,en-GB;q=0.8", ""
188 net::URLRequestContext* request_context = 189 net::URLRequestContext* request_context =
189 url_context_->GetURLRequestContext(); 190 url_context_->GetURLRequestContext();
190 DCHECK(request_context); 191 DCHECK(request_context);
191 std::string accepted_language_list = request_context->accept_language(); 192 std::string accepted_language_list = request_context->accept_language();
(...skipping 30 matching lines...) Expand all
222 url_fetcher_->SetRequestContext(url_context_); 223 url_fetcher_->SetRequestContext(url_context_);
223 url_fetcher_->SetReferrer(config_.origin_url); 224 url_fetcher_->SetReferrer(config_.origin_url);
224 225
225 // The speech recognition API does not require user identification as part 226 // The speech recognition API does not require user identification as part
226 // of requests, so we don't send cookies or auth data for these requests to 227 // of requests, so we don't send cookies or auth data for these requests to
227 // prevent any accidental connection between users who are logged into the 228 // prevent any accidental connection between users who are logged into the
228 // domain for other services (e.g. bookmark sync) with the speech requests. 229 // domain for other services (e.g. bookmark sync) with the speech requests.
229 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | 230 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
230 net::LOAD_DO_NOT_SEND_COOKIES | 231 net::LOAD_DO_NOT_SEND_COOKIES |
231 net::LOAD_DO_NOT_SEND_AUTH_DATA); 232 net::LOAD_DO_NOT_SEND_AUTH_DATA);
233 url_fetcher_destroyed_ = false;
232 url_fetcher_->Start(); 234 url_fetcher_->Start();
233 } 235 }
234 236
235 void GoogleOneShotRemoteEngine::EndRecognition() { 237 void GoogleOneShotRemoteEngine::EndRecognition() {
236 url_fetcher_.reset(); 238 // TODO(primiano) URLFetcher(Core) seems to be currently broken. In particular
239 // I am experiencing a failure in the case of a recognition suddenly aborted,
240 // with a DCHECK in content::URLFetcherCore::CompleteAddingUploadDataChunk().
241 // What happens is that this method (thus the url_fetcher dtor) might be
242 // called immediately after an AppendChunkToUpload. AppendChunkToUpload is
243 // not executed synchronously (inside URLFetcher) but defers its work to a
244 // posted task. However, it seems to me that the posted routine
245 // (CompleteAddingUploadDataChunk) does not take into account the corner case
246 // in which the URLFetcher is destructed in the meanwhile (which in turn
247 // causes a Stop() call on URLFetcherCore)
248 // Therefore I am currently commenting the .reset() call and adding the
249 // url_fetcher_destroyed_ workaround (read hack). This should not cause any
250 // memory leak due to the scoped_ptr smart pointer.
251
252 // url_fetcher_.reset();
253 url_fetcher_destroyed_ = true;
237 } 254 }
238 255
239 void GoogleOneShotRemoteEngine::TakeAudioChunk(const AudioChunk& data) { 256 void GoogleOneShotRemoteEngine::TakeAudioChunk(const AudioChunk& data) {
240 DCHECK(url_fetcher_.get()); 257 DCHECK(url_fetcher_.get() && !url_fetcher_destroyed_);
241 DCHECK(encoder_.get()); 258 DCHECK(encoder_.get());
242 DCHECK_EQ(data.bytes_per_sample(), config_.audio_num_bits_per_sample / 8); 259 DCHECK_EQ(data.bytes_per_sample(), config_.audio_num_bits_per_sample / 8);
243 encoder_->Encode(data); 260 encoder_->Encode(data);
244 scoped_refptr<AudioChunk> encoded_data(encoder_->GetEncodedDataAndClear()); 261 scoped_refptr<AudioChunk> encoded_data(encoder_->GetEncodedDataAndClear());
245 url_fetcher_->AppendChunkToUpload(encoded_data->AsString(), false); 262 url_fetcher_->AppendChunkToUpload(encoded_data->AsString(), false);
246 } 263 }
247 264
248 void GoogleOneShotRemoteEngine::AudioChunksEnded() { 265 void GoogleOneShotRemoteEngine::AudioChunksEnded() {
249 DCHECK(url_fetcher_.get()); 266 DCHECK(url_fetcher_.get() && !url_fetcher_destroyed_);
250 DCHECK(encoder_.get()); 267 DCHECK(encoder_.get());
251 268
252 // UploadAudioChunk requires a non-empty final buffer. So we encode a packet 269 // UploadAudioChunk requires a non-empty final buffer. So we encode a packet
253 // of silence in case encoder had no data already. 270 // of silence in case encoder had no data already.
254 std::vector<int16> samples( 271 std::vector<int16> samples(
255 config_.audio_sample_rate * kAudioPacketIntervalMs / 1000); 272 config_.audio_sample_rate * kAudioPacketIntervalMs / 1000);
256 scoped_refptr<AudioChunk> dummy_chunk( 273 scoped_refptr<AudioChunk> dummy_chunk(
257 new AudioChunk(reinterpret_cast<uint8*>(&samples[0]), 274 new AudioChunk(reinterpret_cast<uint8*>(&samples[0]),
258 samples.size() * sizeof(int16), 275 samples.size() * sizeof(int16),
259 encoder_->bits_per_sample() / 8)); 276 encoder_->bits_per_sample() / 8));
260 encoder_->Encode(*dummy_chunk); 277 encoder_->Encode(*dummy_chunk);
261 encoder_->Flush(); 278 encoder_->Flush();
262 scoped_refptr<AudioChunk> encoded_dummy_data( 279 scoped_refptr<AudioChunk> encoded_dummy_data(
263 encoder_->GetEncodedDataAndClear()); 280 encoder_->GetEncodedDataAndClear());
264 DCHECK(!encoded_dummy_data->IsEmpty()); 281 DCHECK(!encoded_dummy_data->IsEmpty());
265 encoder_.reset(); 282 encoder_.reset();
266 283
267 url_fetcher_->AppendChunkToUpload(encoded_dummy_data->AsString(), true); 284 url_fetcher_->AppendChunkToUpload(encoded_dummy_data->AsString(), true);
268 } 285 }
269 286
270 void GoogleOneShotRemoteEngine::OnURLFetchComplete( 287 void GoogleOneShotRemoteEngine::OnURLFetchComplete(
271 const content::URLFetcher* source) { 288 const content::URLFetcher* source) {
289 if (url_fetcher_destroyed_)
290 return;
272 DCHECK_EQ(url_fetcher_.get(), source); 291 DCHECK_EQ(url_fetcher_.get(), source);
273 SpeechRecognitionResult result; 292 SpeechRecognitionResult result;
274 SpeechRecognitionError error(content::SPEECH_RECOGNITION_ERROR_NETWORK); 293 SpeechRecognitionError error(content::SPEECH_RECOGNITION_ERROR_NETWORK);
275 std::string data; 294 std::string data;
276 295
277 // The default error code in case of parse errors is NETWORK_FAILURE, however 296 // The default error code in case of parse errors is NETWORK_FAILURE, however
278 // ParseServerResponse can change the error to a more appropriate one. 297 // ParseServerResponse can change the error to a more appropriate one.
279 bool error_occurred = (!source->GetStatus().is_success() || 298 bool error_occurred = (!source->GetStatus().is_success() ||
280 source->GetResponseCode() != 200 || 299 source->GetResponseCode() != 200 ||
281 !source->GetResponseAsString(&data) || 300 !source->GetResponseAsString(&data) ||
282 !ParseServerResponse(data, &result, &error)); 301 !ParseServerResponse(data, &result, &error));
283 url_fetcher_.reset(); 302 url_fetcher_.reset();
284 if (error_occurred) { 303 if (error_occurred) {
285 DVLOG(1) << "GoogleOneShotRemoteEngine: Network Error " << error.code; 304 DVLOG(1) << "GoogleOneShotRemoteEngine: Network Error " << error.code;
286 delegate()->OnSpeechRecognitionEngineError(error); 305 delegate()->OnSpeechRecognitionEngineError(error);
287 } else { 306 } else {
288 DVLOG(1) << "GoogleOneShotRemoteEngine: Invoking delegate with result."; 307 DVLOG(1) << "GoogleOneShotRemoteEngine: Invoking delegate with result.";
289 delegate()->OnSpeechRecognitionEngineResult(result); 308 delegate()->OnSpeechRecognitionEngineResult(result);
290 } 309 }
291 } 310 }
292 311
293 bool GoogleOneShotRemoteEngine::IsRecognitionPending() const { 312 bool GoogleOneShotRemoteEngine::IsRecognitionPending() const {
294 return url_fetcher_ != NULL; 313 return url_fetcher_ != NULL && !url_fetcher_destroyed_;
295 } 314 }
296 315
297 int GoogleOneShotRemoteEngine::GetDesiredAudioChunkDurationMs() const { 316 int GoogleOneShotRemoteEngine::GetDesiredAudioChunkDurationMs() const {
298 return kAudioPacketIntervalMs; 317 return kAudioPacketIntervalMs;
299 } 318 }
300 319
301 } // namespace speech 320 } // namespace speech
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698