1 // Copyright (c) 2012 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 <vector>
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/macros.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "chrome/browser/extensions/component_loader.h"
15 #include "chrome/browser/extensions/extension_apitest.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
18 #include "chrome/browser/speech/extension_api/tts_extension_api.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/tts_controller.h"
22 #include "content/public/browser/tts_platform.h"
23 #include "content/public/test/browser_test.h"
24 #include "content/public/test/test_utils.h"
25 #include "extensions/browser/event_router.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/browser/notification_types.h"
28 #include "net/base/network_change_notifier.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 using ::testing::AnyNumber;
33 using ::testing::DoAll;
34 using ::testing::Invoke;
35 using ::testing::InSequence;
36 using ::testing::InvokeWithoutArgs;
37 using ::testing::Return;
38 using ::testing::SaveArg;
39 using ::testing::SetArgPointee;
40 using ::testing::StrictMock;
41 using ::testing::_;
42
43 namespace {
44 int g_saved_utterance_id;
45 }
46
47 namespace extensions {
48
49 class MockTtsPlatformImpl : public content::TtsPlatform {
50 public:
MockTtsPlatformImpl()51 MockTtsPlatformImpl() : should_fake_get_voices_(false) {}
52
PlatformImplSupported()53 bool PlatformImplSupported() override { return true; }
PlatformImplInitialized()54 bool PlatformImplInitialized() override { return true; }
55
WillSpeakUtteranceWithVoice(content::TtsUtterance * utterance,const content::VoiceData & voice_data)56 void WillSpeakUtteranceWithVoice(
57 content::TtsUtterance* utterance,
58 const content::VoiceData& voice_data) override {}
59
LoadBuiltInTtsEngine(content::BrowserContext * browser_context)60 bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override {
61 return false;
62 }
63
ClearError()64 void ClearError() override { error_ = ""; }
65
SetError(const std::string & error)66 void SetError(const std::string& error) override { error_ = error; }
67
GetError()68 std::string GetError() override { return error_; }
69
70 // Work-around for functions that take move-only types as arguments.
71 // https://github.com/google/googlemock/blob/master/googlemock/docs/CookBook.md
72 // Delegate the Speak() method to DoSpeak(), which doesn't take any move
73 // parameters.
Speak(int utterance_id,const std::string & utterance,const std::string & lang,const content::VoiceData & voice,const content::UtteranceContinuousParameters & params,base::OnceCallback<void (bool)> on_speak_finished)74 void Speak(int utterance_id,
75 const std::string& utterance,
76 const std::string& lang,
77 const content::VoiceData& voice,
78 const content::UtteranceContinuousParameters& params,
79 base::OnceCallback<void(bool)> on_speak_finished) override {
80 DoSpeak(utterance_id, utterance, lang, voice, params);
81 // Logic for PlatformSpeakError test. Needs to fail the first time, but
82 // succeed the second time.
83 if (speak_error_test_) {
84 speak_error_count_ > 0 ? std::move(on_speak_finished).Run(true)
85 : std::move(on_speak_finished).Run(false);
86 ++speak_error_count_;
87 } else {
88 std::move(on_speak_finished).Run(true);
89 }
90 }
91 MOCK_METHOD5(DoSpeak,
92 void(int utterance_id,
93 const std::string& utterance,
94 const std::string& lang,
95 const content::VoiceData& voice,
96 const content::UtteranceContinuousParameters& params));
97
98 MOCK_METHOD0(StopSpeaking, bool(void));
99
100 MOCK_METHOD0(Pause, void(void));
101
102 MOCK_METHOD0(Resume, void(void));
103
104 MOCK_METHOD0(IsSpeaking, bool(void));
105
106 // Fake this method to add a native voice.
GetVoices(std::vector<content::VoiceData> * voices)107 void GetVoices(std::vector<content::VoiceData>* voices) override {
108 if (!should_fake_get_voices_)
109 return;
110
111 content::VoiceData voice;
112 voice.name = "TestNativeVoice";
113 voice.native = true;
114 voice.lang = "en-GB";
115 voice.events.insert(content::TTS_EVENT_START);
116 voice.events.insert(content::TTS_EVENT_END);
117 voices->push_back(voice);
118 }
119
Shutdown()120 void Shutdown() override {}
121
set_should_fake_get_voices(bool val)122 void set_should_fake_get_voices(bool val) { should_fake_get_voices_ = val; }
123
SetErrorToEpicFail()124 void SetErrorToEpicFail() { SetError("epic fail"); }
125
SendEndEventOnSavedUtteranceId()126 void SendEndEventOnSavedUtteranceId() {
127 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
128 FROM_HERE,
129 base::BindOnce(&MockTtsPlatformImpl::SendEvent,
130 ptr_factory_.GetWeakPtr(), false, g_saved_utterance_id,
131 content::TTS_EVENT_END, 0, 0, std::string()),
132 base::TimeDelta());
133 }
134
SendEndEvent(int utterance_id,const std::string & utterance,const std::string & lang,const content::VoiceData & voice,const content::UtteranceContinuousParameters & params)135 void SendEndEvent(int utterance_id,
136 const std::string& utterance,
137 const std::string& lang,
138 const content::VoiceData& voice,
139 const content::UtteranceContinuousParameters& params) {
140 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
141 FROM_HERE,
142 base::BindOnce(&MockTtsPlatformImpl::SendEvent,
143 ptr_factory_.GetWeakPtr(), false, utterance_id,
144 content::TTS_EVENT_END, utterance.size(), 0,
145 std::string()),
146 base::TimeDelta());
147 }
148
SendEndEventWhenQueueNotEmpty(int utterance_id,const std::string & utterance,const std::string & lang,const content::VoiceData & voice,const content::UtteranceContinuousParameters & params)149 void SendEndEventWhenQueueNotEmpty(
150 int utterance_id,
151 const std::string& utterance,
152 const std::string& lang,
153 const content::VoiceData& voice,
154 const content::UtteranceContinuousParameters& params) {
155 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
156 FROM_HERE,
157 base::BindOnce(&MockTtsPlatformImpl::SendEvent,
158 ptr_factory_.GetWeakPtr(), true, utterance_id,
159 content::TTS_EVENT_END, utterance.size(), 0,
160 std::string()),
161 base::TimeDelta());
162 }
163
SendWordEvents(int utterance_id,const std::string & utterance,const std::string & lang,const content::VoiceData & voice,const content::UtteranceContinuousParameters & params)164 void SendWordEvents(int utterance_id,
165 const std::string& utterance,
166 const std::string& lang,
167 const content::VoiceData& voice,
168 const content::UtteranceContinuousParameters& params) {
169 for (int i = 0; i < static_cast<int>(utterance.size()); i++) {
170 if (i == 0 || utterance[i - 1] == ' ') {
171 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
172 FROM_HERE,
173 base::BindOnce(&MockTtsPlatformImpl::SendEvent,
174 ptr_factory_.GetWeakPtr(), false, utterance_id,
175 content::TTS_EVENT_WORD, i, 1, std::string()),
176 base::TimeDelta());
177 }
178 }
179 }
180
SendEvent(bool wait_for_non_empty_queue,int utterance_id,content::TtsEventType event_type,int char_index,int length,const std::string & message)181 void SendEvent(bool wait_for_non_empty_queue,
182 int utterance_id,
183 content::TtsEventType event_type,
184 int char_index,
185 int length,
186 const std::string& message) {
187 content::TtsController* tts_controller =
188 content::TtsController::GetInstance();
189 if (wait_for_non_empty_queue && tts_controller->QueueSize() == 0) {
190 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE,
192 base::BindOnce(&MockTtsPlatformImpl::SendEvent,
193 ptr_factory_.GetWeakPtr(), true, utterance_id,
194 event_type, char_index, length, message),
195 base::TimeDelta::FromMilliseconds(100));
196 return;
197 }
198
199 tts_controller->OnTtsEvent(utterance_id, event_type, char_index, length,
200 message);
201 }
202
SetSpeakErrorTest(bool value)203 void SetSpeakErrorTest(bool value) { speak_error_test_ = value; }
204
205 private:
206 bool speak_error_test_ = false;
207 int speak_error_count_ = 0;
208 bool should_fake_get_voices_;
209 std::string error_;
210 base::WeakPtrFactory<MockTtsPlatformImpl> ptr_factory_{this};
211 };
212
213 class FakeNetworkOnlineStateForTest : public net::NetworkChangeNotifier {
214 public:
FakeNetworkOnlineStateForTest(bool online)215 explicit FakeNetworkOnlineStateForTest(bool online) : online_(online) {}
~FakeNetworkOnlineStateForTest()216 ~FakeNetworkOnlineStateForTest() override {}
217
GetCurrentConnectionType() const218 ConnectionType GetCurrentConnectionType() const override {
219 return online_ ?
220 net::NetworkChangeNotifier::CONNECTION_ETHERNET :
221 net::NetworkChangeNotifier::CONNECTION_NONE;
222 }
223
224 private:
225 bool online_;
226 DISALLOW_COPY_AND_ASSIGN(FakeNetworkOnlineStateForTest);
227 };
228
229 class EventRouterAddListenerWaiter : public EventRouter::Observer {
230 public:
EventRouterAddListenerWaiter(Profile * profile,const std::string & event_name)231 EventRouterAddListenerWaiter(Profile* profile, const std::string& event_name)
232 : event_router_(EventRouter::EventRouter::Get(profile)) {
233 DCHECK(profile);
234 event_router_->RegisterObserver(this, event_name);
235 }
236
~EventRouterAddListenerWaiter()237 ~EventRouterAddListenerWaiter() override {
238 event_router_->UnregisterObserver(this);
239 }
240
Wait()241 void Wait() { loop_runner_.Run(); }
242
243 // EventRouter::Observer overrides.
OnListenerAdded(const EventListenerInfo & details)244 void OnListenerAdded(const EventListenerInfo& details) override {
245 loop_runner_.Quit();
246 }
247
248 private:
249 EventRouter* const event_router_;
250 base::RunLoop loop_runner_;
251
252 DISALLOW_COPY_AND_ASSIGN(EventRouterAddListenerWaiter);
253 };
254
255 class TtsApiTest : public ExtensionApiTest {
256 public:
SetUpInProcessBrowserTestFixture()257 void SetUpInProcessBrowserTestFixture() override {
258 ExtensionApiTest::SetUpInProcessBrowserTestFixture();
259 content::TtsController* tts_controller =
260 content::TtsController::GetInstance();
261 tts_controller->SetTtsPlatform(&mock_platform_impl_);
262 tts_controller->SetTtsEngineDelegate(TtsExtensionEngine::GetInstance());
263 }
264
AddNetworkSpeechSynthesisExtension()265 void AddNetworkSpeechSynthesisExtension() {
266 content::WindowedNotificationObserver observer(
267 NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
268 content::NotificationService::AllSources());
269 ExtensionService* service =
270 extensions::ExtensionSystem::Get(profile())->extension_service();
271 service->component_loader()->AddNetworkSpeechSynthesisExtension();
272 observer.Wait();
273 ASSERT_EQ(Manifest::COMPONENT,
274 content::Source<const Extension>(observer.source())->location());
275 }
276
277 protected:
HasVoiceWithName(const std::string & name)278 bool HasVoiceWithName(const std::string& name) {
279 std::vector<content::VoiceData> voices;
280 content::TtsController::GetInstance()->GetVoices(profile(), &voices);
281 for (auto& voice : voices) {
282 if (voice.name == name)
283 return true;
284 }
285
286 return false;
287 }
288
289 StrictMock<MockTtsPlatformImpl> mock_platform_impl_;
290 };
291
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakOptionalArgs)292 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakOptionalArgs) {
293 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
294
295 InSequence s;
296 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
297 .WillOnce(Return(true));
298 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "", _, _, _)).WillOnce(Return());
299 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
300 .WillOnce(Return(true));
301 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "Alpha", _, _, _))
302 .WillOnce(Return());
303 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
304 .WillOnce(Return(true));
305 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "Bravo", _, _, _))
306 .WillOnce(Return());
307 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
308 .WillOnce(Return(true));
309 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "Charlie", _, _, _))
310 .WillOnce(Return());
311 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
312 .WillOnce(Return(true));
313 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "Echo", _, _, _))
314 .WillOnce(Return());
315 ASSERT_TRUE(RunExtensionTest("tts/optional_args")) << message_;
316 }
317
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakFinishesImmediately)318 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakFinishesImmediately) {
319 InSequence s;
320 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
321 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
322 .WillOnce(Return(true));
323 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, _, _, _, _))
324 .WillOnce(DoAll(
325 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
326 Return()));
327 ASSERT_TRUE(RunExtensionTest("tts/speak_once")) << message_;
328 }
329
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakInterrupt)330 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakInterrupt) {
331 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
332
333 // One utterance starts speaking, and then a second interrupts.
334 InSequence s;
335 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
336 .WillOnce(Return(true));
337 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 1", _, _, _))
338 .WillOnce(Return());
339 // Expect the second utterance and allow it to finish.
340 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
341 .WillOnce(Return(true));
342 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 2", _, _, _))
343 .WillOnce(DoAll(
344 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
345 Return()));
346 ASSERT_TRUE(RunExtensionTest("tts/interrupt")) << message_;
347 }
348
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakQueueInterrupt)349 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakQueueInterrupt) {
350 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
351
352 // In this test, two utterances are queued, and then a third
353 // interrupts. Speak(, _) never gets called on the second utterance.
354 InSequence s;
355 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
356 .WillOnce(Return(true));
357 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 1", _, _, _))
358 .WillOnce(Return());
359 // Don't expect the second utterance, because it's queued up and the
360 // first never finishes.
361 // Expect the third utterance and allow it to finish successfully.
362 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
363 .WillOnce(Return(true));
364 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 3", _, _, _))
365 .WillOnce(DoAll(
366 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
367 Return()));
368 ASSERT_TRUE(RunExtensionTest("tts/queue_interrupt")) << message_;
369 }
370
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakEnqueue)371 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakEnqueue) {
372 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
373
374 InSequence s;
375 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
376 .WillOnce(Return(true));
377 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 1", _, _, _))
378 .WillOnce(
379 DoAll(Invoke(&mock_platform_impl_,
380 &MockTtsPlatformImpl::SendEndEventWhenQueueNotEmpty),
381 Return()));
382 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "text 2", _, _, _))
383 .WillOnce(DoAll(
384 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
385 Return()));
386 ASSERT_TRUE(RunExtensionTest("tts/enqueue")) << message_;
387 }
388
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformSpeakError)389 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakError) {
390 EXPECT_CALL(mock_platform_impl_, IsSpeaking())
391 .Times(AnyNumber());
392
393 mock_platform_impl_.SetSpeakErrorTest(true);
394
395 InSequence s;
396 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
397 .WillOnce(Return(true));
398 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "first try", _, _, _))
399 .WillOnce(
400 DoAll(InvokeWithoutArgs(&mock_platform_impl_,
401 &MockTtsPlatformImpl::SetErrorToEpicFail),
402 Return()));
403 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
404 .WillOnce(Return(true));
405
406 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "second try", _, _, _))
407 .WillOnce(DoAll(
408 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
409 Return()));
410 ASSERT_TRUE(RunExtensionTest("tts/speak_error")) << message_;
411 }
412
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformWordCallbacks)413 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformWordCallbacks) {
414 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
415
416 InSequence s;
417 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
418 .WillOnce(Return(true));
419 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "one two three", _, _, _))
420 .WillOnce(DoAll(
421 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendWordEvents),
422 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
423 Return()));
424 ASSERT_TRUE(RunExtensionTest("tts/word_callbacks")) << message_;
425 }
426
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformPauseResume)427 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformPauseResume) {
428 EXPECT_CALL(mock_platform_impl_, IsSpeaking())
429 .Times(AnyNumber());
430
431 InSequence s;
432 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "test 1", _, _, _))
433 .WillOnce(DoAll(
434 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
435 Return()));
436 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
437 .WillOnce(Return(true));
438 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "test 2", _, _, _))
439 .WillOnce(DoAll(SaveArg<0>(&g_saved_utterance_id), Return()));
440 EXPECT_CALL(mock_platform_impl_, Pause());
441 EXPECT_CALL(mock_platform_impl_, Resume())
442 .WillOnce(
443 InvokeWithoutArgs(
444 &mock_platform_impl_,
445 &MockTtsPlatformImpl::SendEndEventOnSavedUtteranceId));
446 ASSERT_TRUE(RunExtensionTest("tts/pause_resume")) << message_;
447 }
448
IN_PROC_BROWSER_TEST_F(TtsApiTest,PlatformPauseSpeakNoEnqueue)449 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformPauseSpeakNoEnqueue) {
450 // While paused, one utterance is enqueued, and then a second utterance that
451 // cannot be enqueued cancels both.
452 InSequence s;
453 EXPECT_CALL(mock_platform_impl_, StopSpeaking()).WillOnce(Return(true));
454 ASSERT_TRUE(RunExtensionTest("tts/pause_speak_no_enqueue")) << message_;
455 }
456
457 //
458 // TTS Engine tests.
459 //
460
IN_PROC_BROWSER_TEST_F(TtsApiTest,RegisterEngine)461 IN_PROC_BROWSER_TEST_F(TtsApiTest, RegisterEngine) {
462 mock_platform_impl_.set_should_fake_get_voices(true);
463
464 EXPECT_CALL(mock_platform_impl_, IsSpeaking())
465 .Times(AnyNumber());
466 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
467 .WillRepeatedly(Return(true));
468
469 {
470 InSequence s;
471 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "native speech", _, _, _))
472 .WillOnce(DoAll(
473 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
474 Return()));
475 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "native speech 2", _, _, _))
476 .WillOnce(DoAll(
477 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
478 Return()));
479 EXPECT_CALL(mock_platform_impl_, DoSpeak(_, "native speech 3", _, _, _))
480 .WillOnce(DoAll(
481 Invoke(&mock_platform_impl_, &MockTtsPlatformImpl::SendEndEvent),
482 Return()));
483 }
484
485 // TODO(katie): Expect the deprecated gender warning rather than ignoring
486 // warnings.
487 ASSERT_TRUE(RunExtensionTestWithFlags("tts_engine/register_engine",
488 kFlagIgnoreManifestWarnings, kFlagNone))
489 << message_;
490 }
491
492 // https://crbug.com/709115 tracks test flakiness.
493 #if defined(OS_POSIX)
494 #define MAYBE_EngineError DISABLED_EngineError
495 #else
496 #define MAYBE_EngineError EngineError
497 #endif
IN_PROC_BROWSER_TEST_F(TtsApiTest,MAYBE_EngineError)498 IN_PROC_BROWSER_TEST_F(TtsApiTest, MAYBE_EngineError) {
499 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
500 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
501 .WillRepeatedly(Return(true));
502
503 ASSERT_TRUE(RunExtensionTest("tts_engine/engine_error")) << message_;
504 }
505
IN_PROC_BROWSER_TEST_F(TtsApiTest,EngineWordCallbacks)506 IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineWordCallbacks) {
507 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
508 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
509 .WillRepeatedly(Return(true));
510
511 ASSERT_TRUE(RunExtensionTest("tts_engine/engine_word_callbacks")) << message_;
512 }
513
IN_PROC_BROWSER_TEST_F(TtsApiTest,LangMatching)514 IN_PROC_BROWSER_TEST_F(TtsApiTest, LangMatching) {
515 EXPECT_CALL(mock_platform_impl_, IsSpeaking());
516 EXPECT_CALL(mock_platform_impl_, StopSpeaking())
517 .WillRepeatedly(Return(true));
518
519 ASSERT_TRUE(RunExtensionTest("tts_engine/lang_matching")) << message_;
520 }
521
IN_PROC_BROWSER_TEST_F(TtsApiTest,NetworkSpeechEngine)522 IN_PROC_BROWSER_TEST_F(TtsApiTest, NetworkSpeechEngine) {
523 // Simulate online network state.
524 net::NetworkChangeNotifier::DisableForTest disable_for_test;
525 FakeNetworkOnlineStateForTest fake_online_state(true);
526
527 ASSERT_NO_FATAL_FAILURE(AddNetworkSpeechSynthesisExtension());
528 ASSERT_TRUE(RunExtensionTest("tts_engine/network_speech_engine")) << message_;
529 }
530
IN_PROC_BROWSER_TEST_F(TtsApiTest,NoNetworkSpeechEngineWhenOffline)531 IN_PROC_BROWSER_TEST_F(TtsApiTest, NoNetworkSpeechEngineWhenOffline) {
532 // Simulate offline network state.
533 net::NetworkChangeNotifier::DisableForTest disable_for_test;
534 FakeNetworkOnlineStateForTest fake_online_state(false);
535
536 ASSERT_NO_FATAL_FAILURE(AddNetworkSpeechSynthesisExtension());
537 // Test should fail when offline.
538 ASSERT_FALSE(RunExtensionTest("tts_engine/network_speech_engine"));
539 }
540
541 // http://crbug.com/122474
IN_PROC_BROWSER_TEST_F(TtsApiTest,EngineApi)542 IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineApi) {
543 ASSERT_TRUE(RunExtensionTest("tts_engine/engine_api")) << message_;
544 }
545
IN_PROC_BROWSER_TEST_F(TtsApiTest,UpdateVoicesApi)546 IN_PROC_BROWSER_TEST_F(TtsApiTest, UpdateVoicesApi) {
547 ASSERT_TRUE(RunExtensionTest("tts_engine/update_voices_api")) << message_;
548 }
549
IN_PROC_BROWSER_TEST_F(TtsApiTest,PRE_VoicesAreCached)550 IN_PROC_BROWSER_TEST_F(TtsApiTest, PRE_VoicesAreCached) {
551 EXPECT_FALSE(HasVoiceWithName("Dynamic Voice 1"));
552 EXPECT_FALSE(HasVoiceWithName("Dynamic Voice 2"));
553 ASSERT_TRUE(RunExtensionTest("tts_engine/call_update_voices")) << message_;
554 EXPECT_TRUE(HasVoiceWithName("Dynamic Voice 1"));
555 EXPECT_TRUE(HasVoiceWithName("Dynamic Voice 2"));
556 }
557
IN_PROC_BROWSER_TEST_F(TtsApiTest,VoicesAreCached)558 IN_PROC_BROWSER_TEST_F(TtsApiTest, VoicesAreCached) {
559 // Make sure the dynamically loaded voices are available even though
560 // the extension didn't "run". Note that the voices might not be available
561 // immediately when the test runs, but the test should pass shortly after
562 // the extension's event listeners are registered.
563 while (!HasVoiceWithName("Dynamic Voice 1") ||
564 !HasVoiceWithName("Dynamic Voice 2")) {
565 // Wait for the extension's event listener to be registered before
566 // checking what voices are registered.
567 EventRouterAddListenerWaiter waiter(profile(), tts_engine_events::kOnStop);
568 waiter.Wait();
569 }
570 }
571
572 } // namespace extensions
573