// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/app_mode/startup_app_launcher.h"

#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/callback.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/scoped_command_line.h"
#include "base/version.h"
#include "chrome/browser/ash/app_mode/app_session.h"
#include "chrome/browser/ash/app_mode/kiosk_app_external_loader.h"
#include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
#include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
#include "chrome/browser/ash/app_mode/test_kiosk_extension_builder.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/policy/core/device_local_account.h"
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/chromeos/extensions/test_external_cache.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/install_tracker.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/account_id/account_id.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/version_info/channel.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/external_install_info.h"
#include "extensions/browser/test_event_router.h"
#include "extensions/common/api/app_runtime.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/manifest.h"
#include "url/gurl.h"

using extensions::ExternalInstallInfoFile;
using extensions::ExternalInstallInfoUpdateUrl;
using extensions::Manifest;
using extensions::mojom::ManifestLocation;
using ::testing::AssertionFailure;
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;

namespace ash {

namespace {

constexpr char kTestPrimaryAppId[] = "abcdefghabcdefghabcdefghabcdefgh";

constexpr char kSecondaryAppId[] = "aaaabbbbaaaabbbbaaaabbbbaaaabbbb";

constexpr char kExtraSecondaryAppId[] = "aaaaccccaaaaccccaaaaccccaaaacccc";

constexpr char kTestUserAccount[] = "user@test";

enum class LaunchState {
  kNotStarted,
  kInitializingNetwork,
  kInstallingApp,
  kReadyToLaunch,
  kLaunchSucceeded,
  kLaunchFailed
};

class TestAppLaunchDelegate : public StartupAppLauncher::Delegate {
 public:
  TestAppLaunchDelegate() = default;
  ~TestAppLaunchDelegate() override = default;

  const std::vector<LaunchState>& launch_state_changes() const {
    return launch_state_changes_;
  }
  KioskAppLaunchError::Error launch_error() const { return launch_error_; }

  void set_network_ready(bool network_ready) { network_ready_ = network_ready; }
  void set_should_skip_app_installation(bool skip_app_installation) {
    should_skip_app_installation_ = skip_app_installation;
  }
  void set_showing_network_config_screen(bool showing) {
    showing_network_config_screen_ = showing;
  }

  void ClearLaunchStateChanges() { launch_state_changes_.clear(); }

  void WaitForLaunchStates(const std::set<LaunchState>& states) {
    if (states.count(launch_state_))
      return;

    ASSERT_FALSE(run_loop_.get());

    waiting_for_launch_states_ = states;
    run_loop_ = std::make_unique<base::RunLoop>();
    run_loop_->Run();
  }

  // StartupAppLauncher::Delegate:
  void InitializeNetwork() override {
    SetLaunchState(LaunchState::kInitializingNetwork);
  }
  bool IsNetworkReady() const override { return network_ready_; }
  bool ShouldSkipAppInstallation() const override {
    return should_skip_app_installation_;
  }
  void OnAppInstalling() override {
    SetLaunchState(LaunchState::kInstallingApp);
  }
  void OnAppPrepared() override { SetLaunchState(LaunchState::kReadyToLaunch); }
  void OnAppLaunched() override {
    SetLaunchState(LaunchState::kLaunchSucceeded);
  }
  void OnLaunchFailed(KioskAppLaunchError::Error error) override {
    launch_error_ = error;
    SetLaunchState(LaunchState::kLaunchFailed);
  }
  bool IsShowingNetworkConfigScreen() const override {
    return showing_network_config_screen_;
  }

 private:
  void SetLaunchState(LaunchState state) {
    launch_state_changes_.push_back(state);
    launch_state_ = state;

    if (run_loop_ && waiting_for_launch_states_.count(state)) {
      waiting_for_launch_states_.clear();
      std::move(run_loop_)->Quit();
    }
  }

  LaunchState launch_state_ = LaunchState::kNotStarted;
  std::vector<LaunchState> launch_state_changes_;
  KioskAppLaunchError::Error launch_error_ = KioskAppLaunchError::Error::kNone;

  bool network_ready_ = false;
  bool showing_network_config_screen_ = false;

  bool should_skip_app_installation_ = false;

  std::unique_ptr<base::RunLoop> run_loop_;
  std::set<LaunchState> waiting_for_launch_states_;

  DISALLOW_COPY_AND_ASSIGN(TestAppLaunchDelegate);
};

class AppLaunchTracker : public extensions::TestEventRouter::EventObserver {
 public:
  AppLaunchTracker(const std::string& app_id,
                   extensions::TestEventRouter* event_router)
      : app_id_(app_id), event_router_(event_router) {
    event_router->AddEventObserver(this);
  }
  ~AppLaunchTracker() override { event_router_->RemoveEventObserver(this); }

