| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/test/mock_google_streaming_server.h" |
| |
| #include "base/bind.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/sys_byteorder.h" |
| #include "base/values.h" |
| #include "content/browser/speech/google_streaming_remote_engine.h" |
| #include "content/browser/speech/proto/google_streaming_api.pb.h" |
| #include "content/browser/speech/speech_recognition_manager_impl.h" |
| #include "net/base/escape.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "net/url_request/url_request_status.h" |
| |
| using base::HostToNet32; |
| using base::checked_cast; |
| |
| namespace content { |
| |
| MockGoogleStreamingServer::MockGoogleStreamingServer(Delegate* delegate) |
| : delegate_(delegate), |
| kDownstreamUrlFetcherId( |
| GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTesting), |
| kUpstreamUrlFetcherId( |
| GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTesting) { |
| url_fetcher_factory_.SetDelegateForTests(this); |
| } |
| |
| MockGoogleStreamingServer::~MockGoogleStreamingServer() { |
| } |
| |
| void MockGoogleStreamingServer::OnRequestStart(int fetcher_id) { |
| if (fetcher_id != kDownstreamUrlFetcherId) |
| return; |
| |
| // Extract request argument from the the request URI. |
| std::string query = GetURLFetcher(true)->GetOriginalURL().query(); |
| std::vector<std::string> query_params; |
| Tokenize(query, "&", &query_params); |
| const net::UnescapeRule::Type kUnescapeAll = |
| net::UnescapeRule::NORMAL | |
| net::UnescapeRule::SPACES | |
| net::UnescapeRule::URL_SPECIAL_CHARS | |
| net::UnescapeRule::REPLACE_PLUS_WITH_SPACE; |
| for (size_t i = 0; i < query_params.size(); ++i) { |
| const std::string query_param = query_params[i]; |
| std::vector<std::string> param_parts; |
| Tokenize(query_param, "=", ¶m_parts); |
| if (param_parts.size() != 2) |
| continue; |
| std::string param_key = net::UnescapeURLComponent(param_parts[0], |
| kUnescapeAll); |
| std::string param_value = net::UnescapeURLComponent(param_parts[1], |
| kUnescapeAll); |
| if (param_key == "lang") { |
| request_language = param_value; |
| } else if (param_key == "lm") { |
| request_grammar = param_value; |
| } |
| } |
| |
| delegate_->OnClientConnected(); |
| } |
| |
| void MockGoogleStreamingServer::OnChunkUpload(int fetcher_id) { |
| if (fetcher_id != kUpstreamUrlFetcherId) |
| return; |
| delegate_->OnClientAudioUpload(); |
| if (GetURLFetcher(false)->did_receive_last_chunk()) |
| delegate_->OnClientAudioUploadComplete(); |
| } |
| |
| void MockGoogleStreamingServer::OnRequestEnd(int fetcher_id) { |
| if (fetcher_id != kDownstreamUrlFetcherId) |
| return; |
| url_fetcher_factory_.RemoveFetcherFromMap(kDownstreamUrlFetcherId); |
| delegate_->OnClientDisconnected(); |
| } |
| |
| void MockGoogleStreamingServer::SimulateResult( |
| const SpeechRecognitionResult& result) { |
| proto::SpeechRecognitionEvent proto_event; |
| proto_event.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS); |
| proto::SpeechRecognitionResult* proto_result = proto_event.add_result(); |
| proto_result->set_final(!result.is_provisional); |
| for (size_t i = 0; i < result.hypotheses.size(); ++i) { |
| proto::SpeechRecognitionAlternative* proto_alternative = |
| proto_result->add_alternative(); |
| const SpeechRecognitionHypothesis& hypothesis = result.hypotheses[i]; |
| proto_alternative->set_confidence(hypothesis.confidence); |
| proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis.utterance)); |
| } |
| |
| std::string msg_string; |
| proto_event.SerializeToString(&msg_string); |
| |
| // Prepend 4 byte prefix length indication to the protobuf message as |
| // envisaged by the google streaming recognition webservice protocol. |
| uint32 prefix = HostToNet32(checked_cast<uint32>(msg_string.size())); |
| msg_string.insert(0, reinterpret_cast<char*>(&prefix), sizeof(prefix)); |
| |
| SimulateServerResponse(true, msg_string); |
| } |
| |
| void MockGoogleStreamingServer::SimulateServerFailure() { |
| SimulateServerResponse(false, ""); |
| } |
| |
| void MockGoogleStreamingServer::SimulateMalformedResponse() { |
| std::string json = |
| "{\"status\":0,\"hypotheses\":""[{\"unknownkey\":\"hello\"}]}"; |
| SimulateServerResponse(true, json); |
| } |
| |
| const std::string& MockGoogleStreamingServer::GetRequestLanguage() const { |
| return request_language; |
| } |
| |
| const std::string& MockGoogleStreamingServer::GetRequestGrammar() const { |
| return request_grammar; |
| } |
| |
| void MockGoogleStreamingServer::SimulateServerResponse( |
| bool success, const std::string& http_response) { |
| net::TestURLFetcher* fetcher = GetURLFetcher(true); |
| |
| net::URLRequestStatus status; |
| status.set_status(success ? net::URLRequestStatus::SUCCESS : |
| net::URLRequestStatus::FAILED); |
| fetcher->set_status(status); |
| fetcher->set_response_code(success ? 200 : 500); |
| fetcher->SetResponseString(http_response); |
| fetcher->delegate()->OnURLFetchDownloadProgress(fetcher, 0, 0); |
| } |
| |
| // Can return NULL if the SpeechRecognizer has not requested the connection yet. |
| net::TestURLFetcher* MockGoogleStreamingServer::GetURLFetcher( |
| bool downstream) const { |
| return url_fetcher_factory_.GetFetcherByID( |
| downstream ? kDownstreamUrlFetcherId : kUpstreamUrlFetcherId); |
| } |
| |
| } // namespace content |