1 // Copyright 2014 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.
5 #include "chrome/browser/speech/extension_api/tts_engine_extension_observer.h"
7 #include "base/logging.h"
8 #include "base/memory/singleton.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system_factory.h"
11 #include "chrome/browser/profiles/incognito_helpers.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
14 #include "chrome/browser/speech/tts_controller.h"
15 #include "components/keyed_service/content/browser_context_dependency_manager.h"
16 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
17 #include "components/keyed_service/core/keyed_service.h"
18 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_system.h"
21 // Factory to load one instance of TtsExtensionLoaderChromeOs per profile.
22 class TtsEngineExtensionObserverFactory
23 : public BrowserContextKeyedServiceFactory {
25 static TtsEngineExtensionObserver* GetForProfile(Profile* profile) {
26 return static_cast<TtsEngineExtensionObserver*>(
27 GetInstance()->GetServiceForBrowserContext(profile, true));
30 static TtsEngineExtensionObserverFactory* GetInstance() {
31 return Singleton<TtsEngineExtensionObserverFactory>::get();
35 friend struct DefaultSingletonTraits<TtsEngineExtensionObserverFactory>;
37 TtsEngineExtensionObserverFactory()
38 : BrowserContextKeyedServiceFactory(
39 "TtsEngineExtensionObserver",
40 BrowserContextDependencyManager::GetInstance()) {
41 DependsOn(extensions::ExtensionSystemFactory::GetInstance());
44 ~TtsEngineExtensionObserverFactory() override {}
46 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);
53 KeyedService* BuildServiceInstanceFor(
54 content::BrowserContext* profile) const override {
55 return new TtsEngineExtensionObserver(static_cast<Profile*>(profile));
59 TtsEngineExtensionObserver* TtsEngineExtensionObserver::GetInstance(
61 return TtsEngineExtensionObserverFactory::GetInstance()->GetForProfile(
65 TtsEngineExtensionObserver::TtsEngineExtensionObserver(Profile* profile)
66 : extension_registry_observer_(this), profile_(profile) {
67 extension_registry_observer_.Add(
68 extensions::ExtensionRegistry::Get(profile_));
70 extensions::ExtensionSystem* system =
71 extensions::ExtensionSystem::Get(profile_);
73 extensions::EventRouter* event_router = system->event_router();
75 event_router->RegisterObserver(this, tts_engine_events::kOnSpeak);
76 event_router->RegisterObserver(this, tts_engine_events::kOnStop);
79 TtsEngineExtensionObserver::~TtsEngineExtensionObserver() {
82 bool TtsEngineExtensionObserver::SawExtensionLoad(
83 const std::string& extension_id,
85 bool previously_loaded =
86 engine_extension_ids_.find(extension_id) != engine_extension_ids_.end();
89 engine_extension_ids_.insert(extension_id);
91 return previously_loaded;
94 void TtsEngineExtensionObserver::Shutdown() {
95 extensions::EventRouter::Get(profile_)->UnregisterObserver(this);
98 bool TtsEngineExtensionObserver::IsLoadedTtsEngine(
99 const std::string& extension_id) {
100 extensions::ExtensionSystem* system =
101 extensions::ExtensionSystem::Get(profile_);
103 extensions::EventRouter* event_router = system->event_router();
104 DCHECK(event_router);
105 if (event_router->ExtensionHasEventListener(extension_id,
106 tts_engine_events::kOnSpeak) &&
107 event_router->ExtensionHasEventListener(extension_id,
108 tts_engine_events::kOnStop)) {
115 void TtsEngineExtensionObserver::OnListenerAdded(
116 const extensions::EventListenerInfo& details) {
117 if (!IsLoadedTtsEngine(details.extension_id))
120 TtsController::GetInstance()->VoicesChanged();
121 engine_extension_ids_.insert(details.extension_id);
124 void TtsEngineExtensionObserver::OnExtensionUnloaded(
125 content::BrowserContext* browser_context,
126 const extensions::Extension* extension,
127 extensions::UnloadedExtensionInfo::Reason reason) {
128 if (engine_extension_ids_.find(extension->id()) !=
129 engine_extension_ids_.end()) {
130 engine_extension_ids_.erase(extension->id());
131 TtsController::GetInstance()->VoicesChanged();