diff options
author | plundblad@chromium.org <plundblad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-07 00:29:12 +0000 |
---|---|---|
committer | plundblad@chromium.org <plundblad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-07 00:29:12 +0000 |
commit | 7a5f27003d21d0f0829f369451c7de67dc969eff (patch) | |
tree | 10b0cbb11b8770d2dcc06747124c5a84b9d93699 | |
parent | 68780860e0e5ff26d9d2a8af6dc97539985062f9 (diff) | |
download | chromium_src-7a5f27003d21d0f0829f369451c7de67dc969eff.zip chromium_src-7a5f27003d21d0f0829f369451c7de67dc969eff.tar.gz chromium_src-7a5f27003d21d0f0829f369451c7de67dc969eff.tar.bz2 |
Revert "Automatically trigger installation of high-quality speech synthesis extension."
This reverts commit r241081.
Reason: changing the builtin tts engine to use an event page instead of a persistent background page can cause tts to stop working for some users.
BUG=339322
TBR=dpolukhin@chromium.org, thakis@chromium.org, dtseng@chromium.org, kalman@chromium.org, dmazzoni@chromium.org
Review URL: https://codereview.chromium.org/149233004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249559 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 247 insertions, 363 deletions
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h index 0e27d08..5c80cc6 100644 --- a/chrome/browser/chromeos/login/user_manager_impl.h +++ b/chrome/browser/chromeos/login/user_manager_impl.h @@ -33,10 +33,6 @@ class PrefService; class ProfileSyncService; -namespace extensions { -class ExternalComponentLoaderTest; -} - namespace policy { struct DeviceLocalAccount; } @@ -172,7 +168,6 @@ class UserManagerImpl void StopPolicyObserverForTesting(); private: - friend class extensions::ExternalComponentLoaderTest; friend class SupervisedUserManagerImpl; friend class UserManager; friend class WallpaperManager; diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 0ef7a9f..e31c954 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc @@ -333,13 +333,6 @@ void ComponentLoader::AddNetworkSpeechSynthesisExtension() { base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis"))); } -#if defined(OS_CHROMEOS) -void ComponentLoader::AddChromeOsSpeechSynthesisExtension() { - Add(IDR_SPEECH_SYNTHESIS_MANIFEST, - base::FilePath(extension_misc::kSpeechSynthesisExtensionPath)); -} -#endif - void ComponentLoader::AddWithName(int manifest_resource_id, const base::FilePath& root_directory, const std::string& name) { @@ -433,10 +426,6 @@ void ComponentLoader::AddDefaultComponentExtensionsForKioskMode( // Component extensions needed for kiosk apps. AddFileManagerExtension(); - -#if defined(OS_CHROMEOS) - ComponentLoader::AddChromeOsSpeechSynthesisExtension(); -#endif } void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages( @@ -585,10 +574,6 @@ void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages( #endif #endif // defined(GOOGLE_CHROME_BUILD) -#if defined(OS_CHROMEOS) - AddChromeOsSpeechSynthesisExtension(); -#endif // defined(OS_CHROMEOS) - #if defined(ENABLE_PLUGINS) base::FilePath pdf_path; content::PluginService* plugin_service = diff --git a/chrome/browser/extensions/component_loader.h b/chrome/browser/extensions/component_loader.h index bef24f9..816d1ea 100644 --- a/chrome/browser/extensions/component_loader.h +++ b/chrome/browser/extensions/component_loader.h @@ -126,9 +126,6 @@ class ComponentLoader { void AddImageLoaderExtension(); void AddBookmarksExtensions(); void AddNetworkSpeechSynthesisExtension(); -#if defined(OS_CHROMEOS) - void AddChromeOsSpeechSynthesisExtension(); -#endif void AddWithName(int manifest_resource_id, const base::FilePath& root_directory, diff --git a/chrome/browser/extensions/external_component_loader.cc b/chrome/browser/extensions/external_component_loader.cc index 1b6e2b9..579a38b 100644 --- a/chrome/browser/extensions/external_component_loader.cc +++ b/chrome/browser/extensions/external_component_loader.cc @@ -20,40 +20,13 @@ namespace extensions { -#if defined(OS_CHROMEOS) -namespace { -// Table mapping language codes to the extension ids of high-quality -// speech synthesis extensions. See the comment in StartLoading() for more. -struct LangToExtensionId { - const char* lang; - const char* extension_id; -}; -LangToExtensionId kLangToExtensionIdTable[] = { - { "en-US", extension_misc::kHighQuality_en_US_ExtensionId } -}; -} // anonymous namespace -#endif // defined(OS_CHROMEOS) - ExternalComponentLoader::ExternalComponentLoader(Profile* profile) : profile_(profile) { -#if defined(OS_CHROMEOS) - pref_change_registrar_.reset(new PrefChangeRegistrar()); - pref_change_registrar_->Init(profile->GetPrefs()); - pref_change_registrar_->Add( - prefs::kHighQualitySpeechSynthesisLanguages, - base::Bind(&ExternalComponentLoader::StartLoading, AsWeakPtr())); - - for (size_t i = 0; i < arraysize(kLangToExtensionIdTable); ++i) { - lang_to_extension_id_map_[kLangToExtensionIdTable[i].lang] = - kLangToExtensionIdTable[i].extension_id; - } -#endif } ExternalComponentLoader::~ExternalComponentLoader() {} void ExternalComponentLoader::StartLoading() { - CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); prefs_.reset(new base::DictionaryValue()); std::string appId = extension_misc::kInAppPaymentsSupportAppId; prefs_->SetString(appId + ".external_update_url", @@ -73,48 +46,7 @@ void ExternalComponentLoader::StartLoading() { extension_urls::GetWebstoreUpdateUrl().spec()); } } - -#if defined(OS_CHROMEOS) - // Chrome OS comes with medium-quality speech synthesis extensions built-in. - // When the user speaks a certain threshold of utterances in the same - // session, we set a preference indicating that high quality speech is - // enabled for that language. Here, we check the preference and prepare - // the list of external extensions to be installed based on that. - PrefService* pref_service = profile_->GetPrefs(); - const base::ListValue* languages = - pref_service->GetList(prefs::kHighQualitySpeechSynthesisLanguages); - for (size_t i = 0; i < languages->GetSize(); ++i) { - std::string lang; - if (!languages->GetString(i, &lang)) - continue; - - base::hash_map<std::string, std::string>::iterator iter = - lang_to_extension_id_map_.find(lang); - if (iter == lang_to_extension_id_map_.end()) - continue; - - std::string extension_id = iter->second; - base::DictionaryValue* extension = new base::DictionaryValue(); - prefs_->Set(extension_id, extension); - extension->SetString(ExternalProviderImpl::kExternalUpdateUrl, - extension_urls::GetWebstoreUpdateUrl().spec()); - base::ListValue* supported_locales = new base::ListValue(); - supported_locales->AppendString(g_browser_process->GetApplicationLocale()); - extension->Set(ExternalProviderImpl::kSupportedLocales, supported_locales); - extension->SetBoolean(ExternalProviderImpl::kIsFromWebstore, true); - } -#endif // defined(OS_CHROMEOS) - LoadFinished(); } -// static -void ExternalComponentLoader::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { -#if defined(OS_CHROMEOS) - registry->RegisterListPref(prefs::kHighQualitySpeechSynthesisLanguages, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); -#endif -} - } // namespace extensions diff --git a/chrome/browser/extensions/external_component_loader.h b/chrome/browser/extensions/external_component_loader.h index b27d504..02bb459 100644 --- a/chrome/browser/extensions/external_component_loader.h +++ b/chrome/browser/extensions/external_component_loader.h @@ -8,13 +8,9 @@ #include <string> #include "base/compiler_specific.h" -#include "base/containers/hash_tables.h" -#include "base/memory/weak_ptr.h" #include "chrome/browser/extensions/external_loader.h" #include "chrome/browser/profiles/profile.h" -class PrefChangeRegistrar; - namespace extensions { // A specialization of the ExternalLoader that loads a hard-coded list of @@ -23,17 +19,12 @@ namespace extensions { // and don't get access to component only APIs. // Instances of this class are expected to be created and destroyed on the UI // thread and they are expecting public method calls from the UI thread. -class ExternalComponentLoader - : public ExternalLoader, - public base::SupportsWeakPtr<ExternalComponentLoader> { +class ExternalComponentLoader : public ExternalLoader { public: explicit ExternalComponentLoader(Profile* profile); static bool IsEnhancedBookmarksExperimentEnabled(); - // Register speech synthesis prefs for a profile. - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - protected: virtual void StartLoading() OVERRIDE; @@ -44,17 +35,6 @@ class ExternalComponentLoader // The profile that this loader is associated with. It listens for // preference changes for that profile. Profile* profile_; - -#if defined(OS_CHROMEOS) - // The pref change registrar, so we can watch for pref changes. - scoped_ptr<PrefChangeRegistrar> pref_change_registrar_; - - // A map from language code to the extension id of the high-quality - // extension for that language in the web store, if any - for loading - // speech synthesis component extensions. - base::hash_map<std::string, std::string> lang_to_extension_id_map_; -#endif - DISALLOW_COPY_AND_ASSIGN(ExternalComponentLoader); }; diff --git a/chrome/browser/extensions/external_component_loader_unittest.cc b/chrome/browser/extensions/external_component_loader_unittest.cc deleted file mode 100644 index 6fb03ee..0000000 --- a/chrome/browser/extensions/external_component_loader_unittest.cc +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2013 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. - -#include "chrome/browser/extensions/external_component_loader.h" - -#include "base/values.h" -#include "chrome/browser/extensions/external_provider_impl.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/speech/tts_platform.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/test/test_browser_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/login/user_manager_impl.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/device_settings_service.h" -#endif // defined(OS_CHROMEOS) - -using content::BrowserThread; -using extensions::ExternalProviderImpl; -using extensions::ExternalProviderInterface; -using extensions::Manifest; -using extensions::ProviderCollection; - -namespace extensions { - -namespace { -class TestUtterance : public Utterance { - public: - explicit TestUtterance(Profile* profile) : Utterance(profile) { - } - - virtual ~TestUtterance() { - set_finished_for_testing(true); - } -}; - -class FakeVisitorInterface - : public ExternalProviderInterface::VisitorInterface { - public: - FakeVisitorInterface() {} - virtual ~FakeVisitorInterface() {} - - virtual bool OnExternalExtensionFileFound( - const std::string& id, - const base::Version* version, - const base::FilePath& path, - Manifest::Location location, - int creation_flags, - bool mark_acknowledged) OVERRIDE { - return true; - } - - virtual bool OnExternalExtensionUpdateUrlFound( - const std::string& id, - const GURL& update_url, - Manifest::Location location, - int creation_flags, - bool mark_acknowledged) OVERRIDE { - return true; - } - - virtual void OnExternalProviderReady( - const ExternalProviderInterface* provider) OVERRIDE {} -}; -} // anonymous namespace - -#if defined(OS_CHROMEOS) -class ExternalComponentLoaderTest : public testing::Test { - public: - ExternalComponentLoaderTest() - : ui_thread_(BrowserThread::UI, &message_loop_), - user_manager_enabler_(new chromeos::UserManagerImpl()) { - } - - virtual ~ExternalComponentLoaderTest() {} - - // testing::Test overrides: - virtual void SetUp() OVERRIDE { - testing_profile_.reset(new TestingProfile()); - ExternalProviderImpl::CreateExternalProviders( - &service_, testing_profile_.get(), &providers_); - } - - virtual void TearDown() OVERRIDE { - } - - bool IsHighQualityEnglishSpeechExtensionInstalled() { - const std::string& id = extension_misc::kHighQuality_en_US_ExtensionId; - for (size_t i = 0; i < providers_.size(); ++i) { - if (!providers_[i]->IsReady()) - continue; - if (providers_[i]->HasExtension(id)) - return true; - } - return false; - } - - protected: - base::MessageLoop message_loop_; - content::TestBrowserThread ui_thread_; - chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; - chromeos::ScopedTestCrosSettings test_cros_settings_; - chromeos::ScopedUserManagerEnabler user_manager_enabler_; - scoped_ptr<Profile> testing_profile_; - FakeVisitorInterface service_; - ProviderCollection providers_; - - private: - DISALLOW_COPY_AND_ASSIGN(ExternalComponentLoaderTest); -}; - -TEST_F(ExternalComponentLoaderTest, Speaking100TimesInstallsSpeechExtension) { - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); - - TtsPlatformImpl* tts_platform = TtsPlatformImpl::GetInstance(); - TestUtterance utterance(testing_profile_.get()); - VoiceData voice_data; - voice_data.lang = "en-US"; - voice_data.extension_id = extension_misc::kSpeechSynthesisExtensionId; - - // 99 times should not be sufficient. - for (int i = 0; i < 99; i++) - tts_platform->WillSpeakUtteranceWithVoice(&utterance, voice_data); - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); - - // The 100th time should install it. - tts_platform->WillSpeakUtteranceWithVoice(&utterance, voice_data); - ASSERT_TRUE(IsHighQualityEnglishSpeechExtensionInstalled()); -} - -TEST_F(ExternalComponentLoaderTest, - UsingOtherVoiceDoesNotTriggerInstallingSpeechExtension) { - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); - - TtsPlatformImpl* tts_platform = TtsPlatformImpl::GetInstance(); - TestUtterance utterance(testing_profile_.get()); - VoiceData voice_data; - voice_data.lang = "en-US"; - voice_data.extension_id = "dummy"; // Some other extension id. - - for (int i = 0; i < 100; i++) - tts_platform->WillSpeakUtteranceWithVoice(&utterance, voice_data); - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); -} - -TEST_F(ExternalComponentLoaderTest, - UnsupportedLangDoesNotTriggerInstallingSpeechExtension) { - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); - - TtsPlatformImpl* tts_platform = TtsPlatformImpl::GetInstance(); - TestUtterance utterance(testing_profile_.get()); - VoiceData voice_data; - voice_data.lang = "tlh"; // Klingon - voice_data.extension_id = extension_misc::kSpeechSynthesisExtensionId; - - for (int i = 0; i < 100; i++) - tts_platform->WillSpeakUtteranceWithVoice(&utterance, voice_data); - ASSERT_FALSE(IsHighQualityEnglishSpeechExtensionInstalled()); -} -#endif // defined(OS_CHROMEOS) - -} // namespace extensions diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index b443a35..9f9f489 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -26,7 +26,6 @@ #include "chrome/browser/extensions/api/commands/command_service.h" #include "chrome/browser/extensions/api/tabs/tabs_api.h" #include "chrome/browser/extensions/extension_web_ui.h" -#include "chrome/browser/extensions/external_component_loader.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/geolocation/geolocation_prefs.h" @@ -344,7 +343,6 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { chrome_browser_net::Predictor::RegisterProfilePrefs(registry); DownloadPrefs::RegisterProfilePrefs(registry); extensions::ExtensionPrefs::RegisterProfilePrefs(registry); - extensions::ExternalComponentLoader::RegisterProfilePrefs(registry); ExtensionWebUI::RegisterProfilePrefs(registry); HostContentSettingsMap::RegisterProfilePrefs(registry); IncognitoModePrefs::RegisterProfilePrefs(registry); diff --git a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json index 4252fdc..26cce46 100644 --- a/chrome/browser/resources/chromeos/speech_synthesis/manifest.json +++ b/chrome/browser/resources/chromeos/speech_synthesis/manifest.json @@ -1,7 +1,7 @@ { - "name": "Chrome OS text-to-speech component extension", - "version": "1.0.2", - "description": "Chrome OS native text-to-speech implemented using native client.", + "name": "Chrome OS built-in text-to-speech extension", + "version": "0.0.2", + "description": "Text-to-speech (TTS) voice extension using Native Client technology.", "manifest_version": 2, "background": { "scripts": [ @@ -13,8 +13,7 @@ "voice_data_hmm_it-IT.js", "tts_controller.js", "tts_main.js" - ], - "persistent": false + ] }, "permissions": [ "ttsEngine", @@ -42,13 +41,13 @@ "event_types": [ "start", "word", "end", "error" ] }, { - "voice_name": "Chrome OS US English Female", + "voice_name": "Chrome OS US English", "lang": "en-US", "gender": "female", "event_types": [ "start", "word", "end", "error" ] }, { - "voice_name": "Chrome OS British English Female", + "voice_name": "Chrome OS British English", "lang": "en-GB", "gender": "female", "event_types": [ "start", "word", "end", "error" ] diff --git a/chrome/browser/speech/tts_chromeos.cc b/chrome/browser/speech/tts_chromeos.cc index 1c86c56..e42cb0c 100644 --- a/chrome/browser/speech/tts_chromeos.cc +++ b/chrome/browser/speech/tts_chromeos.cc @@ -2,27 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/prefs/scoped_user_pref_update.h" -#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/speech/tts_extension_loader_chromeos.h" #include "chrome/browser/speech/tts_platform.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/pref_names.h" - -namespace { - -// Trigger installing high-quality speech after this many utterances -// have been spoken in one session. -const int kHighQualitySpeechUtteranceThreshold = 100; - -} // anonymous namespace // Chrome OS doesn't have native TTS, instead it includes a built-in -// component extension that provides speech synthesis. This class monitors -// use of this component extension and triggers installing a higher-quality -// speech synthesis extension if a certain number of utterances are spoken -// in a single session. +// component extension that provides speech synthesis. This class includes +// an implementation of LoadBuiltInTtsExtension and dummy implementations of +// everything else. class TtsPlatformImplChromeOs : public TtsPlatformImpl { public: @@ -31,6 +17,10 @@ class TtsPlatformImplChromeOs return false; } + virtual bool LoadBuiltInTtsExtension(Profile* profile) OVERRIDE { + return TtsExtensionLoaderChromeOs::GetInstance(profile)->LoadTtsExtension(); + } + virtual bool Speak( int utterance_id, const std::string& utterance, @@ -40,63 +30,33 @@ class TtsPlatformImplChromeOs return false; } - virtual bool StopSpeaking() OVERRIDE { return false; } + virtual bool StopSpeaking() OVERRIDE { + return false; + } + virtual void Pause() OVERRIDE {} + virtual void Resume() OVERRIDE {} - virtual bool IsSpeaking() OVERRIDE { return false; } - virtual void GetVoices(std::vector<VoiceData>* out_voices) OVERRIDE {} - virtual void WillSpeakUtteranceWithVoice( - const Utterance* utterance, - const VoiceData& voice_data) OVERRIDE; + virtual bool IsSpeaking() OVERRIDE { + return false; + } + + virtual void GetVoices(std::vector<VoiceData>* out_voices) OVERRIDE { + } // Get the single instance of this class. static TtsPlatformImplChromeOs* GetInstance(); private: - TtsPlatformImplChromeOs(); + TtsPlatformImplChromeOs() {} virtual ~TtsPlatformImplChromeOs() {} friend struct DefaultSingletonTraits<TtsPlatformImplChromeOs>; - // A count of the number of utterances spoken for each language - // using the built-in speech synthesis. When enough utterances have - // been spoken in a single session, automatically enable install - // the high-quality speech synthesis extension for that language. - base::hash_map<std::string, int> lang_utterance_count_; - DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplChromeOs); }; -TtsPlatformImplChromeOs::TtsPlatformImplChromeOs() { -} - -void TtsPlatformImplChromeOs::WillSpeakUtteranceWithVoice( - const Utterance* utterance, - const VoiceData& voice_data) { - CHECK(utterance); - CHECK(utterance->profile()); - - if (utterance->profile()->IsOffTheRecord()) - return; - - if (voice_data.extension_id != extension_misc::kSpeechSynthesisExtensionId) - return; - - lang_utterance_count_[voice_data.lang]++; - if (lang_utterance_count_[voice_data.lang] != - kHighQualitySpeechUtteranceThreshold) { - return; - } - - // Add this language to the list that are allowed to install a - // component extension for high-quality speech synthesis, overriding - // the lower-quality one. - ListPrefUpdate updater(utterance->profile()->GetPrefs(), - prefs::kHighQualitySpeechSynthesisLanguages); - updater->AppendIfNotPresent(new base::StringValue(voice_data.lang)); -} - // static TtsPlatformImpl* TtsPlatformImpl::GetInstance() { return TtsPlatformImplChromeOs::GetInstance(); diff --git a/chrome/browser/speech/tts_controller.cc b/chrome/browser/speech/tts_controller.cc index b966885..503786d 100644 --- a/chrome/browser/speech/tts_controller.cc +++ b/chrome/browser/speech/tts_controller.cc @@ -196,6 +196,14 @@ void TtsController::SpeakNow(Utterance* utterance) { if (!success) current_utterance_ = NULL; + // If the native voice wasn't able to process this speech, see if + // the browser has built-in TTS that isn't loaded yet. + if (!success && + GetPlatformImpl()->LoadBuiltInTtsExtension(utterance->profile())) { + utterance_queue_.push(utterance); + return; + } + if (!success) { utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, GetPlatformImpl()->error()); @@ -306,6 +314,11 @@ void TtsController::SpeakNextUtterance() { } } +void TtsController::RetrySpeakingQueuedUtterances() { + if (current_utterance_ == NULL && !utterance_queue_.empty()) + SpeakNextUtterance(); +} + void TtsController::ClearUtteranceQueue(bool send_events) { while (!utterance_queue_.empty()) { Utterance* utterance = utterance_queue_.front(); diff --git a/chrome/browser/speech/tts_controller.h b/chrome/browser/speech/tts_controller.h index c4329e4..c8d1c10 100644 --- a/chrome/browser/speech/tts_controller.h +++ b/chrome/browser/speech/tts_controller.h @@ -102,7 +102,7 @@ class Utterance { // when the utterance is done speaking. Before speaking this utterance, // its other parameters like text, rate, pitch, etc. should all be set. explicit Utterance(Profile* profile); - virtual ~Utterance(); + ~Utterance(); // Sends an event to the delegate. If the event type is TTS_EVENT_END // or TTS_EVENT_ERROR, deletes the utterance. If |char_index| is -1, @@ -189,9 +189,6 @@ class Utterance { int id() const { return id_; } bool finished() const { return finished_; } - protected: - void set_finished_for_testing(bool finished) { finished_ = finished; } - private: // The profile that initiated this utterance. Profile* profile_; @@ -286,6 +283,10 @@ class TtsController { // if supported, and all voices registered by extensions. void GetVoices(Profile* profile, std::vector<VoiceData>* out_voices); + // Called by TtsExtensionLoaderChromeOs::LoadTtsExtension when it + // finishes loading the built-in TTS component extension. + void RetrySpeakingQueuedUtterances(); + // Called by the extension system or platform implementation when the // list of voices may have changed and should be re-queried. void VoicesChanged(); diff --git a/chrome/browser/speech/tts_extension_loader_chromeos.cc b/chrome/browser/speech/tts_extension_loader_chromeos.cc new file mode 100644 index 0000000..3c8f233 --- /dev/null +++ b/chrome/browser/speech/tts_extension_loader_chromeos.cc @@ -0,0 +1,133 @@ +// Copyright 2014 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. + +#include "chrome/browser/speech/tts_extension_loader_chromeos.h" + +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "chrome/browser/extensions/component_loader.h" +#include "chrome/browser/extensions/extension_service.h" +#include "extensions/browser/extension_system.h" +#include "chrome/browser/extensions/extension_system_factory.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" +#include "chrome/browser/speech/tts_controller.h" +#include "chrome/common/extensions/extension_constants.h" +#include "components/browser_context_keyed_service/browser_context_dependency_manager.h" +#include "components/browser_context_keyed_service/browser_context_keyed_service.h" +#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h" +#include "extensions/browser/event_router.h" +#include "grit/browser_resources.h" + +// Factory to load one instance of TtsExtensionLoaderChromeOs per profile. +class TtsExtensionLoaderChromeOsFactory + : public BrowserContextKeyedServiceFactory { + public: + static TtsExtensionLoaderChromeOs* GetForProfile(Profile* profile) { + return static_cast<TtsExtensionLoaderChromeOs*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); + } + + static TtsExtensionLoaderChromeOsFactory* GetInstance() { + return Singleton<TtsExtensionLoaderChromeOsFactory>::get(); + } + + private: + friend struct DefaultSingletonTraits<TtsExtensionLoaderChromeOsFactory>; + + TtsExtensionLoaderChromeOsFactory() : BrowserContextKeyedServiceFactory( + "TtsExtensionLoaderChromeOs", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(extensions::ExtensionSystemFactory::GetInstance()); + } + + virtual ~TtsExtensionLoaderChromeOsFactory() {} + + virtual content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const OVERRIDE{ + // If given an incognito profile (including the Chrome OS login + // profile), share the service with the original profile. + return chrome::GetBrowserContextRedirectedInIncognito(context); + } + + virtual BrowserContextKeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const OVERRIDE { + return new TtsExtensionLoaderChromeOs(static_cast<Profile*>(profile)); + } +}; + +TtsExtensionLoaderChromeOs* +TtsExtensionLoaderChromeOs::GetInstance(Profile* profile) { + return TtsExtensionLoaderChromeOsFactory::GetInstance() + ->GetForProfile(profile); +} + +TtsExtensionLoaderChromeOs::TtsExtensionLoaderChromeOs( + Profile* profile) + : profile_(profile) { + tts_state_ = IsTtsLoadedInThisProfile() ? TTS_LOADED : TTS_NOT_LOADED; + + extensions::ExtensionSystem* system = + extensions::ExtensionSystem::Get(profile_); + DCHECK(system); + extensions::EventRouter* event_router = system->event_router(); + DCHECK(event_router); + event_router->RegisterObserver(this, tts_engine_events::kOnSpeak); + event_router->RegisterObserver(this, tts_engine_events::kOnStop); +} + +bool TtsExtensionLoaderChromeOs::LoadTtsExtension() { + if (tts_state_ == TTS_LOADED || tts_state_ == TTS_LOADING) + return false; + + // Load the component extension into this profile. + VLOG(1) << "Loading TTS component extension."; + tts_state_ = TTS_LOADING; + ExtensionService* extension_service = profile_->GetExtensionService(); + DCHECK(extension_service); + base::FilePath path = + base::FilePath(extension_misc::kSpeechSynthesisExtensionPath); + extension_service->component_loader()->Add(IDR_SPEECH_SYNTHESIS_MANIFEST, + path); + return true; +} + +void TtsExtensionLoaderChromeOs::Shutdown() { + extensions::ExtensionSystem::Get(profile_)-> + event_router()->UnregisterObserver(this); +} + +bool TtsExtensionLoaderChromeOs::IsTtsLoadedInThisProfile() { + extensions::ExtensionSystem* system = + extensions::ExtensionSystem::Get(profile_); + DCHECK(system); + extensions::EventRouter* event_router = system->event_router(); + DCHECK(event_router); + if (event_router->ExtensionHasEventListener( + extension_misc::kSpeechSynthesisExtensionId, + tts_engine_events::kOnSpeak) && + event_router->ExtensionHasEventListener( + extension_misc::kSpeechSynthesisExtensionId, + tts_engine_events::kOnStop)) { + return true; + } + + return false; +} + +void TtsExtensionLoaderChromeOs::OnListenerAdded( + const extensions::EventListenerInfo& details) { + if (details.extension_id != extension_misc::kSpeechSynthesisExtensionId) + return; + + if (!IsTtsLoadedInThisProfile()) + return; + + if (tts_state_ == TTS_LOADING) { + VLOG(1) << "TTS component extension loaded, retrying queued utterances."; + tts_state_ = TTS_LOADED; + TtsController::GetInstance()->RetrySpeakingQueuedUtterances(); + } +} diff --git a/chrome/browser/speech/tts_extension_loader_chromeos.h b/chrome/browser/speech/tts_extension_loader_chromeos.h new file mode 100644 index 0000000..6485042 --- /dev/null +++ b/chrome/browser/speech/tts_extension_loader_chromeos.h @@ -0,0 +1,56 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_SPEECH_TTS_EXTENSION_LOADER_CHROMEOS_H_ +#define CHROME_BROWSER_SPEECH_TTS_EXTENSION_LOADER_CHROMEOS_H_ + +#include "components/browser_context_keyed_service/browser_context_keyed_service.h" +#include "extensions/browser/event_router.h" + +class Profile; + +// Profile-keyed class that loads a built-in TTS component extension +// into a given profile on Chrome OS. +class TtsExtensionLoaderChromeOs + : public BrowserContextKeyedService, + public extensions::EventRouter::Observer { + public: + static TtsExtensionLoaderChromeOs* GetInstance(Profile* profile); + + // Returns true if the extension was not previously loaded and is now + // loading. This class will call + // ExtensionTtsController::RetrySpeakingQueuedUtterances when the + // extension finishes loading. + bool LoadTtsExtension(); + + // Implementation of BrowserContextKeyedService. + virtual void Shutdown() OVERRIDE; + + // Implementation of extensions::EventRouter::Observer. + virtual void OnListenerAdded(const extensions::EventListenerInfo& details) + OVERRIDE; + + private: + // The state of TTS for this profile. + enum TtsState { + TTS_NOT_LOADED, + TTS_LOAD_REQUESTED, + TTS_LOADING, + TTS_LOADED + }; + + explicit TtsExtensionLoaderChromeOs(Profile* profile); + virtual ~TtsExtensionLoaderChromeOs() {} + + bool IsTtsLoadedInThisProfile(); + + Profile* profile_; + TtsState tts_state_; + + friend class TtsExtensionLoaderChromeOsFactory; + + DISALLOW_COPY_AND_ASSIGN(TtsExtensionLoaderChromeOs); +}; + +#endif // CHROME_BROWSER_SPEECH_TTS_EXTENSION_LOADER_CHROMEOS_H_ diff --git a/chrome/browser/speech/tts_platform.cc b/chrome/browser/speech/tts_platform.cc index 3942eff..482f041 100644 --- a/chrome/browser/speech/tts_platform.cc +++ b/chrome/browser/speech/tts_platform.cc @@ -6,6 +6,10 @@ #include <string> +bool TtsPlatformImpl::LoadBuiltInTtsExtension(Profile* profile) { + return false; +} + std::string TtsPlatformImpl::error() { return error_; } diff --git a/chrome/browser/speech/tts_platform.h b/chrome/browser/speech/tts_platform.h index bce9693..e396b7f 100644 --- a/chrome/browser/speech/tts_platform.h +++ b/chrome/browser/speech/tts_platform.h @@ -18,6 +18,13 @@ class TtsPlatformImpl { // Returns true if this platform implementation is supported and available. virtual bool PlatformImplAvailable() = 0; + // Some platforms may provide a built-in TTS extension. Returns true + // if the extension was not previously loaded and is now loading, and + // false if it's already loaded or if there's no extension to load. + // Will call TtsController::RetrySpeakingQueuedUtterances when + // the extension finishes loading. + virtual bool LoadBuiltInTtsExtension(Profile* profile); + // Speak the given utterance with the given parameters if possible, // and return true on success. Utterance will always be nonempty. // If rate, pitch, or volume are -1.0, they will be ignored. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 7d69f4f..fcf6b46 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2101,6 +2101,8 @@ 'browser/speech/tts_chromeos.cc', 'browser/speech/tts_controller.cc', 'browser/speech/tts_controller.h', + 'browser/speech/tts_extension_loader_chromeos.cc', + 'browser/speech/tts_extension_loader_chromeos.h', 'browser/speech/tts_linux.cc', 'browser/speech/tts_mac.mm', 'browser/speech/tts_platform.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 0d38d4d..2a2a8bc 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -933,7 +933,6 @@ 'browser/extensions/extension_ui_unittest.cc', 'browser/extensions/extension_warning_badge_service_unittest.cc', 'browser/extensions/extension_warning_service_unittest.cc', - 'browser/extensions/external_component_loader_unittest.cc', 'browser/extensions/external_policy_loader_unittest.cc', 'browser/extensions/external_provider_impl_unittest.cc', 'browser/extensions/external_provider_impl_chromeos_unittest.cc', diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index 4d14663..e873e1d 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc @@ -138,8 +138,6 @@ const char kSpeechSynthesisExtensionPath[] = "/usr/share/chromeos-assets/speech_synthesis/patts"; const char kSpeechSynthesisExtensionId[] = "gjjabgpgjpampikjhjpfhneeoapjbjaf"; -const char kHighQuality_en_US_ExtensionId[] = - "efdojdlmjknacnljjdedapanceanigkh"; const char kWallpaperManagerId[] = "obklkkbkpaoaejdabbfldmcfplpdgolj"; const char kFirstRunDialogId[] = "jdgcneonijmofocbhmijhacgchbihela"; #else diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index 78e55a6..9b51634 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -257,9 +257,6 @@ namespace extension_misc { extern const char kSpeechSynthesisExtensionPath[]; // The extension id of the speech synthesis extension. extern const char kSpeechSynthesisExtensionId[]; - // The extension id of the high quality speech synthesis extension for - // en-US, which can be installed automatically from the web store. - extern const char kHighQuality_en_US_ExtensionId[]; // The extension id of the wallpaper manager application. extern const char kWallpaperManagerId[]; // The extension id of the first run dialog application. diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index e0645b3..368d6a8 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -880,11 +880,6 @@ const char kMultiProfileNotificationDismissed[] = // for more details of the valid values. const char kMultiProfileUserBehavior[] = "settings.multiprofile_user_behavior"; -// List of the set of language codes for which high quality local speech -// synthesis has been enabled. -const char kHighQualitySpeechSynthesisLanguages[] = - "settings.speech_synthesis.high_quality_languages"; - // A boolean preference indicating whether user has seen first-run tutorial // already. const char kFirstRunTutorialShown[] = "settings.first_run_tutorial_shown"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index d0846d1..5d1eb3b 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -276,7 +276,6 @@ extern const char kMultiProfileNeverShowIntro[]; extern const char kMultiProfileWarningShowDismissed[]; extern const char kMultiProfileNotificationDismissed[]; extern const char kMultiProfileUserBehavior[]; -extern const char kHighQualitySpeechSynthesisLanguages[]; extern const char kFirstRunTutorialShown[]; extern const char kSAMLOfflineSigninTimeLimit[]; extern const char kSAMLLastGAIASignInTime[]; |