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)) { | |
Satish
2011/10/06 09:09:06
Is this check required or is GetInteger returning
Leandro Graciá Gil
2011/10/06 18:26:25
Done.
| |
59 VLOG(1) << "ParseServerResponse: cannot find " << kStatusString | |
60 << " in the response object."; | |
61 return false; | |
62 } | |
63 | |
64 int status; | |
65 if (!response_object->GetInteger(kStatusString, &status)) { | |
66 VLOG(1) << "ParseServerResponse: get " << kStatusString | |
Satish
2011/10/06 09:09:06
could print something like
kStatusString << " is
Leandro Graciá Gil
2011/10/06 18:26:25
Done.
| |
67 << " integer value."; | |
68 return false; | |
69 } | |
70 | |
71 // Process the status. | |
72 switch (status) { | |
73 case speech_input::kErrorNone: | |
74 case speech_input::kErrorNoSpeech: | |
75 case speech_input::kErrorNoMatch: | |
76 break; | |
77 | |
78 default: | |
79 // Other status codes should not be returned by the server. | |
80 VLOG(1) << "ParseServerResponse: unexpected status code " << status; | |
81 return false; | |
82 } | |
83 | |
84 result->error = static_cast<speech_input::SpeechInputError>(status); | |
85 | |
86 // Get the hypotheses. | |
57 Value* hypotheses_value = NULL; | 87 Value* hypotheses_value = NULL; |
58 if (!response_object->Get(kHypothesesString, &hypotheses_value)) { | 88 if (!response_object->Get(kHypothesesString, &hypotheses_value)) { |
59 VLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; | 89 VLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; |
60 return false; | 90 return false; |
61 } | 91 } |
92 | |
62 DCHECK(hypotheses_value); | 93 DCHECK(hypotheses_value); |
63 if (!hypotheses_value->IsType(Value::TYPE_LIST)) { | 94 if (!hypotheses_value->IsType(Value::TYPE_LIST)) { |
64 VLOG(1) << "ParseServerResponse: Unexpected hypotheses type " | 95 VLOG(1) << "ParseServerResponse: Unexpected hypotheses type " |
65 << hypotheses_value->GetType(); | 96 << hypotheses_value->GetType(); |
66 return false; | 97 return false; |
67 } | 98 } |
99 | |
68 const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value); | 100 const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value); |
69 | 101 |
70 size_t index = 0; | 102 size_t index = 0; |
71 for (; index < hypotheses_list->GetSize(); ++index) { | 103 for (; index < hypotheses_list->GetSize(); ++index) { |
72 Value* hypothesis = NULL; | 104 Value* hypothesis = NULL; |
73 if (!hypotheses_list->Get(index, &hypothesis)) { | 105 if (!hypotheses_list->Get(index, &hypothesis)) { |
74 LOG(WARNING) << "ParseServerResponse: Unable to read hypothesis value."; | 106 LOG(WARNING) << "ParseServerResponse: Unable to read hypothesis value."; |
75 break; | 107 break; |
76 } | 108 } |
77 DCHECK(hypothesis); | 109 DCHECK(hypothesis); |
78 if (!hypothesis->IsType(Value::TYPE_DICTIONARY)) { | 110 if (!hypothesis->IsType(Value::TYPE_DICTIONARY)) { |
79 LOG(WARNING) << "ParseServerResponse: Unexpected value type " | 111 LOG(WARNING) << "ParseServerResponse: Unexpected value type " |
80 << hypothesis->GetType(); | 112 << hypothesis->GetType(); |
81 break; | 113 break; |
82 } | 114 } |
83 | 115 |
84 const DictionaryValue* hypothesis_value = | 116 const DictionaryValue* hypothesis_value = |
85 static_cast<DictionaryValue*>(hypothesis); | 117 static_cast<DictionaryValue*>(hypothesis); |
86 string16 utterance; | 118 string16 utterance; |
87 if (!hypothesis_value->GetString(kUtteranceString, &utterance)) { | 119 if (!hypothesis_value->GetString(kUtteranceString, &utterance)) { |
88 LOG(WARNING) << "ParseServerResponse: Missing utterance value."; | 120 LOG(WARNING) << "ParseServerResponse: Missing utterance value."; |
89 break; | 121 break; |
90 } | 122 } |
91 | 123 |
92 // It is not an error if the 'confidence' field is missing. | 124 // It is not an error if the 'confidence' field is missing. |
93 double confidence = 0.0; | 125 double confidence = 0.0; |
94 hypothesis_value->GetDouble(kConfidenceString, &confidence); | 126 hypothesis_value->GetDouble(kConfidenceString, &confidence); |
95 | 127 |
96 result->push_back(speech_input::SpeechInputResultItem(utterance, | 128 result->hypotheses.push_back(speech_input::SpeechInputHypothesis( |
97 confidence)); | 129 utterance, confidence)); |
98 } | 130 } |
99 | 131 |
100 if (index < hypotheses_list->GetSize()) { | 132 if (index < hypotheses_list->GetSize()) { |
101 result->clear(); | 133 result->hypotheses.clear(); |
134 result->error = speech_input::kErrorNetwork; | |
Satish
2011/10/06 09:09:06
See the next comment, if you go with that you can
Leandro Graciá Gil
2011/10/06 18:26:25
Done.
| |
102 return false; | 135 return false; |
103 } | 136 } |
104 | 137 |
105 return true; | 138 return true; |
106 } | 139 } |
107 | 140 |
108 } // namespace | 141 } // namespace |
109 | 142 |
110 namespace speech_input { | 143 namespace speech_input { |
111 | 144 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 DCHECK(url_fetcher_.get()); | 211 DCHECK(url_fetcher_.get()); |
179 url_fetcher_->AppendChunkToUpload(audio_data, is_last_chunk); | 212 url_fetcher_->AppendChunkToUpload(audio_data, is_last_chunk); |
180 } | 213 } |
181 | 214 |
182 void SpeechRecognitionRequest::OnURLFetchComplete(const URLFetcher* source) { | 215 void SpeechRecognitionRequest::OnURLFetchComplete(const URLFetcher* source) { |
183 DCHECK_EQ(url_fetcher_.get(), source); | 216 DCHECK_EQ(url_fetcher_.get(), source); |
184 | 217 |
185 bool error = | 218 bool error = |
186 !source->status().is_success() || source->response_code() != 200; | 219 !source->status().is_success() || source->response_code() != 200; |
187 | 220 |
188 SpeechInputResultArray result; | 221 SpeechInputResult result; |
189 if (!error) | 222 if (!error) |
Satish
2011/10/06 09:09:06
We could remove the 'bool error' parameter in the
Leandro Graciá Gil
2011/10/06 18:26:25
Done.
| |
190 error = !ParseServerResponse(source->GetResponseStringRef(), &result); | 223 error = !ParseServerResponse(source->GetResponseStringRef(), &result); |
191 url_fetcher_.reset(); | 224 url_fetcher_.reset(); |
192 | 225 |
193 DVLOG(1) << "SpeechRecognitionRequest: Invoking delegate with result."; | 226 DVLOG(1) << "SpeechRecognitionRequest: Invoking delegate with result."; |
194 delegate_->SetRecognitionResult(error, result); | 227 delegate_->SetRecognitionResult(error, result); |
195 } | 228 } |
196 | 229 |
197 } // namespace speech_input | 230 } // namespace speech_input |
OLD | NEW |