// 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 <list>
#include <set>
#include <string>

#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/extensions/browsertest_util.h"
#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/policy_extension_reinstaller.h"
#include "chrome/common/chrome_switches.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/content_verifier.h"
#include "extensions/browser/content_verify_job.h"
#include "extensions/browser/crx_file_info.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/external_install_info.h"
#include "extensions/browser/external_provider_interface.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/updater/extension_downloader.h"
#include "extensions/browser/updater/extension_downloader_test_delegate.h"
#include "extensions/browser/updater/manifest_fetch_data.h"
#include "extensions/common/extension_urls.h"

#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif

namespace extensions {

namespace {

// Helper for observing extension registry events.
class RegistryObserver : public ExtensionRegistryObserver {
 public:
  explicit RegistryObserver(ExtensionRegistry* registry) : observer_(this) {
    observer_.Add(registry);
  }
  ~RegistryObserver() override {}

  // Waits until we've seen an unload for extension with |id|, returning true
  // if we saw one or false otherwise (typically because of test timeout).
  bool WaitForUnload(const ExtensionId& id) {
    if (base::ContainsKey(unloaded_, id))
      return true;

    base::RunLoop run_loop;
    awaited_unload_id_ = id;
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
    return base::ContainsKey(unloaded_, id);
  }

  // Same as WaitForUnload, but for an install.
  bool WaitForInstall(const ExtensionId& id) {
    if (base::ContainsKey(installed_, id))
      return true;

    base::RunLoop run_loop;
    awaited_install_id_ = id;
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
    return base::ContainsKey(installed_, id);
  }

  // ExtensionRegistryObserver
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionInfo::Reason reason) override {
    unloaded_.insert(extension->id());
    if (awaited_unload_id_ == extension->id()) {
      awaited_unload_id_.clear();
      base::ResetAndReturn(&quit_closure_).Run();
    }
  }

  void OnExtensionInstalled(content::BrowserContext* browser_context,
                            const Extension* extension,
                            bool is_update) override {
    installed_.insert(extension->id());
    if (awaited_install_id_ == extension->id()) {
      awaited_install_id_.clear();
      base::ResetAndReturn(&quit_closure_).Run();
    }
  }

 private:
  // The id we're waiting for a load/install of respectively.
  ExtensionId awaited_unload_id_;
  ExtensionId awaited_install_id_;

  // The quit closure for stopping a running RunLoop, if we're waiting.
  base::Closure quit_closure_;

  // The extension id's we've seen unloaded and installed, respectively.
  std::set<ExtensionId> unloaded_;
  std::set<ExtensionId> installed_;

  ScopedObserver<ExtensionRegistry, RegistryObserver> observer_;

  DISALLOW_COPY_AND_ASSIGN(RegistryObserver);
};

// Helper for forcing ContentVerifyJob's to return an error.
class JobDelegate : public ContentVerifyJob::TestDelegate {
 public:
  JobDelegate()
      : fail_next_read_(false),
        fail_next_done_(false),
        bytes_read_failed_(0),
        done_reading_failed_(0) {}

  ~JobDelegate() override {}

  void set_id(const ExtensionId& id) { id_ = id; }
  void fail_next_read() { fail_next_read_ = true; }
  void fail_next_done() { fail_next_done_ = true; }

  // Return the number of BytesRead/DoneReading calls we actually failed,
  // respectively.
  int bytes_read_failed() { return bytes_read_failed_; }
  int done_reading_failed() { return done_reading_failed_; }

  ContentVerifyJob::FailureReason BytesRead(const ExtensionId& id,
                                            int count,
                                            const char* data) override {
    if (id == id_ && fail_next_read_) {
      fail_next_read_ = false;
      bytes_read_failed_++;
      return ContentVerifyJob::HASH_MISMATCH;
    }
    return ContentVerifyJob::NONE;
  }