  int kiosk_launch_count() const { return kiosk_launch_count_; }

  // TestEventRouter::EventObserver:
  void OnBroadcastEvent(const extensions::Event& event) override {
    ADD_FAILURE() << "Unexpected broadcast " << event.event_name;
  }

  void OnDispatchEventToExtension(const std::string& extension_id,
                                  const extensions::Event& event) override {
    ASSERT_EQ(extension_id, app_id_);

    ASSERT_EQ(event.event_name,
              extensions::api::app_runtime::OnLaunched::kEventName);
    ASSERT_TRUE(event.event_args);
    ASSERT_EQ(1u, event.event_args->GetList().size());

    const base::Value& launch_data = event.event_args->GetList()[0];
    const base::Value* is_kiosk_session =
        launch_data.FindKeyOfType("isKioskSession", base::Value::Type::BOOLEAN);
    ASSERT_TRUE(is_kiosk_session);
    EXPECT_TRUE(is_kiosk_session->GetBool());
    ++kiosk_launch_count_;
  }

 private:
  const std::string app_id_;
  extensions::TestEventRouter* event_router_;
  int kiosk_launch_count_ = 0;

  DISALLOW_COPY_AND_ASSIGN(AppLaunchTracker);
};

// Simulates extension service behavior related to external extensions loading,
// but does not initiate found extension's CRX installation - instead, it keeps
// track of pending extension installations, and expect the test code to finish
// the pending extension installations.
class TestKioskLoaderVisitor
    : public extensions::ExternalProviderInterface::VisitorInterface {
 public:
  TestKioskLoaderVisitor(content::BrowserContext* browser_context,
                         extensions::ExtensionRegistry* extension_registry,
                         extensions::ExtensionService* extension_service)
      : browser_context_(browser_context),
        extension_registry_(extension_registry),
        extension_service_(extension_service) {}

  ~TestKioskLoaderVisitor() override = default;

  const std::set<std::string>& pending_crx_files() const {
    return pending_crx_files_;
  }
  const std::set<std::string>& pending_update_urls() const {
    return pending_update_urls_;
  }

  bool FinishPendingInstall(const extensions::Extension* extension) {
    if (!pending_crx_files_.count(extension->id()) &&
        !pending_update_urls_.count(extension->id())) {
      return false;
    }

    if (!extension_service_->pending_extension_manager()->IsIdPending(
            extension->id())) {
      return false;
    }

    pending_crx_files_.erase(extension->id());
    pending_update_urls_.erase(extension->id());
    extension_service_->OnExtensionInstalled(
        extension, syncer::StringOrdinal::CreateInitialOrdinal(),
        extensions::kInstallFlagInstallImmediately);
    extensions::InstallTracker::Get(browser_context_)
        ->OnFinishCrxInstall(extension->id(), true);
    return true;
  }

  bool FailPendingInstall(const std::string& extension_id) {
    if (!pending_crx_files_.count(extension_id) &&
        !pending_update_urls_.count(extension_id)) {
      return false;
    }

    if (!extension_service_->pending_extension_manager()->IsIdPending(
            extension_id)) {
      return false;
    }

    pending_crx_files_.erase(extension_id);
    pending_update_urls_.erase(extension_id);
    extensions::InstallTracker::Get(browser_context_)
        ->OnFinishCrxInstall(extension_id, false);
    return true;
  }

  // extensions::ExternalProviderInterface::VisitorInterface:
  bool OnExternalExtensionFileFound(
      const ExternalInstallInfoFile& info) override {
    const extensions::Extension* existing =
        extension_registry_->GetExtensionById(
            info.extension_id, extensions::ExtensionRegistry::EVERYTHING);
    // Alredy exists, and does not require update.
    if (existing && existing->version().CompareTo(info.version) >= 0)
      return false;

    if (!extension_service_->pending_extension_manager()->AddFromExternalFile(
            info.extension_id, info.crx_location, info.version,
            info.creation_flags, info.mark_acknowledged)) {
      return false;
    }

    pending_crx_files_.insert(info.extension_id);
    extensions::InstallTracker::Get(browser_context_)
        ->OnBeginCrxInstall(info.extension_id);
    return true;
  }
  bool OnExternalExtensionUpdateUrlFound(
      const ExternalInstallInfoUpdateUrl& info,
      bool is_initial_load) override {
    if (extension_registry_->GetExtensionById(
            info.extension_id, extensions::ExtensionRegistry::EVERYTHING))
      return false;

    if (!extension_service_->pending_extension_manager()
             ->AddFromExternalUpdateUrl(
                 info.extension_id, info.install_parameter, info.update_url,
                 info.download_location, info.creation_flags,
                 info.mark_acknowledged)) {
      return false;
    }

    pending_update_urls_.insert(info.extension_id);
    extensions::InstallTracker::Get(browser_context_)
        ->OnBeginCrxInstall(info.extension_id);
    return true;
  }
  void OnExternalProviderReady(
      const extensions::ExternalProviderInterface* provider) override {}
  void OnExternalProviderUpdateComplete(
      const extensions::ExternalProviderInterface* provider,
      const std::vector<ExternalInstallInfoUpdateUrl>& update_url_extensions,
      const std::vector<ExternalInstallInfoFile>& file_extensions,
      const std::set<std::string>& removed_extensions) override {
    for (const auto& extension : update_url_extensions)
      OnExternalExtensionUpdateUrlFound(extension, false);

    for (const auto& extension : file_extensions)
      OnExternalExtensionFileFound(extension);

    for (const auto& extension_id : removed_extensions) {
      extension_service_->UninstallExtension(
          extension_id,
          extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, nullptr);
    }
  }

 private:
  content::BrowserContext* const browser_context_;
  extensions::ExtensionRegistry* const extension_registry_;
  extensions::ExtensionService* const extension_service_;

  std::set<std::string> pending_crx_files_;
  std::set<std::string> pending_update_urls_;

  DISALLOW_COPY_AND_ASSIGN(TestKioskLoaderVisitor);
};

}  // namespace

class StartupAppLauncherTest : public extensions::ExtensionServiceTestBase,
                               public KioskAppManager::Overrides {
 public:
  StartupAppLauncherTest() = default;
  ~StartupAppLauncherTest() override = default;

  // testing::Test:
  void SetUp() override {
    command_line_.GetProcessCommandLine()->AppendSwitch(
        switches::kForceAppMode);
    command_line_.GetProcessCommandLine()->AppendSwitch(switches::kAppId);

    KioskAppManager::InitializeForTesting(this);

    InitializePrimaryAppState();

    extensions::ExtensionServiceTestBase::SetUp();

    InitializeKioskAppUser();
    InitializeEmptyExtensionService();
    external_apps_loader_handler_ = std::make_unique<TestKioskLoaderVisitor>(
        browser_context(), registry(), service());
    CreateAndInitializeKioskAppsProviders(external_apps_loader_handler_.get());

    extensions::TestEventRouter* event_router =
        extensions::CreateAndUseTestEventRouter(browser_context());
    app_launch_tracker_ =
        std::make_unique<AppLaunchTracker>(kTestPrimaryAppId, event_router);

    startup_app_launcher_ = std::make_unique<StartupAppLauncher>(
        profile(), kTestPrimaryAppId, &startup_launch_delegate_);
  }

  void TearDown() override {
    startup_app_launcher_.reset();
    external_cache_ = nullptr;

    primary_app_provider_->ServiceShutdown();
    secondary_apps_provider_->ServiceShutdown();
    external_apps_loader_handler_.reset();

    app_launch_tracker_.reset();

    KioskAppManager::Shutdown();

    accounts_settings_helper_.reset();

    extensions::ExtensionServiceTestBase::TearDown();
  }

  // KioskAppManager::Overrides:
  std::unique_ptr<chromeos::ExternalCache> CreateExternalCache(
      chromeos::ExternalCacheDelegate* delegate,
      bool always_check_updates) override {
    auto cache = std::make_unique<chromeos::TestExternalCache>(
        delegate, always_check_updates);
    external_cache_ = cache.get();
    return cache;
  }

  std::unique_ptr<AppSession> CreateAppSession() override {
    EXPECT_FALSE(kiosk_app_session_initialized_);
    kiosk_app_session_initialized_ = true;
    return nullptr;
  }

 protected:
  // Note: These tests should not actually create files, so the actual returned
  // path is not too important. Still, putting it under the test's temp dir, in
  // case something unexpectedly tries to do file I/O with the file paths
  // returned here.
  std::string GetExtensionPath(const std::string& app_id) {
    return temp_dir()
        .GetPath()
        .AppendASCII("test_crx_file")
        .AppendASCII(app_id)
        .value();
  }

  void InitializeLauncherWithNetworkReady() {
    startup_app_launcher_->Initialize();
    EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInitializingNetwork}),
              startup_launch_delegate_.launch_state_changes());
    startup_launch_delegate_.ClearLaunchStateChanges();

    startup_launch_delegate_.set_network_ready(true);
    startup_app_launcher_->ContinueWithNetworkReady();
    EXPECT_TRUE(startup_launch_delegate_.launch_state_changes().empty());
    startup_launch_delegate_.ClearLaunchStateChanges();
  }

  AssertionResult DownloadPrimaryApp(
      const TestKioskExtensionBuilder& app_builder) WARN_UNUSED_RESULT {
    return DownloadPrimaryApp(app_builder.extension_id(),
                              app_builder.version());
  }

  AssertionResult DownloadPrimaryApp(const std::string& app_id,
                                     const std::string& version)
      WARN_UNUSED_RESULT {
    if (!external_cache_)
      return AssertionFailure() << "External cache not initialized";

    if (!external_cache_->pending_downloads().count(app_id))
      return AssertionFailure() << "Download not pending: " << app_id;

    if (!external_cache_->SimulateExtensionDownloadFinished(
            app_id, GetExtensionPath(app_id), version)) {
      return AssertionFailure() << " Finish download attempt failed";
    }

    return AssertionSuccess();
  }

  AssertionResult FinishPrimaryAppInstall(
      const TestKioskExtensionBuilder& app_builder) WARN_UNUSED_RESULT {
    const std::string& id = app_builder.extension_id();
    if (!external_apps_loader_handler_->pending_crx_files().count(id))
      return AssertionFailure() << "App install not peding: " << id;

    scoped_refptr<const extensions::Extension> app = app_builder.Build();
    if (!app)
      return AssertionFailure() << "App builder failed: " << id;

    if (!external_apps_loader_handler_->FinishPendingInstall(app.get()))
      return AssertionFailure() << "Finish install attempt failed: " << id;

    return AssertionSuccess();
  }

  AssertionResult DownloadAndInstallPrimaryApp(
      const TestKioskExtensionBuilder& app_builder) WARN_UNUSED_RESULT {
    AssertionResult download_result = DownloadPrimaryApp(app_builder);
    if (!download_result)
      return download_result;

    AssertionResult install_result = FinishPrimaryAppInstall(app_builder);
    if (!install_result)
      return install_result;

    return AssertionSuccess();
  }

  AssertionResult FinishSecondaryExtensionInstall(
      const TestKioskExtensionBuilder& builder) WARN_UNUSED_RESULT {
    const std::string& id = builder.extension_id();
    if (!external_apps_loader_handler_->pending_update_urls().count(id)) {
      return AssertionFailure()
             << "Secondary extension install not pending: " << id;
    }

    scoped_refptr<const extensions::Extension> extension = builder.Build();
    if (!extension)
      return AssertionFailure() << "Extension builder failed: " << id;

    if (!external_apps_loader_handler_->FinishPendingInstall(extension.get()))
      return AssertionFailure() << "Finish install attempt failed: " << id;

    return AssertionSuccess();
  }

 private:
  void InitializePrimaryAppState() {
    // Inject test kiosk app data to prevent KioskAppManager from attempting to
    // load it.
    // TODO(tbarzic): Introducing a test KioskAppData class that overrides app
    //     data load logic, and injecting a KioskAppData object factory to
    //     KioskAppManager would be a cleaner solution here.
    KioskAppManager::Get()->AddAppForTest(
        kTestPrimaryAppId, AccountId::FromUserEmail(kTestUserAccount),
        GURL("http://cws/"), "");

    accounts_settings_helper_ = std::make_unique<ScopedCrosSettingsTestHelper>(
        false /*create_service*/);
    accounts_settings_helper_->ReplaceDeviceSettingsProviderWithStub();

    auto account = std::make_unique<base::DictionaryValue>();
    account->SetKey(kAccountsPrefDeviceLocalAccountsKeyId,
                    base::Value(kTestUserAccount));
    account->SetKey(kAccountsPrefDeviceLocalAccountsKeyType,
                    base::Value(policy::DeviceLocalAccount::TYPE_KIOSK_APP));
    account->SetKey(kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
                    base::Value(kTestPrimaryAppId));
    base::ListValue accounts;
    accounts.Append(std::move(account));

    accounts_settings_helper_->Set(kAccountsPrefDeviceLocalAccounts, accounts);
    accounts_settings_helper_->SetString(
        kAccountsPrefDeviceLocalAccountAutoLoginId, kTestUserAccount);
    accounts_settings_helper_->SetInteger(
        kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
  }

  void CreateAndInitializeKioskAppsProviders(TestKioskLoaderVisitor* visitor) {
    primary_app_provider_ = std::make_unique<extensions::ExternalProviderImpl>(
        visitor,
        base::MakeRefCounted<KioskAppExternalLoader>(
            KioskAppExternalLoader::AppClass::kPrimary),
        profile(), ManifestLocation::kExternalPolicy,
        ManifestLocation::kInvalidLocation, extensions::Extension::NO_FLAGS);
    InitializeKioskAppsProvider(primary_app_provider_.get());

    secondary_apps_provider_ =
        std::make_unique<extensions::ExternalProviderImpl>(
            visitor,
            base::MakeRefCounted<KioskAppExternalLoader>(
                KioskAppExternalLoader::AppClass::kSecondary),
            profile(), ManifestLocation::kExternalPref,
            ManifestLocation::kExternalPrefDownload,
            extensions::Extension::NO_FLAGS);
    InitializeKioskAppsProvider(secondary_apps_provider_.get());
  }

  void InitializeKioskAppsProvider(extensions::ExternalProviderImpl* provider) {
    provider->set_auto_acknowledge(true);
    provider->set_install_immediately(true);
    provider->set_allow_updates(true);
    provider->VisitRegisteredExtension();
  }

 protected:
  void InitializeKioskAppUser() {
    const AccountId kiosk_account_id(
        AccountId::FromUserEmail(kTestUserAccount));
    auto fake_user_manager_ = std::make_unique<FakeChromeUserManager>();
    fake_user_manager_->AddKioskAppUser(kiosk_account_id);
    fake_user_manager_->LoginUser(kiosk_account_id);

    user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
        std::move(fake_user_manager_));
  }

  TestAppLaunchDelegate startup_launch_delegate_;

  std::unique_ptr<KioskAppLauncher> startup_app_launcher_;
  std::unique_ptr<AppLaunchTracker> app_launch_tracker_;
  std::unique_ptr<TestKioskLoaderVisitor> external_apps_loader_handler_;

  chromeos::TestExternalCache* external_cache_ = nullptr;

  bool kiosk_app_session_initialized_ = false;
  session_manager::SessionManager session_manager_;

 private:
  base::test::ScopedCommandLine command_line_;

  std::unique_ptr<ScopedCrosSettingsTestHelper> accounts_settings_helper_;

  std::unique_ptr<extensions::ExternalProviderImpl> primary_app_provider_;
  std::unique_ptr<extensions::ExternalProviderImpl> secondary_apps_provider_;

  std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;

  DISALLOW_COPY_AND_ASSIGN(StartupAppLauncherTest);
};

