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 "chrome/browser/speech/tts_extension_loader_chromeos.h" 6 7 #include "base/logging.h" 8 #include "base/memory/singleton.h" 9 #include "chrome/browser/extensions/component_loader.h" 10 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_system.h" 12 #include "chrome/browser/extensions/extension_system_factory.h" 13 #include "chrome/browser/profiles/incognito_helpers.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" 16 #include "chrome/browser/speech/tts_controller.h" 17 #include "chrome/common/extensions/extension_constants.h" 18 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h" 19 #include "components/browser_context_keyed_service/browser_context_keyed_service.h" 20 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h" 21 #include "extensions/browser/event_router.h" 22 #include "grit/browser_resources.h" 23 24 // Factory to load one instance of TtsExtensionLoaderChromeOs per profile. 25 class TtsExtensionLoaderChromeOsFactory 26 : public BrowserContextKeyedServiceFactory { 27 public: GetForProfile(Profile * profile)28 static TtsExtensionLoaderChromeOs* GetForProfile(Profile* profile) { 29 return static_cast<TtsExtensionLoaderChromeOs*>( 30 GetInstance()->GetServiceForBrowserContext(profile, true)); 31 } 32 GetInstance()33 static TtsExtensionLoaderChromeOsFactory* GetInstance() { 34 return Singleton<TtsExtensionLoaderChromeOsFactory>::get(); 35 } 36 37 private: 38 friend struct DefaultSingletonTraits<TtsExtensionLoaderChromeOsFactory>; 39 TtsExtensionLoaderChromeOsFactory()40 TtsExtensionLoaderChromeOsFactory() : BrowserContextKeyedServiceFactory( 41 "TtsExtensionLoaderChromeOs", 42 BrowserContextDependencyManager::GetInstance()) { 43 DependsOn(extensions::ExtensionSystemFactory::GetInstance()); 44 } 45 ~TtsExtensionLoaderChromeOsFactory()46 virtual ~TtsExtensionLoaderChromeOsFactory() {} 47 GetBrowserContextToUse(content::BrowserContext * context) const48 virtual content::BrowserContext* GetBrowserContextToUse( 49 content::BrowserContext* context) const OVERRIDE{ 50 // If given an incognito profile (including the Chrome OS login 51 // profile), share the service with the original profile. 52 return chrome::GetBrowserContextRedirectedInIncognito(context); 53 } 54 BuildServiceInstanceFor(content::BrowserContext * profile) const55 virtual BrowserContextKeyedService* BuildServiceInstanceFor( 56 content::BrowserContext* profile) const OVERRIDE { 57 return new TtsExtensionLoaderChromeOs(static_cast<Profile*>(profile)); 58 } 59 }; 60 61 TtsExtensionLoaderChromeOs* GetInstance(Profile * profile)62TtsExtensionLoaderChromeOs::GetInstance(Profile* profile) { 63 return TtsExtensionLoaderChromeOsFactory::GetInstance() 64 ->GetForProfile(profile); 65 } 66 TtsExtensionLoaderChromeOs(Profile * profile)67TtsExtensionLoaderChromeOs::TtsExtensionLoaderChromeOs( 68 Profile* profile) 69 : profile_(profile) { 70 tts_state_ = IsTtsLoadedInThisProfile() ? TTS_LOADED : TTS_NOT_LOADED; 71 72 extensions::ExtensionSystem* system = 73 extensions::ExtensionSystem::Get(profile_); 74 DCHECK(system); 75 extensions::EventRouter* event_router = system->event_router(); 76 DCHECK(event_router); 77 event_router->RegisterObserver(this, tts_engine_events::kOnSpeak); 78 event_router->RegisterObserver(this, tts_engine_events::kOnStop); 79 } 80 LoadTtsExtension()81bool TtsExtensionLoaderChromeOs::LoadTtsExtension() { 82 if (tts_state_ == TTS_LOADED || tts_state_ == TTS_LOADING) 83 return false; 84 85 // Load the component extension into this profile. 86 LOG(INFO) << "Loading TTS component extension."; 87 tts_state_ = TTS_LOADING; 88 ExtensionService* extension_service = profile_->GetExtensionService(); 89 DCHECK(extension_service); 90 extension_service->component_loader()->AddChromeOsSpeechSynthesisExtension(); 91 return true; 92 } 93 Shutdown()94void TtsExtensionLoaderChromeOs::Shutdown() { 95 extensions::ExtensionSystem::Get(profile_)-> 96 event_router()->UnregisterObserver(this); 97 } 98 IsTtsLoadedInThisProfile()99bool TtsExtensionLoaderChromeOs::IsTtsLoadedInThisProfile() { 100 extensions::ExtensionSystem* system = 101 extensions::ExtensionSystem::Get(profile_); 102 DCHECK(system); 103 extensions::EventRouter* event_router = system->event_router(); 104 DCHECK(event_router); 105 if (event_router->ExtensionHasEventListener( 106 extension_misc::kSpeechSynthesisExtensionId, 107 tts_engine_events::kOnSpeak) && 108 event_router->ExtensionHasEventListener( 109 extension_misc::kSpeechSynthesisExtensionId, 110 tts_engine_events::kOnStop)) { 111 return true; 112 } 113 114 return false; 115 } 116 OnListenerAdded(const extensions::EventListenerInfo & details)117void TtsExtensionLoaderChromeOs::OnListenerAdded( 118 const extensions::EventListenerInfo& details) { 119 if (details.extension_id != extension_misc::kSpeechSynthesisExtensionId) 120 return; 121 122 if (!IsTtsLoadedInThisProfile()) 123 return; 124 125 if (tts_state_ == TTS_LOADING) { 126 LOG(INFO) << "TTS component extension loaded, retrying queued utterances."; 127 tts_state_ = TTS_LOADED; 128 TtsController::GetInstance()->RetrySpeakingQueuedUtterances(); 129 } 130 } 131