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.
4
5#include "chrome/browser/extensions/api/hotword_private/hotword_private_api.h"
6
7#include "base/command_line.h"
8#include "base/lazy_instance.h"
9#include "base/prefs/pref_service.h"
10#include "chrome/browser/profiles/profile.h"
11#include "chrome/browser/search/hotword_client.h"
12#include "chrome/browser/search/hotword_service.h"
13#include "chrome/browser/search/hotword_service_factory.h"
14#include "chrome/common/chrome_switches.h"
15#include "chrome/common/pref_names.h"
16#include "extensions/browser/event_router.h"
17
18namespace extensions {
19
20namespace hotword_private_constants {
21const char kHotwordServiceUnavailable[] = "Hotword Service is unavailable.";
22}  // hotword_private_constants
23
24namespace OnEnabledChanged =
25    api::hotword_private::OnEnabledChanged;
26
27static base::LazyInstance<
28    BrowserContextKeyedAPIFactory<HotwordPrivateEventService> > g_factory =
29    LAZY_INSTANCE_INITIALIZER;
30
31HotwordPrivateEventService::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)));
43}
44
45HotwordPrivateEventService::~HotwordPrivateEventService() {
46}
47
48void HotwordPrivateEventService::Shutdown() {
49}
50
51// static
52BrowserContextKeyedAPIFactory<HotwordPrivateEventService>*
53HotwordPrivateEventService::GetFactoryInstance() {
54  return g_factory.Pointer();
55}
56
57// static
58const char* HotwordPrivateEventService::service_name() {
59  return "HotwordPrivateEventService";
60}
61
62void HotwordPrivateEventService::OnEnabledChanged(
63    const std::string& pref_name) {
64  DCHECK(pref_name == std::string(prefs::kHotwordSearchEnabled) ||
65         pref_name == std::string(prefs::kHotwordAlwaysOnSearchEnabled));
66  SignalEvent(OnEnabledChanged::kEventName);
67}
68
69void HotwordPrivateEventService::OnHotwordSessionRequested() {
70  SignalEvent(api::hotword_private::OnHotwordSessionRequested::kEventName);
71}
72
73void HotwordPrivateEventService::OnHotwordSessionStopped() {
74  SignalEvent(api::hotword_private::OnHotwordSessionStopped::kEventName);
75}
76
77void HotwordPrivateEventService::SignalEvent(const std::string& event_name) {
78  EventRouter* router = EventRouter::Get(profile_);
79  if (!router || !router->HasEventListener(event_name))
80    return;
81  scoped_ptr<base::ListValue> args(new base::ListValue());
82  scoped_ptr<Event> event(new Event(event_name, args.Pass()));
83  router->BroadcastEvent(event.Pass());
84}
85
86bool HotwordPrivateSetEnabledFunction::RunSync() {
87  scoped_ptr<api::hotword_private::SetEnabled::Params> params(
88      api::hotword_private::SetEnabled::Params::Create(*args_));
89  EXTENSION_FUNCTION_VALIDATE(params.get());
90
91  PrefService* prefs = GetProfile()->GetPrefs();
92  prefs->SetBoolean(prefs::kHotwordSearchEnabled, params->state);
93  return true;
94}
95
96bool HotwordPrivateSetAudioLoggingEnabledFunction::RunSync() {
97  scoped_ptr<api::hotword_private::SetAudioLoggingEnabled::Params> params(
98      api::hotword_private::SetAudioLoggingEnabled::Params::Create(*args_));
99  EXTENSION_FUNCTION_VALIDATE(params.get());
100
101  // TODO(kcarattini): Sync the chrome pref with the account-level
102  // Audio History setting.
103  PrefService* prefs = GetProfile()->GetPrefs();
104  prefs->SetBoolean(prefs::kHotwordAudioLoggingEnabled, params->state);
105  return true;
106}
107
108bool HotwordPrivateSetHotwordAlwaysOnSearchEnabledFunction::RunSync() {
109  scoped_ptr<api::hotword_private::SetHotwordAlwaysOnSearchEnabled::Params>
110      params(api::hotword_private::SetHotwordAlwaysOnSearchEnabled::Params::
111      Create(*args_));
112  EXTENSION_FUNCTION_VALIDATE(params.get());
113
114  PrefService* prefs = GetProfile()->GetPrefs();
115  prefs->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, params->state);
116  return true;
117}
118
119bool HotwordPrivateGetStatusFunction::RunSync() {
120  api::hotword_private::StatusDetails result;
121
122  HotwordService* hotword_service =
123      HotwordServiceFactory::GetForProfile(GetProfile());
124  if (!hotword_service)
125    result.available = false;
126  else
127    result.available = hotword_service->IsServiceAvailable();
128
129  PrefService* prefs = GetProfile()->GetPrefs();
130  result.enabled_set = prefs->HasPrefPath(prefs::kHotwordSearchEnabled);
131  result.enabled = prefs->GetBoolean(prefs::kHotwordSearchEnabled);
132  result.always_on_enabled =
133      prefs->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled);
134  result.audio_logging_enabled = false;
135  CommandLine* command_line = CommandLine::ForCurrentProcess();
136  result.experimental_hotword_enabled = command_line->HasSwitch(
137      switches::kEnableExperimentalHotwording);
138  if (hotword_service)
139    result.audio_logging_enabled = hotword_service->IsOptedIntoAudioLogging();
140
141  SetResult(result.ToValue().release());
142  return true;
143}
144
145bool HotwordPrivateSetHotwordSessionStateFunction::RunSync() {
146  scoped_ptr<api::hotword_private::SetHotwordSessionState::Params> params(
147      api::hotword_private::SetHotwordSessionState::Params::Create(*args_));
148  EXTENSION_FUNCTION_VALIDATE(params.get());
149
150  HotwordService* hotword_service =
151      HotwordServiceFactory::GetForProfile(GetProfile());
152  if (hotword_service && hotword_service->client())
153    hotword_service->client()->OnHotwordStateChanged(params->started);
154  return true;
155}
156
157bool HotwordPrivateNotifyHotwordRecognitionFunction::RunSync() {
158  HotwordService* hotword_service =
159      HotwordServiceFactory::GetForProfile(GetProfile());
160  if (hotword_service && hotword_service->client())
161    hotword_service->client()->OnHotwordRecognized();
162  return true;
163}
164
165bool HotwordPrivateGetLaunchStateFunction::RunSync() {
166  api::hotword_private::LaunchState result;
167
168  HotwordService* hotword_service =
169      HotwordServiceFactory::GetForProfile(GetProfile());
170  if (!hotword_service) {
171    error_ = hotword_private_constants::kHotwordServiceUnavailable;
172    return false;
173  } else {
174    result.launch_mode =
175        hotword_service->GetHotwordAudioVerificationLaunchMode();
176  }
177
178  SetResult(result.ToValue().release());
179  return true;
180}
181
182}  // namespace extensions
183