// Copyright 2016 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/component_updater/subresource_filter_component_installer.h"

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

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "chrome/test/base/testing_browser_process.h"
#include "components/component_updater/mock_component_updater_service.h"
#include "components/prefs/testing_pref_service.h"
#include "components/subresource_filter/content/browser/content_ruleset_service.h"
#include "components/subresource_filter/core/browser/ruleset_service.h"
#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace {

static const char kTestRulesetVersion[] = "1.2.3.4";

class TestRulesetService : public subresource_filter::RulesetService {
 public:
  TestRulesetService(PrefService* local_state,
                     scoped_refptr<base::SequencedTaskRunner> task_runner,
                     subresource_filter::ContentRulesetService* content_service,
                     const base::FilePath& base_dir)
      : subresource_filter::RulesetService(local_state,
                                           task_runner,
                                           content_service,
                                           base_dir) {}

  ~TestRulesetService() override {}

  using UnindexedRulesetInfo = subresource_filter::UnindexedRulesetInfo;
  void IndexAndStoreAndPublishRulesetIfNeeded(
      const UnindexedRulesetInfo& unindexed_ruleset_info) override {
    unindexed_ruleset_info_ = unindexed_ruleset_info;
  }

  const base::FilePath& ruleset_path() const {
    return unindexed_ruleset_info_.ruleset_path;
  }

  const base::FilePath& license_path() const {
    return unindexed_ruleset_info_.license_path;
  }

  const std::string& content_version() const {
    return unindexed_ruleset_info_.content_version;
  }

 private:
  UnindexedRulesetInfo unindexed_ruleset_info_;

  DISALLOW_COPY_AND_ASSIGN(TestRulesetService);
};

class SubresourceFilterMockComponentUpdateService
    : public component_updater::MockComponentUpdateService {
 public:
  SubresourceFilterMockComponentUpdateService() {}
  ~SubresourceFilterMockComponentUpdateService() override {}

 private:
  DISALLOW_COPY_AND_ASSIGN(SubresourceFilterMockComponentUpdateService);
};

subresource_filter::Configuration CreateConfigUsingRulesetFlavor(
    const std::string& ruleset_flavor) {
  subresource_filter::Configuration config;
  config.general_settings.ruleset_flavor = ruleset_flavor;
  return config;
}

}  //  namespace

namespace component_updater {

class SubresourceFilterComponentInstallerTest : public PlatformTest {
 public:
  SubresourceFilterComponentInstallerTest() {}

  void SetUp() override {
    PlatformTest::SetUp();

    ASSERT_TRUE(component_install_dir_.CreateUniqueTempDir());
    ASSERT_TRUE(ruleset_service_dir_.CreateUniqueTempDir());
    subresource_filter::IndexedRulesetVersion::RegisterPrefs(
        pref_service_.registry());

    auto content_service =
        std::make_unique<subresource_filter::ContentRulesetService>(
            base::ThreadTaskRunnerHandle::Get());
    auto test_ruleset_service = std::make_unique<TestRulesetService>(
        &pref_service_, base::ThreadTaskRunnerHandle::Get(),
        content_service.get(), ruleset_service_dir_.GetPath());
    test_ruleset_service_ = test_ruleset_service.get();
    content_service->set_ruleset_service(std::move(test_ruleset_service));

    TestingBrowserProcess::GetGlobal()->SetRulesetService(
        std::move(content_service));
    policy_ = std::make_unique<SubresourceFilterComponentInstallerPolicy>();
  }

  void TearDown() override {
    TestingBrowserProcess::GetGlobal()->SetRulesetService(nullptr);
    thread_bundle_.RunUntilIdle();
    PlatformTest::TearDown();
  }

  TestRulesetService* service() { return test_ruleset_service_; }

  void WriteStringToFile(const std::string data, const base::FilePath& path) {
    ASSERT_EQ(static_cast<int32_t>(data.length()),
              base::WriteFile(path, data.data(), data.length()));
  }

  base::FilePath component_install_dir() {
    return component_install_dir_.GetPath();
  }