TEST_F(StartupAppLauncherTest, PrimaryAppLaunchFlow) {
  InitializeLauncherWithNetworkReady();

  ASSERT_TRUE(external_cache_);
  EXPECT_EQ(std::set<std::string>({kTestPrimaryAppId}),
            external_cache_->pending_downloads());

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  ASSERT_TRUE(DownloadPrimaryApp(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_builder));

  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, OfflineLaunchWithPrimaryAppPreInstalled) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.set_version("1.0");
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  startup_app_launcher_->Initialize();

  // Given that the app is offline enabled and installed, the app should be
  // launched immediately, without waiting for network or checking for updates.
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());

  // Primary app cache checks finished after the startup app launcher reports
  // it's ready should be ignored - i.e. startup app launcher should not attempt
  // to relaunch the app, nor request the update installation.
  startup_app_launcher_->ContinueWithNetworkReady();
  ASSERT_TRUE(DownloadPrimaryApp(kTestPrimaryAppId, "1.1"));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  EXPECT_TRUE(startup_launch_delegate_.launch_state_changes().empty());

  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest,
       OfflineLaunchWithPrimaryAppPreInstalled_UpdateFoundAfterLaunch) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.set_version("1.0");
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  startup_app_launcher_->Initialize();

  // Given that the app is offline enabled and installed, the app should be
  // launched immediately, without waiting for network or checking for updates.
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());

  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());

  // Primary app cache checks finished after the app launch
  // it's ready should be ignored - i.e. startup app launcher should not attempt
  // to relaunch the app, nor request the update installation.
  startup_app_launcher_->ContinueWithNetworkReady();
  ASSERT_TRUE(DownloadPrimaryApp(kTestPrimaryAppId, "1.1"));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  EXPECT_TRUE(startup_launch_delegate_.launch_state_changes().empty());
}

