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 "base/command_line.h"
6#include "base/prefs/pref_service.h"
7#include "chrome/browser/extensions/api/hotword_private/hotword_private_api.h"
8#include "chrome/browser/extensions/extension_apitest.h"
9#include "chrome/browser/extensions/extension_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/common/switches.h"
17#include "extensions/test/extension_test_message_listener.h"
18
19namespace {
20
21const char kHotwordTestExtensionId[] = "cpfhkdbjfdgdebcjlifoldbijinjfifp";
22
23class MockHotwordService : public HotwordService {
24 public:
25  explicit MockHotwordService(Profile* profile)
26      : HotwordService(profile), service_available_(true) {};
27  virtual ~MockHotwordService() {}
28
29  virtual bool IsServiceAvailable() OVERRIDE {
30    return service_available_;
31  }
32
33  void setServiceAvailable(bool available) {
34    service_available_ = available;
35  }
36
37  static KeyedService* Build(content::BrowserContext* profile) {
38    return new MockHotwordService(static_cast<Profile*>(profile));
39  }
40
41  virtual LaunchMode GetHotwordAudioVerificationLaunchMode() OVERRIDE {
42    return launch_mode_;
43  }
44
45  void SetHotwordAudioVerificationLaunchMode(const LaunchMode& launch_mode) {
46    launch_mode_ = launch_mode;
47  }
48
49 private:
50  bool service_available_;
51  LaunchMode launch_mode_;
52
53  DISALLOW_COPY_AND_ASSIGN(MockHotwordService);
54};
55
56class MockHotwordClient : public HotwordClient {
57 public:
58  MockHotwordClient()
59      : last_enabled_(false),
60        state_changed_count_(0),
61        recognized_count_(0) {
62  }
63
64  virtual ~MockHotwordClient() {}
65
66  virtual void OnHotwordStateChanged(bool enabled) OVERRIDE {
67    last_enabled_ = enabled;
68    state_changed_count_++;
69  }
70
71  virtual void OnHotwordRecognized() OVERRIDE {
72    recognized_count_++;
73  }
74
75  bool last_enabled() const { return last_enabled_; }
76  int state_changed_count() const { return state_changed_count_; }
77  int recognized_count() const { return recognized_count_; }
78
79 private:
80  bool last_enabled_;
81  int state_changed_count_;
82  int recognized_count_;
83
84  DISALLOW_COPY_AND_ASSIGN(MockHotwordClient);
85};
86
87class HotwordPrivateApiTest : public ExtensionApiTest {
88 public:
89  HotwordPrivateApiTest() {}
90  virtual ~HotwordPrivateApiTest() {}
91
92  virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
93    ExtensionApiTest::SetUpCommandLine(command_line);
94
95    // Whitelist the test extensions (which all share a common ID) to use
96    // private APIs.
97    command_line->AppendSwitchASCII(
98        extensions::switches::kWhitelistedExtensionID, kHotwordTestExtensionId);
99  }
100
101  virtual void SetUpOnMainThread() OVERRIDE {
102    ExtensionApiTest::SetUpOnMainThread();
103
104    test_data_dir_ = test_data_dir_.AppendASCII("hotword_private");
105
106    service_ = static_cast<MockHotwordService*>(
107        HotwordServiceFactory::GetInstance()->SetTestingFactoryAndUse(
108            profile(), MockHotwordService::Build));
109  }
110
111  MockHotwordService* service() {
112    return service_;
113  }
114
115 private:
116  MockHotwordService* service_;
117
118  DISALLOW_COPY_AND_ASSIGN(HotwordPrivateApiTest);
119};
120
121}  // anonymous namespace
122
123IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, SetEnabled) {
124  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled));
125
126  ExtensionTestMessageListener listenerTrue("ready", false);
127  ASSERT_TRUE(RunComponentExtensionTest("setEnabledTrue")) << message_;
128  EXPECT_TRUE(listenerTrue.WaitUntilSatisfied());
129  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled));
130
131  ExtensionTestMessageListener listenerFalse("ready", false);
132  ASSERT_TRUE(RunComponentExtensionTest("setEnabledFalse")) << message_;
133  EXPECT_TRUE(listenerFalse.WaitUntilSatisfied());
134  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled));
135}
136
137IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, SetAudioLoggingEnabled) {
138  EXPECT_FALSE(service()->IsOptedIntoAudioLogging());
139  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
140      prefs::kHotwordAudioLoggingEnabled));
141
142  ExtensionTestMessageListener listenerTrue("ready", false);
143  ASSERT_TRUE(RunComponentExtensionTest("setAudioLoggingEnableTrue"))
144      << message_;
145  EXPECT_TRUE(listenerTrue.WaitUntilSatisfied());
146  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
147      prefs::kHotwordAudioLoggingEnabled));
148  EXPECT_TRUE(service()->IsOptedIntoAudioLogging());
149
150  ExtensionTestMessageListener listenerFalse("ready", false);
151  ASSERT_TRUE(RunComponentExtensionTest("setAudioLoggingEnableFalse"))
152      << message_;
153  EXPECT_TRUE(listenerFalse.WaitUntilSatisfied());
154  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
155      prefs::kHotwordAudioLoggingEnabled));
156  EXPECT_FALSE(service()->IsOptedIntoAudioLogging());
157}
158
159IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, SetHotwordAlwaysOnSearchEnabled) {
160  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
161      prefs::kHotwordAlwaysOnSearchEnabled));
162
163  ExtensionTestMessageListener listener("ready", false);
164  ASSERT_TRUE(RunComponentExtensionTest("setHotwordAlwaysOnSearchEnableTrue"))
165      << message_;
166  EXPECT_TRUE(listener.WaitUntilSatisfied());
167  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
168      prefs::kHotwordAlwaysOnSearchEnabled));
169
170  listener.Reset();
171  ASSERT_TRUE(RunComponentExtensionTest("setHotwordAlwaysOnSearchEnableFalse"))
172      << message_;
173  EXPECT_TRUE(listener.WaitUntilSatisfied());
174  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
175      prefs::kHotwordAlwaysOnSearchEnabled));
176}
177
178IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, GetStatus) {
179  ASSERT_TRUE(RunComponentExtensionTest("getEnabled")) << message_;
180}
181
182IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, IsAvailableTrue) {
183  service()->setServiceAvailable(true);
184  ExtensionTestMessageListener listener("available: true", false);
185  ASSERT_TRUE(RunComponentExtensionTest("isAvailable")) << message_;
186  EXPECT_TRUE(listener.WaitUntilSatisfied());
187}
188
189IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, IsAvailableFalse) {
190  service()->setServiceAvailable(false);
191  ExtensionTestMessageListener listener("available: false", false);
192  ASSERT_TRUE(RunComponentExtensionTest("isAvailable")) << message_;
193  EXPECT_TRUE(listener.WaitUntilSatisfied());
194}
195
196IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, AlwaysOnEnabled) {
197  {
198    ExtensionTestMessageListener listener("alwaysOnEnabled: false",
199                                          false);
200    ASSERT_TRUE(RunComponentExtensionTest("alwaysOnEnabled"))
201        << message_;
202    EXPECT_TRUE(listener.WaitUntilSatisfied());
203  }
204
205  profile()->GetPrefs()->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, true);
206  {
207    ExtensionTestMessageListener listener("alwaysOnEnabled: true",
208                                          false);
209    ASSERT_TRUE(RunComponentExtensionTest("alwaysOnEnabled"))
210        << message_;
211    EXPECT_TRUE(listener.WaitUntilSatisfied());
212  }
213}
214
215IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, ExperimentalHotwordEnabled) {
216  // Disabled by default.
217  ExtensionTestMessageListener listener("experimentalHotwordEnabled: false",
218                                        false);
219  ASSERT_TRUE(RunComponentExtensionTest("experimentalHotwordEnabled"))
220      << message_;
221  EXPECT_TRUE(listener.WaitUntilSatisfied());
222}
223
224IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest,
225                       ExperimentalHotwordEnabled_Enabled) {
226  base::CommandLine::ForCurrentProcess()->AppendSwitch(
227      switches::kEnableExperimentalHotwording);
228  ExtensionTestMessageListener listener("experimentalHotwordEnabled: true",
229                                        false);
230  ASSERT_TRUE(RunComponentExtensionTest("experimentalHotwordEnabled"))
231      << message_;
232  EXPECT_TRUE(listener.WaitUntilSatisfied());
233}
234
235IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, OnEnabledChanged) {
236  // Trigger the pref registrar.
237  extensions::HotwordPrivateEventService::GetFactoryInstance();
238  ExtensionTestMessageListener listener("ready", false);
239  ASSERT_TRUE(
240      LoadExtensionAsComponent(test_data_dir_.AppendASCII("onEnabledChanged")));
241  EXPECT_TRUE(listener.WaitUntilSatisfied());
242
243  ExtensionTestMessageListener listenerNotification("notification", false);
244  profile()->GetPrefs()->SetBoolean(prefs::kHotwordSearchEnabled, true);
245  EXPECT_TRUE(listenerNotification.WaitUntilSatisfied());
246
247  listenerNotification.Reset();
248  profile()->GetPrefs()->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled,
249                                    true);
250  EXPECT_TRUE(listenerNotification.WaitUntilSatisfied());
251}
252
253IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, HotwordSession) {
254  extensions::HotwordPrivateEventService::GetFactoryInstance();
255  ExtensionTestMessageListener listener("ready", false);
256  LoadExtensionAsComponent(
257      test_data_dir_.AppendASCII("hotwordSession"));
258  EXPECT_TRUE(listener.WaitUntilSatisfied());
259
260  ExtensionTestMessageListener listenerStopReady("stopReady", false);
261  ExtensionTestMessageListener listenerStopped("stopped", false);
262  MockHotwordClient client;
263  service()->RequestHotwordSession(&client);
264  EXPECT_TRUE(listenerStopReady.WaitUntilSatisfied());
265  service()->StopHotwordSession(&client);
266  EXPECT_TRUE(listenerStopped.WaitUntilSatisfied());
267
268  EXPECT_TRUE(client.last_enabled());
269  EXPECT_EQ(1, client.state_changed_count());
270  EXPECT_EQ(1, client.recognized_count());
271}
272
273IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, GetLaunchStateHotwordOnly) {
274  service()->SetHotwordAudioVerificationLaunchMode(
275      HotwordService::HOTWORD_ONLY);
276  ExtensionTestMessageListener listener("launchMode: 1", false);
277  ASSERT_TRUE(RunComponentExtensionTest("getLaunchState")) << message_;
278  EXPECT_TRUE(listener.WaitUntilSatisfied());
279}
280
281IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest,
282    GetLaunchStateHotwordAudioHistory) {
283  service()->SetHotwordAudioVerificationLaunchMode(
284      HotwordService::HOTWORD_AND_AUDIO_HISTORY);
285  ExtensionTestMessageListener listener("launchMode: 2", false);
286  ASSERT_TRUE(RunComponentExtensionTest("getLaunchState")) << message_;
287  EXPECT_TRUE(listener.WaitUntilSatisfied());
288}
289