  ContentVerifyJob::FailureReason DoneReading(const ExtensionId& id) override {
    if (id == id_ && fail_next_done_) {
      fail_next_done_ = false;
      done_reading_failed_++;
      return ContentVerifyJob::HASH_MISMATCH;
    }
    return ContentVerifyJob::NONE;
  }

 private:
  ExtensionId id_;
  bool fail_next_read_;
  bool fail_next_done_;
  int bytes_read_failed_;
  int done_reading_failed_;

  DISALLOW_COPY_AND_ASSIGN(JobDelegate);
};

class JobObserver : public ContentVerifyJob::TestObserver {
 public:
  JobObserver();
  virtual ~JobObserver();

  enum class Result { SUCCESS, FAILURE };

  // Call this to add an expected job result.
  void ExpectJobResult(const std::string& extension_id,
                       const base::FilePath& relative_path,
                       Result expected_result);

  // Wait to see expected jobs. Returns true when we've seen all expected jobs
  // finish, or false if there was an error or timeout.
  bool WaitForExpectedJobs();

  // ContentVerifyJob::TestObserver interface
  void JobStarted(const std::string& extension_id,
                  const base::FilePath& relative_path) override;

  void JobFinished(const std::string& extension_id,
                   const base::FilePath& relative_path,
                   ContentVerifyJob::FailureReason failure_reason) override;

 private:
  struct ExpectedResult {
   public:
    std::string extension_id;
    base::FilePath path;
    Result result;

    ExpectedResult(const std::string& extension_id, const base::FilePath& path,
                   Result result) {
      this->extension_id = extension_id;
      this->path = path;
      this->result = result;
    }
  };
  std::list<ExpectedResult> expectations_;
  content::BrowserThread::ID creation_thread_;
  scoped_refptr<content::MessageLoopRunner> loop_runner_;
};

void JobObserver::ExpectJobResult(const std::string& extension_id,
                                  const base::FilePath& relative_path,
                                  Result expected_result) {
  expectations_.push_back(ExpectedResult(
      extension_id, relative_path, expected_result));
}

JobObserver::JobObserver() {
  EXPECT_TRUE(
      content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_));
  ContentVerifyJob::SetObserverForTests(this);
}

JobObserver::~JobObserver() {
  ContentVerifyJob::SetObserverForTests(nullptr);
}

bool JobObserver::WaitForExpectedJobs() {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_));
  if (!expectations_.empty()) {
    loop_runner_ = new content::MessageLoopRunner();
    loop_runner_->Run();
    loop_runner_ = nullptr;
  }
  return expectations_.empty();
}

void JobObserver::JobStarted(const std::string& extension_id,
                             const base::FilePath& relative_path) {
}

void JobObserver::JobFinished(const std::string& extension_id,
                              const base::FilePath& relative_path,
                              ContentVerifyJob::FailureReason failure_reason) {
  if (!content::BrowserThread::CurrentlyOn(creation_thread_)) {
    content::BrowserThread::PostTask(
        creation_thread_, FROM_HERE,
        base::Bind(&JobObserver::JobFinished, base::Unretained(this),
                   extension_id, relative_path, failure_reason));
    return;
  }
  Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS
                                                           : Result::FAILURE;
  bool found = false;
  for (std::list<ExpectedResult>::iterator i = expectations_.begin();
       i != expectations_.end(); ++i) {
    if (i->extension_id == extension_id && i->path == relative_path &&
        i->result == result) {
      found = true;
      expectations_.erase(i);
      break;
    }
  }
  if (found) {
    if (expectations_.empty() && loop_runner_.get())
      loop_runner_->Quit();
  } else {
    LOG(WARNING) << "Ignoring unexpected JobFinished " << extension_id << "/"
                 << relative_path.value()
                 << " failure_reason:" << failure_reason;
  }
}

class VerifierObserver : public ContentVerifier::TestObserver {
 public:
  VerifierObserver();
  virtual ~VerifierObserver();

