diff options
Diffstat (limited to 'chromium/content/browser/speech')
17 files changed, 276 insertions, 134 deletions
diff --git a/chromium/content/browser/speech/OWNERS b/chromium/content/browser/speech/OWNERS index b38caa6f1ff..1dede2088d2 100644 --- a/chromium/content/browser/speech/OWNERS +++ b/chromium/content/browser/speech/OWNERS @@ -1,3 +1 @@ -hans@chromium.org tommi@chromium.org -xians@chromium.org diff --git a/chromium/content/browser/speech/audio_buffer.cc b/chromium/content/browser/speech/audio_buffer.cc index 3e7d2a4a68e..823fff5291f 100644 --- a/chromium/content/browser/speech/audio_buffer.cc +++ b/chromium/content/browser/speech/audio_buffer.cc @@ -5,7 +5,6 @@ #include "content/browser/speech/audio_buffer.h" #include "base/logging.h" -#include "base/stl_util.h" namespace content { @@ -13,6 +12,11 @@ AudioChunk::AudioChunk(int bytes_per_sample) : bytes_per_sample_(bytes_per_sample) { } +AudioChunk::AudioChunk(size_t length, int bytes_per_sample) + : data_string_(length, '\0'), bytes_per_sample_(bytes_per_sample) { + DCHECK_EQ(length % bytes_per_sample, 0U); +} + AudioChunk::AudioChunk(const uint8* data, size_t length, int bytes_per_sample) : data_string_(reinterpret_cast<const char*>(data), length), bytes_per_sample_(bytes_per_sample) { @@ -40,7 +44,6 @@ const int16* AudioChunk::SamplesData16() const { return reinterpret_cast<const int16*>(data_string_.data()); } - AudioBuffer::AudioBuffer(int bytes_per_sample) : bytes_per_sample_(bytes_per_sample) { DCHECK(bytes_per_sample == 1 || @@ -64,17 +67,19 @@ scoped_refptr<AudioChunk> AudioBuffer::DequeueSingleChunk() { } scoped_refptr<AudioChunk> AudioBuffer::DequeueAll() { - scoped_refptr<AudioChunk> chunk(new AudioChunk(bytes_per_sample_)); size_t resulting_length = 0; ChunksContainer::const_iterator it; // In order to improve performance, calulate in advance the total length // and then copy the chunks. for (it = chunks_.begin(); it != chunks_.end(); ++it) { - resulting_length += (*it)->data_string_.length(); + resulting_length += (*it)->AsString().length(); } - chunk->data_string_.reserve(resulting_length); + scoped_refptr<AudioChunk> chunk( + new AudioChunk(resulting_length, bytes_per_sample_)); + uint8* dest = chunk->writable_data(); for (it = chunks_.begin(); it != chunks_.end(); ++it) { - chunk->data_string_.append((*it)->data_string_); + memcpy(dest, (*it)->AsString().data(), (*it)->AsString().length()); + dest += (*it)->AsString().length(); } Clear(); return chunk; diff --git a/chromium/content/browser/speech/audio_buffer.h b/chromium/content/browser/speech/audio_buffer.h index 783ae6679f3..7b0fd7e19df 100644 --- a/chromium/content/browser/speech/audio_buffer.h +++ b/chromium/content/browser/speech/audio_buffer.h @@ -19,6 +19,8 @@ class CONTENT_EXPORT AudioChunk : public base::RefCountedThreadSafe<AudioChunk> { public: explicit AudioChunk(int bytes_per_sample); + // Creates a chunk of |length| bytes, initialized to zeros. + AudioChunk(size_t length, int bytes_per_sample); AudioChunk(const uint8* data, size_t length, int bytes_per_sample); bool IsEmpty() const; @@ -27,14 +29,14 @@ class CONTENT_EXPORT AudioChunk : const std::string& AsString() const; int16 GetSample16(size_t index) const; const int16* SamplesData16() const; - friend class AudioBuffer; + uint8* writable_data() { return reinterpret_cast<uint8*>(&data_string_[0]); } private: - ~AudioChunk() {} friend class base::RefCountedThreadSafe<AudioChunk>; + ~AudioChunk() {} std::string data_string_; - int bytes_per_sample_; + const int bytes_per_sample_; DISALLOW_COPY_AND_ASSIGN(AudioChunk); }; @@ -51,7 +53,8 @@ class AudioBuffer { // Dequeues, in FIFO order, a single chunk respecting the length of the // corresponding Enqueue call (in a nutshell: multiple Enqueue calls followed - // by Dequeue calls will return the individual chunks without merging them). + // by DequeueSingleChunk calls will return the individual chunks without + // merging them). scoped_refptr<AudioChunk> DequeueSingleChunk(); // Dequeues all previously enqueued chunks, merging them in a single chunk. @@ -66,7 +69,7 @@ class AudioBuffer { private: typedef std::deque<scoped_refptr<AudioChunk> > ChunksContainer; ChunksContainer chunks_; - int bytes_per_sample_; + const int bytes_per_sample_; DISALLOW_COPY_AND_ASSIGN(AudioBuffer); }; diff --git a/chromium/content/browser/speech/audio_encoder.cc b/chromium/content/browser/speech/audio_encoder.cc index 09b5dca287d..e145ddaba40 100644 --- a/chromium/content/browser/speech/audio_encoder.cc +++ b/chromium/content/browser/speech/audio_encoder.cc @@ -108,7 +108,7 @@ const int kMaxSpeexFrameLength = 110; // (44kbps rate sampled at 32kHz). // Since the frame length gets written out as a byte in the encoded packet, // make sure it is within the byte range. -COMPILE_ASSERT(kMaxSpeexFrameLength <= 0xFF, invalidLength); +static_assert(kMaxSpeexFrameLength <= 0xFF, "invalid length"); class SpeexEncoder : public AudioEncoder { public: diff --git a/chromium/content/browser/speech/chunked_byte_buffer.cc b/chromium/content/browser/speech/chunked_byte_buffer.cc index ae8a6ce8245..5fcf5d18fe6 100644 --- a/chromium/content/browser/speech/chunked_byte_buffer.cc +++ b/chromium/content/browser/speech/chunked_byte_buffer.cc @@ -14,8 +14,8 @@ namespace { static const size_t kHeaderLength = sizeof(uint32); -COMPILE_ASSERT(sizeof(size_t) >= kHeaderLength, - ChunkedByteBufferNotSupportedOnThisArchitecture); +static_assert(sizeof(size_t) >= kHeaderLength, + "chunked byte buffer not supported on this architecture"); uint32 ReadBigEndian32(const uint8* buffer) { return (static_cast<uint32>(buffer[3])) | diff --git a/chromium/content/browser/speech/endpointer/endpointer_unittest.cc b/chromium/content/browser/speech/endpointer/endpointer_unittest.cc index 807b6f68287..c65a7c9b4e1 100644 --- a/chromium/content/browser/speech/endpointer/endpointer_unittest.cc +++ b/chromium/content/browser/speech/endpointer/endpointer_unittest.cc @@ -13,7 +13,7 @@ const int kSampleRate = 8000; // 8 k samples per second for AMR encoding. // At 8 sample per second a 20 ms frame is 160 samples, which corrsponds // to the AMR codec. const int kFrameSize = kSampleRate / kFrameRate; // 160 samples. -COMPILE_ASSERT(kFrameSize == 160, invalid_frame_size); +static_assert(kFrameSize == 160, "invalid frame size"); } namespace content { diff --git a/chromium/content/browser/speech/google_one_shot_remote_engine.cc b/chromium/content/browser/speech/google_one_shot_remote_engine.cc index e52e713deb5..77f5c2cb6f6 100644 --- a/chromium/content/browser/speech/google_one_shot_remote_engine.cc +++ b/chromium/content/browser/speech/google_one_shot_remote_engine.cc @@ -55,7 +55,7 @@ bool ParseServerResponse(const std::string& response_body, } if (!response_value->IsType(base::Value::TYPE_DICTIONARY)) { - VLOG(1) << "ParseServerResponse: Unexpected response type " + DVLOG(1) << "ParseServerResponse: Unexpected response type " << response_value->GetType(); return false; } @@ -65,7 +65,7 @@ bool ParseServerResponse(const std::string& response_body, // Get the status. int status; if (!response_object->GetInteger(kStatusString, &status)) { - VLOG(1) << "ParseServerResponse: " << kStatusString + DVLOG(1) << "ParseServerResponse: " << kStatusString << " is not a valid integer value."; return false; } @@ -83,21 +83,21 @@ bool ParseServerResponse(const std::string& response_body, default: error->code = SPEECH_RECOGNITION_ERROR_NETWORK; // Other status codes should not be returned by the server. - VLOG(1) << "ParseServerResponse: unexpected status code " << status; + DVLOG(1) << "ParseServerResponse: unexpected status code " << status; return false; } // Get the hypotheses. const base::Value* hypotheses_value = NULL; if (!response_object->Get(kHypothesesString, &hypotheses_value)) { - VLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; + DVLOG(1) << "ParseServerResponse: Missing hypotheses attribute."; return false; } DCHECK(hypotheses_value); if (!hypotheses_value->IsType(base::Value::TYPE_LIST)) { - VLOG(1) << "ParseServerResponse: Unexpected hypotheses type " - << hypotheses_value->GetType(); + DVLOG(1) << "ParseServerResponse: Unexpected hypotheses type " + << hypotheses_value->GetType(); return false; } @@ -210,10 +210,8 @@ void GoogleOneShotRemoteEngine::StartRecognition() { config_.audio_sample_rate, config_.audio_num_bits_per_sample)); DCHECK(encoder_.get()); - url_fetcher_.reset(net::URLFetcher::Create(url_fetcher_id_for_tests, - url, - net::URLFetcher::POST, - this)); + url_fetcher_ = net::URLFetcher::Create(url_fetcher_id_for_tests, url, + net::URLFetcher::POST, this); url_fetcher_->SetChunkedUpload(encoder_->mime_type()); url_fetcher_->SetRequestContext(url_context_.get()); url_fetcher_->SetReferrer(config_.origin_url); @@ -247,12 +245,10 @@ void GoogleOneShotRemoteEngine::AudioChunksEnded() { // UploadAudioChunk requires a non-empty final buffer. So we encode a packet // of silence in case encoder had no data already. - std::vector<int16> samples( - config_.audio_sample_rate * kAudioPacketIntervalMs / 1000); - scoped_refptr<AudioChunk> dummy_chunk( - new AudioChunk(reinterpret_cast<uint8*>(&samples[0]), - samples.size() * sizeof(int16), - encoder_->bits_per_sample() / 8)); + size_t sample_count = + config_.audio_sample_rate * kAudioPacketIntervalMs / 1000; + scoped_refptr<AudioChunk> dummy_chunk(new AudioChunk( + sample_count * sizeof(int16), encoder_->bits_per_sample() / 8)); encoder_->Encode(*dummy_chunk.get()); encoder_->Flush(); scoped_refptr<AudioChunk> encoded_dummy_data( diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.cc b/chromium/content/browser/speech/google_streaming_remote_engine.cc index 7fea0fa90a6..fc8c6d24254 100644 --- a/chromium/content/browser/speech/google_streaming_remote_engine.cc +++ b/chromium/content/browser/speech/google_streaming_remote_engine.cc @@ -4,8 +4,10 @@ #include "content/browser/speech/google_streaming_remote_engine.h" +#include <algorithm> #include <vector> +#include "base/big_endian.h" #include "base/bind.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" @@ -81,6 +83,7 @@ GoogleStreamingRemoteEngine::GoogleStreamingRemoteEngine( previous_response_length_(0), got_last_definitive_result_(false), is_dispatching_event_(false), + use_framed_post_data_(false), state_(STATE_IDLE) {} GoogleStreamingRemoteEngine::~GoogleStreamingRemoteEngine() {} @@ -297,6 +300,18 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) { DCHECK(encoder_.get()); const std::string request_key = GenerateRequestKey(); + // Only use the framed post data format when a preamble needs to be logged. + use_framed_post_data_ = (config_.preamble && + !config_.preamble->sample_data.empty() && + !config_.auth_token.empty() && + !config_.auth_scope.empty()); + if (use_framed_post_data_) { + preamble_encoder_.reset(AudioEncoder::Create( + kDefaultAudioCodec, + config_.preamble->sample_rate, + config_.preamble->sample_depth * 8)); + } + // Setup downstream fetcher. std::vector<std::string> downstream_args; downstream_args.push_back( @@ -307,9 +322,8 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) { std::string(kDownstreamUrl) + JoinString(downstream_args, '&')); - downstream_fetcher_.reset(URLFetcher::Create( - kDownstreamUrlFetcherIdForTesting, downstream_url, URLFetcher::GET, - this)); + downstream_fetcher_ = URLFetcher::Create( + kDownstreamUrlFetcherIdForTesting, downstream_url, URLFetcher::GET, this); downstream_fetcher_->SetRequestContext(url_context_.get()); downstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | @@ -342,14 +356,30 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) { upstream_args.push_back("continuous"); if (config_.interim_results) upstream_args.push_back("interim"); - + if (!config_.auth_token.empty() && !config_.auth_scope.empty()) { + upstream_args.push_back( + "authScope=" + net::EscapeQueryParamValue(config_.auth_scope, true)); + upstream_args.push_back( + "authToken=" + net::EscapeQueryParamValue(config_.auth_token, true)); + } + if (use_framed_post_data_) { + std::string audio_format; + if (preamble_encoder_) + audio_format = preamble_encoder_->mime_type() + ","; + audio_format += encoder_->mime_type(); + upstream_args.push_back( + "audioFormat=" + net::EscapeQueryParamValue(audio_format, true)); + } GURL upstream_url(std::string(kWebServiceBaseUrl) + std::string(kUpstreamUrl) + JoinString(upstream_args, '&')); - upstream_fetcher_.reset(URLFetcher::Create( - kUpstreamUrlFetcherIdForTesting, upstream_url, URLFetcher::POST, this)); - upstream_fetcher_->SetChunkedUpload(encoder_->mime_type()); + upstream_fetcher_ = URLFetcher::Create(kUpstreamUrlFetcherIdForTesting, + upstream_url, URLFetcher::POST, this); + if (use_framed_post_data_) + upstream_fetcher_->SetChunkedUpload("application/octet-stream"); + else + upstream_fetcher_->SetChunkedUpload(encoder_->mime_type()); upstream_fetcher_->SetRequestContext(url_context_.get()); upstream_fetcher_->SetReferrer(config_.origin_url); upstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | @@ -357,6 +387,19 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) { net::LOAD_DO_NOT_SEND_AUTH_DATA); upstream_fetcher_->Start(); previous_response_length_ = 0; + + if (preamble_encoder_) { + // Encode and send preamble right away. + scoped_refptr<AudioChunk> chunk = new AudioChunk( + reinterpret_cast<const uint8*>(config_.preamble->sample_data.data()), + config_.preamble->sample_data.size(), + config_.preamble->sample_depth); + preamble_encoder_->Encode(*chunk); + preamble_encoder_->Flush(); + scoped_refptr<AudioChunk> encoded_data( + preamble_encoder_->GetEncodedDataAndClear()); + UploadAudioChunk(encoded_data->AsString(), FRAME_PREAMBLE_AUDIO, false); + } return STATE_BOTH_STREAMS_CONNECTED; } @@ -370,7 +413,7 @@ GoogleStreamingRemoteEngine::TransmitAudioUpstream( DCHECK_EQ(audio.bytes_per_sample(), config_.audio_num_bits_per_sample / 8); encoder_->Encode(audio); scoped_refptr<AudioChunk> encoded_data(encoder_->GetEncodedDataAndClear()); - upstream_fetcher_->AppendChunkToUpload(encoded_data->AsString(), false); + UploadAudioChunk(encoded_data->AsString(), FRAME_RECOGNITION_AUDIO, false); return state_; } @@ -401,20 +444,17 @@ GoogleStreamingRemoteEngine::ProcessDownstreamResponse( case proto::SpeechRecognitionEvent::STATUS_ABORTED: return Abort(SPEECH_RECOGNITION_ERROR_ABORTED); case proto::SpeechRecognitionEvent::STATUS_AUDIO_CAPTURE: - return Abort(SPEECH_RECOGNITION_ERROR_AUDIO); + return Abort(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE); case proto::SpeechRecognitionEvent::STATUS_NETWORK: return Abort(SPEECH_RECOGNITION_ERROR_NETWORK); case proto::SpeechRecognitionEvent::STATUS_NOT_ALLOWED: - // TODO(hans): We need a better error code for this. - return Abort(SPEECH_RECOGNITION_ERROR_ABORTED); + return Abort(SPEECH_RECOGNITION_ERROR_NOT_ALLOWED); case proto::SpeechRecognitionEvent::STATUS_SERVICE_NOT_ALLOWED: - // TODO(hans): We need a better error code for this. - return Abort(SPEECH_RECOGNITION_ERROR_ABORTED); + return Abort(SPEECH_RECOGNITION_ERROR_SERVICE_NOT_ALLOWED); case proto::SpeechRecognitionEvent::STATUS_BAD_GRAMMAR: return Abort(SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR); case proto::SpeechRecognitionEvent::STATUS_LANGUAGE_NOT_SUPPORTED: - // TODO(hans): We need a better error code for this. - return Abort(SPEECH_RECOGNITION_ERROR_ABORTED); + return Abort(SPEECH_RECOGNITION_ERROR_LANGUAGE_NOT_SUPPORTED); } } @@ -471,12 +511,10 @@ GoogleStreamingRemoteEngine::CloseUpstreamAndWaitForResults( // The encoder requires a non-empty final buffer. So we encode a packet // of silence in case encoder had no data already. - std::vector<short> samples( - config_.audio_sample_rate * kAudioPacketIntervalMs / 1000); - scoped_refptr<AudioChunk> dummy_chunk = - new AudioChunk(reinterpret_cast<uint8*>(&samples[0]), - samples.size() * sizeof(short), - encoder_->bits_per_sample() / 8); + size_t sample_count = + config_.audio_sample_rate * kAudioPacketIntervalMs / 1000; + scoped_refptr<AudioChunk> dummy_chunk = new AudioChunk( + sample_count * sizeof(int16), encoder_->bits_per_sample() / 8); encoder_->Encode(*dummy_chunk.get()); encoder_->Flush(); scoped_refptr<AudioChunk> encoded_dummy_data = @@ -484,7 +522,9 @@ GoogleStreamingRemoteEngine::CloseUpstreamAndWaitForResults( DCHECK(!encoded_dummy_data->IsEmpty()); encoder_.reset(); - upstream_fetcher_->AppendChunkToUpload(encoded_dummy_data->AsString(), true); + UploadAudioChunk(encoded_dummy_data->AsString(), + FRAME_RECOGNITION_AUDIO, + true); got_last_definitive_result_ = false; return STATE_WAITING_DOWNSTREAM_RESULTS; } @@ -572,6 +612,20 @@ std::string GoogleStreamingRemoteEngine::GenerateRequestKey() const { return base::HexEncode(reinterpret_cast<void*>(&key), sizeof(key)); } +void GoogleStreamingRemoteEngine::UploadAudioChunk(const std::string& data, + FrameType type, + bool is_final) { + if (use_framed_post_data_) { + std::string frame(data.size() + 8, 0); + base::WriteBigEndian(&frame[0], static_cast<uint32_t>(data.size())); + base::WriteBigEndian(&frame[4], static_cast<uint32_t>(type)); + frame.replace(8, data.size(), data); + upstream_fetcher_->AppendChunkToUpload(frame, is_final); + } else { + upstream_fetcher_->AppendChunkToUpload(data, is_final); + } +} + GoogleStreamingRemoteEngine::FSMEventArgs::FSMEventArgs(FSMEvent event_value) : event(event_value) { } diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.h b/chromium/content/browser/speech/google_streaming_remote_engine.h index 961ef0877db..15b866ba63b 100644 --- a/chromium/content/browser/speech/google_streaming_remote_engine.h +++ b/chromium/content/browser/speech/google_streaming_remote_engine.h @@ -79,6 +79,13 @@ class CONTENT_EXPORT GoogleStreamingRemoteEngine static const int kWebserviceStatusNoError; static const int kWebserviceStatusErrorNoMatch; + // Frame type for framed POST data. Do NOT change these. They must match + // values the server expects. + enum FrameType { + FRAME_PREAMBLE_AUDIO = 0, + FRAME_RECOGNITION_AUDIO = 1 + }; + // Data types for the internal Finite State Machine (FSM). enum FSMState { STATE_IDLE = 0, @@ -143,15 +150,21 @@ class CONTENT_EXPORT GoogleStreamingRemoteEngine std::string GetAcceptedLanguages() const; std::string GenerateRequestKey() const; + // Upload a single chunk of audio data. Handles both unframed and framed + // upload formats, and uses the appropriate one. + void UploadAudioChunk(const std::string& data, FrameType type, bool is_final); + SpeechRecognitionEngineConfig config_; scoped_ptr<net::URLFetcher> upstream_fetcher_; scoped_ptr<net::URLFetcher> downstream_fetcher_; scoped_refptr<net::URLRequestContextGetter> url_context_; scoped_ptr<AudioEncoder> encoder_; + scoped_ptr<AudioEncoder> preamble_encoder_; ChunkedByteBuffer chunked_byte_buffer_; size_t previous_response_length_; bool got_last_definitive_result_; bool is_dispatching_event_; + bool use_framed_post_data_; FSMState state_; DISALLOW_COPY_AND_ASSIGN(GoogleStreamingRemoteEngine); diff --git a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc index 57947e61e5d..c3d7ce5c4e1 100644 --- a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc +++ b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc @@ -4,6 +4,7 @@ #include <queue> +#include "base/big_endian.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/numerics/safe_conversions.h" @@ -27,6 +28,10 @@ using net::TestURLFetcherFactory; namespace content { +// Frame types for framed POST data. +static const uint32_t kFrameTypePreamble = 0; +static const uint32_t kFrameTypeRecognitionAudio = 1; + // Note: the terms upstream and downstream are from the point-of-view of the // client (engine_under_test_). @@ -73,10 +78,12 @@ class GoogleStreamingRemoteEngineTest : public SpeechRecognitionEngineDelegate, void EndMockRecognition(); void InjectDummyAudioChunk(); size_t UpstreamChunksUploadedFromLastCall(); + std::string LastUpstreamChunkUploaded(); void ProvideMockProtoResultDownstream( const proto::SpeechRecognitionEvent& result); void ProvideMockResultDownstream(const SpeechRecognitionResult& result); void ExpectResultsReceived(const SpeechRecognitionResults& result); + void ExpectFramedChunk(const std::string& chunk, uint32_t type); void CloseMockDownstream(DownstreamError error); scoped_ptr<GoogleStreamingRemoteEngine> engine_under_test_; @@ -325,6 +332,56 @@ TEST_F(GoogleStreamingRemoteEngineTest, Stability) { ASSERT_EQ(0U, results_.size()); } +TEST_F(GoogleStreamingRemoteEngineTest, SendPreamble) { + const size_t kPreambleLength = 100; + scoped_refptr<SpeechRecognitionSessionPreamble> preamble = + new SpeechRecognitionSessionPreamble(); + preamble->sample_rate = 16000; + preamble->sample_depth = 2; + preamble->sample_data.assign(kPreambleLength, 0); + SpeechRecognitionEngine::Config config; + config.auth_token = "foo"; + config.auth_scope = "bar"; + config.preamble = preamble; + engine_under_test_->SetConfig(config); + + StartMockRecognition(); + ASSERT_TRUE(GetUpstreamFetcher()); + // First chunk uploaded should be the preamble. + ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall()); + std::string chunk = LastUpstreamChunkUploaded(); + ExpectFramedChunk(chunk, kFrameTypePreamble); + + for (int i = 0; i < 3; ++i) { + InjectDummyAudioChunk(); + ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall()); + chunk = LastUpstreamChunkUploaded(); + ExpectFramedChunk(chunk, kFrameTypeRecognitionAudio); + } + engine_under_test_->AudioChunksEnded(); + ASSERT_TRUE(engine_under_test_->IsRecognitionPending()); + + // Simulate a protobuf message streamed from the server containing a single + // result with one hypotheses. + SpeechRecognitionResults results; + results.push_back(SpeechRecognitionResult()); + SpeechRecognitionResult& result = results.back(); + result.is_provisional = false; + result.hypotheses.push_back( + SpeechRecognitionHypothesis(base::UTF8ToUTF16("hypothesis 1"), 0.1F)); + + ProvideMockResultDownstream(result); + ExpectResultsReceived(results); + ASSERT_TRUE(engine_under_test_->IsRecognitionPending()); + + // Ensure everything is closed cleanly after the downstream is closed. + CloseMockDownstream(DOWNSTREAM_ERROR_NONE); + ASSERT_FALSE(engine_under_test_->IsRecognitionPending()); + EndMockRecognition(); + ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); + ASSERT_EQ(0U, results_.size()); +} + void GoogleStreamingRemoteEngineTest::SetUp() { engine_under_test_.reset( new GoogleStreamingRemoteEngine(NULL /*URLRequestContextGetter*/)); @@ -397,6 +454,13 @@ size_t GoogleStreamingRemoteEngineTest::UpstreamChunksUploadedFromLastCall() { return new_chunks; } +std::string GoogleStreamingRemoteEngineTest::LastUpstreamChunkUploaded() { + TestURLFetcher* upstream_fetcher = GetUpstreamFetcher(); + DCHECK(upstream_fetcher); + DCHECK(!upstream_fetcher->upload_chunks().empty()); + return upstream_fetcher->upload_chunks().back(); +} + void GoogleStreamingRemoteEngineTest::ProvideMockProtoResultDownstream( const proto::SpeechRecognitionEvent& result) { TestURLFetcher* downstream_fetcher = GetDownstreamFetcher(); @@ -483,6 +547,15 @@ bool GoogleStreamingRemoteEngineTest::ResultsAreEqual( return true; } +void GoogleStreamingRemoteEngineTest::ExpectFramedChunk( + const std::string& chunk, uint32_t type) { + uint32_t value; + base::ReadBigEndian(&chunk[0], &value); + EXPECT_EQ(chunk.size() - 8, value); + base::ReadBigEndian(&chunk[4], &value); + EXPECT_EQ(type, value); +} + std::string GoogleStreamingRemoteEngineTest::SerializeProtobufResponse( const proto::SpeechRecognitionEvent& msg) { std::string msg_string; diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc index 02671a4786f..8bc0749f40e 100644 --- a/chromium/content/browser/speech/speech_recognition_browsertest.cc +++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc @@ -94,7 +94,7 @@ class SpeechRecognitionBrowserTest : } std::string GetPageFragment() { - return shell()->web_contents()->GetURL().ref(); + return shell()->web_contents()->GetLastCommittedURL().ref(); } const StreamingServerState &streaming_server_state() { @@ -188,13 +188,8 @@ class SpeechRecognitionBrowserTest : // Simply loads the test page and checks if it was able to create a Speech // Recognition object in JavaScript, to make sure the Web Speech API is enabled. -// http://crbug.com/396414 -#if defined(OS_WIN) || defined(OS_MACOSX) -#define MAYBE_Precheck DISABLED_Precheck -#else -#define MAYBE_Precheck Precheck -#endif -IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, MAYBE_Precheck) { +// Flaky on all platforms. http://crbug.com/396414. +IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, DISABLED_Precheck) { NavigateToURLBlockUntilNavigationsComplete( shell(), GetTestUrlFromFragment("precheck"), 2); diff --git a/chromium/content/browser/speech/speech_recognition_engine.h b/chromium/content/browser/speech/speech_recognition_engine.h index 73ba26ec7e5..4f945b510ec 100644 --- a/chromium/content/browser/speech/speech_recognition_engine.h +++ b/chromium/content/browser/speech/speech_recognition_engine.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "content/common/content_export.h" +#include "content/public/browser/speech_recognition_session_preamble.h" #include "content/public/common/speech_recognition_grammar.h" #include "content/public/common/speech_recognition_result.h" @@ -59,6 +60,9 @@ class SpeechRecognitionEngine { std::string origin_url; int audio_sample_rate; int audio_num_bits_per_sample; + std::string auth_token; + std::string auth_scope; + scoped_refptr<SpeechRecognitionSessionPreamble> preamble; }; virtual ~SpeechRecognitionEngine() {} diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc index 1a054204c44..f02c29f1dd4 100644 --- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc +++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc @@ -39,7 +39,7 @@ namespace { SpeechRecognitionManagerImpl* g_speech_recognition_manager_impl; void ShowAudioInputSettingsOnFileThread(media::AudioManager* audio_manager) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); audio_manager->ShowAudioInputSettings(); } @@ -69,7 +69,7 @@ SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl( last_session_id_(kSessionIDInvalid), is_dispatching_event_(false), delegate_(GetContentClient()->browser()-> - GetSpeechRecognitionManagerDelegate()), + CreateSpeechRecognitionManagerDelegate()), weak_factory_(this) { DCHECK(!g_speech_recognition_manager_impl); g_speech_recognition_manager_impl = this; @@ -91,7 +91,7 @@ SpeechRecognitionManagerImpl::~SpeechRecognitionManagerImpl() { int SpeechRecognitionManagerImpl::CreateSession( const SpeechRecognitionSessionConfig& config) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); const int session_id = GetNextSessionID(); DCHECK(!SessionExists(session_id)); @@ -132,6 +132,9 @@ int SpeechRecognitionManagerImpl::CreateSession( remote_engine_config.hardware_info = hardware_info; remote_engine_config.origin_url = can_report_metrics ? config.origin_url : std::string(); + remote_engine_config.auth_token = config.auth_token; + remote_engine_config.auth_scope = config.auth_scope; + remote_engine_config.preamble = config.preamble; SpeechRecognitionEngine* google_remote_engine; if (config.is_legacy_api) { @@ -157,7 +160,7 @@ int SpeechRecognitionManagerImpl::CreateSession( } void SpeechRecognitionManagerImpl::StartSession(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -181,7 +184,7 @@ void SpeechRecognitionManagerImpl::StartSession(int session_id) { void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, bool ask_user, bool is_allowed) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -229,7 +232,7 @@ void SpeechRecognitionManagerImpl::MediaRequestPermissionCallback( int session_id, const MediaStreamDevices& devices, scoped_ptr<MediaStreamUIProxy> stream_ui) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); SessionsTable::iterator iter = sessions_.find(session_id); if (iter == sessions_.end()) @@ -252,7 +255,7 @@ void SpeechRecognitionManagerImpl::MediaRequestPermissionCallback( } void SpeechRecognitionManagerImpl::AbortSession(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -273,7 +276,7 @@ void SpeechRecognitionManagerImpl::AbortSession(int session_id) { } void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -294,7 +297,7 @@ void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) { // (if any). void SpeechRecognitionManagerImpl::OnRecognitionStart(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -313,7 +316,7 @@ void SpeechRecognitionManagerImpl::OnRecognitionStart(int session_id) { } void SpeechRecognitionManagerImpl::OnAudioStart(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -326,7 +329,7 @@ void SpeechRecognitionManagerImpl::OnAudioStart(int session_id) { void SpeechRecognitionManagerImpl::OnEnvironmentEstimationComplete( int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -338,7 +341,7 @@ void SpeechRecognitionManagerImpl::OnEnvironmentEstimationComplete( } void SpeechRecognitionManagerImpl::OnSoundStart(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -350,7 +353,7 @@ void SpeechRecognitionManagerImpl::OnSoundStart(int session_id) { } void SpeechRecognitionManagerImpl::OnSoundEnd(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -361,7 +364,7 @@ void SpeechRecognitionManagerImpl::OnSoundEnd(int session_id) { } void SpeechRecognitionManagerImpl::OnAudioEnd(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -379,7 +382,7 @@ void SpeechRecognitionManagerImpl::OnAudioEnd(int session_id) { void SpeechRecognitionManagerImpl::OnRecognitionResults( int session_id, const SpeechRecognitionResults& results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -391,7 +394,7 @@ void SpeechRecognitionManagerImpl::OnRecognitionResults( void SpeechRecognitionManagerImpl::OnRecognitionError( int session_id, const SpeechRecognitionError& error) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -403,7 +406,7 @@ void SpeechRecognitionManagerImpl::OnRecognitionError( void SpeechRecognitionManagerImpl::OnAudioLevelsChange( int session_id, float volume, float noise_volume) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -414,7 +417,7 @@ void SpeechRecognitionManagerImpl::OnAudioLevelsChange( } void SpeechRecognitionManagerImpl::OnRecognitionEnd(int session_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!SessionExists(session_id)) return; @@ -432,9 +435,9 @@ void SpeechRecognitionManagerImpl::OnRecognitionEnd(int session_id) { int SpeechRecognitionManagerImpl::GetSession( int render_process_id, int render_view_id, int request_id) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); SessionsTable::const_iterator iter; - for(iter = sessions_.begin(); iter != sessions_.end(); ++iter) { + for (iter = sessions_.begin(); iter != sessions_.end(); ++iter) { const int session_id = iter->first; const SpeechRecognitionSessionContext& context = iter->second->context; if (context.render_process_id == render_process_id && @@ -456,7 +459,7 @@ void SpeechRecognitionManagerImpl::AbortAllSessionsForRenderProcess( // This method gracefully destroys sessions for the listener. However, since // the listener itself is likely to be destroyed after this call, we avoid // dispatching further events to it, marking the |listener_is_active| flag. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (SessionsTable::iterator it = sessions_.begin(); it != sessions_.end(); ++it) { Session* session = it->second; @@ -470,7 +473,7 @@ void SpeechRecognitionManagerImpl::AbortAllSessionsForRenderProcess( void SpeechRecognitionManagerImpl::AbortAllSessionsForRenderView( int render_process_id, int render_view_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (SessionsTable::iterator it = sessions_.begin(); it != sessions_.end(); ++it) { Session* session = it->second; @@ -484,7 +487,7 @@ void SpeechRecognitionManagerImpl::AbortAllSessionsForRenderView( // ----------------------- Core FSM implementation --------------------------- void SpeechRecognitionManagerImpl::DispatchEvent(int session_id, FSMEvent event) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // There are some corner cases in which the session might be deleted (due to // an EndRecognition event) between a request (e.g. Abort) and its dispatch. @@ -648,7 +651,7 @@ bool SpeechRecognitionManagerImpl::SessionExists(int session_id) const { SpeechRecognitionManagerImpl::Session* SpeechRecognitionManagerImpl::GetSession(int session_id) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); SessionsTable::const_iterator iter = sessions_.find(session_id); DCHECK(iter != sessions_.end()); return iter->second; diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc index f6fb3900a5e..a08ffe17661 100644 --- a/chromium/content/browser/speech/speech_recognizer_impl.cc +++ b/chromium/content/browser/speech/speech_recognizer_impl.cc @@ -13,7 +13,6 @@ #include "content/browser/speech/google_one_shot_remote_engine.h" #include "content/public/browser/speech_recognition_event_listener.h" #include "media/base/audio_converter.h" -#include "net/url_request/url_request_context_getter.h" #if defined(OS_WIN) #include "media/audio/win/core_audio_util_win.h" @@ -56,7 +55,6 @@ class SpeechRecognizerImpl::OnDataConverter const AudioParameters input_parameters_; const AudioParameters output_parameters_; bool waiting_for_input_; - scoped_ptr<uint8[]> converted_data_; DISALLOW_COPY_AND_ASSIGN(OnDataConverter); }; @@ -108,20 +106,20 @@ const int SpeechRecognizerImpl::kNoSpeechTimeoutMs = 8000; const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300; media::AudioManager* SpeechRecognizerImpl::audio_manager_for_tests_ = NULL; -COMPILE_ASSERT(SpeechRecognizerImpl::kNumBitsPerAudioSample % 8 == 0, - kNumBitsPerAudioSample_must_be_a_multiple_of_8); +static_assert(SpeechRecognizerImpl::kNumBitsPerAudioSample % 8 == 0, + "kNumBitsPerAudioSample must be a multiple of 8"); // SpeechRecognizerImpl::OnDataConverter implementation SpeechRecognizerImpl::OnDataConverter::OnDataConverter( - const AudioParameters& input_params, const AudioParameters& output_params) + const AudioParameters& input_params, + const AudioParameters& output_params) : audio_converter_(input_params, output_params, false), input_bus_(AudioBus::Create(input_params)), output_bus_(AudioBus::Create(output_params)), input_parameters_(input_params), output_parameters_(output_params), - waiting_for_input_(false), - converted_data_(new uint8[output_parameters_.GetBytesPerBuffer()]) { + waiting_for_input_(false) { audio_converter_.AddInput(this); } @@ -140,16 +138,13 @@ scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert( waiting_for_input_ = true; audio_converter_.Convert(output_bus_.get()); - output_bus_->ToInterleaved( - output_bus_->frames(), output_parameters_.bits_per_sample() / 8, - converted_data_.get()); - - // TODO(primiano): Refactor AudioChunk to avoid the extra-copy here - // (see http://crbug.com/249316 for details). - return scoped_refptr<AudioChunk>(new AudioChunk( - converted_data_.get(), - output_parameters_.GetBytesPerBuffer(), - output_parameters_.bits_per_sample() / 8)); + scoped_refptr<AudioChunk> chunk( + new AudioChunk(output_parameters_.GetBytesPerBuffer(), + output_parameters_.bits_per_sample() / 8)); + output_bus_->ToInterleaved(output_bus_->frames(), + output_parameters_.bits_per_sample() / 8, + chunk->writable_data()); + return chunk; } double SpeechRecognizerImpl::OnDataConverter::ProvideInput( @@ -236,12 +231,12 @@ void SpeechRecognizerImpl::StopAudioCapture() { bool SpeechRecognizerImpl::IsActive() const { // Checking the FSM state from another thread (thus, while the FSM is // potentially concurrently evolving) is meaningless. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return state_ != STATE_IDLE && state_ != STATE_ENDED; } bool SpeechRecognizerImpl::IsCapturingAudio() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // See IsActive(). + DCHECK_CURRENTLY_ON(BrowserThread::IO); // See IsActive(). const bool is_capturing_audio = state_ >= STATE_STARTING && state_ <= STATE_RECOGNIZING; DCHECK((is_capturing_audio && (audio_controller_.get() != NULL)) || @@ -255,7 +250,7 @@ SpeechRecognizerImpl::recognition_engine() const { } SpeechRecognizerImpl::~SpeechRecognizerImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); endpointer_.EndSession(); if (audio_controller_.get()) { audio_controller_->Close( @@ -317,7 +312,7 @@ void SpeechRecognizerImpl::OnSpeechRecognitionEngineError( // does, but they will become flaky if TestAudioInputController will be fixed. void SpeechRecognizerImpl::DispatchEvent(const FSMEventArgs& event_args) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_LE(event_args.event, EVENT_MAX_VALUE); DCHECK_LE(state_, STATE_MAX_VALUE); @@ -508,7 +503,7 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) { // TODO(xians): Check if the OS has the device with |device_id_|, return // |SPEECH_AUDIO_ERROR_DETAILS_NO_MIC| if the target device does not exist. if (!audio_manager->HasAudioInputDevices()) { - return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO, + return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, SPEECH_AUDIO_ERROR_DETAILS_NO_MIC)); } @@ -518,7 +513,8 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) { device_id_); if (!in_params.IsValid() && !unit_test_is_active) { DLOG(ERROR) << "Invalid native audio input parameters"; - return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO)); + return Abort( + SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE)); } // Audio converter shall provide audio based on these parameters as output. @@ -569,7 +565,8 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) { audio_manager, this, input_parameters, device_id_, NULL); if (!audio_controller_.get()) { - return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO)); + return Abort( + SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE)); } audio_log_->OnCreated(0, input_parameters, device_id_); @@ -654,7 +651,8 @@ SpeechRecognizerImpl::AbortSilently(const FSMEventArgs& event_args) { SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::AbortWithError(const FSMEventArgs& event_args) { if (event_args.event == EVENT_AUDIO_ERROR) { - return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO)); + return Abort( + SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE)); } else if (event_args.event == EVENT_ENGINE_ERROR) { return Abort(event_args.engine_error); } diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc index 2e8c57e87b2..0a43def06b3 100644 --- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc +++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc @@ -37,7 +37,7 @@ SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { } void SpeechRecognizerImplAndroid::StartRecognition( const std::string& device_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(xians): Open the correct device for speech on Android. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( &SpeechRecognitionEventListener::OnRecognitionStart, @@ -52,7 +52,7 @@ void SpeechRecognizerImplAndroid::StartRecognition( void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread( std::string language, bool continuous, bool interim_results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); JNIEnv* env = AttachCurrentThread(); j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(env, GetApplicationContext(), reinterpret_cast<intptr_t>(this))); @@ -68,7 +68,7 @@ void SpeechRecognizerImplAndroid::AbortRecognition() { &content::SpeechRecognizerImplAndroid::AbortRecognition, this)); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); JNIEnv* env = AttachCurrentThread(); if (!j_recognition_.is_null()) Java_SpeechRecognition_abortRecognition(env, j_recognition_.obj()); @@ -80,19 +80,19 @@ void SpeechRecognizerImplAndroid::StopAudioCapture() { &content::SpeechRecognizerImplAndroid::StopAudioCapture, this)); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); JNIEnv* env = AttachCurrentThread(); if (!j_recognition_.is_null()) Java_SpeechRecognition_stopRecognition(env, j_recognition_.obj()); } bool SpeechRecognizerImplAndroid::IsActive() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return state_ != STATE_IDLE; } bool SpeechRecognizerImplAndroid::IsCapturingAudio() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return state_ == STATE_CAPTURING_AUDIO; } @@ -103,7 +103,7 @@ void SpeechRecognizerImplAndroid::OnAudioStart(JNIEnv* env, jobject obj) { static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL))); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); state_ = STATE_CAPTURING_AUDIO; listener()->OnAudioStart(session_id()); } @@ -115,7 +115,7 @@ void SpeechRecognizerImplAndroid::OnSoundStart(JNIEnv* env, jobject obj) { static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL))); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); listener()->OnSoundStart(session_id()); } @@ -126,7 +126,7 @@ void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env, jobject obj) { static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL))); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); listener()->OnSoundEnd(session_id()); } @@ -137,7 +137,7 @@ void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) { static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL))); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (state_ == STATE_CAPTURING_AUDIO) state_ = STATE_AWAITING_FINAL_RESULT; listener()->OnAudioEnd(session_id()); @@ -145,7 +145,7 @@ void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) { void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj, jobjectArray strings, jfloatArray floats, jboolean provisional) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::vector<base::string16> options; AppendJavaStringArrayToStringVector(env, strings, &options); std::vector<float> scores(options.size(), 0.0); @@ -167,7 +167,7 @@ void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj, void SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread( SpeechRecognitionResults const &results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); listener()->OnRecognitionResults(session_id(), results); } @@ -179,7 +179,7 @@ void SpeechRecognizerImplAndroid::OnRecognitionError(JNIEnv* env, static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL), error)); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); SpeechRecognitionErrorCode code = static_cast<SpeechRecognitionErrorCode>(error); listener()->OnRecognitionError(session_id(), SpeechRecognitionError(code)); @@ -193,7 +193,7 @@ void SpeechRecognizerImplAndroid::OnRecognitionEnd(JNIEnv* env, static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL))); return; } - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); state_ = STATE_IDLE; listener()->OnRecognitionEnd(session_id()); } diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.h b/chromium/content/browser/speech/speech_recognizer_impl_android.h index cdf0b4db6d8..11895c441fe 100644 --- a/chromium/content/browser/speech/speech_recognizer_impl_android.h +++ b/chromium/content/browser/speech/speech_recognizer_impl_android.h @@ -24,11 +24,11 @@ class CONTENT_EXPORT SpeechRecognizerImplAndroid : public SpeechRecognizer { int session_id); // SpeechRecognizer methods. - virtual void StartRecognition(const std::string& device_id) override; - virtual void AbortRecognition() override; - virtual void StopAudioCapture() override; - virtual bool IsActive() const override; - virtual bool IsCapturingAudio() const override; + void StartRecognition(const std::string& device_id) override; + void AbortRecognition() override; + void StopAudioCapture() override; + bool IsActive() const override; + bool IsCapturingAudio() const override; // Called from Java methods via JNI. void OnAudioStart(JNIEnv* env, jobject obj); @@ -53,7 +53,7 @@ class CONTENT_EXPORT SpeechRecognizerImplAndroid : public SpeechRecognizer { std::string language, bool continuous, bool interim_results); void OnRecognitionResultsOnIOThread(SpeechRecognitionResults const &results); - virtual ~SpeechRecognizerImplAndroid(); + ~SpeechRecognizerImplAndroid() override; base::android::ScopedJavaGlobalRef<jobject> j_recognition_; State state_; diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc index 7168fb64973..3e8ef284287 100644 --- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc +++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc @@ -380,7 +380,7 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) { EXPECT_TRUE(recognition_started_); EXPECT_FALSE(audio_started_); EXPECT_FALSE(result_received_); - EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO, error_); + EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_); CheckFinalEventsConsistency(); } @@ -400,7 +400,7 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) { EXPECT_TRUE(recognition_started_); EXPECT_TRUE(audio_started_); EXPECT_FALSE(result_received_); - EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO, error_); + EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_); CheckFinalEventsConsistency(); } |