Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "content/browser/speech/speech_recognition_request.h" | 5 #include "content/browser/speech/speech_recognition_request.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" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "net/base/escape.h" | 13 #include "net/base/escape.h" |
| 14 #include "net/base/load_flags.h" | 14 #include "net/base/load_flags.h" |
| 15 #include "net/url_request/url_request_context.h" | 15 #include "net/url_request/url_request_context.h" |
| 16 #include "net/url_request/url_request_context_getter.h" | 16 #include "net/url_request/url_request_context_getter.h" |
| 17 #include "net/url_request/url_request_status.h" | 17 #include "net/url_request/url_request_status.h" |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 const char* const kDefaultSpeechRecognitionUrl = | 21 const char* const kDefaultSpeechRecognitionUrl = |
| 22 "https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&"; | 22 "https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&"; |
| 23 const char* const kStatusString = "status"; | |
| 23 const char* const kHypothesesString = "hypotheses"; | 24 const char* const kHypothesesString = "hypotheses"; |
| 24 const char* const kUtteranceString = "utterance"; | 25 const char* const kUtteranceString = "utterance"; |
| 25 const char* const kConfidenceString = "confidence"; | 26 const char* const kConfidenceString = "confidence"; |
| 26 | 27 |
| 27 // TODO(satish): Remove this hardcoded value once the page is allowed to | 28 // TODO(satish): Remove this hardcoded value once the page is allowed to |
| 28 // set this via an attribute. | 29 // set this via an attribute. |
| 29 const int kMaxResults = 6; | 30 const int kMaxResults = 6; |
| 30 | 31 |
| 31 bool ParseServerResponse(const std::string& response_body, | 32 bool ParseServerResponse(const std::string& response_body, |
| 32 speech_input::SpeechInputResultArray* result) { | 33 speech_input::SpeechInputResult* result) { |
| 33 if (response_body.empty()) { | 34 if (response_body.empty()) { |
| 34 LOG(WARNING) << "ParseServerResponse: Response was empty."; | 35 LOG(WARNING) << "ParseServerResponse: Response was empty."; |
| 35 return false; | 36 return false; |
| 36 } | 37 } |
| 37 DVLOG(1) << "ParseServerResponse: Parsing response " << response_body; | 38 DVLOG(1) << "ParseServerResponse: Parsing response " << response_body; |
| 38 | 39 |
| 39 // Parse the response, ignoring comments. | 40 // Parse the response, ignoring comments. |
| 40 std::string error_msg; | 41 std::string error_msg; |
| 41 scoped_ptr<Value> response_value(base::JSONReader::ReadAndReturnError( | 42 scoped_ptr<Value> response_value(base::JSONReader::ReadAndReturnError( |
| 42 response_body, false, NULL, &error_msg)); | 43 response_body, false, NULL, &error_msg)); |
| 43 if (response_value == NULL) { | 44 if (response_value == NULL) { |
| 44 LOG(WARNING) << "ParseServerResponse: JSONReader failed : " << error_msg; | 45 LOG(WARNING) << "ParseServerResponse: JSONReader failed : " << error_msg; |
| 45 return false; | 46 return false; |
| 46 } | 47 } |
| 47 | 48 |
| 48 if (!response_value->IsType(Value::TYPE_DICTIONARY)) { | 49 if (!response_value->IsType(Value::TYPE_DICTIONARY)) { |
| 49 VLOG(1) << "ParseServerResponse: Unexpected response type " | 50 VLOG(1) << "ParseServerResponse: Unexpected response type " |
| 50 << response_value->GetType(); | 51 << response_value->GetType(); |
| 51 return false; | 52 return false; |
| 52 } | 53 } |
| 53 const DictionaryValue* response_object = | 54 const DictionaryValue* response_object = |
| 54 static_cast<DictionaryValue*>(response_value.get()); | 55 static_cast<DictionaryValue*>(response_value.get()); |
| 55 | 56 |
| 56 // Get the hypotheses | 57 // Get the status. |
| 58 if (!response_object->HasKey(kStatusString)) { | |
| 59 VLOG(1) << "ParseServerResponse: cannot find " << kStatusString | |
| 60 << " in the response object."; | |
| 61 return false; | |
| 62 } | |
| 63 | |
| 64 Value* status_value = NULL; | |
| 65 response_object->GetWithoutPathExpansion(kStatusString, &status_value); | |
|
Satish
2011/10/04 20:36:33
since the 'path' here is the first parameter and i
Leandro Graciá Gil
2011/10/05 22:09:00
I think you're getting it the other way around. Ge
| |
| 66 DCHECK(status_value); | |
| 67 | |
| 68 if (!status_value->IsType(Value::TYPE_INTEGER)) { | |
| 69 VLOG(1) << "ParseServerResponse: Unexpected response status type " | |
| 70 << status_value->GetType(); | |
|
Satish
2011/10/04 20:36:33
return false here?
Leandro Graciá Gil
2011/10/05 22:09:00
Done.
| |
| 71 } | |
| 72 | |
| 73 int status; | |
| 74 DCHECK(status_value->GetAsInteger(&status)); | |
| 75 | |
| 76 // Process the status. | |
| 77 switch (status) { | |
| 78 case speech_input::kStatusSuccess: | |
| 79 case speech_input::kStatusNoSpeech: | |
| 80 case speech_input::kStatusNoMatch: | |
| 81 break; | |
| 82 | |
| 83 default: | |
| 84 // Other status codes should not be returned by the server. | |
| 85 VLOG(1) << "ParseServerResponse: unexpected status code " << status; | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 result->status = static_cast<speech_input::SpeechInputResultStatus>(status); | |
| 90 | |
| 91 // Get the hypotheses. | |
| 57 Value* hypotheses_value = NULL; | 92 Value* hypotheses_value = NULL; |
| 58 if (!response_object->Get(kHypothesesString, &hypotheses_value)) { | 93 if (!response_object->Get(kHypothesesString, &hypotheses_value)) { |
| 59 VLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; | 94 VLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; |
| 60 return false; | 95 return false; |
| 61 } | 96 } |
| 97 | |
| 62 DCHECK(hypotheses_value); | 98 DCHECK(hypotheses_value); |
| 63 if (!hypotheses_value->IsType(Value::TYPE_LIST)) { | 99 if (!hypotheses_value->IsType(Value::TYPE_LIST)) { |
| 64 VLOG(1) << "ParseServerResponse: Unexpected hypotheses type " | 100 VLOG(1) << "ParseServerResponse: Unexpected hypotheses type " |
| 65 << hypotheses_value->GetType(); | 101 << hypotheses_value->GetType(); |
| 66 return false; | 102 return false; |
| 67 } | 103 } |
| 104 | |
| 68 const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value); | 105 const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value); |
| 69 | 106 |
| 70 size_t index = 0; | 107 size_t index = 0; |
| 71 for (; index < hypotheses_list->GetSize(); ++index) { | 108 for (; index < hypotheses_list->GetSize(); ++index) { |
| 72 Value* hypothesis = NULL; | 109 Value* hypothesis = NULL; |
| 73 if (!hypotheses_list->Get(index, &hypothesis)) { | 110 if (!hypotheses_list->Get(index, &hypothesis)) { |
| 74 LOG(WARNING) << "ParseServerResponse: Unable to read hypothesis value."; | 111 LOG(WARNING) << "ParseServerResponse: Unable to read hypothesis value."; |
| 75 break; | 112 break; |
| 76 } | 113 } |
| 77 DCHECK(hypothesis); | 114 DCHECK(hypothesis); |
| 78 if (!hypothesis->IsType(Value::TYPE_DICTIONARY)) { | 115 if (!hypothesis->IsType(Value::TYPE_DICTIONARY)) { |
| 79 LOG(WARNING) << "ParseServerResponse: Unexpected value type " | 116 LOG(WARNING) << "ParseServerResponse: Unexpected value type " |
| 80 << hypothesis->GetType(); | 117 << hypothesis->GetType(); |
| 81 break; | 118 break; |
| 82 } | 119 } |
| 83 | 120 |
| 84 const DictionaryValue* hypothesis_value = | 121 const DictionaryValue* hypothesis_value = |
| 85 static_cast<DictionaryValue*>(hypothesis); | 122 static_cast<DictionaryValue*>(hypothesis); |
| 86 string16 utterance; | 123 string16 utterance; |
| 87 if (!hypothesis_value->GetString(kUtteranceString, &utterance)) { | 124 if (!hypothesis_value->GetString(kUtteranceString, &utterance)) { |
| 88 LOG(WARNING) << "ParseServerResponse: Missing utterance value."; | 125 LOG(WARNING) << "ParseServerResponse: Missing utterance value."; |
| 89 break; | 126 break; |
| 90 } | 127 } |
| 91 | 128 |
| 92 // It is not an error if the 'confidence' field is missing. | 129 // It is not an error if the 'confidence' field is missing. |
| 93 double confidence = 0.0; | 130 double confidence = 0.0; |
| 94 hypothesis_value->GetDouble(kConfidenceString, &confidence); | 131 hypothesis_value->GetDouble(kConfidenceString, &confidence); |
| 95 | 132 |
| 96 result->push_back(speech_input::SpeechInputResultItem(utterance, | 133 result->hypotheses.push_back(speech_input::SpeechInputResultItem( |
| 97 confidence)); | 134 utterance, confidence)); |
| 98 } | 135 } |
| 99 | 136 |
| 100 if (index < hypotheses_list->GetSize()) { | 137 if (index < hypotheses_list->GetSize()) { |
| 101 result->clear(); | 138 result->hypotheses.clear(); |
| 139 result->status = speech_input::kStatusAborted; | |
|
Satish
2011/10/04 20:36:33
is kStatusAborted the right error code? seems like
Leandro Graciá Gil
2011/10/05 22:09:00
Changed to network error since it seems the closes
| |
| 102 return false; | 140 return false; |
| 103 } | 141 } |
| 104 | 142 |
| 105 return true; | 143 return true; |
| 106 } | 144 } |
| 107 | 145 |
| 108 } // namespace | 146 } // namespace |
| 109 | 147 |
| 110 namespace speech_input { | 148 namespace speech_input { |
| 111 | 149 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 DCHECK(url_fetcher_.get()); | 216 DCHECK(url_fetcher_.get()); |
| 179 url_fetcher_->AppendChunkToUpload(audio_data, is_last_chunk); | 217 url_fetcher_->AppendChunkToUpload(audio_data, is_last_chunk); |
| 180 } | 218 } |
| 181 | 219 |
| 182 void SpeechRecognitionRequest::OnURLFetchComplete(const URLFetcher* source) { | 220 void SpeechRecognitionRequest::OnURLFetchComplete(const URLFetcher* source) { |
| 183 DCHECK_EQ(url_fetcher_.get(), source); | 221 DCHECK_EQ(url_fetcher_.get(), source); |
| 184 | 222 |
| 185 bool error = | 223 bool error = |
| 186 !source->status().is_success() || source->response_code() != 200; | 224 !source->status().is_success() || source->response_code() != 200; |
| 187 | 225 |
| 188 SpeechInputResultArray result; | 226 SpeechInputResult result; |
| 189 if (!error) | 227 if (!error) |
| 190 error = !ParseServerResponse(source->GetResponseStringRef(), &result); | 228 error = !ParseServerResponse(source->GetResponseStringRef(), &result); |
| 191 url_fetcher_.reset(); | 229 url_fetcher_.reset(); |
| 192 | 230 |
| 193 DVLOG(1) << "SpeechRecognitionRequest: Invoking delegate with result."; | 231 DVLOG(1) << "SpeechRecognitionRequest: Invoking delegate with result."; |
| 194 delegate_->SetRecognitionResult(error, result); | 232 delegate_->SetRecognitionResult(error, result); |
| 195 } | 233 } |
| 196 | 234 |
| 197 } // namespace speech_input | 235 } // namespace speech_input |
| OLD | NEW |