Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / speech / extension_api / tts_extension_apitest.cc
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 "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/extensions/component_loader.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/speech/extension_api/tts_extension_api.h"
13 #include "chrome/browser/speech/tts_controller.h"
14 #include "chrome/browser/speech/tts_platform.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "extensions/browser/extension_system.h"
17 #include "net/base/network_change_notifier.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 // Needed for CreateFunctor.
22 #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
23 #include "testing/gmock_mutant.h"
24
25 using ::testing::AnyNumber;
26 using ::testing::CreateFunctor;
27 using ::testing::DoAll;
28 using ::testing::InSequence;
29 using ::testing::InvokeWithoutArgs;
30 using ::testing::Return;
31 using ::testing::SaveArg;
32 using ::testing::StrictMock;
33 using ::testing::_;
34
35 namespace {
36 int g_saved_utterance_id;
37 }
38
39 namespace extensions {
40
41 class MockTtsPlatformImpl : public TtsPlatformImpl {
42  public:
43   MockTtsPlatformImpl()
44       : ptr_factory_(this) {}
45
46   virtual bool PlatformImplAvailable() {
47     return true;
48   }
49
50   MOCK_METHOD5(Speak,
51                bool(int utterance_id,
52                     const std::string& utterance,
53                     const std::string& lang,
54                     const VoiceData& voice,
55                     const UtteranceContinuousParameters& params));
56
57   MOCK_METHOD0(StopSpeaking, bool(void));
58
59   MOCK_METHOD0(Pause, void(void));
60
61   MOCK_METHOD0(Resume, void(void));
62
63   MOCK_METHOD0(IsSpeaking, bool(void));
64
65   MOCK_METHOD1(GetVoices, void(std::vector<VoiceData>*));
66
67   void SetErrorToEpicFail() {
68     set_error("epic fail");
69   }
70
71   void SendEndEventOnSavedUtteranceId() {
72     base::MessageLoop::current()->PostDelayedTask(
73         FROM_HERE, base::Bind(
74             &MockTtsPlatformImpl::SendEvent,
75             ptr_factory_.GetWeakPtr(),
76             false, g_saved_utterance_id, TTS_EVENT_END, 0, std::string()),
77         base::TimeDelta());
78   }
79
80   void SendEndEvent(int utterance_id,
81                     const std::string& utterance,
82                     const std::string& lang,
83                     const VoiceData& voice,
84                     const UtteranceContinuousParameters& params) {
85     base::MessageLoop::current()->PostDelayedTask(
86         FROM_HERE, base::Bind(
87             &MockTtsPlatformImpl::SendEvent,
88             ptr_factory_.GetWeakPtr(),
89             false, utterance_id, TTS_EVENT_END, utterance.size(),
90             std::string()),
91         base::TimeDelta());
92   }
93
94   void SendEndEventWhenQueueNotEmpty(
95       int utterance_id,
96       const std::string& utterance,
97       const std::string& lang,
98       const VoiceData& voice,
99       const UtteranceContinuousParameters& params) {
100     base::MessageLoop::current()->PostDelayedTask(
101         FROM_HERE, base::Bind(
102             &MockTtsPlatformImpl::SendEvent,
103             ptr_factory_.GetWeakPtr(),
104             true, utterance_id, TTS_EVENT_END, utterance.size(), std::string()),
105         base::TimeDelta());
106   }
107
108   void SendWordEvents(int utterance_id,
109                       const std::string& utterance,
110                       const std::string& lang,
111                       const VoiceData& voice,
112                       const UtteranceContinuousParameters& params) {
113     for (int i = 0; i < static_cast<int>(utterance.size()); i++) {
114       if (i == 0 || utterance[i - 1] == ' ') {
115         base::MessageLoop::current()->PostDelayedTask(
116             FROM_HERE, base::Bind(
117                 &MockTtsPlatformImpl::SendEvent,
118                 ptr_factory_.GetWeakPtr(),
119                 false, utterance_id, TTS_EVENT_WORD, i,
120                 std::string()),
121             base::TimeDelta());
122       }
123     }
124   }
125
126   void SendEvent(bool wait_for_non_empty_queue,
127                  int utterance_id,
128                  TtsEventType event_type,
129                  int char_index,
130                  const std::string& message) {
131     TtsController* controller = TtsController::GetInstance();
132     if (wait_for_non_empty_queue && controller->QueueSize() == 0) {
133       base::MessageLoop::current()->PostDelayedTask(
134           FROM_HERE, base::Bind(
135               &MockTtsPlatformImpl::SendEvent,
136               ptr_factory_.GetWeakPtr(),
137               true, utterance_id, event_type, char_index, message),
138           base::TimeDelta::FromMilliseconds(100));
139       return;
140     }
141
142     controller->OnTtsEvent(utterance_id, event_type, char_index, message);
143   }
144
145  private:
146   base::WeakPtrFactory<MockTtsPlatformImpl> ptr_factory_;
147 };
148
149 class FakeNetworkOnlineStateForTest : public net::NetworkChangeNotifier {
150  public:
151   explicit FakeNetworkOnlineStateForTest(bool online) : online_(online) {}
152   virtual ~FakeNetworkOnlineStateForTest() {}
153
154   virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
155     return online_ ?
156         net::NetworkChangeNotifier::CONNECTION_ETHERNET :
157         net::NetworkChangeNotifier::CONNECTION_NONE;
158   }
159
160  private:
161   bool online_;
162   DISALLOW_COPY_AND_ASSIGN(FakeNetworkOnlineStateForTest);
163 };
164
165 class TtsApiTest : public ExtensionApiTest {
166  public:
167   virtual void SetUpInProcessBrowserTestFixture() {
168     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
169     TtsController::GetInstance()->SetPlatformImpl(&mock_platform_impl_);
170     EXPECT_CALL(mock_platform_impl_, GetVoices(_))
171         .Times(AnyNumber());
172   }
173
174  protected:
175   StrictMock<MockTtsPlatformImpl> mock_platform_impl_;
176 };
177
178 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakOptionalArgs) {
179   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
180
181   InSequence s;
182   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
183       .WillOnce(Return(true));
184   EXPECT_CALL(mock_platform_impl_, Speak(_, "", _, _, _))
185       .WillOnce(Return(true));
186   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
187       .WillOnce(Return(true));
188   EXPECT_CALL(mock_platform_impl_, Speak(_, "Alpha", _, _, _))
189       .WillOnce(Return(true));
190   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
191       .WillOnce(Return(true));
192   EXPECT_CALL(mock_platform_impl_, Speak(_, "Bravo", _, _, _))
193       .WillOnce(Return(true));
194   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
195       .WillOnce(Return(true));
196   EXPECT_CALL(mock_platform_impl_, Speak(_, "Charlie", _, _, _))
197       .WillOnce(Return(true));
198   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
199       .WillOnce(Return(true));
200   EXPECT_CALL(mock_platform_impl_, Speak(_, "Echo", _, _, _))
201       .WillOnce(Return(true));
202   ASSERT_TRUE(RunExtensionTest("tts/optional_args")) << message_;
203 }
204
205 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakFinishesImmediately) {
206   InSequence s;
207   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
208   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
209       .WillOnce(Return(true));
210   EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _))
211       .WillOnce(DoAll(
212           Invoke(&mock_platform_impl_,
213                  &MockTtsPlatformImpl::SendEndEvent),
214           Return(true)));
215   ASSERT_TRUE(RunExtensionTest("tts/speak_once")) << message_;
216 }
217
218 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakInterrupt) {
219   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
220
221   // One utterance starts speaking, and then a second interrupts.
222   InSequence s;
223   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
224       .WillOnce(Return(true));
225   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _, _))
226       .WillOnce(Return(true));
227   // Expect the second utterance and allow it to finish.
228   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
229       .WillOnce(Return(true));
230   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 2", _, _, _))
231       .WillOnce(DoAll(
232           Invoke(&mock_platform_impl_,
233                  &MockTtsPlatformImpl::SendEndEvent),
234           Return(true)));
235   ASSERT_TRUE(RunExtensionTest("tts/interrupt")) << message_;
236 }
237
238 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakQueueInterrupt) {
239   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
240
241   // In this test, two utterances are queued, and then a third
242   // interrupts. Speak(, _) never gets called on the second utterance.
243   InSequence s;
244   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
245       .WillOnce(Return(true));
246   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _, _))
247       .WillOnce(Return(true));
248   // Don't expect the second utterance, because it's queued up and the
249   // first never finishes.
250   // Expect the third utterance and allow it to finish successfully.
251   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
252       .WillOnce(Return(true));
253   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 3", _, _, _))
254       .WillOnce(DoAll(
255           Invoke(&mock_platform_impl_,
256                  &MockTtsPlatformImpl::SendEndEvent),
257           Return(true)));
258   ASSERT_TRUE(RunExtensionTest("tts/queue_interrupt")) << message_;
259 }
260
261 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakEnqueue) {
262   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
263
264   InSequence s;
265   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
266       .WillOnce(Return(true));
267   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _, _))
268       .WillOnce(DoAll(
269           Invoke(&mock_platform_impl_,
270                  &MockTtsPlatformImpl::SendEndEventWhenQueueNotEmpty),
271           Return(true)));
272   EXPECT_CALL(mock_platform_impl_, Speak(_, "text 2", _, _, _))
273       .WillOnce(DoAll(
274           Invoke(&mock_platform_impl_,
275                  &MockTtsPlatformImpl::SendEndEvent),
276           Return(true)));
277   ASSERT_TRUE(RunExtensionTest("tts/enqueue")) << message_;
278 }
279
280 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakError) {
281   EXPECT_CALL(mock_platform_impl_, IsSpeaking())
282       .Times(AnyNumber());
283
284   InSequence s;
285   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
286       .WillOnce(Return(true));
287   EXPECT_CALL(mock_platform_impl_, Speak(_, "first try", _, _, _))
288       .WillOnce(DoAll(
289           InvokeWithoutArgs(
290               CreateFunctor(&mock_platform_impl_,
291                             &MockTtsPlatformImpl::SetErrorToEpicFail)),
292           Return(false)));
293   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
294       .WillOnce(Return(true));
295   EXPECT_CALL(mock_platform_impl_, Speak(_, "second try", _, _, _))
296       .WillOnce(DoAll(
297           Invoke(&mock_platform_impl_,
298                  &MockTtsPlatformImpl::SendEndEvent),
299           Return(true)));
300   ASSERT_TRUE(RunExtensionTest("tts/speak_error")) << message_;
301 }
302
303 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformWordCallbacks) {
304   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
305
306   InSequence s;
307   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
308       .WillOnce(Return(true));
309   EXPECT_CALL(mock_platform_impl_, Speak(_, "one two three", _, _, _))
310       .WillOnce(DoAll(
311           Invoke(&mock_platform_impl_,
312                  &MockTtsPlatformImpl::SendWordEvents),
313           Invoke(&mock_platform_impl_,
314                  &MockTtsPlatformImpl::SendEndEvent),
315           Return(true)));
316   ASSERT_TRUE(RunExtensionTest("tts/word_callbacks")) << message_;
317 }
318
319 IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformPauseResume) {
320   EXPECT_CALL(mock_platform_impl_, IsSpeaking())
321       .Times(AnyNumber());
322
323   InSequence s;
324   EXPECT_CALL(mock_platform_impl_, Speak(_, "test 1", _, _, _))
325       .WillOnce(DoAll(
326           Invoke(&mock_platform_impl_,
327                  &MockTtsPlatformImpl::SendEndEvent),
328           Return(true)));
329   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
330       .WillOnce(Return(true));
331   EXPECT_CALL(mock_platform_impl_, Speak(_, "test 2", _, _, _))
332       .WillOnce(DoAll(
333           SaveArg<0>(&g_saved_utterance_id),
334           Return(true)));
335   EXPECT_CALL(mock_platform_impl_, Pause());
336   EXPECT_CALL(mock_platform_impl_, Resume())
337       .WillOnce(
338           InvokeWithoutArgs(
339               &mock_platform_impl_,
340               &MockTtsPlatformImpl::SendEndEventOnSavedUtteranceId));
341   ASSERT_TRUE(RunExtensionTest("tts/pause_resume")) << message_;
342 }
343
344 //
345 // TTS Engine tests.
346 //
347
348 IN_PROC_BROWSER_TEST_F(TtsApiTest, RegisterEngine) {
349   EXPECT_CALL(mock_platform_impl_, IsSpeaking())
350       .Times(AnyNumber());
351   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
352       .WillRepeatedly(Return(true));
353
354   {
355     InSequence s;
356     EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech", _, _, _))
357       .WillOnce(DoAll(
358           Invoke(&mock_platform_impl_,
359                  &MockTtsPlatformImpl::SendEndEvent),
360           Return(true)));
361     EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech 2", _, _, _))
362       .WillOnce(DoAll(
363           Invoke(&mock_platform_impl_,
364                  &MockTtsPlatformImpl::SendEndEvent),
365           Return(true)));
366     EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech 3", _, _, _))
367       .WillOnce(DoAll(
368           Invoke(&mock_platform_impl_,
369                  &MockTtsPlatformImpl::SendEndEvent),
370           Return(true)));
371   }
372
373   ASSERT_TRUE(RunExtensionTest("tts_engine/register_engine")) << message_;
374 }
375
376 IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineError) {
377   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
378   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
379       .WillRepeatedly(Return(true));
380
381   ASSERT_TRUE(RunExtensionTest("tts_engine/engine_error")) << message_;
382 }
383
384 IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineWordCallbacks) {
385   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
386   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
387       .WillRepeatedly(Return(true));
388
389   ASSERT_TRUE(RunExtensionTest("tts_engine/engine_word_callbacks")) << message_;
390 }
391
392 IN_PROC_BROWSER_TEST_F(TtsApiTest, LangMatching) {
393   EXPECT_CALL(mock_platform_impl_, IsSpeaking());
394   EXPECT_CALL(mock_platform_impl_, StopSpeaking())
395       .WillRepeatedly(Return(true));
396
397   ASSERT_TRUE(RunExtensionTest("tts_engine/lang_matching")) << message_;
398 }
399
400 IN_PROC_BROWSER_TEST_F(TtsApiTest, NetworkSpeechEngine) {
401   // Simulate online network state.
402   net::NetworkChangeNotifier::DisableForTest disable_for_test;
403   FakeNetworkOnlineStateForTest fake_online_state(true);
404
405   ExtensionService* service = extensions::ExtensionSystem::Get(
406       profile())->extension_service();
407   service->component_loader()->AddNetworkSpeechSynthesisExtension();
408   ASSERT_TRUE(RunExtensionTest("tts_engine/network_speech_engine")) << message_;
409 }
410
411 IN_PROC_BROWSER_TEST_F(TtsApiTest, NoNetworkSpeechEngineWhenOffline) {
412   // Simulate offline network state.
413   net::NetworkChangeNotifier::DisableForTest disable_for_test;
414   FakeNetworkOnlineStateForTest fake_online_state(false);
415
416   ExtensionService* service = extensions::ExtensionSystem::Get(
417       profile())->extension_service();
418   service->component_loader()->AddNetworkSpeechSynthesisExtension();
419   // Test should fail when offline.
420   ASSERT_FALSE(RunExtensionTest("tts_engine/network_speech_engine"));
421 }
422
423 // http://crbug.com/122474
424 IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineApi) {
425   ASSERT_TRUE(RunExtensionTest("tts_engine/engine_api")) << message_;
426 }
427
428 }  // namespace extensions