TEST_F(StartupAppLauncherTest, PrimaryAppDownloadFailure) {
  InitializeLauncherWithNetworkReady();

  ASSERT_TRUE(external_cache_);
  EXPECT_EQ(std::set<std::string>({kTestPrimaryAppId}),
            external_cache_->pending_downloads());
  ASSERT_TRUE(
      external_cache_->SimulateExtensionDownloadFailed(kTestPrimaryAppId));

  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchFailed}),
            startup_launch_delegate_.launch_state_changes());

  EXPECT_EQ(KioskAppLaunchError::Error::kUnableToDownload,
            startup_launch_delegate_.launch_error());

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, PrimaryAppCrxInstallFailure) {
  InitializeLauncherWithNetworkReady();

  ASSERT_TRUE(DownloadPrimaryApp(kTestPrimaryAppId, "1.0"));
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(
      external_apps_loader_handler_->FailPendingInstall(kTestPrimaryAppId));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchFailed}),
            startup_launch_delegate_.launch_state_changes());

  EXPECT_EQ(KioskAppLaunchError::Error::kUnableToInstall,
            startup_launch_delegate_.launch_error());

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, PrimaryAppNotKioskEnabled) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.set_kiosk_enabled(false);
  ASSERT_TRUE(DownloadPrimaryApp(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchFailed}),
            startup_launch_delegate_.launch_state_changes());

  EXPECT_EQ(KioskAppLaunchError::Error::kNotKioskEnabled,
            startup_launch_delegate_.launch_error());

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, PrimaryAppIsExtension) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_EXTENSION,
                                                kTestPrimaryAppId);
  ASSERT_TRUE(DownloadPrimaryApp(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchFailed}),
            startup_launch_delegate_.launch_state_changes());

  EXPECT_EQ(KioskAppLaunchError::Error::kNotKioskEnabled,
            startup_launch_delegate_.launch_error());

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, LaunchWithSecondaryApps) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(
      kExtraSecondaryAppId, false);

  ASSERT_TRUE(DownloadPrimaryApp(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_builder));

  // Installing primary app with a non-installed secondary app should notify
  // delegate about pending app installation - in this case for secondary app.
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  TestKioskExtensionBuilder secondary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                  kSecondaryAppId);
  secondary_app_builder.set_kiosk_enabled(false);
  ASSERT_TRUE(FinishSecondaryExtensionInstall(secondary_app_builder));

  TestKioskExtensionBuilder disabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kExtraSecondaryAppId);
  ASSERT_TRUE(FinishSecondaryExtensionInstall(disabled_secondary_app_builder));

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kExtraSecondaryAppId));
  EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
            extensions::ExtensionPrefs::Get(browser_context())
                ->GetDisableReasons(kExtraSecondaryAppId));

  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kExtraSecondaryAppId));
  EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
            extensions::ExtensionPrefs::Get(browser_context())
                ->GetDisableReasons(kExtraSecondaryAppId));
}

