• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)62 TtsExtensionLoaderChromeOs::GetInstance(Profile* profile) {
63   return TtsExtensionLoaderChromeOsFactory::GetInstance()
64       ->GetForProfile(profile);
65 }
66 
TtsExtensionLoaderChromeOs(Profile * profile)67 TtsExtensionLoaderChromeOs::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()81 bool 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()94 void TtsExtensionLoaderChromeOs::Shutdown() {
95   extensions::ExtensionSystem::Get(profile_)->
96       event_router()->UnregisterObserver(this);
97 }
98 
IsTtsLoadedInThisProfile()99 bool 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)117 void 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