  const std::set<std::string>& completed_fetches() {
    return completed_fetches_;
  }

  // Returns when we've seen OnFetchComplete for |extension_id|.
  void WaitForFetchComplete(const std::string& extension_id);

  // ContentVerifier::TestObserver
  void OnFetchComplete(const std::string& extension_id, bool success) override;

 private:
  std::set<std::string> completed_fetches_;
  std::string id_to_wait_for_;
  scoped_refptr<content::MessageLoopRunner> loop_runner_;
};

VerifierObserver::VerifierObserver() {
  ContentVerifier::SetObserverForTests(this);
}

VerifierObserver::~VerifierObserver() {
  ContentVerifier::SetObserverForTests(nullptr);
}

void VerifierObserver::WaitForFetchComplete(const std::string& extension_id) {
  EXPECT_TRUE(id_to_wait_for_.empty());
  EXPECT_EQ(loop_runner_.get(), nullptr);
  id_to_wait_for_ = extension_id;
  loop_runner_ = new content::MessageLoopRunner();
  loop_runner_->Run();
  id_to_wait_for_.clear();
  loop_runner_ = nullptr;
}

void VerifierObserver::OnFetchComplete(const std::string& extension_id,
                                       bool success) {
  completed_fetches_.insert(extension_id);
  if (extension_id == id_to_wait_for_)
    loop_runner_->Quit();
}

// This lets us intercept requests for update checks of extensions, and
// substitute a local file as a simulated response.
class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
 public:
  DownloaderTestDelegate() {}

  // This makes it so that update check requests for |extension_id| will return
  // a downloaded file of |crx_path| that is claimed to have version
  // |version_string|.
  void AddResponse(const ExtensionId& extension_id,
                   const std::string& version_string,
                   const base::FilePath& crx_path) {
    responses_[extension_id] = std::make_pair(version_string, crx_path);
  }

  const std::vector<std::unique_ptr<ManifestFetchData>>& requests() {
    return requests_;
  }

  // ExtensionDownloaderTestDelegate:
  void StartUpdateCheck(
      ExtensionDownloader* downloader,
      ExtensionDownloaderDelegate* delegate,
      std::unique_ptr<ManifestFetchData> fetch_data) override {
    requests_.push_back(std::move(fetch_data));
    const ManifestFetchData* data = requests_.back().get();

    for (const auto& id : data->extension_ids()) {
      if (ContainsKey(responses_, id)) {
        // We use PostTask here instead of calling OnExtensionDownloadFinished
        // immeditately, because the calling code isn't expecting a synchronous
        // response (in non-test situations there are at least 2 network
        // requests needed before a file could be returned).
        base::ThreadTaskRunnerHandle::Get()->PostTask(
            FROM_HERE,
            base::Bind(
                &ExtensionDownloaderDelegate::OnExtensionDownloadFinished,
                base::Unretained(delegate),
                CRXFileInfo(id, responses_[id].second),
                false /* pass_file_ownership */, GURL(), responses_[id].first,
                ExtensionDownloaderDelegate::PingResult(), data->request_ids(),
                ExtensionDownloaderDelegate::InstallCallback()));
      }
    }
  }

 private:
  // The requests we've received.
  std::vector<std::unique_ptr<ManifestFetchData>> requests_;

  // The prepared responses - this maps an extension id to a (version string,
  // crx file path) pair.
  std::map<std::string, std::pair<ExtensionId, base::FilePath>> responses_;

  DISALLOW_COPY_AND_ASSIGN(DownloaderTestDelegate);
};

// This lets us simulate the behavior of an enterprise policy that wants
// a given extension to be installed via the webstore.
class TestExternalProvider : public ExternalProviderInterface {
 public:
  TestExternalProvider(VisitorInterface* visitor,
                       const ExtensionId& extension_id)
      : visitor_(visitor), extension_id_(extension_id) {}

  ~TestExternalProvider() override {}

