// Copyright 2014 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 "base/message_loop/message_loop_proxy.h"
#include "chrome/browser/apps/ephemeral_app_launcher.h"
#include "chrome/browser/apps/ephemeral_app_service.h"
#include "chrome/browser/extensions/extension_install_checker.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/install_tracker.h"
#include "chrome/browser/extensions/test_blacklist.h"
#include "chrome/browser/extensions/webstore_installer_test.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"

using extensions::Extension;
using extensions::ExtensionPrefs;
using extensions::ExtensionRegistry;
using extensions::ExtensionSystem;
using extensions::InstallTracker;
namespace webstore_install = extensions::webstore_install;

namespace {

const char kWebstoreDomain[] = "cws.com";
const char kAppDomain[] = "app.com";
const char kNonAppDomain[] = "nonapp.com";
const char kTestDataPath[] = "extensions/platform_apps/ephemeral_launcher";

const char kExtensionId[] = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeid";
const char kExtensionTestPath[] = "extension";
const char kLegacyAppId[] = "lnbochkobjfnhbnbljgfgokadhmbahcn";
const char kLegacyAppTestPath[] = "legacy_app";
const char kNonExistentId[] = "baaaaaaaaaaaaaaaaaaaaaaaaaaaadid";
const char kDefaultAppId[] = "kbiancnbopdghkfedjhfdoegjadfjeal";
const char kDefaultAppCrxFilename[] = "app.crx";
const char kDefaultAppTestPath[] = "app";
const char kAppWithPermissionsId[] = "mbfcnecjknjpipkfkoangpfnhhlpamki";
const char kAppWithPermissionsFilename[] = "app_with_permissions.crx";
const char kHostedAppId[] = "haaaaaaaaaaaaaaaaaaaaaaaaaaappid";
const char kHostedAppLaunchUrl[] = "http://foo.bar.com";

class ExtensionInstallCheckerMock : public extensions::ExtensionInstallChecker {
 public:
  ExtensionInstallCheckerMock(Profile* profile,
                              const std::string& requirements_error)
      : extensions::ExtensionInstallChecker(profile),
        requirements_error_(requirements_error) {}

  ~ExtensionInstallCheckerMock() override {}

 private:
  void CheckRequirements() override {
    // Simulate an asynchronous operation.
    base::MessageLoopProxy::current()->PostTask(
        FROM_HERE,
        base::Bind(&ExtensionInstallCheckerMock::RequirementsErrorCheckDone,
                   base::Unretained(this),
                   current_sequence_number()));
  }

  void RequirementsErrorCheckDone(int sequence_number) {
    std::vector<std::string> errors;
    errors.push_back(requirements_error_);
    OnRequirementsCheckDone(sequence_number, errors);
  }

  std::string requirements_error_;
};

class EphemeralAppLauncherForTest : public EphemeralAppLauncher {
 public:
  EphemeralAppLauncherForTest(const std::string& id,
                              Profile* profile,
                              const LaunchCallback& callback)
      : EphemeralAppLauncher(id, profile, NULL, callback),
        install_initiated_(false),
        install_prompt_created_(false) {}

  EphemeralAppLauncherForTest(const std::string& id, Profile* profile)
      : EphemeralAppLauncher(id, profile, NULL, LaunchCallback()),
        install_initiated_(false),
        install_prompt_created_(false) {}

  bool install_initiated() const { return install_initiated_; }
  bool install_prompt_created() const { return install_prompt_created_; }

  void set_requirements_error(const std::string& error) {
    requirements_check_error_ = error;
  }

 private:
  // Override necessary functions for testing.

  scoped_ptr<extensions::ExtensionInstallChecker> CreateInstallChecker()
      override {
    if (requirements_check_error_.empty()) {
      return EphemeralAppLauncher::CreateInstallChecker();
    } else {
      return scoped_ptr<extensions::ExtensionInstallChecker>(
          new ExtensionInstallCheckerMock(profile(),
                                          requirements_check_error_));
    }
  }

  scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() override {
    install_prompt_created_ = true;
    return EphemeralAppLauncher::CreateInstallUI();
  }

