[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / speech / speech_recognition_browsertest.cc
blobee5e28e83ffa6b41e0eca1ca2ef5af1db84ca687
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 <list>
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "content/browser/speech/google_streaming_remote_engine.h"
15 #include "content/browser/speech/speech_recognition_manager_impl.h"
16 #include "content/browser/speech/speech_recognizer_impl.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_types.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "content/public/test/content_browser_test.h"
22 #include "content/public/test/content_browser_test_utils.h"
23 #include "content/public/test/test_utils.h"
24 #include "content/shell/browser/shell.h"
25 #include "content/test/mock_google_streaming_server.h"
26 #include "media/audio/mock_audio_manager.h"
27 #include "media/audio/test_audio_input_controller_factory.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 using base::RunLoop;
32 namespace content {
34 class SpeechRecognitionBrowserTest :
35 public ContentBrowserTest,
36 public MockGoogleStreamingServer::Delegate,
37 public media::TestAudioInputControllerDelegate {
38 public:
39 enum StreamingServerState {
40 kIdle,
41 kTestAudioControllerOpened,
42 kClientConnected,
43 kClientAudioUpload,
44 kClientAudioUploadComplete,
45 kTestAudioControllerClosed,
46 kClientDisconnected
49 // MockGoogleStreamingServerDelegate methods.
50 void OnClientConnected() override {
51 ASSERT_EQ(kTestAudioControllerOpened, streaming_server_state_);
52 streaming_server_state_ = kClientConnected;
55 void OnClientAudioUpload() override {
56 if (streaming_server_state_ == kClientConnected)
57 streaming_server_state_ = kClientAudioUpload;
60 void OnClientAudioUploadComplete() override {
61 ASSERT_EQ(kTestAudioControllerClosed, streaming_server_state_);
62 streaming_server_state_ = kClientAudioUploadComplete;
65 void OnClientDisconnected() override {
66 ASSERT_EQ(kClientAudioUploadComplete, streaming_server_state_);
67 streaming_server_state_ = kClientDisconnected;
70 // media::TestAudioInputControllerDelegate methods.
71 void TestAudioControllerOpened(
72 media::TestAudioInputController* controller) override {
73 ASSERT_EQ(kIdle, streaming_server_state_);
74 streaming_server_state_ = kTestAudioControllerOpened;
75 const int capture_packet_interval_ms =
76 (1000 * controller->audio_parameters().frames_per_buffer()) /
77 controller->audio_parameters().sample_rate();
78 ASSERT_EQ(GoogleStreamingRemoteEngine::kAudioPacketIntervalMs,
79 capture_packet_interval_ms);
80 FeedAudioController(500 /* ms */, /*noise=*/ false);
81 FeedAudioController(1000 /* ms */, /*noise=*/ true);
82 FeedAudioController(1000 /* ms */, /*noise=*/ false);
85 void TestAudioControllerClosed(
86 media::TestAudioInputController* controller) override {
87 ASSERT_EQ(kClientAudioUpload, streaming_server_state_);
88 streaming_server_state_ = kTestAudioControllerClosed;
89 mock_streaming_server_->MockGoogleStreamingServer::SimulateResult(
90 GetGoodSpeechResult());
93 // Helper methods used by test fixtures.
94 GURL GetTestUrlFromFragment(const std::string fragment) {
95 return GURL(GetTestUrl("speech", "web_speech_recognition.html").spec() +
96 "#" + fragment);
99 std::string GetPageFragment() {
100 return shell()->web_contents()->GetLastCommittedURL().ref();
103 const StreamingServerState &streaming_server_state() {
104 return streaming_server_state_;
107 protected:
108 // ContentBrowserTest methods.
109 void SetUpInProcessBrowserTestFixture() override {
110 test_audio_input_controller_factory_.set_delegate(this);
111 media::AudioInputController::set_factory_for_testing(
112 &test_audio_input_controller_factory_);
113 mock_streaming_server_.reset(new MockGoogleStreamingServer(this));
114 streaming_server_state_ = kIdle;
117 void SetUpOnMainThread() override {
118 ASSERT_TRUE(SpeechRecognitionManagerImpl::GetInstance());
119 SpeechRecognizerImpl::SetAudioManagerForTesting(
120 new media::MockAudioManager(BrowserThread::GetMessageLoopProxyForThread(
121 BrowserThread::IO)));
124 void TearDownOnMainThread() override {
125 SpeechRecognizerImpl::SetAudioManagerForTesting(NULL);
128 void TearDownInProcessBrowserTestFixture() override {
129 test_audio_input_controller_factory_.set_delegate(NULL);
130 mock_streaming_server_.reset();
133 private:
134 static void FeedSingleBufferToAudioController(
135 scoped_refptr<media::TestAudioInputController> controller,
136 size_t buffer_size,
137 bool fill_with_noise) {
138 DCHECK(controller.get());
139 const media::AudioParameters& audio_params = controller->audio_parameters();
140 scoped_ptr<uint8[]> audio_buffer(new uint8[buffer_size]);
141 if (fill_with_noise) {
142 for (size_t i = 0; i < buffer_size; ++i)
143 audio_buffer[i] = static_cast<uint8>(127 * sin(i * 3.14F /
144 (16 * buffer_size)));
145 } else {
146 memset(audio_buffer.get(), 0, buffer_size);
149 scoped_ptr<media::AudioBus> audio_bus =
150 media::AudioBus::Create(audio_params);
151 audio_bus->FromInterleaved(&audio_buffer.get()[0],
152 audio_bus->frames(),
153 audio_params.bits_per_sample() / 8);
154 controller->event_handler()->OnData(controller.get(), audio_bus.get());
157 void FeedAudioController(int duration_ms, bool feed_with_noise) {
158 media::TestAudioInputController* controller =
159 test_audio_input_controller_factory_.controller();
160 ASSERT_TRUE(controller);
161 const media::AudioParameters& audio_params = controller->audio_parameters();
162 const size_t buffer_size = audio_params.GetBytesPerBuffer();
163 const int ms_per_buffer = audio_params.frames_per_buffer() * 1000 /
164 audio_params.sample_rate();
165 // We can only simulate durations that are integer multiples of the
166 // buffer size. In this regard see
167 // SpeechRecognitionEngine::GetDesiredAudioChunkDurationMs().
168 ASSERT_EQ(0, duration_ms % ms_per_buffer);
170 const int n_buffers = duration_ms / ms_per_buffer;
171 for (int i = 0; i < n_buffers; ++i) {
172 base::ThreadTaskRunnerHandle::Get()->PostTask(
173 FROM_HERE,
174 base::Bind(&FeedSingleBufferToAudioController,
175 scoped_refptr<media::TestAudioInputController>(controller),
176 buffer_size, feed_with_noise));
180 SpeechRecognitionResult GetGoodSpeechResult() {
181 SpeechRecognitionResult result;
182 result.hypotheses.push_back(SpeechRecognitionHypothesis(
183 base::UTF8ToUTF16("Pictures of the moon"), 1.0F));
184 return result;
187 StreamingServerState streaming_server_state_;
188 scoped_ptr<MockGoogleStreamingServer> mock_streaming_server_;
189 media::TestAudioInputControllerFactory test_audio_input_controller_factory_;
192 // Simply loads the test page and checks if it was able to create a Speech
193 // Recognition object in JavaScript, to make sure the Web Speech API is enabled.
194 // Flaky on all platforms. http://crbug.com/396414.
195 IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, DISABLED_Precheck) {
196 NavigateToURLBlockUntilNavigationsComplete(
197 shell(), GetTestUrlFromFragment("precheck"), 2);
199 EXPECT_EQ(kIdle, streaming_server_state());
200 EXPECT_EQ("success", GetPageFragment());
203 IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, OneShotRecognition) {
204 NavigateToURLBlockUntilNavigationsComplete(
205 shell(), GetTestUrlFromFragment("oneshot"), 2);
207 EXPECT_EQ(kClientDisconnected, streaming_server_state());
208 EXPECT_EQ("goodresult1", GetPageFragment());
211 } // namespace content