TEST_F(StartupAppLauncherTest, LaunchWithSecondaryExtension) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);

  ASSERT_TRUE(DownloadPrimaryApp(primary_app_builder));

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_builder));

  // Installing primary app with a non-installed secondary app should notify
  // delegate about pending app installation - in this case for secondary app.
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kInstallingApp}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  TestKioskExtensionBuilder secondary_extension_builder(
      Manifest::TYPE_EXTENSION, kSecondaryAppId);
  secondary_extension_builder.set_kiosk_enabled(false);
  ASSERT_TRUE(FinishSecondaryExtensionInstall(secondary_extension_builder));

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
}

TEST_F(StartupAppLauncherTest, OfflineWithPrimaryAndSecondaryAppInstalled) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.set_version("1.0");
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  TestKioskExtensionBuilder secondary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                  kSecondaryAppId);
  secondary_app_builder.set_kiosk_enabled(false);
  scoped_refptr<const extensions::Extension> secondary_app =
      secondary_app_builder.Build();
  service()->AddExtension(secondary_app.get());

  startup_app_launcher_->Initialize();

  // Given that the app is offline enabled and installed, the app should be
  // launched immediately, without waiting for network or checking for updates.
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());

  // Primary app cache checks finished after the startup app launcher reports
  // it's ready should be ignored - i.e. startup app launcher should not attempt
  // to relaunch the app, nor request the update installation.
  startup_app_launcher_->ContinueWithNetworkReady();
  ASSERT_TRUE(DownloadPrimaryApp(kTestPrimaryAppId, "1.1"));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  EXPECT_TRUE(startup_launch_delegate_.launch_state_changes().empty());

  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, IgnoreSecondaryAppsSecondaryApps) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);

  ASSERT_TRUE(DownloadAndInstallPrimaryApp(primary_app_builder));

  startup_launch_delegate_.ClearLaunchStateChanges();

  TestKioskExtensionBuilder secondary_extension_builder(
      Manifest::TYPE_PLATFORM_APP, kSecondaryAppId);
  secondary_extension_builder.set_kiosk_enabled(true);
  secondary_extension_builder.AddSecondaryExtension(kExtraSecondaryAppId);

  ASSERT_TRUE(FinishSecondaryExtensionInstall(secondary_extension_builder));

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());
  startup_launch_delegate_.ClearLaunchStateChanges();

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kLaunchSucceeded}),
            startup_launch_delegate_.launch_state_changes());
  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
  EXPECT_FALSE(registry()->GetInstalledExtension(kExtraSecondaryAppId));

  EXPECT_TRUE(kiosk_app_session_initialized_);
  EXPECT_TRUE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest, SecondaryAppCrxInstallFailure) {
  InitializeLauncherWithNetworkReady();

  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);

  ASSERT_TRUE(DownloadAndInstallPrimaryApp(primary_app_builder));
  startup_launch_delegate_.ClearLaunchStateChanges();

  ASSERT_EQ(std::set<std::string>({kSecondaryAppId}),
            external_apps_loader_handler_->pending_update_urls());
  ASSERT_TRUE(
      external_apps_loader_handler_->FailPendingInstall(kSecondaryAppId));

  EXPECT_EQ(KioskAppLaunchError::Error::kUnableToInstall,
            startup_launch_delegate_.launch_error());

  EXPECT_FALSE(kiosk_app_session_initialized_);
  EXPECT_FALSE(session_manager_.IsSessionStarted());
}