  // ExternalProviderInterface:
  void ServiceShutdown() override {}

  void VisitRegisteredExtension() override {
    visitor_->OnExternalExtensionUpdateUrlFound(
        ExternalInstallInfoUpdateUrl(
            extension_id_, std::string() /* install_parameter */,
            base::MakeUnique<GURL>(extension_urls::GetWebstoreUpdateUrl()),
            Manifest::EXTERNAL_POLICY_DOWNLOAD, 0 /* creation_flags */,
            true /* mark_acknowledged */),
        true /* is_initial_load */);
    visitor_->OnExternalProviderReady(this);
  }

  bool HasExtension(const ExtensionId& id) const override {
    return id == std::string("npnbmohejbjohgpjnmjagbafnjhkmgko");
  }

  bool GetExtensionDetails(
      const ExtensionId& id,
      Manifest::Location* location,
      std::unique_ptr<base::Version>* version) const override {
    ADD_FAILURE() << "Unexpected GetExtensionDetails call; id:" << id;
    return false;
  }

  bool IsReady() const override { return true; }

 private:
  VisitorInterface* visitor_;
  ExtensionId extension_id_;
  base::Closure quit_closure_;

  DISALLOW_COPY_AND_ASSIGN(TestExternalProvider);
};

// This lets us simulate a policy-installed extension being "force" installed;
// ie a user is not allowed to manually uninstall/disable it.
class ForceInstallProvider : public ManagementPolicy::Provider {
 public:
  explicit ForceInstallProvider(const ExtensionId& id) : id_(id) {}
  ~ForceInstallProvider() override {}

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

  // MananagementPolicy::Provider:
  bool UserMayModifySettings(const Extension* extension,
                             base::string16* error) const override {
    return extension->id() != id_;
  }
  bool MustRemainEnabled(const Extension* extension,
                         base::string16* error) const override {
    return extension->id() == id_;
  }

 private:
  // The extension id we want to disallow uninstall/disable for.
  ExtensionId id_;

  DISALLOW_COPY_AND_ASSIGN(ForceInstallProvider);
};

class ScopedContentVerifyJobDelegateOverride {
 public:
  explicit ScopedContentVerifyJobDelegateOverride(JobDelegate* delegate) {
    ContentVerifyJob::SetDelegateForTests(delegate);
  }
  ~ScopedContentVerifyJobDelegateOverride() {
    ContentVerifyJob::SetDelegateForTests(nullptr);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ScopedContentVerifyJobDelegateOverride);
};

}  // namespace

class ContentVerifierTest : public ExtensionBrowserTest {
 public:
  ContentVerifierTest() {}
  ~ContentVerifierTest() override {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    ExtensionBrowserTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(
        switches::kExtensionContentVerification,
        switches::kExtensionContentVerificationEnforce);
  }