  scoped_ptr<extensions::WebstoreInstaller::Approval> CreateApproval()
      const override {
    install_initiated_ = true;
    return EphemeralAppLauncher::CreateApproval();
  }

 private:
  ~EphemeralAppLauncherForTest() override {}
  friend class base::RefCountedThreadSafe<EphemeralAppLauncherForTest>;

  mutable bool install_initiated_;
  std::string requirements_check_error_;
  bool install_prompt_created_;
};

class LaunchObserver {
 public:
  LaunchObserver()
      : done_(false),
        waiting_(false),
        result_(webstore_install::OTHER_ERROR) {}

  webstore_install::Result result() const { return result_; }
  const std::string& error() const { return error_; }

  void OnLaunchCallback(webstore_install::Result result,
                        const std::string& error) {
    result_ = result;
    error_ = error;
    done_ = true;
    if (waiting_) {
      waiting_ = false;
      base::MessageLoopForUI::current()->Quit();
    }
  }

  void Wait() {
    if (done_)
      return;

    waiting_ = true;
    content::RunMessageLoop();
  }

 private:
  bool done_;
  bool waiting_;
  webstore_install::Result result_;
  std::string error_;
};

class ManagementPolicyMock : public extensions::ManagementPolicy::Provider {
 public:
  ManagementPolicyMock() {}

  std::string GetDebugPolicyProviderName() const override {
    return "ManagementPolicyMock";
  }

  bool UserMayLoad(const Extension* extension,
                   base::string16* error) const override {
    return false;
  }
};

}  // namespace

class EphemeralAppLauncherTest : public WebstoreInstallerTest {
 public:
  EphemeralAppLauncherTest()
      : WebstoreInstallerTest(kWebstoreDomain,
                              kTestDataPath,
                              kDefaultAppCrxFilename,
                              kAppDomain,
                              kNonAppDomain) {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    WebstoreInstallerTest::SetUpCommandLine(command_line);

    // Make event pages get suspended immediately.
    extensions::ProcessManager::SetEventPageIdleTimeForTesting(1);
    extensions::ProcessManager::SetEventPageSuspendingTimeForTesting(1);

    // Enable ephemeral apps flag.
    command_line->AppendSwitch(switches::kEnableEphemeralApps);
  }

  void SetUpOnMainThread() override {
    WebstoreInstallerTest::SetUpOnMainThread();

    // Disable ephemeral apps immediately after they stop running in tests.
    EphemeralAppService::Get(profile())->set_disable_delay_for_test(0);
  }

  base::FilePath GetTestPath(const char* test_name) {
    return test_data_dir_.AppendASCII("platform_apps/ephemeral_launcher")
        .AppendASCII(test_name);
  }

  const Extension* GetInstalledExtension(const std::string& id) {
    return ExtensionRegistry::Get(profile())
        ->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
  }

