1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/test/mock_google_streaming_server.h"
8 #include "base/safe_numerics.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/sys_byteorder.h"
12 #include "base/values.h"
13 #include "content/browser/speech/google_streaming_remote_engine.h"
14 #include "content/browser/speech/proto/google_streaming_api.pb.h"
15 #include "content/browser/speech/speech_recognition_manager_impl.h"
16 #include "net/base/escape.h"
17 #include "net/url_request/url_fetcher_delegate.h"
18 #include "net/url_request/url_request_status.h"
20 using base::HostToNet32
;
21 using base::checked_numeric_cast
;
25 MockGoogleStreamingServer::MockGoogleStreamingServer(Delegate
* delegate
)
26 : delegate_(delegate
),
27 kDownstreamUrlFetcherId(
28 GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTesting
),
29 kUpstreamUrlFetcherId(
30 GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTesting
) {
31 url_fetcher_factory_
.SetDelegateForTests(this);
34 MockGoogleStreamingServer::~MockGoogleStreamingServer() {
37 void MockGoogleStreamingServer::OnRequestStart(int fetcher_id
) {
38 if (fetcher_id
!= kDownstreamUrlFetcherId
)
41 // Extract request argument from the the request URI.
42 std::string query
= GetURLFetcher(true)->GetOriginalURL().query();
43 std::vector
<std::string
> query_params
;
44 Tokenize(query
, "&", &query_params
);
45 const net::UnescapeRule::Type kUnescapeAll
=
46 net::UnescapeRule::NORMAL
|
47 net::UnescapeRule::SPACES
|
48 net::UnescapeRule::URL_SPECIAL_CHARS
|
49 net::UnescapeRule::REPLACE_PLUS_WITH_SPACE
;
50 for (size_t i
= 0; i
< query_params
.size(); ++i
) {
51 const std::string query_param
= query_params
[i
];
52 std::vector
<std::string
> param_parts
;
53 Tokenize(query_param
, "=", ¶m_parts
);
54 if (param_parts
.size() != 2)
56 std::string param_key
= net::UnescapeURLComponent(param_parts
[0],
58 std::string param_value
= net::UnescapeURLComponent(param_parts
[1],
60 if (param_key
== "lang") {
61 request_language
= param_value
;
62 } else if (param_key
== "lm") {
63 request_grammar
= param_value
;
67 delegate_
->OnClientConnected();
70 void MockGoogleStreamingServer::OnChunkUpload(int fetcher_id
) {
71 if (fetcher_id
!= kUpstreamUrlFetcherId
)
73 delegate_
->OnClientAudioUpload();
74 if (GetURLFetcher(false)->did_receive_last_chunk())
75 delegate_
->OnClientAudioUploadComplete();
78 void MockGoogleStreamingServer::OnRequestEnd(int fetcher_id
) {
79 if (fetcher_id
!= kDownstreamUrlFetcherId
)
81 url_fetcher_factory_
.RemoveFetcherFromMap(kDownstreamUrlFetcherId
);
82 delegate_
->OnClientDisconnected();
85 void MockGoogleStreamingServer::SimulateResult(
86 const SpeechRecognitionResult
& result
) {
87 proto::SpeechRecognitionEvent proto_event
;
88 proto_event
.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS
);
89 proto::SpeechRecognitionResult
* proto_result
= proto_event
.add_result();
90 proto_result
->set_final(!result
.is_provisional
);
91 for (size_t i
= 0; i
< result
.hypotheses
.size(); ++i
) {
92 proto::SpeechRecognitionAlternative
* proto_alternative
=
93 proto_result
->add_alternative();
94 const SpeechRecognitionHypothesis
& hypothesis
= result
.hypotheses
[i
];
95 proto_alternative
->set_confidence(hypothesis
.confidence
);
96 proto_alternative
->set_transcript(base::UTF16ToUTF8(hypothesis
.utterance
));
99 std::string msg_string
;
100 proto_event
.SerializeToString(&msg_string
);
102 // Prepend 4 byte prefix length indication to the protobuf message as
103 // envisaged by the google streaming recognition webservice protocol.
104 uint32 prefix
= HostToNet32(checked_numeric_cast
<uint32
>(msg_string
.size()));
105 msg_string
.insert(0, reinterpret_cast<char*>(&prefix
), sizeof(prefix
));
107 SimulateServerResponse(true, msg_string
);
110 void MockGoogleStreamingServer::SimulateServerFailure() {
111 SimulateServerResponse(false, "");
114 void MockGoogleStreamingServer::SimulateMalformedResponse() {
116 "{\"status\":0,\"hypotheses\":""[{\"unknownkey\":\"hello\"}]}";
117 SimulateServerResponse(true, json
);
120 const std::string
& MockGoogleStreamingServer::GetRequestLanguage() const {
121 return request_language
;
124 const std::string
& MockGoogleStreamingServer::GetRequestGrammar() const {
125 return request_grammar
;
128 void MockGoogleStreamingServer::SimulateServerResponse(
129 bool success
, const std::string
& http_response
) {
130 net::TestURLFetcher
* fetcher
= GetURLFetcher(true);
132 net::URLRequestStatus status
;
133 status
.set_status(success
? net::URLRequestStatus::SUCCESS
:
134 net::URLRequestStatus::FAILED
);
135 fetcher
->set_status(status
);
136 fetcher
->set_response_code(success
? 200 : 500);
137 fetcher
->SetResponseString(http_response
);
138 fetcher
->delegate()->OnURLFetchDownloadProgress(fetcher
, 0, 0);
141 // Can return NULL if the SpeechRecognizer has not requested the connection yet.
142 net::TestURLFetcher
* MockGoogleStreamingServer::GetURLFetcher(
143 bool downstream
) const {
144 return url_fetcher_factory_
.GetFetcherByID(
145 downstream
? kDownstreamUrlFetcherId
: kUpstreamUrlFetcherId
);
148 } // namespace content