| // Copyright (c) 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Unit tests for the TTS Controller. |
| |
| #include "chrome/browser/speech/tts_controller_delegate_impl.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "content/public/browser/tts_controller.h" |
| #include "content/public/browser/tts_platform.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/mojom/speech/speech_synthesis.mojom.h" |
| |
| // Subclass of TtsController with a public ctor and dtor. |
| class MockTtsControllerDelegate : public TtsControllerDelegateImpl { |
| public: |
| MockTtsControllerDelegate() {} |
| ~MockTtsControllerDelegate() override {} |
| |
| PrefService* pref_service_ = nullptr; |
| |
| private: |
| const PrefService* GetPrefService(content::TtsUtterance* utterance) override { |
| return pref_service_; |
| } |
| }; |
| |
| TEST(TtsControllerDelegateImplTest, TestTtsControllerUtteranceDefaults) { |
| std::unique_ptr<MockTtsControllerDelegate> tts_controller_delegate = |
| std::make_unique<MockTtsControllerDelegate>(); |
| |
| double rate = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| double pitch = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| double volume = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| |
| std::unique_ptr<content::TtsUtterance> utterance1 = |
| content::TtsUtterance::Create(); |
| tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs( |
| utterance1.get(), &rate, &pitch, &volume); |
| // Updated to global defaults. |
| EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultRate, rate); |
| EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultPitch, pitch); |
| EXPECT_EQ(blink::mojom::kSpeechSynthesisDefaultVolume, volume); |
| |
| // Now we will set prefs and expect those to be used as defaults. |
| rate = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| pitch = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| volume = blink::mojom::kSpeechSynthesisDoublePrefNotSet; |
| TestingPrefServiceSimple pref_service_; |
| pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechRate, 1.5); |
| pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechPitch, 2.0); |
| pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechVolume, 0.5); |
| tts_controller_delegate->pref_service_ = &pref_service_; |
| |
| std::unique_ptr<content::TtsUtterance> utterance2 = |
| content::TtsUtterance::Create(); |
| tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs( |
| utterance2.get(), &rate, &pitch, &volume); |
| // Updated to pref values. |
| EXPECT_EQ(1.5f, rate); |
| EXPECT_EQ(2.0f, pitch); |
| EXPECT_EQ(0.5f, volume); |
| |
| // If we explicitly set rate, pitch and volume, they should not be changed. |
| rate = 1.1f; |
| pitch = 1.2f; |
| volume = 1.3f; |
| |
| std::unique_ptr<content::TtsUtterance> utterance3 = |
| content::TtsUtterance::Create(); |
| tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs( |
| utterance3.get(), &rate, &pitch, &volume); |
| // Updated to pref values. |
| EXPECT_EQ(1.1f, rate); |
| EXPECT_EQ(1.2f, pitch); |
| EXPECT_EQ(1.3f, volume); |
| } |
| |
| TEST(TtsControllerDelegateImplTest, GetPreferredVoiceIdsForUtterance) { |
| MockTtsControllerDelegate delegate; |
| std::unique_ptr<content::TtsUtterance> utterance = |
| content::TtsUtterance::Create(); |
| auto ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get()); |
| EXPECT_EQ(nullptr, ids.get()); |
| |
| TestingPrefServiceSimple pref_service; |
| // Uses default pref voices. |
| base::Value lang_to_voices(base::Value::Type::DICTIONARY); |
| lang_to_voices.SetKey( |
| "es", base::Value("{\"name\":\"Voice7\",\"extension\":\"id7\"}")); |
| lang_to_voices.SetKey( |
| "he", base::Value("{\"name\":\"Voice8\",\"extension\":\"id8\"}")); |
| lang_to_voices.SetKey( |
| "noLanguageCode", |
| base::Value("{\"name\":\"Android\",\"extension\":\"x\"}")); |
| pref_service.registry()->RegisterDictionaryPref( |
| prefs::kTextToSpeechLangToVoiceName, std::move(lang_to_voices)); |
| delegate.pref_service_ = &pref_service; |
| |
| ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get()); |
| ASSERT_TRUE(ids.get()); |
| EXPECT_FALSE(ids->lang_voice_id.has_value()); |
| EXPECT_FALSE(ids->locale_voice_id.has_value()); |
| ASSERT_TRUE(ids->any_locale_voice_id.has_value()); |
| EXPECT_EQ("Android", ids->any_locale_voice_id->name); |
| EXPECT_EQ("x", ids->any_locale_voice_id->id); |
| |
| // Change the language of the Utterance to 'es' which should match one of the |
| // registered keys. |
| utterance->SetLang("es"); |
| ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get()); |
| ASSERT_TRUE(ids.get()); |
| ASSERT_TRUE(ids->lang_voice_id.has_value()); |
| EXPECT_EQ("Voice7", ids->lang_voice_id->name); |
| EXPECT_EQ("id7", ids->lang_voice_id->id); |
| EXPECT_FALSE(ids->locale_voice_id.has_value()); |
| ASSERT_TRUE(ids->any_locale_voice_id.has_value()); |
| EXPECT_EQ("Android", ids->any_locale_voice_id->name); |
| EXPECT_EQ("x", ids->any_locale_voice_id->id); |
| |
| // Change the application locale to 'he' which should match one of the |
| // registered keys. |
| g_browser_process->SetApplicationLocale("he"); |
| ids = delegate.GetPreferredVoiceIdsForUtterance(utterance.get()); |
| ASSERT_TRUE(ids.get()); |
| ASSERT_TRUE(ids->lang_voice_id.has_value()); |
| EXPECT_EQ("Voice7", ids->lang_voice_id->name); |
| EXPECT_EQ("id7", ids->lang_voice_id->id); |
| EXPECT_TRUE(ids->locale_voice_id.has_value()); |
| EXPECT_EQ("Voice8", ids->locale_voice_id->name); |
| EXPECT_EQ("id8", ids->locale_voice_id->id); |
| ASSERT_TRUE(ids->any_locale_voice_id.has_value()); |
| EXPECT_EQ("Android", ids->any_locale_voice_id->name); |
| EXPECT_EQ("x", ids->any_locale_voice_id->id); |
| } |