TEST_F(StartupAppLauncherTest,
       SecondaryAppEnabledOnLaunchOverridesInstalledAppState) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                               false);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(
      kExtraSecondaryAppId, true);
  primary_app_builder.set_version("1.0");

  // Add the secondary app that should be disabled on startup - make it enabled
  // initially, so the test can verify the app gets disabled regardless of the
  // initial state.
  TestKioskExtensionBuilder disabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kSecondaryAppId);
  scoped_refptr<const extensions::Extension> disabled_secondary_app =
      disabled_secondary_app_builder.Build();
  service()->AddExtension(disabled_secondary_app.get());

  // Add the secondary app that should be enabled on startup - make it disabled
  // initially, so the test can verify the app gets enabled regardless of the
  // initial state.
  TestKioskExtensionBuilder enabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kExtraSecondaryAppId);

  scoped_refptr<const extensions::Extension> enabled_secondary_app =
      enabled_secondary_app_builder.Build();
  service()->AddExtension(enabled_secondary_app.get());
  service()->DisableExtension(enabled_secondary_app->id(),
                              extensions::disable_reason::DISABLE_USER_ACTION);

  InitializeLauncherWithNetworkReady();
  ASSERT_TRUE(DownloadAndInstallPrimaryApp(primary_app_builder));

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kSecondaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtraSecondaryAppId));
}