  void SetCrxFilename(const std::string& filename) {
    GURL crx_url = GenerateTestServerUrl(kWebstoreDomain, filename);
    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryUpdateURL, crx_url.spec());
  }

  void StartLauncherAndCheckResult(EphemeralAppLauncherForTest* launcher,
                                   webstore_install::Result expected_result,
                                   bool expect_install_initiated) {
    ExtensionTestMessageListener launched_listener("launched", false);
    LaunchObserver launch_observer;

    launcher->launch_callback_ = base::Bind(&LaunchObserver::OnLaunchCallback,
                                            base::Unretained(&launch_observer));
    launcher->Start();
    launch_observer.Wait();

    // Verify the launch result.
    EXPECT_EQ(expected_result, launch_observer.result());
    EXPECT_EQ(expect_install_initiated, launcher->install_initiated());

    // Verify that the app was actually launched if the launcher succeeded.
    if (launch_observer.result() == webstore_install::SUCCESS)
      EXPECT_TRUE(launched_listener.WaitUntilSatisfied());
    else
      EXPECT_FALSE(launched_listener.was_satisfied());

    // Check the reference count to ensure the launcher instance will not be
    // leaked.
    EXPECT_TRUE(launcher->HasOneRef());
  }

  void RunLaunchTest(const std::string& id,
                     webstore_install::Result expected_result,
                     bool expect_install_initiated) {
    InstallTracker* tracker = InstallTracker::Get(profile());
    ASSERT_TRUE(tracker);
    bool was_install_active = !!tracker->GetActiveInstall(id);

    scoped_refptr<EphemeralAppLauncherForTest> launcher(
        new EphemeralAppLauncherForTest(id, profile()));
    StartLauncherAndCheckResult(
        launcher.get(), expected_result, expect_install_initiated);

    // Verify that the install was deregistered from the InstallTracker.
    EXPECT_EQ(was_install_active, !!tracker->GetActiveInstall(id));
  }

  void ValidateAppInstalledEphemerally(const std::string& id) {
    EXPECT_TRUE(GetInstalledExtension(id));
    EXPECT_TRUE(extensions::util::IsEphemeralApp(id, profile()));
  }

  const Extension* InstallAndDisableApp(
      const char* test_path,
      Extension::DisableReason disable_reason) {
    const Extension* app = InstallExtension(GetTestPath(test_path), 1);
    EXPECT_TRUE(app);
    if (!app)
      return NULL;

    ExtensionService* service =
        ExtensionSystem::Get(profile())->extension_service();
    service->DisableExtension(app->id(), disable_reason);

    if (disable_reason == Extension::DISABLE_PERMISSIONS_INCREASE) {
      // When an extension is disabled due to a permissions increase, this
      // flag needs to be set too, for some reason.
      ExtensionPrefs::Get(profile())
          ->SetDidExtensionEscalatePermissions(app, true);
    }

    EXPECT_TRUE(
        ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
            app->id()));
    return app;
  }
};

class EphemeralAppLauncherTestDisabled : public EphemeralAppLauncherTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    // Skip EphemeralAppLauncherTest as it enables the feature.
    WebstoreInstallerTest::SetUpCommandLine(command_line);
  }
};

// Verifies that an ephemeral app will not be installed and launched if the
// feature is disabled.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTestDisabled, FeatureDisabled) {
  RunLaunchTest(
      kDefaultAppCrxFilename, webstore_install::LAUNCH_FEATURE_DISABLED, false);
  EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
}

// Verifies that an app with no permission warnings will be installed
// ephemerally and launched without prompting the user.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
                       LaunchAppWithNoPermissionWarnings) {
  content::WindowedNotificationObserver unloaded_signal(
      extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
      content::Source<Profile>(profile()));

  scoped_refptr<EphemeralAppLauncherForTest> launcher(
      new EphemeralAppLauncherForTest(kDefaultAppId, profile()));
  StartLauncherAndCheckResult(launcher.get(), webstore_install::SUCCESS, true);
  ValidateAppInstalledEphemerally(kDefaultAppId);

  // Apps with no permission warnings should not result in a prompt.
  EXPECT_FALSE(launcher->install_prompt_created());

  // Ephemeral apps are unloaded after they stop running.
  unloaded_signal.Wait();

  // After an app has been installed ephemerally, it can be launched again
  // without installing from the web store.
  RunLaunchTest(kDefaultAppId, webstore_install::SUCCESS, false);
}

// Verifies that an app with permission warnings will be installed
// ephemerally and launched if accepted by the user.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
                       LaunchAppWithPermissionsWarnings) {
  SetCrxFilename(kAppWithPermissionsFilename);
  AutoAcceptInstall();

  scoped_refptr<EphemeralAppLauncherForTest> launcher(
      new EphemeralAppLauncherForTest(kAppWithPermissionsId, profile()));
  StartLauncherAndCheckResult(launcher.get(), webstore_install::SUCCESS, true);
  ValidateAppInstalledEphemerally(kAppWithPermissionsId);
  EXPECT_TRUE(launcher->install_prompt_created());
}

