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