  virtual void OpenPageAndWaitForUnload() {
    ScopedContentVerifyJobDelegateOverride scoped_delegate(&delegate_);
    std::string id = "npnbmohejbjohgpjnmjagbafnjhkmgko";
    delegate_.set_id(id);

    // |unload_observer| needs to destroy before the ExtensionRegistry gets
    // deleted, which happens before TearDownOnMainThread is called.
    RegistryObserver unload_observer(ExtensionRegistry::Get(profile()));
    const Extension* extension = InstallExtensionFromWebstore(
        test_data_dir_.AppendASCII("content_verifier/v1.crx"), 1);
    ASSERT_TRUE(extension);
    ASSERT_EQ(id, extension->id());
    page_url_ = extension->GetResourceURL("page.html");

    // This call passes false for |check_navigation_success|, because checking
    // for navigation success needs the WebContents to still exist after the
    // navigation, whereas this navigation triggers an unload which destroys
    // the WebContents.
    AddTabAtIndexToBrowser(browser(), 1, page_url_, ui::PAGE_TRANSITION_LINK,
                           false);

    EXPECT_TRUE(unload_observer.WaitForUnload(id));
    ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
    int reasons = prefs->GetDisableReasons(id);
    EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED);
  }

  void TestContentScriptExtension(const std::string& crx_relpath,
                                  const std::string& id,
                                  const std::string& script_relpath) {
    VerifierObserver verifier_observer;

    // Install the extension with content scripts. The initial read of the
    // content scripts will fail verification because they are read before the
    // content verification system has completed a one-time processing of the
    // expected hashes. (The extension only contains the root level hashes of
    // the merkle tree, but the content verification system builds the entire
    // tree and caches it in the extension install directory - see
    // ContentHashFetcher for more details).
    const Extension* extension = InstallExtensionFromWebstore(
        test_data_dir_.AppendASCII(crx_relpath), 1);
    ASSERT_TRUE(extension);
    EXPECT_EQ(id, extension->id());

    // Wait for the content verification code to finish processing the hashes.
    if (!base::ContainsKey(verifier_observer.completed_fetches(), id))
      verifier_observer.WaitForFetchComplete(id);

    // Now disable the extension, since content scripts are read at enable time,
    // set up our job observer, and re-enable, expecting a success this time.
    DisableExtension(id);
    JobObserver job_observer;
    base::FilePath script_relfilepath =
        base::FilePath().AppendASCII(script_relpath);
    job_observer.ExpectJobResult(id, script_relfilepath,
                                 JobObserver::Result::SUCCESS);
    EnableExtension(id);
    EXPECT_TRUE(job_observer.WaitForExpectedJobs());

    // Now alter the contents of the content script, reload the extension, and
    // expect to see a job failure due to the content script content hash not
    // being what was signed by the webstore.
    base::FilePath scriptfile = extension->path().AppendASCII(script_relpath);
    std::string extra = "some_extra_function_call();";
    ASSERT_TRUE(base::AppendToFile(scriptfile, extra.data(), extra.size()));
    DisableExtension(id);
    job_observer.ExpectJobResult(id, script_relfilepath,
                                 JobObserver::Result::FAILURE);
    EnableExtension(id);
    EXPECT_TRUE(job_observer.WaitForExpectedJobs());
  }

 protected:
  JobDelegate delegate_;
  GURL page_url_;
};

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnRead) {
#if defined(OS_WIN)
  if (content::IsBrowserSideNavigationEnabled() &&
      base::win::GetVersion() >= base::win::VERSION_WIN10) {
    // http://crbug.com/699437
    return;
  }
#endif
  EXPECT_EQ(0, delegate_.bytes_read_failed());
  delegate_.fail_next_read();
  OpenPageAndWaitForUnload();
  EXPECT_EQ(1, delegate_.bytes_read_failed());
}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnDone) {
#if defined(OS_WIN)
  if (content::IsBrowserSideNavigationEnabled() &&
      base::win::GetVersion() >= base::win::VERSION_WIN10) {
    // http://crbug.com/699437
    return;
  }
#endif
  EXPECT_EQ(0, delegate_.done_reading_failed());
  delegate_.fail_next_done();
  OpenPageAndWaitForUnload();
  EXPECT_EQ(1, delegate_.done_reading_failed());
}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) {
  JobObserver job_observer;
  std::string id = "hoipipabpcoomfapcecilckodldhmpgl";

  job_observer.ExpectJobResult(
      id, base::FilePath(FILE_PATH_LITERAL("background.js")),
      JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(id,
                               base::FilePath(FILE_PATH_LITERAL("page.html")),
                               JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("page.js")),
                               JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(
      id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")),
      JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(id,
                               base::FilePath(FILE_PATH_LITERAL("page2.js")),
                               JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs1.js")),
                               JobObserver::Result::SUCCESS);
  job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs2.js")),
                               JobObserver::Result::SUCCESS);

  VerifierObserver verifier_observer;

  // Install a test extension we copied from the webstore that has actual
  // signatures, and contains paths with a leading "./" in various places.
  const Extension* extension = InstallExtensionFromWebstore(
      test_data_dir_.AppendASCII("content_verifier/dot_slash_paths.crx"), 1);

  ASSERT_TRUE(extension);
  ASSERT_EQ(extension->id(), id);

  // The content scripts might fail verification the first time since the
  // one-time processing might not be finished yet - if that's the case then
  // we want to wait until that work is done.
  if (!base::ContainsKey(verifier_observer.completed_fetches(), id))
    verifier_observer.WaitForFetchComplete(id);

  // Now disable/re-enable the extension to cause the content scripts to be
  // read again.
  DisableExtension(id);
  EnableExtension(id);

  EXPECT_TRUE(job_observer.WaitForExpectedJobs());
}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, ContentScripts) {
  TestContentScriptExtension("content_verifier/content_script.crx",
                             "jmllhlobpjcnnomjlipadejplhmheiif", "script.js");
}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, ContentScriptsInLocales) {
  TestContentScriptExtension("content_verifier/content_script_locales.crx",
                             "jaghonccckpcikmliipifpoodmeofoon",
                             "_locales/en/content_script.js");
}

