Index: content/browser/speech/google_one_shot_remote_engine.cc |
diff --git a/content/browser/speech/google_one_shot_remote_engine.cc b/content/browser/speech/google_one_shot_remote_engine.cc |
index 452a34a9004ec13439814185552709119cf79706..539983a7c01ccb57e8d37d8d5542b901698d4fca 100644 |
--- a/content/browser/speech/google_one_shot_remote_engine.cc |
+++ b/content/browser/speech/google_one_shot_remote_engine.cc |
@@ -166,7 +166,8 @@ GoogleOneShotRemoteEngineConfig::~GoogleOneShotRemoteEngineConfig() {} |
GoogleOneShotRemoteEngine::GoogleOneShotRemoteEngine( |
net::URLRequestContextGetter* context) |
- : url_context_(context) { |
+ : url_context_(context), |
+ url_fetcher_destroyed_(false) { |
} |
GoogleOneShotRemoteEngine::~GoogleOneShotRemoteEngine() {} |
@@ -178,7 +179,7 @@ void GoogleOneShotRemoteEngine::SetConfig( |
void GoogleOneShotRemoteEngine::StartRecognition() { |
DCHECK(delegate()); |
- DCHECK(!url_fetcher_.get()); |
+ DCHECK(!url_fetcher_.get() || url_fetcher_destroyed_); |
std::string lang_param = config_.language; |
if (lang_param.empty() && url_context_) { |
@@ -229,15 +230,31 @@ void GoogleOneShotRemoteEngine::StartRecognition() { |
url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
net::LOAD_DO_NOT_SEND_COOKIES | |
net::LOAD_DO_NOT_SEND_AUTH_DATA); |
+ url_fetcher_destroyed_ = false; |
url_fetcher_->Start(); |
} |
void GoogleOneShotRemoteEngine::EndRecognition() { |
- url_fetcher_.reset(); |
+ // TODO(primiano) URLFetcher(Core) seems to be currently broken. In particular |
+ // I am experiencing a failure in the case of a recognition suddenly aborted, |
+ // with a DCHECK in content::URLFetcherCore::CompleteAddingUploadDataChunk(). |
+ // What happens is that this method (thus the url_fetcher dtor) might be |
+ // called immediately after an AppendChunkToUpload. AppendChunkToUpload is |
+ // not executed synchronously (inside URLFetcher) but defers its work to a |
+ // posted task. However, it seems to me that the posted routine |
+ // (CompleteAddingUploadDataChunk) does not take into account the corner case |
+ // in which the URLFetcher is destructed in the meanwhile (which in turn |
+ // causes a Stop() call on URLFetcherCore) |
+ // Therefore I am currently commenting the .reset() call and adding the |
+ // url_fetcher_destroyed_ workaround (read hack). This should not cause any |
+ // memory leak due to the scoped_ptr smart pointer. |
+ |
+ // url_fetcher_.reset(); |
+ url_fetcher_destroyed_ = true; |
} |
void GoogleOneShotRemoteEngine::TakeAudioChunk(const AudioChunk& data) { |
- DCHECK(url_fetcher_.get()); |
+ DCHECK(url_fetcher_.get() && !url_fetcher_destroyed_); |
DCHECK(encoder_.get()); |
DCHECK_EQ(data.bytes_per_sample(), config_.audio_num_bits_per_sample / 8); |
encoder_->Encode(data); |
@@ -246,7 +263,7 @@ void GoogleOneShotRemoteEngine::TakeAudioChunk(const AudioChunk& data) { |
} |
void GoogleOneShotRemoteEngine::AudioChunksEnded() { |
- DCHECK(url_fetcher_.get()); |
+ DCHECK(url_fetcher_.get() && !url_fetcher_destroyed_); |
DCHECK(encoder_.get()); |
// UploadAudioChunk requires a non-empty final buffer. So we encode a packet |
@@ -269,6 +286,8 @@ void GoogleOneShotRemoteEngine::AudioChunksEnded() { |
void GoogleOneShotRemoteEngine::OnURLFetchComplete( |
const content::URLFetcher* source) { |
+ if (url_fetcher_destroyed_) |
+ return; |
DCHECK_EQ(url_fetcher_.get(), source); |
SpeechRecognitionResult result; |
SpeechRecognitionError error(content::SPEECH_RECOGNITION_ERROR_NETWORK); |
@@ -291,7 +310,7 @@ void GoogleOneShotRemoteEngine::OnURLFetchComplete( |
} |
bool GoogleOneShotRemoteEngine::IsRecognitionPending() const { |
- return url_fetcher_ != NULL; |
+ return url_fetcher_ != NULL && !url_fetcher_destroyed_; |
} |
int GoogleOneShotRemoteEngine::GetDesiredAudioChunkDurationMs() const { |