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