Home | History | Annotate | Download | only in test
      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.
      4 
      5 #include "content/test/mock_google_streaming_server.h"
      6 
      7 #include "base/bind.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"
     19 
     20 using base::HostToNet32;
     21 using base::checked_numeric_cast;
     22 
     23 namespace content {
     24 
     25 MockGoogleStreamingServer::MockGoogleStreamingServer(Delegate* delegate)
     26     : delegate_(delegate),
     27       kDownstreamUrlFetcherId(
     28           GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTesting),
     29       kUpstreamUrlFetcherId(
     30           GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTesting) {
     31   url_fetcher_factory_.SetDelegateForTests(this);
     32 }
     33 
     34 MockGoogleStreamingServer::~MockGoogleStreamingServer() {
     35 }
     36 
     37 void MockGoogleStreamingServer::OnRequestStart(int fetcher_id) {
     38   if (fetcher_id != kDownstreamUrlFetcherId)
     39     return;
     40 
     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, "=", &param_parts);
     54     if (param_parts.size() != 2)
     55       continue;
     56     std::string param_key = net::UnescapeURLComponent(param_parts[0],
     57                                                       kUnescapeAll);
     58     std::string param_value = net::UnescapeURLComponent(param_parts[1],
     59                                                         kUnescapeAll);
     60     if (param_key == "lang") {
     61       request_language = param_value;
     62     } else if (param_key == "lm") {
     63       request_grammar = param_value;
     64     }
     65   }
     66 
     67   delegate_->OnClientConnected();
     68 }
     69 
     70 void MockGoogleStreamingServer::OnChunkUpload(int fetcher_id) {
     71   if (fetcher_id != kUpstreamUrlFetcherId)
     72       return;
     73   delegate_->OnClientAudioUpload();
     74   if (GetURLFetcher(false)->did_receive_last_chunk())
     75     delegate_->OnClientAudioUploadComplete();
     76 }
     77 
     78 void MockGoogleStreamingServer::OnRequestEnd(int fetcher_id) {
     79   if (fetcher_id != kDownstreamUrlFetcherId)
     80     return;
     81   url_fetcher_factory_.RemoveFetcherFromMap(kDownstreamUrlFetcherId);
     82   delegate_->OnClientDisconnected();
     83 }
     84 
     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(UTF16ToUTF8(hypothesis.utterance));
     97   }
     98 
     99   std::string msg_string;
    100   proto_event.SerializeToString(&msg_string);
    101 
    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));
    106 
    107   SimulateServerResponse(true, msg_string);
    108 }
    109 
    110 void MockGoogleStreamingServer::SimulateServerFailure() {
    111   SimulateServerResponse(false, "");
    112 }
    113 
    114 void MockGoogleStreamingServer::SimulateMalformedResponse() {
    115   std::string json =
    116       "{\"status\":0,\"hypotheses\":""[{\"unknownkey\":\"hello\"}]}";
    117   SimulateServerResponse(true, json);
    118 }
    119 
    120 const std::string& MockGoogleStreamingServer::GetRequestLanguage() const {
    121   return request_language;
    122 }
    123 
    124 const std::string& MockGoogleStreamingServer::GetRequestGrammar() const {
    125   return request_grammar;
    126 }
    127 
    128 void MockGoogleStreamingServer::SimulateServerResponse(
    129     bool success, const std::string& http_response) {
    130   net::TestURLFetcher* fetcher = GetURLFetcher(true);
    131 
    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);
    139 }
    140 
    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);
    146 }
    147 
    148 }  // namespace content
    149