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