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/extensions/api/hotword_private/hotword_private_api.h"
7 #include "base/lazy_instance.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/search/hotword_client.h"
11 #include "chrome/browser/search/hotword_service.h"
12 #include "chrome/browser/search/hotword_service_factory.h"
13 #include "chrome/browser/ui/app_list/app_list_service.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/common/pref_names.h"
16 #include "extensions/browser/event_router.h"
18 namespace extensions {
20 namespace hotword_private_constants {
21 const char kHotwordServiceUnavailable[] = "Hotword Service is unavailable.";
22 } // hotword_private_constants
24 namespace OnEnabledChanged =
25 api::hotword_private::OnEnabledChanged;
27 static base::LazyInstance<
28 BrowserContextKeyedAPIFactory<HotwordPrivateEventService> > g_factory =
29 LAZY_INSTANCE_INITIALIZER;
31 HotwordPrivateEventService::HotwordPrivateEventService(
32 content::BrowserContext* context)
33 : profile_(Profile::FromBrowserContext(context)) {
34 pref_change_registrar_.Init(profile_->GetPrefs());
35 pref_change_registrar_.Add(
36 prefs::kHotwordSearchEnabled,
37 base::Bind(&HotwordPrivateEventService::OnEnabledChanged,
38 base::Unretained(this)));
39 pref_change_registrar_.Add(
40 prefs::kHotwordAlwaysOnSearchEnabled,
41 base::Bind(&HotwordPrivateEventService::OnEnabledChanged,
42 base::Unretained(this)));
45 HotwordPrivateEventService::~HotwordPrivateEventService() {
48 void HotwordPrivateEventService::Shutdown() {
52 BrowserContextKeyedAPIFactory<HotwordPrivateEventService>*
53 HotwordPrivateEventService::GetFactoryInstance() {
54 return g_factory.Pointer();
58 const char* HotwordPrivateEventService::service_name() {
59 return "HotwordPrivateEventService";
62 void HotwordPrivateEventService::OnEnabledChanged(
63 const std::string& pref_name) {
64 DCHECK(pref_name == std::string(prefs::kHotwordSearchEnabled) ||
65 pref_name == std::string(prefs::kHotwordAlwaysOnSearchEnabled) ||
66 pref_name == std::string(
67 hotword_internal::kHotwordTrainingEnabled));
68 SignalEvent(OnEnabledChanged::kEventName);
71 void HotwordPrivateEventService::OnHotwordSessionRequested() {
72 SignalEvent(api::hotword_private::OnHotwordSessionRequested::kEventName);
75 void HotwordPrivateEventService::OnHotwordSessionStopped() {
76 SignalEvent(api::hotword_private::OnHotwordSessionStopped::kEventName);
79 void HotwordPrivateEventService::OnFinalizeSpeakerModel() {
80 SignalEvent(api::hotword_private::OnFinalizeSpeakerModel::kEventName);
83 void HotwordPrivateEventService::OnHotwordTriggered() {
84 SignalEvent(api::hotword_private::OnHotwordTriggered::kEventName);
87 void HotwordPrivateEventService::SignalEvent(const std::string& event_name) {
88 EventRouter* router = EventRouter::Get(profile_);
89 if (!router || !router->HasEventListener(event_name))
91 scoped_ptr<base::ListValue> args(new base::ListValue());
92 scoped_ptr<Event> event(new Event(event_name, args.Pass()));
93 router->BroadcastEvent(event.Pass());
96 bool HotwordPrivateSetEnabledFunction::RunSync() {
97 scoped_ptr<api::hotword_private::SetEnabled::Params> params(
98 api::hotword_private::SetEnabled::Params::Create(*args_));
99 EXTENSION_FUNCTION_VALIDATE(params.get());
101 PrefService* prefs = GetProfile()->GetPrefs();
102 prefs->SetBoolean(prefs::kHotwordSearchEnabled, params->state);
106 bool HotwordPrivateSetAudioLoggingEnabledFunction::RunSync() {
107 scoped_ptr<api::hotword_private::SetAudioLoggingEnabled::Params> params(
108 api::hotword_private::SetAudioLoggingEnabled::Params::Create(*args_));
109 EXTENSION_FUNCTION_VALIDATE(params.get());
111 // TODO(kcarattini): Sync the chrome pref with the account-level
112 // Audio History setting.
113 PrefService* prefs = GetProfile()->GetPrefs();
114 prefs->SetBoolean(prefs::kHotwordAudioLoggingEnabled, params->state);
118 bool HotwordPrivateSetHotwordAlwaysOnSearchEnabledFunction::RunSync() {
119 scoped_ptr<api::hotword_private::SetHotwordAlwaysOnSearchEnabled::Params>
120 params(api::hotword_private::SetHotwordAlwaysOnSearchEnabled::Params::
122 EXTENSION_FUNCTION_VALIDATE(params.get());
124 PrefService* prefs = GetProfile()->GetPrefs();
125 prefs->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, params->state);
129 bool HotwordPrivateGetStatusFunction::RunSync() {
130 api::hotword_private::StatusDetails result;
132 HotwordService* hotword_service =
133 HotwordServiceFactory::GetForProfile(GetProfile());
134 if (!hotword_service) {
135 result.available = false;
137 result.available = hotword_service->IsServiceAvailable();
138 result.audio_logging_enabled = hotword_service->IsOptedIntoAudioLogging();
139 result.training_enabled = hotword_service->IsTraining();
142 PrefService* prefs = GetProfile()->GetPrefs();
143 result.enabled_set = prefs->HasPrefPath(prefs::kHotwordSearchEnabled);
144 result.enabled = prefs->GetBoolean(prefs::kHotwordSearchEnabled);
145 result.always_on_enabled =
146 prefs->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled);
147 result.audio_logging_enabled = false;
148 result.experimental_hotword_enabled =
149 HotwordService::IsExperimentalHotwordingEnabled();
151 SetResult(result.ToValue().release());
155 bool HotwordPrivateSetHotwordSessionStateFunction::RunSync() {
156 scoped_ptr<api::hotword_private::SetHotwordSessionState::Params> params(
157 api::hotword_private::SetHotwordSessionState::Params::Create(*args_));
158 EXTENSION_FUNCTION_VALIDATE(params.get());
160 HotwordService* hotword_service =
161 HotwordServiceFactory::GetForProfile(GetProfile());
162 if (hotword_service &&
163 hotword_service->client() &&
164 !hotword_service->IsTraining())
165 hotword_service->client()->OnHotwordStateChanged(params->started);
169 bool HotwordPrivateNotifyHotwordRecognitionFunction::RunSync() {
170 HotwordService* hotword_service =
171 HotwordServiceFactory::GetForProfile(GetProfile());
172 if (hotword_service) {
173 if (hotword_service->IsTraining()) {
174 hotword_service->NotifyHotwordTriggered();
175 } else if (hotword_service->client()) {
176 hotword_service->client()->OnHotwordRecognized();
177 } else if (HotwordService::IsExperimentalHotwordingEnabled() &&
178 hotword_service->IsAlwaysOnEnabled()) {
179 Browser* browser = GetCurrentBrowser();
180 // If a Browser does not exist, fall back to the universally available,
181 // but not recommended, way.
182 AppListService* app_list_service = AppListService::Get(
183 browser ? browser->host_desktop_type() : chrome::GetActiveDesktop());
184 CHECK(app_list_service);
185 app_list_service->ShowForVoiceSearch(GetProfile());
191 bool HotwordPrivateGetLaunchStateFunction::RunSync() {
192 HotwordService* hotword_service =
193 HotwordServiceFactory::GetForProfile(GetProfile());
194 if (!hotword_service) {
195 error_ = hotword_private_constants::kHotwordServiceUnavailable;
199 api::hotword_private::LaunchState result;
201 hotword_service->GetHotwordAudioVerificationLaunchMode();
202 SetResult(result.ToValue().release());
206 bool HotwordPrivateStartTrainingFunction::RunSync() {
207 HotwordService* hotword_service =
208 HotwordServiceFactory::GetForProfile(GetProfile());
209 if (!hotword_service) {
210 error_ = hotword_private_constants::kHotwordServiceUnavailable;
214 hotword_service->StartTraining();
218 bool HotwordPrivateFinalizeSpeakerModelFunction::RunSync() {
219 HotwordService* hotword_service =
220 HotwordServiceFactory::GetForProfile(GetProfile());
221 if (!hotword_service) {
222 error_ = hotword_private_constants::kHotwordServiceUnavailable;
226 hotword_service->FinalizeSpeakerModel();
230 bool HotwordPrivateStopTrainingFunction::RunSync() {
231 HotwordService* hotword_service =
232 HotwordServiceFactory::GetForProfile(GetProfile());
233 if (!hotword_service) {
234 error_ = hotword_private_constants::kHotwordServiceUnavailable;
238 hotword_service->StopTraining();
242 } // namespace extensions