Chromium Code Reviews| Index: chrome/browser/speech/tts_engine_extension_observer.cc |
| diff --git a/chrome/browser/speech/tts_engine_extension_observer.cc b/chrome/browser/speech/tts_engine_extension_observer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5dfdd52a417d6cda0c42c17479a44239d111155d |
| --- /dev/null |
| +++ b/chrome/browser/speech/tts_engine_extension_observer.cc |
| @@ -0,0 +1,138 @@ |
| +// 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_engine_extension_observer.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/memory/singleton.h" |
| +#include "chrome/browser/extensions/extension_service.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 "components/keyed_service/content/browser_context_dependency_manager.h" |
| +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" |
| +#include "components/keyed_service/core/keyed_service.h" |
| +#include "extensions/browser/event_router.h" |
| +#include "extensions/browser/extension_system.h" |
| +#include "grit/browser_resources.h" |
| + |
| +// Factory to load one instance of TtsExtensionLoaderChromeOs per profile. |
| +class TtsEngineExtensionObserverFactory |
| + : public BrowserContextKeyedServiceFactory { |
| + public: |
| + static TtsEngineExtensionObserver* GetForProfile(Profile* profile) { |
| + return static_cast<TtsEngineExtensionObserver*>( |
| + GetInstance()->GetServiceForBrowserContext(profile, true)); |
| + } |
| + |
| + static TtsEngineExtensionObserverFactory* GetInstance() { |
| + return Singleton<TtsEngineExtensionObserverFactory>::get(); |
| + } |
| + |
| + private: |
| + friend struct DefaultSingletonTraits<TtsEngineExtensionObserverFactory>; |
| + |
| + TtsEngineExtensionObserverFactory() |
| + : BrowserContextKeyedServiceFactory( |
| + "TtsEngineExtensionObserver", |
| + BrowserContextDependencyManager::GetInstance()) { |
| + DependsOn(extensions::ExtensionSystemFactory::GetInstance()); |
| + } |
| + |
| + virtual ~TtsEngineExtensionObserverFactory() {} |
| + |
| + 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 KeyedService* BuildServiceInstanceFor( |
| + content::BrowserContext* profile) const OVERRIDE { |
| + return new TtsEngineExtensionObserver(static_cast<Profile*>(profile)); |
| + } |
| +}; |
| + |
| +TtsEngineExtensionObserver* TtsEngineExtensionObserver::GetInstance( |
| + Profile* profile) { |
| + return TtsEngineExtensionObserverFactory::GetInstance()->GetForProfile( |
| + profile); |
| +} |
| + |
| +TtsEngineExtensionObserver::TtsEngineExtensionObserver(Profile* profile) |
| + : extension_registry_observer_(this), |
| + profile_(profile), |
| + saw_tts_engine_added_(false) { |
| + extension_registry_observer_.Add( |
| + extensions::ExtensionRegistry::Get(profile_)); |
| + |
| + 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 TtsEngineExtensionObserver::SawExtensionLoad( |
| + const std::string& extension_id, |
| + bool update) { |
| + bool previously_loaded = |
| + engine_extension_ids_.find(extension_id) != engine_extension_ids_.end(); |
| + |
| + if (update) |
| + engine_extension_ids_.insert(extension_id); |
| + |
| + return previously_loaded; |
| +} |
| + |
| +void TtsEngineExtensionObserver::Shutdown() { |
| + extensions::EventRouter::Get(profile_)->UnregisterObserver(this); |
| +} |
| + |
| +bool TtsEngineExtensionObserver::IsLoadedTtsEngine( |
| + const std::string& extension_id) { |
| + extensions::ExtensionSystem* system = |
| + extensions::ExtensionSystem::Get(profile_); |
| + DCHECK(system); |
| + extensions::EventRouter* event_router = system->event_router(); |
| + DCHECK(event_router); |
| + if (event_router->ExtensionHasEventListener(extension_id, |
| + tts_engine_events::kOnSpeak) && |
| + event_router->ExtensionHasEventListener(extension_id, |
| + tts_engine_events::kOnStop)) { |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| +void TtsEngineExtensionObserver::OnListenerAdded( |
| + const extensions::EventListenerInfo& details) { |
| + if (!IsLoadedTtsEngine(details.extension_id)) |
| + return; |
| + |
| + if (!saw_tts_engine_added_) { |
| + saw_tts_engine_added_ = true; |
| + TtsController::GetInstance()->RetrySpeakingQueuedUtterances(); |
| + } |
| + |
| + TtsController::GetInstance()->VoicesChanged(); |
|
dmazzoni
2014/07/07 15:37:26
Should this be before RetrySpeaking...?
David Tseng
2014/07/08 23:43:31
I didn't see a need since both calls are async. A
|
| + engine_extension_ids_.insert(details.extension_id); |
| +} |
| + |
| +void TtsEngineExtensionObserver::OnExtensionUnloaded( |
| + content::BrowserContext* browser_context, |
| + const extensions::Extension* extension, |
| + extensions::UnloadedExtensionInfo::Reason reason) { |
| + if (engine_extension_ids_.find(extension->id()) != |
| + engine_extension_ids_.end()) { |
| + engine_extension_ids_.erase(extension->id()); |
| + TtsController::GetInstance()->VoicesChanged(); |
| + } |
| +} |