1 // Copyright (c) 2018 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 // Unit tests for the TTS Controller.
6 
7 #include "chrome/browser/speech/tts_controller_delegate_impl.h"
8 
9 #include "base/memory/ptr_util.h"
10 #include "base/values.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/prefs/pref_registry_simple.h"
14 #include "components/prefs/testing_pref_service.h"
15 #include "content/public/browser/tts_controller.h"
16 #include "content/public/browser/tts_platform.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/blink/public/mojom/speech/speech_synthesis.mojom.h"
19 
20 // Subclass of TtsController with a public ctor and dtor.
21 class MockTtsControllerDelegate : public TtsControllerDelegateImpl {
22  public:
MockTtsControllerDelegate()23   MockTtsControllerDelegate() {}
~MockTtsControllerDelegate()24   ~MockTtsControllerDelegate() override {}
25 
26   PrefService* pref_service_ = nullptr;
27 
28  private:
GetPrefService(content::TtsUtterance * utterance)29   const PrefService* GetPrefService(content::TtsUtterance* utterance) override {
30     return pref_service_;
31   }
32 };
33 
TEST(TtsControllerDelegateImplTest,TestTtsControllerUtteranceDefaults)34 TEST(TtsControllerDelegateImplTest, TestTtsControllerUtteranceDefaults) {
35   std::unique_ptr<MockTtsControllerDelegate> tts_controller_delegate =
36       std::make_unique<MockTtsControllerDelegate>();
37 
38   double rate = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
39   double pitch = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
40   double volume = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
41 
42   std::unique_ptr<content::TtsUtterance> utterance1 =
43       content::TtsUtterance::Create(nullptr);
44   tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
45       utterance1.get(), &rate, &pitch, &volume);
46   // Updated to global defaults.
47   EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultRate, rate);
48   EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultPitch, pitch);
49   EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultVolume, volume);
50 
51   // Now we will set prefs and expect those to be used as defaults.
52   rate = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
53   pitch = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
54   volume = blink::mojom::kSpeechSynthesisDoublePrefNotSet;
55   TestingPrefServiceSimple pref_service_;
56   pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechRate, 1.5);
57   pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechPitch, 2.0);
58   pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechVolume, 0.5);
59   tts_controller_delegate->pref_service_ = &pref_service_;
60 
61   std::unique_ptr<content::TtsUtterance> utterance2 =
62       content::TtsUtterance::Create(nullptr);
63   tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
64       utterance2.get(), &rate, &pitch, &volume);
65   // Updated to pref values.
66   EXPECT_EQ(1.5f, rate);
67   EXPECT_EQ(2.0f, pitch);
68   EXPECT_EQ(0.5f, volume);
69 
70   // If we explicitly set rate, pitch and volume, they should not be changed.
71   rate = 1.1f;
72   pitch = 1.2f;
73   volume = 1.3f;
74 
75   std::unique_ptr<content::TtsUtterance> utterance3 =
76       content::TtsUtterance::Create(nullptr);
77   tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
78       utterance3.get(), &rate, &pitch, &volume);
79   // Updated to pref values.
80   EXPECT_EQ(1.1f, rate);
81   EXPECT_EQ(1.2f, pitch);
82   EXPECT_EQ(1.3f, volume);
83 }
84 
TEST(TtsControllerDelegateImplTest,GetPreferredVoiceIdsForUtterance)85 TEST(TtsControllerDelegateImplTest, GetPreferredVoiceIdsForUtterance) {
86   MockTtsControllerDelegate delegate;
87   std::unique_ptr<content::TtsUtterance> utterance =
88       content::TtsUtterance::Create(nullptr);
89   auto ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get());
90   EXPECT_EQ(nullptr, ids.get());
91 
92   TestingPrefServiceSimple pref_service;
93   // Uses default pref voices.
94   base::Value lang_to_voices(base::Value::Type::DICTIONARY);
95   lang_to_voices.SetKey(
96       "es", base::Value("{\"name\":\"Voice7\",\"extension\":\"id7\"}"));
97   lang_to_voices.SetKey(
98       "he", base::Value("{\"name\":\"Voice8\",\"extension\":\"id8\"}"));
99   lang_to_voices.SetKey(
100       "noLanguageCode",
101       base::Value("{\"name\":\"Android\",\"extension\":\"x\"}"));
102   pref_service.registry()->RegisterDictionaryPref(
103       prefs::kTextToSpeechLangToVoiceName, std::move(lang_to_voices));
104   delegate.pref_service_ = &pref_service;
105 
106   ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get());
107   ASSERT_TRUE(ids.get());
108   EXPECT_FALSE(ids->lang_voice_id.has_value());
109   EXPECT_FALSE(ids->locale_voice_id.has_value());
110   ASSERT_TRUE(ids->any_locale_voice_id.has_value());
111   EXPECT_EQ("Android", ids->any_locale_voice_id->name);
112   EXPECT_EQ("x", ids->any_locale_voice_id->id);
113 
114   // Change the language of the Utterance to 'es' which should match one of the
115   // registered keys.
116   utterance->SetLang("es");
117   ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get());
118   ASSERT_TRUE(ids.get());
119   ASSERT_TRUE(ids->lang_voice_id.has_value());
120   EXPECT_EQ("Voice7", ids->lang_voice_id->name);
121   EXPECT_EQ("id7", ids->lang_voice_id->id);
122   EXPECT_FALSE(ids->locale_voice_id.has_value());
123   ASSERT_TRUE(ids->any_locale_voice_id.has_value());
124   EXPECT_EQ("Android", ids->any_locale_voice_id->name);
125   EXPECT_EQ("x", ids->any_locale_voice_id->id);
126 
127   // Change the application locale to 'he' which should match one of the
128   // registered keys.
129   g_browser_process->SetApplicationLocale("he");
130   ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get());
131   ASSERT_TRUE(ids.get());
132   ASSERT_TRUE(ids->lang_voice_id.has_value());
133   EXPECT_EQ("Voice7", ids->lang_voice_id->name);
134   EXPECT_EQ("id7", ids->lang_voice_id->id);
135   EXPECT_TRUE(ids->locale_voice_id.has_value());
136   EXPECT_EQ("Voice8", ids->locale_voice_id->name);
137   EXPECT_EQ("id8", ids->locale_voice_id->id);
138   ASSERT_TRUE(ids->any_locale_voice_id.has_value());
139   EXPECT_EQ("Android", ids->any_locale_voice_id->name);
140   EXPECT_EQ("x", ids->any_locale_voice_id->id);
141 }
142