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