// 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/macros.h"
#include "base/run_loop.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_reenabler.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/extension_system_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/test_extensions_browser_client.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/value_builder.h"

namespace extensions {

namespace {

// A simple provider that says all extensions must remain disabled.
class TestManagementProvider : public ManagementPolicy::Provider {
 public:
  TestManagementProvider() {}
  ~TestManagementProvider() override {}

 private:
  // MananagementPolicy::Provider:
  std::string GetDebugPolicyProviderName() const override { return "test"; }
  bool MustRemainDisabled(const Extension* extension,
                          disable_reason::DisableReason* reason,
                          base::string16* error) const override {
    return true;
  }

  DISALLOW_COPY_AND_ASSIGN(TestManagementProvider);
};

// A helper class for all the various callbacks associated with reenabling an
// extension. This class also helps store the results of the run.
class CallbackHelper {
 public:
  CallbackHelper() {}
  ~CallbackHelper() {}

  // Get a callback to run on the completion of the reenable process and reset
  // |result_|.
  ExtensionReenabler::Callback GetCallback() {
    result_.reset();
    return base::Bind(&CallbackHelper::OnComplete,
                      base::Unretained(this));
  }

  // Check if we have receved any result, and if it matches the expected one.
  bool has_result() const { return result_ != nullptr; }
  bool result_matches(ExtensionReenabler::ReenableResult expected) const {
    return result_.get() && *result_ == expected;
  }

  // Create a test ExtensionInstallPrompt that will not display any UI (which
  // causes unit tests to crash), but rather runs the given |quit_closure| (with
  // the prompt still active|.
  ExtensionInstallPrompt::ShowDialogCallback CreateShowCallback(
      const base::Closure& quit_closure) {
    quit_closure_ = quit_closure;
    return base::Bind(&CallbackHelper::OnShow, base::Unretained(this));
  }

 private:
  // The callback to run once the reenable process finishes.
  void OnComplete(ExtensionReenabler::ReenableResult result) {
    result_.reset(new ExtensionReenabler::ReenableResult(result));
  }

  // The callback to run when a test ExtensionInstallPrompt is ready to show.
  void OnShow(ExtensionInstallPromptShowParams* show_params,
              const ExtensionInstallPrompt::DoneCallback& done_callback,
              std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
    DCHECK(!quit_closure_.is_null());
    quit_closure_.Run();
    quit_closure_ = base::Closure();
  }

  // The closure to quit the currently-running loop; used with test
  // ExtensionInstallPrompts.
  base::Closure quit_closure_;

  // The result of the reenable process, or null if the process hasn't finished.
  std::unique_ptr<ExtensionReenabler::ReenableResult> result_;

  DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
};

}  // namespace

class ExtensionReenablerUnitTest : public ExtensionServiceTestBase {
 public:
  ExtensionReenablerUnitTest() {}
  ~ExtensionReenablerUnitTest() override {}

 private:
  void SetUp() override;
  void TearDown() override;

  std::unique_ptr<TestExtensionsBrowserClient> test_browser_client_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionReenablerUnitTest);
};

void ExtensionReenablerUnitTest::SetUp() {
  ExtensionServiceTestBase::SetUp();
  InitializeEmptyExtensionService();
  // We need a TestExtensionsBrowserClient because the real one tries to
  // implicitly convert any browser context to a (non-Testing)Profile.
  test_browser_client_.reset(new TestExtensionsBrowserClient(profile()));
  test_browser_client_->set_extension_system_factory(
      ExtensionSystemFactory::GetInstance());
  ExtensionsBrowserClient::Set(test_browser_client_.get());
}

void ExtensionReenablerUnitTest::TearDown() {
  profile_.reset();
  ExtensionsBrowserClient::Set(nullptr);
  test_browser_client_.reset();
  ExtensionServiceTestBase::TearDown();
}