// Tests the case of a corrupt extension that is force-installed by policy and
// should not be allowed to be manually uninstalled/disabled by the user.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest, PolicyCorrupted) {
  ExtensionSystem* system = ExtensionSystem::Get(profile());
  ExtensionService* service = system->extension_service();

  // The id of our test extension.
  std::string id("npnbmohejbjohgpjnmjagbafnjhkmgko");

  // Setup fake policy and update check objects.
  ForceInstallProvider policy(id);
  DownloaderTestDelegate downloader;
  system->management_policy()->RegisterProvider(&policy);
  ExtensionDownloader::set_test_delegate(&downloader);
  service->AddProviderForTesting(
      base::MakeUnique<TestExternalProvider>(service, id));

  base::FilePath crx_path =
      test_data_dir_.AppendASCII("content_verifier/v1.crx");
  const Extension* extension =
      InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
  EXPECT_NE(extension, nullptr);

  downloader.AddResponse(id, extension->VersionString(), crx_path);

  RegistryObserver registry_observer(ExtensionRegistry::Get(profile()));
  ContentVerifier* verifier = system->content_verifier();
  verifier->VerifyFailed(extension->id(), ContentVerifyJob::HASH_MISMATCH);

  // Make sure the extension first got disabled due to corruption.
  EXPECT_TRUE(registry_observer.WaitForUnload(id));
  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
  int reasons = prefs->GetDisableReasons(id);
  EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED);

  // Make sure the extension then got re-installed, and that after reinstall it
  // is no longer disabled due to corruption.
  EXPECT_TRUE(registry_observer.WaitForInstall(id));
  reasons = prefs->GetDisableReasons(id);
  EXPECT_FALSE(reasons & Extension::DISABLE_CORRUPTED);

  // Make sure that the update check request properly included a parameter
  // indicating that this was a corrupt policy reinstall.
  bool found = false;
  for (const auto& request : downloader.requests()) {
    if (request->Includes(id)) {
      std::string query = request->full_url().query();
      for (const auto& part : base::SplitString(
               query, "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
        if (base::StartsWith(part, "x=", base::CompareCase::SENSITIVE) &&
            part.find(std::string("id%3D") + id) != std::string::npos) {
          found = true;
          EXPECT_NE(std::string::npos, part.find("installsource%3Dreinstall"));
        }
      }
    }
  }
  EXPECT_TRUE(found);
}

class ContentVerifierPolicyTest : public ContentVerifierTest {
 public:
  // We need to do this work here because the force-install policy values are
  // checked pretty early on in the startup of the ExtensionService, which
  // happens between SetUpInProcessBrowserTestFixture and SetUpOnMainThread.
  void SetUpInProcessBrowserTestFixture() override {
    ContentVerifierTest::SetUpInProcessBrowserTestFixture();

    EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
        .WillRepeatedly(testing::Return(true));

    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
        &policy_provider_);
    ExtensionManagementPolicyUpdater management_policy(&policy_provider_);
    management_policy.SetIndividualExtensionAutoInstalled(
        id_, extension_urls::kChromeWebstoreUpdateURL, true /* forced */);