TEST_F(StartupAppLauncherTest,
       KeepInstalledAppStateWithNoEnabledOnLaunchProperty) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);
  primary_app_builder.AddSecondaryExtension(kExtraSecondaryAppId);
  primary_app_builder.set_version("1.0");

  TestKioskExtensionBuilder enabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kSecondaryAppId);
  scoped_refptr<const extensions::Extension> enabled_secondary_app =
      enabled_secondary_app_builder.Build();
  service()->AddExtension(enabled_secondary_app.get());

  TestKioskExtensionBuilder disabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kExtraSecondaryAppId);

  scoped_refptr<const extensions::Extension> disabled_secondary_app =
      disabled_secondary_app_builder.Build();
  service()->AddExtension(disabled_secondary_app.get());
  service()->DisableExtension(disabled_secondary_app->id(),
                              extensions::disable_reason::DISABLE_USER_ACTION);

  InitializeLauncherWithNetworkReady();
  ASSERT_TRUE(DownloadAndInstallPrimaryApp(primary_app_builder));

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kExtraSecondaryAppId));
}

TEST_F(StartupAppLauncherTest,
       DoNotEnableSecondayAppsDisabledForNonUserActionReason) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                               true);
  primary_app_builder.set_version("1.0");

  // Add the secondary app that should be enabled on startup - make it disabled
  // initially, so the test can verify the app gets enabled regardless of the
  // initial state.
  TestKioskExtensionBuilder secondary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                  kSecondaryAppId);

  // Disable the secodnary app for a reason different than user action - that
  // disable reason should not be overriden during the kiosk launch.
  scoped_refptr<const extensions::Extension> secondary_app =
      secondary_app_builder.Build();
  service()->AddExtension(secondary_app.get());
  service()->DisableExtension(
      secondary_app->id(),
      extensions::disable_reason::DISABLE_USER_ACTION |
          extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY);

  InitializeLauncherWithNetworkReady();
  ASSERT_TRUE(DownloadAndInstallPrimaryApp(primary_app_builder));

  EXPECT_TRUE(external_apps_loader_handler_->pending_crx_files().empty());
  EXPECT_TRUE(external_apps_loader_handler_->pending_update_urls().empty());
  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  startup_app_launcher_->LaunchApp();

  EXPECT_EQ(1, app_launch_tracker_->kiosk_launch_count());

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kSecondaryAppId));
  EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
            extensions::ExtensionPrefs::Get(browser_context())
                ->GetDisableReasons(kSecondaryAppId));
}