// Test that the ExtensionReenabler reenables disabled extensions.
TEST_F(ExtensionReenablerUnitTest, TestReenablingDisabledExtension) {
  // Create a simple extension and add it to the service.
  scoped_refptr<const Extension> extension =
      ExtensionBuilder()
          .SetManifest(DictionaryBuilder()
                           .Set("name", "test ext")
                           .Set("version", "1.0")
                           .Set("manifest_version", 2)
                           .Set("description", "a test ext")
                           .Build())
          .SetID(crx_file::id_util::GenerateId("test ext"))
          .Build();
  service()->AddExtension(extension.get());
  EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));

  CallbackHelper callback_helper;

  // Check that the ExtensionReenabler can re-enable disabled extensions.
  {
    // Disable the extension due to a permissions increase (the only type of
    // disablement we handle with the ExtensionReenabler so far).
    service()->DisableExtension(extension->id(),
                                disable_reason::DISABLE_PERMISSIONS_INCREASE);
    // Sanity check that it's disabled.
    EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));

    // Automatically confirm install prompts.
    ScopedTestDialogAutoConfirm auto_confirm(
        ScopedTestDialogAutoConfirm::ACCEPT);

    // Run the ExtensionReenabler.
    std::unique_ptr<ExtensionReenabler> extension_reenabler =
        ExtensionReenabler::PromptForReenable(extension, profile(),
                                              nullptr,  // No web contents.
                                              GURL(),   // No referrer.
                                              callback_helper.GetCallback());
    base::RunLoop().RunUntilIdle();

    // The extension should be enabled.
    EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
    EXPECT_TRUE(
        callback_helper.result_matches(ExtensionReenabler::REENABLE_SUCCESS));
  }

  // Check that we don't re-enable extensions that must remain disabled, and
  // that the re-enabler reports failure correctly.
  {
    ScopedTestDialogAutoConfirm auto_confirm(
        ScopedTestDialogAutoConfirm::ACCEPT);

    ManagementPolicy* management_policy =
        ExtensionSystem::Get(browser_context())->management_policy();
    ASSERT_TRUE(management_policy);
    TestManagementProvider test_provider;
    management_policy->RegisterProvider(&test_provider);
    service()->DisableExtension(extension->id(),
                                disable_reason::DISABLE_PERMISSIONS_INCREASE);

    std::unique_ptr<ExtensionReenabler> extension_reenabler =
        ExtensionReenabler::PromptForReenable(extension, profile(),
                                              nullptr,  // No web contents.
                                              GURL(),   // No referrer.
                                              callback_helper.GetCallback());
    base::RunLoop().RunUntilIdle();

    // The extension should be enabled.
    EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
    EXPECT_TRUE(
        callback_helper.result_matches(ExtensionReenabler::NOT_ALLOWED));

    management_policy->UnregisterProvider(&test_provider);
  }

  // Check that canceling the re-enable prompt doesn't re-enable the extension.
  {
    // Disable it again, and try canceling the prompt.
    service()->DisableExtension(extension->id(),
                                disable_reason::DISABLE_PERMISSIONS_INCREASE);
    ScopedTestDialogAutoConfirm auto_confirm(
        ScopedTestDialogAutoConfirm::CANCEL);
    std::unique_ptr<ExtensionReenabler> extension_reenabler =
        ExtensionReenabler::PromptForReenable(extension, profile(),
                                              nullptr,  // No web contents.
                                              GURL(),   // No referrer.
                                              callback_helper.GetCallback());
    base::RunLoop().RunUntilIdle();

    // The extension should remain disabled.
    EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
    EXPECT_TRUE(
        callback_helper.result_matches(ExtensionReenabler::USER_CANCELED));
  }

  // Test that if the extension is re-enabled while the prompt is active, the
  // prompt exits and reports success.
  {
    base::RunLoop run_loop;
    std::unique_ptr<ExtensionReenabler> extension_reenabler =
        ExtensionReenabler::PromptForReenableWithCallbackForTest(
            extension, profile(), callback_helper.GetCallback(),
            callback_helper.CreateShowCallback(run_loop.QuitClosure()));
    run_loop.Run();

    // We shouldn't have any result yet (the user hasn't confirmed or canceled).
    EXPECT_FALSE(callback_helper.has_result());

    // Reenable the extension. This should count as a success for reenabling.
    service()->GrantPermissionsAndEnableExtension(extension.get());
    EXPECT_TRUE(
        callback_helper.result_matches(ExtensionReenabler::REENABLE_SUCCESS));
  }

  // Test that prematurely destroying the re-enable prompt doesn't crash and
  // reports an "aborted" result.
  {
    // Disable again, and create another prompt.
    service()->DisableExtension(extension->id(),
                                disable_reason::DISABLE_PERMISSIONS_INCREASE);
    base::RunLoop run_loop;
    std::unique_ptr<ExtensionReenabler> extension_reenabler =
        ExtensionReenabler::PromptForReenableWithCallbackForTest(
            extension, profile(), callback_helper.GetCallback(),
            callback_helper.CreateShowCallback(run_loop.QuitClosure()));
    run_loop.Run();
    EXPECT_FALSE(callback_helper.has_result());
    // Destroy the reenabler to simulate the owning context being shut down
    // (e.g., the tab closing).
    extension_reenabler.reset();
    EXPECT_TRUE(
        callback_helper.result_matches(ExtensionReenabler::ABORTED));
  }
}

}  // namespace extensions