    ExtensionDownloader::set_test_delegate(&downloader_);
    base::FilePath crx_path =
        test_data_dir_.AppendASCII("content_verifier/v1.crx");
    std::string version = "2";
    downloader_.AddResponse(id_, version, crx_path);
  }

  void SetUpOnMainThread() override {
    extensions::browsertest_util::CreateAndInitializeLocalCache();
  }

 protected:
  // The id of the extension we want to have force-installed.
  std::string id_ = "npnbmohejbjohgpjnmjagbafnjhkmgko";

 private:
  policy::MockConfigurationPolicyProvider policy_provider_;
  DownloaderTestDelegate downloader_;
};

// We want to test what happens at startup with a corroption-disabled policy
// force installed extension. So we set that up in the PRE test here.
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest,
                       PRE_PolicyCorruptedOnStartup) {
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
  RegistryObserver registry_observer(registry);

  // Wait for the extension to be installed by policy we set up in
  // SetUpInProcessBrowserTestFixture.
  if (!registry->GetInstalledExtension(id_)) {
    EXPECT_TRUE(registry_observer.WaitForInstall(id_));
  }

  // Simulate corruption of the extension so that we can test what happens
  // at startup in the non-PRE test.
  ExtensionSystem* system = ExtensionSystem::Get(profile());
  ContentVerifier* verifier = system->content_verifier();
  verifier->VerifyFailed(id_, ContentVerifyJob::HASH_MISMATCH);
  EXPECT_TRUE(registry_observer.WaitForUnload(id_));
  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
  int reasons = prefs->GetDisableReasons(id_);
  EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED);
}

// Now actually test what happens on the next startup after the PRE test above.
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest, PolicyCorruptedOnStartup) {
  // Depdending on timing, the extension may have already been reinstalled
  // between SetUpInProcessBrowserTestFixture and now (usually not during local
  // testing on a developer machine, but sometimes on a heavily loaded system
  // such as the build waterfall / trybots). If the reinstall didn't already
  // happen, wait for it.
  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
  int disable_reasons = prefs->GetDisableReasons(id_);
  if (disable_reasons & Extension::DISABLE_CORRUPTED) {
    RegistryObserver registry_observer(registry);
    EXPECT_TRUE(registry_observer.WaitForInstall(id_));
    disable_reasons = prefs->GetDisableReasons(id_);
  }
  EXPECT_FALSE(disable_reasons & Extension::DISABLE_CORRUPTED);
  EXPECT_TRUE(registry->enabled_extensions().Contains(id_));
}

namespace {

// A helper for intercepting the normal action that
// ChromeContentVerifierDelegate would take on discovering corruption, letting
// us track the delay for each consecutive reinstall.
class DelayTracker {
 public:
  DelayTracker()
      : action_(base::Bind(&DelayTracker::ReinstallAction,
                           base::Unretained(this))) {
    PolicyExtensionReinstaller::set_policy_reinstall_action_for_test(&action_);
  }

  ~DelayTracker() {
    PolicyExtensionReinstaller::set_policy_reinstall_action_for_test(nullptr);
  }

  const std::vector<base::TimeDelta>& calls() { return calls_; }

  void ReinstallAction(const base::Closure& callback, base::TimeDelta delay) {
    saved_callback_ = callback;
    calls_.push_back(delay);
  }

  void Proceed() {
    ASSERT_TRUE(saved_callback_);
    ASSERT_TRUE(!saved_callback_->is_null());
    // Run() will set |saved_callback_| again, so use a temporary: |callback|.
    base::Closure callback = saved_callback_.value();
    saved_callback_.reset();
    callback.Run();
  }