// Verifies that an app with permission warnings will not be installed
// ephemerally if cancelled by the user.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
                       CancelInstallAppWithPermissionWarnings) {
  SetCrxFilename(kAppWithPermissionsFilename);
  AutoCancelInstall();

  scoped_refptr<EphemeralAppLauncherForTest> launcher(
      new EphemeralAppLauncherForTest(kAppWithPermissionsId, profile()));
  StartLauncherAndCheckResult(
      launcher.get(), webstore_install::USER_CANCELLED, false);
  EXPECT_FALSE(GetInstalledExtension(kAppWithPermissionsId));
  EXPECT_TRUE(launcher->install_prompt_created());
}

// Verifies that an extension will not be installed ephemerally.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, InstallExtension) {
  RunLaunchTest(
      kExtensionId, webstore_install::LAUNCH_UNSUPPORTED_EXTENSION_TYPE, false);
  EXPECT_FALSE(GetInstalledExtension(kExtensionId));
}

// Verifies that an already installed extension will not be launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchExtension) {
  const Extension* extension =
      InstallExtension(GetTestPath(kExtensionTestPath), 1);
  ASSERT_TRUE(extension);
  RunLaunchTest(extension->id(),
                webstore_install::LAUNCH_UNSUPPORTED_EXTENSION_TYPE,
                false);
}

// Verifies that a legacy packaged app will not be installed ephemerally.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, InstallLegacyApp) {
  RunLaunchTest(
      kLegacyAppId, webstore_install::LAUNCH_UNSUPPORTED_EXTENSION_TYPE, false);
  EXPECT_FALSE(GetInstalledExtension(kLegacyAppId));
}

// Verifies that a legacy packaged app that is already installed can be
// launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchLegacyApp) {
  const Extension* extension =
      InstallExtension(GetTestPath(kLegacyAppTestPath), 1);
  ASSERT_TRUE(extension);
  RunLaunchTest(extension->id(), webstore_install::SUCCESS, false);
}

// Verifies that a hosted app is not installed. Launch succeeds because we
// navigate to its launch url.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchHostedApp) {
  LaunchObserver launch_observer;

  scoped_refptr<EphemeralAppLauncherForTest> launcher(
      new EphemeralAppLauncherForTest(
          kHostedAppId,
          profile(),
          base::Bind(&LaunchObserver::OnLaunchCallback,
                     base::Unretained(&launch_observer))));
  launcher->Start();
  launch_observer.Wait();

  EXPECT_EQ(webstore_install::SUCCESS, launch_observer.result());
  EXPECT_FALSE(launcher->install_initiated());
  EXPECT_FALSE(GetInstalledExtension(kHostedAppId));

  // Verify that a navigation to the launch url was attempted.
  Browser* browser =
      FindBrowserWithProfile(profile(), chrome::GetActiveDesktop());
  ASSERT_TRUE(browser);
  content::WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  ASSERT_TRUE(web_contents);
  EXPECT_EQ(GURL(kHostedAppLaunchUrl), web_contents->GetVisibleURL());
}

// Verifies that the EphemeralAppLauncher handles non-existent extension ids.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, NonExistentExtensionId) {
  RunLaunchTest(
      kNonExistentId, webstore_install::WEBSTORE_REQUEST_ERROR, false);
  EXPECT_FALSE(GetInstalledExtension(kNonExistentId));
}

// Verifies that an app blocked by management policy is not installed
// ephemerally.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlockedByPolicy) {
  // Register a provider that blocks the installation of all apps.
  ManagementPolicyMock policy;
  ExtensionSystem::Get(profile())->management_policy()->RegisterProvider(
      &policy);

  RunLaunchTest(kDefaultAppId, webstore_install::BLOCKED_BY_POLICY, false);
  EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
}

// Verifies that an app blacklisted for malware is not installed ephemerally.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlacklistedForMalware) {
  // Mock a BLACKLISTED_MALWARE return status.
  extensions::TestBlacklist blacklist_tester(
      extensions::Blacklist::Get(profile()));
  blacklist_tester.SetBlacklistState(
      kDefaultAppId, extensions::BLACKLISTED_MALWARE, false);

  RunLaunchTest(kDefaultAppId, webstore_install::BLACKLISTED, false);
  EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
}

