1 // Copyright 2013 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/chromeos/app_mode/kiosk_app_manager.h"
6
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chromeos/app_mode/fake_cws.h"
17 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
18 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
19 #include "chrome/browser/chromeos/policy/device_local_account.h"
20 #include "chrome/browser/chromeos/settings/cros_settings.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/test/base/in_process_browser_test.h"
25 #include "chromeos/settings/cros_settings_names.h"
26 #include "content/public/test/test_utils.h"
27 #include "extensions/common/extension.h"
28 #include "net/base/host_port_pair.h"
29 #include "net/dns/mock_host_resolver.h"
30 #include "net/test/embedded_test_server/embedded_test_server.h"
31
32 using content::BrowserThread;
33
34 namespace chromeos {
35
36 namespace {
37
38 // An app to test local fs data persistence across app update. V1 app writes
39 // data into local fs. V2 app reads and verifies the data.
40 // Webstore data json is in
41 // chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
42 // detail/bmbpicmpniaclbbpdkfglgipkkebnbjf
43 // The version 1.0.0 installed is in
44 // chrome/test/data/chromeos/app_mode/webstore/downloads/
45 // bmbpicmpniaclbbpdkfglgipkkebnbjf.crx
46 // The version 2.0.0 crx is in
47 // chrome/test/data/chromeos/app_mode/webstore/downloads/
48 // bmbpicmpniaclbbpdkfglgipkkebnbjf_v2_read_and_verify_data.crx
49 const char kTestLocalFsKioskApp[] = "bmbpicmpniaclbbpdkfglgipkkebnbjf";
50 const char kTestLocalFsKioskAppName[] = "Kiosk App With Local Data";
51
52 // Helper KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback
53 // implementation.
ConsumerKioskAutoLaunchStatusCheck(KioskAppManager::ConsumerKioskAutoLaunchStatus * out_status,const base::Closure & runner_quit_task,KioskAppManager::ConsumerKioskAutoLaunchStatus in_status)54 void ConsumerKioskAutoLaunchStatusCheck(
55 KioskAppManager::ConsumerKioskAutoLaunchStatus* out_status,
56 const base::Closure& runner_quit_task,
57 KioskAppManager::ConsumerKioskAutoLaunchStatus in_status) {
58 LOG(INFO) << "ConsumerKioskAutoLaunchStatus = " << in_status;
59 *out_status = in_status;
60 runner_quit_task.Run();
61 }
62
63 // Helper KioskAppManager::EnableKioskModeCallback implementation.
ConsumerKioskModeLockCheck(bool * out_locked,const base::Closure & runner_quit_task,bool in_locked)64 void ConsumerKioskModeLockCheck(
65 bool* out_locked,
66 const base::Closure& runner_quit_task,
67 bool in_locked) {
68 LOG(INFO) << "kiosk locked = " << in_locked;
69 *out_locked = in_locked;
70 runner_quit_task.Run();
71 }
72
73 // Helper EnterpriseInstallAttributes::LockResultCallback implementation.
OnEnterpriseDeviceLock(policy::EnterpriseInstallAttributes::LockResult * out_locked,const base::Closure & runner_quit_task,policy::EnterpriseInstallAttributes::LockResult in_locked)74 void OnEnterpriseDeviceLock(
75 policy::EnterpriseInstallAttributes::LockResult* out_locked,
76 const base::Closure& runner_quit_task,
77 policy::EnterpriseInstallAttributes::LockResult in_locked) {
78 LOG(INFO) << "Enterprise lock = " << in_locked;
79 *out_locked = in_locked;
80 runner_quit_task.Run();
81 }
82
MakeApp(const std::string & name,const std::string & version,const std::string & url,const std::string & id)83 scoped_refptr<extensions::Extension> MakeApp(const std::string& name,
84 const std::string& version,
85 const std::string& url,
86 const std::string& id) {
87 std::string err;
88 base::DictionaryValue value;
89 value.SetString("name", name);
90 value.SetString("version", version);
91 value.SetString("app.launch.web_url", url);
92 scoped_refptr<extensions::Extension> app =
93 extensions::Extension::Create(
94 base::FilePath(),
95 extensions::Manifest::INTERNAL,
96 value,
97 extensions::Extension::WAS_INSTALLED_BY_DEFAULT,
98 id,
99 &err);
100 EXPECT_EQ(err, "");
101 return app;
102 }
103
104 class TestKioskAppManagerObserver : public KioskAppManagerObserver {
105 public:
TestKioskAppManagerObserver(KioskAppManager * manager)106 explicit TestKioskAppManagerObserver(KioskAppManager* manager)
107 : manager_(manager),
108 data_changed_count_(0),
109 load_failure_count_(0) {
110 manager_->AddObserver(this);
111 }
~TestKioskAppManagerObserver()112 virtual ~TestKioskAppManagerObserver() {
113 manager_->RemoveObserver(this);
114 }
115
Reset()116 void Reset() {
117 data_changed_count_ = 0;
118 load_failure_count_ = 0;
119 }
120
data_changed_count() const121 int data_changed_count() const { return data_changed_count_; }
load_failure_count() const122 int load_failure_count() const { return load_failure_count_; }
123
124 private:
125 // KioskAppManagerObserver overrides:
OnKioskAppDataChanged(const std::string & app_id)126 virtual void OnKioskAppDataChanged(const std::string& app_id) OVERRIDE {
127 ++data_changed_count_;
128 }
OnKioskAppDataLoadFailure(const std::string & app_id)129 virtual void OnKioskAppDataLoadFailure(const std::string& app_id) OVERRIDE {
130 ++load_failure_count_;
131 }
132
133 KioskAppManager* manager_;
134 int data_changed_count_;
135 int load_failure_count_;
136
137 DISALLOW_COPY_AND_ASSIGN(TestKioskAppManagerObserver);
138 };
139
140 class AppDataLoadWaiter : public KioskAppManagerObserver {
141 public:
AppDataLoadWaiter(KioskAppManager * manager,int data_loaded_threshold)142 AppDataLoadWaiter(KioskAppManager* manager, int data_loaded_threshold)
143 : runner_(NULL),
144 manager_(manager),
145 loaded_(false),
146 quit_(false),
147 data_change_count_(0),
148 data_loaded_threshold_(data_loaded_threshold) {
149 manager_->AddObserver(this);
150 }
151
~AppDataLoadWaiter()152 virtual ~AppDataLoadWaiter() { manager_->RemoveObserver(this); }
153
Wait()154 void Wait() {
155 if (quit_)
156 return;
157 runner_ = new content::MessageLoopRunner;
158 runner_->Run();
159 }
160
loaded() const161 bool loaded() const { return loaded_; }
162
163 private:
164 // KioskAppManagerObserver overrides:
OnKioskAppDataChanged(const std::string & app_id)165 virtual void OnKioskAppDataChanged(const std::string& app_id) OVERRIDE {
166 ++data_change_count_;
167 if (data_change_count_ < data_loaded_threshold_)
168 return;
169 loaded_ = true;
170 quit_ = true;
171 if (runner_)
172 runner_->Quit();
173 }
174
OnKioskAppDataLoadFailure(const std::string & app_id)175 virtual void OnKioskAppDataLoadFailure(const std::string& app_id) OVERRIDE {
176 loaded_ = false;
177 quit_ = true;
178 if (runner_)
179 runner_->Quit();
180 }
181
182 scoped_refptr<content::MessageLoopRunner> runner_;
183 KioskAppManager* manager_;
184 bool loaded_;
185 bool quit_;
186 int data_change_count_;
187 int data_loaded_threshold_;
188
189 DISALLOW_COPY_AND_ASSIGN(AppDataLoadWaiter);
190 };
191
192 } // namespace
193
194 class KioskAppManagerTest : public InProcessBrowserTest {
195 public:
KioskAppManagerTest()196 KioskAppManagerTest() : fake_cws_(new FakeCWS()) {}
~KioskAppManagerTest()197 virtual ~KioskAppManagerTest() {}
198
199 // InProcessBrowserTest overrides:
SetUp()200 virtual void SetUp() OVERRIDE {
201 base::FilePath test_data_dir;
202 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
203 embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
204 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
205 // Stop IO thread here because no threads are allowed while
206 // spawning sandbox host process. See crbug.com/322732.
207 embedded_test_server()->StopThread();
208
209 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
210
211 InProcessBrowserTest::SetUp();
212 }
213
SetUpCommandLine(CommandLine * command_line)214 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
215 InProcessBrowserTest::SetUpCommandLine(command_line);
216
217 // Initialize fake_cws_ to setup web store gallery.
218 fake_cws_->Init(embedded_test_server());
219 }
220
SetUpOnMainThread()221 virtual void SetUpOnMainThread() OVERRIDE {
222 InProcessBrowserTest::SetUpOnMainThread();
223
224 // Restart the thread as the sandbox host process has already been spawned.
225 embedded_test_server()->RestartThreadAndListen();
226 }
227
SetUpInProcessBrowserTestFixture()228 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
229 InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
230
231 host_resolver()->AddRule("*", "127.0.0.1");
232 }
233
GetAppIds() const234 std::string GetAppIds() const {
235 KioskAppManager::Apps apps;
236 manager()->GetApps(&apps);
237
238 std::string str;
239 for (size_t i = 0; i < apps.size(); ++i) {
240 if (i > 0)
241 str += ',';
242 str += apps[i].app_id;
243 }
244
245 return str;
246 }
247
248 // Locks device for enterprise.
LockDeviceForEnterprise()249 policy::EnterpriseInstallAttributes::LockResult LockDeviceForEnterprise() {
250 scoped_ptr<policy::EnterpriseInstallAttributes::LockResult> lock_result(
251 new policy::EnterpriseInstallAttributes::LockResult(
252 policy::EnterpriseInstallAttributes::LOCK_NOT_READY));
253 scoped_refptr<content::MessageLoopRunner> runner =
254 new content::MessageLoopRunner;
255 policy::BrowserPolicyConnectorChromeOS* connector =
256 g_browser_process->platform_part()->browser_policy_connector_chromeos();
257 connector->GetInstallAttributes()->LockDevice(
258 "user@domain.com",
259 policy::DEVICE_MODE_ENTERPRISE,
260 "device-id",
261 base::Bind(
262 &OnEnterpriseDeviceLock, lock_result.get(), runner->QuitClosure()));
263 runner->Run();
264 return *lock_result.get();
265 }
266
SetExistingApp(const std::string & app_id,const std::string & app_name,const std::string & icon_file_name)267 void SetExistingApp(const std::string& app_id,
268 const std::string& app_name,
269 const std::string& icon_file_name) {
270 base::FilePath test_dir;
271 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
272 base::FilePath data_dir = test_dir.AppendASCII("chromeos/app_mode/");
273
274 // Copy the icon file to temp dir for using because ClearAppData test
275 // deletes it.
276 base::FilePath icon_path = temp_dir_.path().AppendASCII(icon_file_name);
277 base::CopyFile(data_dir.AppendASCII(icon_file_name), icon_path);
278
279 scoped_ptr<base::DictionaryValue> apps_dict(new base::DictionaryValue);
280 apps_dict->SetString(app_id + ".name", app_name);
281 apps_dict->SetString(app_id + ".icon", icon_path.MaybeAsASCII());
282
283 PrefService* local_state = g_browser_process->local_state();
284 DictionaryPrefUpdate dict_update(local_state,
285 KioskAppManager::kKioskDictionaryName);
286 dict_update->Set(KioskAppManager::kKeyApps, apps_dict.release());
287
288 // Make the app appear in device settings.
289 base::ListValue device_local_accounts;
290 scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
291 entry->SetStringWithoutPathExpansion(
292 kAccountsPrefDeviceLocalAccountsKeyId,
293 app_id + "_id");
294 entry->SetIntegerWithoutPathExpansion(
295 kAccountsPrefDeviceLocalAccountsKeyType,
296 policy::DeviceLocalAccount::TYPE_KIOSK_APP);
297 entry->SetStringWithoutPathExpansion(
298 kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
299 app_id);
300 device_local_accounts.Append(entry.release());
301 CrosSettings::Get()->Set(kAccountsPrefDeviceLocalAccounts,
302 device_local_accounts);
303 }
304
GetCachedCrx(const std::string & app_id,base::FilePath * file_path,std::string * version)305 bool GetCachedCrx(const std::string& app_id,
306 base::FilePath* file_path,
307 std::string* version) {
308 return manager()->GetCachedCrx(app_id, file_path, version);
309 }
310
UpdateAppData()311 void UpdateAppData() { manager()->UpdateAppData(); }
312
RunAddNewAppTest(const std::string & id,const std::string & version,const std::string & app_name)313 void RunAddNewAppTest(const std::string& id,
314 const std::string& version,
315 const std::string& app_name) {
316 std::string crx_file_name = id + ".crx";
317 fake_cws_->SetUpdateCrx(id, crx_file_name, version);
318
319 AppDataLoadWaiter waiter(manager(), 3);
320 manager()->AddApp(id);
321 waiter.Wait();
322 EXPECT_TRUE(waiter.loaded());
323
324 // Check CRX file is cached.
325 base::FilePath crx_path;
326 std::string crx_version;
327 EXPECT_TRUE(GetCachedCrx(id, &crx_path, &crx_version));
328 EXPECT_TRUE(base::PathExists(crx_path));
329 EXPECT_EQ(version, crx_version);
330 // Verify the original crx file is identical to the cached file.
331 base::FilePath test_data_dir;
332 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
333 std::string src_file_path_str =
334 std::string("chromeos/app_mode/webstore/downloads/") + crx_file_name;
335 base::FilePath src_file_path = test_data_dir.Append(src_file_path_str);
336 EXPECT_TRUE(base::PathExists(src_file_path));
337 EXPECT_TRUE(base::ContentsEqual(src_file_path, crx_path));
338
339 // Check manifest data is cached correctly.
340 KioskAppManager::Apps apps;
341 manager()->GetApps(&apps);
342 ASSERT_EQ(1u, apps.size());
343 EXPECT_EQ(id, apps[0].app_id);
344 EXPECT_EQ(app_name, apps[0].name);
345 EXPECT_EQ(gfx::Size(16, 16), apps[0].icon.size());
346
347 // Check data is cached in local state.
348 PrefService* local_state = g_browser_process->local_state();
349 const base::DictionaryValue* dict =
350 local_state->GetDictionary(KioskAppManager::kKioskDictionaryName);
351
352 std::string name;
353 std::string name_key = "apps." + id + ".name";
354 EXPECT_TRUE(dict->GetString(name_key, &name));
355 EXPECT_EQ(apps[0].name, name);
356
357 std::string icon_path_string;
358 std::string icon_path_key = "apps." + id + ".icon";
359 EXPECT_TRUE(dict->GetString(icon_path_key, &icon_path_string));
360
361 base::FilePath expected_icon_path;
362 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &expected_icon_path));
363 expected_icon_path =
364 expected_icon_path.AppendASCII(KioskAppManager::kIconCacheDir)
365 .AppendASCII(apps[0].app_id)
366 .AddExtension(".png");
367 EXPECT_EQ(expected_icon_path.value(), icon_path_string);
368 }
369
manager() const370 KioskAppManager* manager() const { return KioskAppManager::Get(); }
fake_cws()371 FakeCWS* fake_cws() { return fake_cws_.get(); }
372
373 private:
374 base::ScopedTempDir temp_dir_;
375 scoped_ptr<FakeCWS> fake_cws_;
376
377 DISALLOW_COPY_AND_ASSIGN(KioskAppManagerTest);
378 };
379
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,Basic)380 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, Basic) {
381 // Add a couple of apps. Use "fake_app_x" that do not have data on the test
382 // server to avoid pending data loads that could be lingering on tear down and
383 // cause DCHECK failure in utility_process_host_impl.cc.
384 manager()->AddApp("fake_app_1");
385 manager()->AddApp("fake_app_2");
386 EXPECT_EQ("fake_app_1,fake_app_2", GetAppIds());
387
388 // Set an auto launch app.
389 manager()->SetAutoLaunchApp("fake_app_1");
390 EXPECT_EQ("fake_app_1", manager()->GetAutoLaunchApp());
391
392 // Clear the auto launch app.
393 manager()->SetAutoLaunchApp("");
394 EXPECT_EQ("", manager()->GetAutoLaunchApp());
395 EXPECT_FALSE(manager()->IsAutoLaunchEnabled());
396
397 // Set another auto launch app.
398 manager()->SetAutoLaunchApp("fake_app_2");
399 EXPECT_EQ("fake_app_2", manager()->GetAutoLaunchApp());
400
401 // Check auto launch permissions.
402 EXPECT_FALSE(manager()->IsAutoLaunchEnabled());
403 manager()->SetEnableAutoLaunch(true);
404 EXPECT_TRUE(manager()->IsAutoLaunchEnabled());
405
406 // Remove the auto launch app.
407 manager()->RemoveApp("fake_app_2");
408 EXPECT_EQ("fake_app_1", GetAppIds());
409 EXPECT_EQ("", manager()->GetAutoLaunchApp());
410
411 // Add the just removed auto launch app again and it should no longer be
412 // the auto launch app.
413 manager()->AddApp("fake_app_2");
414 EXPECT_EQ("", manager()->GetAutoLaunchApp());
415 manager()->RemoveApp("fake_app_2");
416 EXPECT_EQ("fake_app_1", GetAppIds());
417
418 // Set a none exist app as auto launch.
419 manager()->SetAutoLaunchApp("none_exist_app");
420 EXPECT_EQ("", manager()->GetAutoLaunchApp());
421 EXPECT_FALSE(manager()->IsAutoLaunchEnabled());
422
423 // Add an existing app again.
424 manager()->AddApp("fake_app_1");
425 EXPECT_EQ("fake_app_1", GetAppIds());
426 }
427
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,LoadCached)428 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, LoadCached) {
429 SetExistingApp("app_1", "Cached App1 Name", "red16x16.png");
430
431 fake_cws()->SetNoUpdate("app_1");
432 AppDataLoadWaiter waiter(manager(), 1);
433 waiter.Wait();
434 EXPECT_TRUE(waiter.loaded());
435
436 KioskAppManager::Apps apps;
437 manager()->GetApps(&apps);
438 EXPECT_EQ(1u, apps.size());
439 EXPECT_EQ("app_1", apps[0].app_id);
440 EXPECT_EQ("Cached App1 Name", apps[0].name);
441 EXPECT_EQ(gfx::Size(16, 16), apps[0].icon.size());
442 }
443
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,ClearAppData)444 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, ClearAppData) {
445 SetExistingApp("app_1", "Cached App1 Name", "red16x16.png");
446
447 PrefService* local_state = g_browser_process->local_state();
448 const base::DictionaryValue* dict =
449 local_state->GetDictionary(KioskAppManager::kKioskDictionaryName);
450 const base::DictionaryValue* apps_dict;
451 EXPECT_TRUE(dict->GetDictionary(KioskAppManager::kKeyApps, &apps_dict));
452 EXPECT_TRUE(apps_dict->HasKey("app_1"));
453
454 manager()->ClearAppData("app_1");
455
456 EXPECT_FALSE(apps_dict->HasKey("app_1"));
457 }
458
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,UpdateAppDataFromProfile)459 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, UpdateAppDataFromProfile) {
460 SetExistingApp("app_1", "Cached App1 Name", "red16x16.png");
461
462 fake_cws()->SetNoUpdate("app_1");
463 AppDataLoadWaiter waiter(manager(), 1);
464 waiter.Wait();
465 EXPECT_TRUE(waiter.loaded());
466
467 KioskAppManager::Apps apps;
468 manager()->GetApps(&apps);
469 EXPECT_EQ(1u, apps.size());
470 EXPECT_EQ("app_1", apps[0].app_id);
471 EXPECT_EQ("Cached App1 Name", apps[0].name);
472
473 scoped_refptr<extensions::Extension> updated_app =
474 MakeApp("Updated App1 Name", "2.0", "http://localhost/", "app_1");
475 manager()->UpdateAppDataFromProfile(
476 "app_1", browser()->profile(), updated_app.get());
477
478 waiter.Wait();
479 EXPECT_TRUE(waiter.loaded());
480
481 manager()->GetApps(&apps);
482 EXPECT_EQ(1u, apps.size());
483 EXPECT_EQ("app_1", apps[0].app_id);
484 EXPECT_EQ("Updated App1 Name", apps[0].name);
485 }
486
487 // Test is flaky. See http://crbug.com/379769 for details.
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,DISABLED_BadApp)488 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, DISABLED_BadApp) {
489 AppDataLoadWaiter waiter(manager(), 2);
490 manager()->AddApp("unknown_app");
491 TestKioskAppManagerObserver observer(manager());
492 waiter.Wait();
493 EXPECT_FALSE(waiter.loaded());
494
495 EXPECT_EQ("", GetAppIds());
496 EXPECT_EQ(1, observer.load_failure_count());
497 }
498
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,GoodApp)499 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, GoodApp) {
500 // Webstore data json is in
501 // chrome/test/data/chromeos/app_mode/webstore/inlineinstall/detail/app_1
502 fake_cws()->SetNoUpdate("app_1");
503 AppDataLoadWaiter waiter(manager(), 2);
504 manager()->AddApp("app_1");
505 waiter.Wait();
506 EXPECT_TRUE(waiter.loaded());
507
508 // Check data is correct.
509 KioskAppManager::Apps apps;
510 manager()->GetApps(&apps);
511 ASSERT_EQ(1u, apps.size());
512 EXPECT_EQ("app_1", apps[0].app_id);
513 EXPECT_EQ("Name of App 1", apps[0].name);
514 EXPECT_EQ(gfx::Size(16, 16), apps[0].icon.size());
515
516 // Check data is cached in local state.
517 PrefService* local_state = g_browser_process->local_state();
518 const base::DictionaryValue* dict =
519 local_state->GetDictionary(KioskAppManager::kKioskDictionaryName);
520
521 std::string name;
522 EXPECT_TRUE(dict->GetString("apps.app_1.name", &name));
523 EXPECT_EQ(apps[0].name, name);
524
525 std::string icon_path_string;
526 EXPECT_TRUE(dict->GetString("apps.app_1.icon", &icon_path_string));
527
528 base::FilePath expected_icon_path;
529 ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &expected_icon_path));
530 expected_icon_path = expected_icon_path.
531 AppendASCII(KioskAppManager::kIconCacheDir).
532 AppendASCII(apps[0].app_id).AddExtension(".png");
533 EXPECT_EQ(expected_icon_path.value(), icon_path_string);
534 }
535
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,DownloadNewApp)536 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, DownloadNewApp) {
537 base::FilePath crx_path;
538 RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName);
539 }
540
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,RemoveApp)541 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, RemoveApp) {
542 // Add a new app.
543 RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName);
544 KioskAppManager::Apps apps;
545 manager()->GetApps(&apps);
546 ASSERT_EQ(1u, apps.size());
547 base::FilePath crx_path;
548 std::string version;
549 EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
550 EXPECT_TRUE(base::PathExists(crx_path));
551 EXPECT_EQ("1.0.0", version);
552
553 // Remove the app now.
554 manager()->RemoveApp(kTestLocalFsKioskApp);
555 content::BrowserThread::GetBlockingPool()->FlushForTesting();
556 manager()->GetApps(&apps);
557 ASSERT_EQ(0u, apps.size());
558 EXPECT_FALSE(base::PathExists(crx_path));
559 EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
560 }
561
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,UpdateApp)562 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, UpdateApp) {
563 // Add a version 1 app first.
564 RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName);
565 KioskAppManager::Apps apps;
566 manager()->GetApps(&apps);
567 ASSERT_EQ(1u, apps.size());
568 base::FilePath crx_path;
569 std::string version;
570 EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
571 EXPECT_TRUE(base::PathExists(crx_path));
572 EXPECT_EQ("1.0.0", version);
573
574 // Update to version 2.
575 fake_cws()->SetUpdateCrx(
576 kTestLocalFsKioskApp,
577 "bmbpicmpniaclbbpdkfglgipkkebnbjf_v2_read_and_verify_data.crx",
578 "2.0.0");
579 AppDataLoadWaiter waiter(manager(), 1);
580 UpdateAppData();
581 waiter.Wait();
582 EXPECT_TRUE(waiter.loaded());
583
584 // Verify the app has been updated to v2.
585 manager()->GetApps(&apps);
586 ASSERT_EQ(1u, apps.size());
587 base::FilePath new_crx_path;
588 std::string new_version;
589 EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &new_crx_path, &new_version));
590 EXPECT_EQ("2.0.0", new_version);
591 EXPECT_TRUE(base::PathExists(new_crx_path));
592 // Get original version 2 source download crx file path.
593 base::FilePath test_data_dir;
594 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
595 base::FilePath v2_file_path = test_data_dir.Append(FILE_PATH_LITERAL(
596 "chromeos/app_mode/webstore/downloads/"
597 "bmbpicmpniaclbbpdkfglgipkkebnbjf_v2_read_and_verify_data.crx"));
598 EXPECT_TRUE(base::PathExists(v2_file_path));
599 EXPECT_TRUE(base::ContentsEqual(v2_file_path, new_crx_path));
600 }
601
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,UpdateAndRemoveApp)602 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, UpdateAndRemoveApp) {
603 // Add a version 1 app first.
604 RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName);
605 KioskAppManager::Apps apps;
606 manager()->GetApps(&apps);
607 ASSERT_EQ(1u, apps.size());
608 base::FilePath v1_crx_path;
609 std::string version;
610 EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v1_crx_path, &version));
611 EXPECT_TRUE(base::PathExists(v1_crx_path));
612 EXPECT_EQ("1.0.0", version);
613
614 // Update to version 2.
615 fake_cws()->SetUpdateCrx(
616 kTestLocalFsKioskApp,
617 "bmbpicmpniaclbbpdkfglgipkkebnbjf_v2_read_and_verify_data.crx",
618 "2.0.0");
619 AppDataLoadWaiter waiter(manager(), 1);
620 UpdateAppData();
621 waiter.Wait();
622 EXPECT_TRUE(waiter.loaded());
623
624 // Verify the app has been updated to v2.
625 manager()->GetApps(&apps);
626 ASSERT_EQ(1u, apps.size());
627 base::FilePath v2_crx_path;
628 std::string new_version;
629 EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &new_version));
630 EXPECT_EQ("2.0.0", new_version);
631 // Verify both v1 and v2 crx files exist.
632 EXPECT_TRUE(base::PathExists(v1_crx_path));
633 EXPECT_TRUE(base::PathExists(v2_crx_path));
634
635 // Remove the app now.
636 manager()->RemoveApp(kTestLocalFsKioskApp);
637 content::BrowserThread::GetBlockingPool()->FlushForTesting();
638 manager()->GetApps(&apps);
639 ASSERT_EQ(0u, apps.size());
640 // Verify both v1 and v2 crx files are removed.
641 EXPECT_FALSE(base::PathExists(v1_crx_path));
642 EXPECT_FALSE(base::PathExists(v2_crx_path));
643 EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &version));
644 }
645
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,EnableConsumerKiosk)646 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest, EnableConsumerKiosk) {
647 scoped_ptr<KioskAppManager::ConsumerKioskAutoLaunchStatus> status(
648 new KioskAppManager::ConsumerKioskAutoLaunchStatus(
649 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED));
650 scoped_ptr<bool> locked(new bool(false));
651
652 scoped_refptr<content::MessageLoopRunner> runner =
653 new content::MessageLoopRunner;
654 manager()->GetConsumerKioskAutoLaunchStatus(
655 base::Bind(&ConsumerKioskAutoLaunchStatusCheck,
656 status.get(),
657 runner->QuitClosure()));
658 runner->Run();
659 EXPECT_EQ(*status.get(),
660 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
661
662 scoped_refptr<content::MessageLoopRunner> runner2 =
663 new content::MessageLoopRunner;
664 manager()->EnableConsumerKioskAutoLaunch(
665 base::Bind(&ConsumerKioskModeLockCheck,
666 locked.get(),
667 runner2->QuitClosure()));
668 runner2->Run();
669 EXPECT_TRUE(*locked.get());
670
671 scoped_refptr<content::MessageLoopRunner> runner3 =
672 new content::MessageLoopRunner;
673 manager()->GetConsumerKioskAutoLaunchStatus(
674 base::Bind(&ConsumerKioskAutoLaunchStatusCheck,
675 status.get(),
676 runner3->QuitClosure()));
677 runner3->Run();
678 EXPECT_EQ(*status.get(),
679 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED);
680 }
681
IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,PreventEnableConsumerKioskForEnterprise)682 IN_PROC_BROWSER_TEST_F(KioskAppManagerTest,
683 PreventEnableConsumerKioskForEnterprise) {
684 // First, lock the device as enterprise.
685 EXPECT_EQ(LockDeviceForEnterprise(),
686 policy::EnterpriseInstallAttributes::LOCK_SUCCESS);
687
688 scoped_ptr<KioskAppManager::ConsumerKioskAutoLaunchStatus> status(
689 new KioskAppManager::ConsumerKioskAutoLaunchStatus(
690 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED));
691 scoped_ptr<bool> locked(new bool(true));
692
693 scoped_refptr<content::MessageLoopRunner> runner =
694 new content::MessageLoopRunner;
695 manager()->GetConsumerKioskAutoLaunchStatus(
696 base::Bind(&ConsumerKioskAutoLaunchStatusCheck,
697 status.get(),
698 runner->QuitClosure()));
699 runner->Run();
700 EXPECT_EQ(*status.get(),
701 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
702
703 scoped_refptr<content::MessageLoopRunner> runner2 =
704 new content::MessageLoopRunner;
705 manager()->EnableConsumerKioskAutoLaunch(
706 base::Bind(&ConsumerKioskModeLockCheck,
707 locked.get(),
708 runner2->QuitClosure()));
709 runner2->Run();
710 EXPECT_FALSE(*locked.get());
711
712 scoped_refptr<content::MessageLoopRunner> runner3 =
713 new content::MessageLoopRunner;
714 manager()->GetConsumerKioskAutoLaunchStatus(
715 base::Bind(&ConsumerKioskAutoLaunchStatusCheck,
716 status.get(),
717 runner3->QuitClosure()));
718 runner3->Run();
719 EXPECT_EQ(*status.get(),
720 KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
721 }
722
723 } // namespace chromeos
724