  // If |license_contents| is null, no license file will be created.
  void CreateTestSubresourceFilterRuleset(const std::string& ruleset_contents,
                                          const std::string* license_contents) {
    base::FilePath ruleset_data_path = component_install_dir().Append(
        subresource_filter::kUnindexedRulesetDataFileName);
    ASSERT_NO_FATAL_FAILURE(
        WriteStringToFile(ruleset_contents, ruleset_data_path));

    base::FilePath license_path = component_install_dir().Append(
        subresource_filter::kUnindexedRulesetLicenseFileName);
    if (license_contents) {
      ASSERT_NO_FATAL_FAILURE(
          WriteStringToFile(*license_contents, license_path));
    }
  }

  void LoadSubresourceFilterRuleset(int ruleset_format) {
    std::unique_ptr<base::DictionaryValue> manifest(new base::DictionaryValue);
    manifest->SetInteger(
        SubresourceFilterComponentInstallerPolicy::kManifestRulesetFormatKey,
        ruleset_format);
    ASSERT_TRUE(
        policy_->VerifyInstallation(*manifest, component_install_dir()));
    const base::Version expected_version(kTestRulesetVersion);
    policy_->ComponentReady(expected_version, component_install_dir(),
                            std::move(manifest));
    base::RunLoop().RunUntilIdle();
  }

  update_client::InstallerAttributes GetInstallerAttributes() {
    return policy_->GetInstallerAttributes();
  }

 protected:
  content::TestBrowserThreadBundle thread_bundle_;

 private:

  base::ScopedTempDir component_install_dir_;
  base::ScopedTempDir ruleset_service_dir_;

  std::unique_ptr<SubresourceFilterComponentInstallerPolicy> policy_;
  TestingPrefServiceSimple pref_service_;