 private:
  std::vector<base::TimeDelta> calls_;
  base::Optional<base::Closure> saved_callback_;
  PolicyExtensionReinstaller::ReinstallCallback action_;

  DISALLOW_COPY_AND_ASSIGN(DelayTracker);
};

}  // namespace

IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest, Backoff) {
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
  ExtensionSystem* system = ExtensionSystem::Get(profile());
  ContentVerifier* verifier = system->content_verifier();

  // Wait for the extension to be installed by the policy we set up in
  // SetUpInProcessBrowserTestFixture.
  if (!registry->GetInstalledExtension(id_)) {
    RegistryObserver registry_observer(registry);
    EXPECT_TRUE(registry_observer.WaitForInstall(id_));
  }

  // Setup to intercept reinstall action, so we can see what the delay would
  // have been for the real action.
  DelayTracker delay_tracker;

  // Do 4 iterations of disabling followed by reinstall.
  const size_t iterations = 4;
  for (size_t i = 0; i < iterations; i++) {
    RegistryObserver registry_observer(registry);
    verifier->VerifyFailed(id_, ContentVerifyJob::HASH_MISMATCH);
    EXPECT_TRUE(registry_observer.WaitForUnload(id_));
    // Resolve the request to |delay_tracker|, so the reinstallation can
    // proceed.
    delay_tracker.Proceed();
    EXPECT_TRUE(registry_observer.WaitForInstall(id_));
  }
  const std::vector<base::TimeDelta>& calls = delay_tracker.calls();

  // After |delay_tracker| resolves the 4 (|iterations|) reinstallation
  // requests, it will get an additional request (right away) for retrying
  // reinstallation.
  // Note: the additional request in non-test environment will arrive with
  // a (backoff) delay. But during test, |delay_tracker| issues the request
  // immediately.
  ASSERT_EQ(iterations, calls.size() - 1);
  // Assert that the first reinstall action happened with a delay of 0, and
  // then kept growing each additional time.
  EXPECT_EQ(base::TimeDelta(), delay_tracker.calls()[0]);
  for (size_t i = 1; i < delay_tracker.calls().size(); i++) {
    EXPECT_LT(calls[i - 1], calls[i]);
  }
}

// Tests that if CheckForExternalUpdates() fails, then we retry reinstalling
// corrupted policy extensions. For example: if network is unavailable,
// CheckForExternalUpdates() will fail.
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest, FailedUpdateRetries) {
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
  ExtensionSystem* system = ExtensionSystem::Get(profile());
  ExtensionService* service = system->extension_service();
  ContentVerifier* verifier = system->content_verifier();

  // Wait for the extension to be installed by the policy we set up in
  // SetUpInProcessBrowserTestFixture.
  if (!registry->GetInstalledExtension(id_)) {
    RegistryObserver registry_observer(registry);
    EXPECT_TRUE(registry_observer.WaitForInstall(id_));
  }

  DelayTracker delay_tracker;
  service->set_external_updates_disabled_for_test(true);
  RegistryObserver registry_observer(registry);
  verifier->VerifyFailed(id_, ContentVerifyJob::HASH_MISMATCH);
  EXPECT_TRUE(registry_observer.WaitForUnload(id_));

  const std::vector<base::TimeDelta>& calls = delay_tracker.calls();
  ASSERT_EQ(1u, calls.size());
  EXPECT_EQ(base::TimeDelta(), delay_tracker.calls()[0]);

  delay_tracker.Proceed();

  // Remove the override and set ExtensionService to update again. The extension
  // should be now installed.
  PolicyExtensionReinstaller::set_policy_reinstall_action_for_test(nullptr);
  service->set_external_updates_disabled_for_test(false);
  delay_tracker.Proceed();

  EXPECT_TRUE(registry_observer.WaitForInstall(id_));
}

}  // namespace extensions