// Verifies that an app with unknown blacklist status is installed ephemerally
// and launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlacklistStateUnknown) {
  // Mock a BLACKLISTED_MALWARE return status.
  extensions::TestBlacklist blacklist_tester(
      extensions::Blacklist::Get(profile()));
  blacklist_tester.SetBlacklistState(
      kDefaultAppId, extensions::BLACKLISTED_UNKNOWN, false);

  RunLaunchTest(kDefaultAppId, webstore_install::SUCCESS, true);
  ValidateAppInstalledEphemerally(kDefaultAppId);
}

// Verifies that an app with unsupported requirements is not installed
// ephemerally.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, UnsupportedRequirements) {
  scoped_refptr<EphemeralAppLauncherForTest> launcher(
      new EphemeralAppLauncherForTest(kDefaultAppId, profile()));
  launcher->set_requirements_error("App has unsupported requirements");

  StartLauncherAndCheckResult(
      launcher.get(), webstore_install::REQUIREMENT_VIOLATIONS, false);
  EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
}

// Verifies that an app disabled due to permissions increase can be enabled
// and launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, EnableAndLaunchApp) {
  const Extension* app = InstallAndDisableApp(
      kDefaultAppTestPath, Extension::DISABLE_PERMISSIONS_INCREASE);
  ASSERT_TRUE(app);

  AutoAcceptInstall();
  RunLaunchTest(app->id(), webstore_install::SUCCESS, false);
}

// Verifies that if the user cancels the enable flow, the app will not be
// enabled and launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, EnableCancelled) {
  const Extension* app = InstallAndDisableApp(
      kDefaultAppTestPath, Extension::DISABLE_PERMISSIONS_INCREASE);
  ASSERT_TRUE(app);

  AutoCancelInstall();
  RunLaunchTest(app->id(), webstore_install::USER_CANCELLED, false);
}

// Verifies that an installed app that had been blocked by policy cannot be
// launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchAppBlockedByPolicy) {
  const Extension* app = InstallExtension(GetTestPath(kDefaultAppTestPath), 1);
  ASSERT_TRUE(app);

  // Simulate blocking of the app after it has been installed.
  ManagementPolicyMock policy;
  ExtensionSystem::Get(profile())->management_policy()->RegisterProvider(
      &policy);
  ExtensionSystem::Get(profile())->extension_service()->CheckManagementPolicy();

  RunLaunchTest(app->id(), webstore_install::BLOCKED_BY_POLICY, false);
}

// Verifies that an installed blacklisted app cannot be launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchBlacklistedApp) {
  const Extension* app = InstallExtension(GetTestPath(kDefaultAppTestPath), 1);
  ASSERT_TRUE(app);

  ExtensionService* service =
      ExtensionSystem::Get(profile())->extension_service();
  service->BlacklistExtensionForTest(app->id());
  ASSERT_TRUE(
      ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains(
          app->id()));

  RunLaunchTest(app->id(), webstore_install::BLACKLISTED, false);
}

// Verifies that an installed app with unsupported requirements cannot be
// launched.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
                       LaunchAppWithUnsupportedRequirements) {
  const Extension* app = InstallAndDisableApp(
      kDefaultAppTestPath, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
  ASSERT_TRUE(app);

  RunLaunchTest(app->id(), webstore_install::REQUIREMENT_VIOLATIONS, false);
}

// Verifies that a launch will fail if the app is currently being installed.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, InstallInProgress) {
  extensions::ActiveInstallData install_data(kDefaultAppId);
  InstallTracker::Get(profile())->AddActiveInstall(install_data);

  RunLaunchTest(kDefaultAppId, webstore_install::INSTALL_IN_PROGRESS, false);
}

// Verifies that a launch will fail if a duplicate launch is in progress.
IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, DuplicateLaunchInProgress) {
  extensions::ActiveInstallData install_data(kDefaultAppId);
  install_data.is_ephemeral = true;
  InstallTracker::Get(profile())->AddActiveInstall(install_data);

  RunLaunchTest(kDefaultAppId, webstore_install::LAUNCH_IN_PROGRESS, false);
}
