Home | History | Annotate | Download | only in speech
      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:
     28   static TtsExtensionLoaderChromeOs* GetForProfile(Profile* profile) {
     29     return static_cast<TtsExtensionLoaderChromeOs*>(
     30         GetInstance()->GetServiceForBrowserContext(profile, true));
     31   }
     32 
     33   static TtsExtensionLoaderChromeOsFactory* GetInstance() {
     34     return Singleton<TtsExtensionLoaderChromeOsFactory>::get();
     35   }
     36 
     37  private:
     38   friend struct DefaultSingletonTraits<TtsExtensionLoaderChromeOsFactory>;
     39 
     40   TtsExtensionLoaderChromeOsFactory() : BrowserContextKeyedServiceFactory(
     41       "TtsExtensionLoaderChromeOs",
     42       BrowserContextDependencyManager::GetInstance()) {
     43     DependsOn(extensions::ExtensionSystemFactory::GetInstance());
     44   }
     45 
     46   virtual ~TtsExtensionLoaderChromeOsFactory() {}
     47 
     48   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 
     55   virtual BrowserContextKeyedService* BuildServiceInstanceFor(
     56       content::BrowserContext* profile) const OVERRIDE {
     57     return new TtsExtensionLoaderChromeOs(static_cast<Profile*>(profile));
     58   }
     59 };
     60 
     61 TtsExtensionLoaderChromeOs*
     62 TtsExtensionLoaderChromeOs::GetInstance(Profile* profile) {
     63   return TtsExtensionLoaderChromeOsFactory::GetInstance()
     64       ->GetForProfile(profile);
     65 }
     66 
     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 
     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 
     94 void TtsExtensionLoaderChromeOs::Shutdown() {
     95   extensions::ExtensionSystem::Get(profile_)->
     96       event_router()->UnregisterObserver(this);
     97 }
     98 
     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 
    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