  TestRulesetService* test_ruleset_service_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(SubresourceFilterComponentInstallerTest);
};

TEST_F(SubresourceFilterComponentInstallerTest,
       TestComponentRegistrationWhenFeatureDisabled) {
  base::test::ScopedFeatureList scoped_disable;
  scoped_disable.InitAndDisableFeature(
      subresource_filter::kSafeBrowsingSubresourceFilter);
  std::unique_ptr<SubresourceFilterMockComponentUpdateService>
      component_updater(new SubresourceFilterMockComponentUpdateService());
  EXPECT_CALL(*component_updater, RegisterComponent(testing::_)).Times(0);
  RegisterSubresourceFilterComponent(component_updater.get());
  thread_bundle_.RunUntilIdle();
}

TEST_F(SubresourceFilterComponentInstallerTest,
       TestComponentRegistrationWhenFeatureEnabled) {
  base::test::ScopedFeatureList scoped_enable;
  scoped_enable.InitAndEnableFeature(
      subresource_filter::kSafeBrowsingSubresourceFilter);
  std::unique_ptr<SubresourceFilterMockComponentUpdateService>
      component_updater(new SubresourceFilterMockComponentUpdateService());
  EXPECT_CALL(*component_updater, RegisterComponent(testing::_))
      .Times(1)
      .WillOnce(testing::Return(true));
  RegisterSubresourceFilterComponent(component_updater.get());
  thread_bundle_.RunUntilIdle();
}

TEST_F(SubresourceFilterComponentInstallerTest, LoadEmptyRuleset) {
  ASSERT_TRUE(service());
  ASSERT_NO_FATAL_FAILURE(
      CreateTestSubresourceFilterRuleset(std::string(), nullptr));
  ASSERT_NO_FATAL_FAILURE(LoadSubresourceFilterRuleset(
      SubresourceFilterComponentInstallerPolicy::kCurrentRulesetFormat));
  EXPECT_EQ(kTestRulesetVersion, service()->content_version());
  std::string actual_ruleset_contents;
  ASSERT_TRUE(base::ReadFileToString(service()->ruleset_path(),
                                     &actual_ruleset_contents));
  EXPECT_TRUE(actual_ruleset_contents.empty()) << actual_ruleset_contents;
  EXPECT_FALSE(base::PathExists(service()->license_path()));
}

TEST_F(SubresourceFilterComponentInstallerTest, FutureVersionIgnored) {
  ASSERT_TRUE(service());
  const std::string expected_ruleset_contents = "future stuff";
  ASSERT_NO_FATAL_FAILURE(
      CreateTestSubresourceFilterRuleset(expected_ruleset_contents, nullptr));
  ASSERT_NO_FATAL_FAILURE(LoadSubresourceFilterRuleset(
      SubresourceFilterComponentInstallerPolicy::kCurrentRulesetFormat + 1));
  EXPECT_EQ(std::string(), service()->content_version());
  EXPECT_TRUE(service()->ruleset_path().empty());
  EXPECT_TRUE(service()->license_path().empty());
}

TEST_F(SubresourceFilterComponentInstallerTest, LoadFileWithData) {
  ASSERT_TRUE(service());
  const std::string expected_ruleset_contents = "foobar";
  const std::string expected_license_contents = "license";
  ASSERT_NO_FATAL_FAILURE(CreateTestSubresourceFilterRuleset(
      expected_ruleset_contents, &expected_license_contents));
  ASSERT_NO_FATAL_FAILURE(LoadSubresourceFilterRuleset(
      SubresourceFilterComponentInstallerPolicy::kCurrentRulesetFormat));
  EXPECT_EQ(kTestRulesetVersion, service()->content_version());
  std::string actual_ruleset_contents;
  std::string actual_license_contents;
  ASSERT_TRUE(base::ReadFileToString(service()->ruleset_path(),
                                     &actual_ruleset_contents));
  EXPECT_EQ(expected_ruleset_contents, actual_ruleset_contents);
  ASSERT_TRUE(base::ReadFileToString(service()->license_path(),
                                     &actual_license_contents));
  EXPECT_EQ(expected_license_contents, actual_license_contents);
}

TEST_F(SubresourceFilterComponentInstallerTest, InstallerTag) {
  const struct {
    const char* expected_installer_tag_selected;
    std::vector<std::string> ruleset_flavors;
  } kTestCases[] = {{"", std::vector<std::string>()},
                    {"", {""}},
                    {"a", {"a"}},
                    {"b", {"b"}},
                    {"c", {"c"}},
                    {"d", {"d"}},
                    {"invalid", {"e"}},
                    {"invalid", {"foo"}},
                    {"", {"", ""}},
                    {"a", {"a", ""}},
                    {"a", {"", "a"}},
                    {"a", {"a", "a"}},
                    {"c", {"b", "", "c"}},
                    {"b", {"", "b", "a"}},
                    {"c", {"aaa", "c", "aba"}},
                    {"invalid", {"", "a", "e"}},
                    {"invalid", {"foo", "a", "b"}}};

  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(::testing::Message()
                 << "ruleset_flavors: "
                 << ::testing::PrintToString(test_case.ruleset_flavors));

    std::vector<subresource_filter::Configuration> configs;
    for (const auto& ruleset_flavor : test_case.ruleset_flavors)
      configs.push_back(CreateConfigUsingRulesetFlavor(ruleset_flavor));
    subresource_filter::testing::ScopedSubresourceFilterConfigurator
        scoped_configuration(std::move(configs));

    EXPECT_EQ(test_case.expected_installer_tag_selected,
              SubresourceFilterComponentInstallerPolicy::GetInstallerTag());
  }
}

TEST_F(SubresourceFilterComponentInstallerTest, InstallerAttributesDefault) {
  subresource_filter::testing::ScopedSubresourceFilterConfigurator
      scoped_configuration((subresource_filter::Configuration()));
  EXPECT_EQ(update_client::InstallerAttributes(), GetInstallerAttributes());
}

TEST_F(SubresourceFilterComponentInstallerTest, InstallerAttributesCustomTag) {
  constexpr char kTagKey[] = "tag";
  constexpr char kTagValue[] = "a";

  subresource_filter::testing::ScopedSubresourceFilterConfigurator
      scoped_configuration(CreateConfigUsingRulesetFlavor(kTagValue));
  EXPECT_EQ(update_client::InstallerAttributes({{kTagKey, kTagValue}}),
            GetInstallerAttributes());
}

}  // namespace component_updater