TEST_F(StartupAppLauncherTest, PrimaryAppUpdatesToDisabledOnLaunch) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtension(kSecondaryAppId);
  primary_app_builder.set_version("1.0");
  primary_app_builder.set_offline_enabled(false);
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  TestKioskExtensionBuilder secondary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                  kSecondaryAppId);
  scoped_refptr<const extensions::Extension> secondary_app =
      secondary_app_builder.Build();
  service()->AddExtension(secondary_app.get());

  TestKioskExtensionBuilder primary_app_update(Manifest::TYPE_PLATFORM_APP,
                                               kTestPrimaryAppId);
  primary_app_update.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                              false);
  primary_app_update.set_version("1.1");

  InitializeLauncherWithNetworkReady();
  ASSERT_TRUE(DownloadPrimaryApp(primary_app_update));
  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_update));

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  startup_app_launcher_->LaunchApp();

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kSecondaryAppId));
  EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
            extensions::ExtensionPrefs::Get(browser_context())
                ->GetDisableReasons(kSecondaryAppId));
}

TEST_F(StartupAppLauncherTest, PrimaryAppUpdatesToEnabledOnLaunch) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                               false);
  primary_app_builder.set_version("1.0");
  primary_app_builder.set_offline_enabled(false);
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  TestKioskExtensionBuilder secondary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                  kSecondaryAppId);
  scoped_refptr<const extensions::Extension> secondary_app =
      secondary_app_builder.Build();
  service()->AddExtension(secondary_app.get());
  service()->DisableExtension(secondary_app->id(),
                              extensions::disable_reason::DISABLE_USER_ACTION);

  TestKioskExtensionBuilder primary_app_update(Manifest::TYPE_PLATFORM_APP,
                                               kTestPrimaryAppId);
  primary_app_update.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                              true);
  primary_app_update.set_version("1.1");

  InitializeLauncherWithNetworkReady();
  ASSERT_TRUE(DownloadPrimaryApp(primary_app_update));
  ASSERT_TRUE(FinishPrimaryAppInstall(primary_app_update));

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  startup_app_launcher_->LaunchApp();

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kSecondaryAppId));
}

TEST_F(StartupAppLauncherTest, SecondaryExtensionStateOnSessionRestore) {
  TestKioskExtensionBuilder primary_app_builder(Manifest::TYPE_PLATFORM_APP,
                                                kTestPrimaryAppId);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(kSecondaryAppId,
                                                               false);
  primary_app_builder.AddSecondaryExtensionWithEnabledOnLaunch(
      kExtraSecondaryAppId, true);
  primary_app_builder.set_version("1.0");
  scoped_refptr<const extensions::Extension> primary_app =
      primary_app_builder.Build();
  service()->AddExtension(primary_app.get());

  // Add the secondary app that should be disabled on launch - make it enabled
  // initially, and let test verify it remains enabled during the launch.
  TestKioskExtensionBuilder disabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kSecondaryAppId);
  scoped_refptr<const extensions::Extension> disabled_secondary_app =
      disabled_secondary_app_builder.Build();
  service()->AddExtension(disabled_secondary_app.get());

  // Add the secondary app that should be enabled on launch - make it disabled
  // initially, and let test verify the app remains disabled during the launch.
  TestKioskExtensionBuilder enabled_secondary_app_builder(
      Manifest::TYPE_PLATFORM_APP, kExtraSecondaryAppId);

  scoped_refptr<const extensions::Extension> enabled_secondary_app =
      enabled_secondary_app_builder.Build();
  service()->AddExtension(enabled_secondary_app.get());
  service()->DisableExtension(enabled_secondary_app->id(),
                              extensions::disable_reason::DISABLE_USER_ACTION);

  // This matches the delegate settings during session restart (e.g. after a
  // browser process crash).
  startup_launch_delegate_.set_should_skip_app_installation(true);
  startup_launch_delegate_.set_network_ready(true);
  startup_app_launcher_->Initialize();

  startup_launch_delegate_.WaitForLaunchStates({LaunchState::kReadyToLaunch});
  EXPECT_EQ(std::vector<LaunchState>({LaunchState::kReadyToLaunch}),
            startup_launch_delegate_.launch_state_changes());

  startup_app_launcher_->LaunchApp();

  EXPECT_TRUE(registry()->enabled_extensions().Contains(kTestPrimaryAppId));
  EXPECT_TRUE(registry()->disabled_extensions().Contains(kSecondaryAppId));
  EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtraSecondaryAppId));
}

}  // namespace ash
