// 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 "chrome/browser/extensions/shared_module_service.h"

#include <memory>
#include <string>
#include <utility>

#include "base/memory/ref_counted.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "components/crx_file/id_util.h"
#include "components/sync/model/string_ordinal.h"
#include "components/version_info/version_info.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/install_flag.h"
#include "extensions/browser/uninstall_reason.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/value_builder.h"

namespace extensions {

namespace {

// Return an extension with |id| which imports all the modules that are in the
// container |import_ids|.
scoped_refptr<const Extension> CreateExtensionImportingModules(
    const std::vector<std::string>& import_ids,
    const std::string& id,
    const std::string& version) {
  DictionaryBuilder builder;
  builder.Set("name", "Has Dependent Modules")
         .Set("version", version)
         .Set("manifest_version", 2);
  if (!import_ids.empty()) {
    ListBuilder import_list;
    for (const std::string& import_id : import_ids)
      import_list.Append(DictionaryBuilder().Set("id", import_id).Build());
    builder.Set("import", import_list.Build());
  }
  return ExtensionBuilder()
      .SetManifest(builder.Build())
      .AddFlags(Extension::FROM_WEBSTORE)
      .SetID(id)
      .Build();
}

scoped_refptr<const Extension> CreateSharedModule(
    const std::string& module_id) {
  std::unique_ptr<base::DictionaryValue> manifest =
      DictionaryBuilder()
          .Set("name", "Shared Module")
          .Set("version", "1.0")
          .Set("manifest_version", 2)
          .Set("export",
               DictionaryBuilder()
                   .Set("resources", ListBuilder().Append("foo.js").Build())
                   .Build())
          .Build();

  return ExtensionBuilder()
      .SetManifest(std::move(manifest))
      .AddFlags(Extension::FROM_WEBSTORE)
      .SetID(crx_file::id_util::GenerateId(module_id))
      .Build();
}

}  // namespace

class SharedModuleServiceUnitTest : public ExtensionServiceTestBase {
 public:
  SharedModuleServiceUnitTest() :
      // The "export" key is open for dev-channel only, but unit tests
      // run as stable channel on the official Windows build.
      current_channel_(version_info::Channel::UNKNOWN) {}
 protected:
  void SetUp() override;

  // Install an extension and notify the ExtensionService.
  testing::AssertionResult InstallExtension(const Extension* extension,
                                            bool is_update);
  ScopedCurrentChannel current_channel_;
};

void SharedModuleServiceUnitTest::SetUp() {
  ExtensionServiceTestBase::SetUp();
  InitializeGoodInstalledExtensionService();
  service()->Init();
}

testing::AssertionResult SharedModuleServiceUnitTest::InstallExtension(
    const Extension* extension,
    bool is_update) {

  const Extension* old = registry()->GetExtensionById(
      extension->id(),
      ExtensionRegistry::ENABLED);

  // Verify the extension is not already installed, if it is not update.
  if (!is_update) {
    if (old)
      return testing::AssertionFailure() << "Extension already installed.";
  } else {
    if (!old)
      return testing::AssertionFailure() << "The extension does not exist.";
  }

  // Notify the service that the extension is installed. This adds it to the
  // registry, notifies interested parties, etc.
  service()->OnExtensionInstalled(
      extension, syncer::StringOrdinal(), kInstallFlagInstallImmediately);

  // Verify that the extension is now installed.
  if (!registry()->GetExtensionById(extension->id(),
                                    ExtensionRegistry::ENABLED)) {
    return testing::AssertionFailure() << "Could not install extension.";
  }

  return testing::AssertionSuccess();
}

TEST_F(SharedModuleServiceUnitTest, AddDependentSharedModules) {
  // Create an extension that has a dependency.
  std::string import_id = crx_file::id_util::GenerateId("id");
  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
  scoped_refptr<const Extension> extension = CreateExtensionImportingModules(
      std::vector<std::string>(1, import_id), extension_id, "1.0");

  PendingExtensionManager* pending_extension_manager =
      service()->pending_extension_manager();

  // Verify that we don't currently want to install the imported module.
  EXPECT_FALSE(pending_extension_manager->IsIdPending(import_id));

  // Try to satisfy imports for the extension. This should queue the imported
  // module's installation.
  service()->shared_module_service()->SatisfyImports(extension.get());
  EXPECT_TRUE(pending_extension_manager->IsIdPending(import_id));
}

TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUninstall) {
  // Create a module which exports a resource, and install it.
  scoped_refptr<const Extension> shared_module =
      CreateSharedModule("shared_module");

  EXPECT_TRUE(InstallExtension(shared_module.get(), false));

  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
  // Create and install an extension that imports our new module.
  scoped_refptr<const Extension> importing_extension =
      CreateExtensionImportingModules(
          std::vector<std::string>(1, shared_module->id()), extension_id,
          "1.0");
  EXPECT_TRUE(InstallExtension(importing_extension.get(), false));

  // Uninstall the extension that imports our module.
  std::u16string error;
  service()->UninstallExtension(importing_extension->id(),
                                extensions::UNINSTALL_REASON_FOR_TESTING,
                                &error);
  EXPECT_TRUE(error.empty());

  // Since the module was only referenced by that single extension, it should
  // have been uninstalled as a side-effect of uninstalling the extension that
  // depended upon it.
  EXPECT_FALSE(registry()->GetExtensionById(shared_module->id(),
                                            ExtensionRegistry::EVERYTHING));
}

TEST_F(SharedModuleServiceUnitTest, PruneSharedModulesOnUpdate) {
  // Create two modules which export a resource, and install them.
  scoped_refptr<const Extension> shared_module_1 =
      CreateSharedModule("shared_module_1");
  EXPECT_TRUE(InstallExtension(shared_module_1.get(), false));

  std::unique_ptr<base::DictionaryValue> manifest_2 =
      DictionaryBuilder()
          .Set("name", "Shared Module 2")
          .Set("version", "1.0")
          .Set("manifest_version", 2)
          .Set("export",
               DictionaryBuilder()
                   .Set("resources", ListBuilder().Append("foo.js").Build())
                   .Build())
          .Build();
  scoped_refptr<const Extension> shared_module_2 =
      CreateSharedModule("shared_module_2");
  EXPECT_TRUE(InstallExtension(shared_module_2.get(), false));

  std::string extension_id = crx_file::id_util::GenerateId("extension_id");

  // Create and install an extension v1.0 that imports our new module 1.
  scoped_refptr<const Extension> importing_extension_1 =
      CreateExtensionImportingModules(
          std::vector<std::string>(1, shared_module_1->id()), extension_id,
          "1.0");
  EXPECT_TRUE(InstallExtension(importing_extension_1.get(), false));

  // Create and install a new version of the extension that imports our new
  // module 2.
  scoped_refptr<const Extension> importing_extension_2 =
      CreateExtensionImportingModules(
          std::vector<std::string>(1, shared_module_2->id()), extension_id,
          "1.1");
  EXPECT_TRUE(InstallExtension(importing_extension_2.get(), true));

  // Since the extension v1.1 depends the module 2 insteand module 1.
  // So the module 1 should be uninstalled.
  EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
                                            ExtensionRegistry::EVERYTHING));
  EXPECT_TRUE(registry()->GetExtensionById(shared_module_2->id(),
                                            ExtensionRegistry::EVERYTHING));

  // Create and install a new version of the extension that does not import any
  // module.
  scoped_refptr<const Extension> importing_extension_3 =
      CreateExtensionImportingModules(std::vector<std::string>(), extension_id,
                                      "1.2");
  EXPECT_TRUE(InstallExtension(importing_extension_3.get(), true));

  // Since the extension v1.2 does not depend any module, so the all models
  // should have been uninstalled.
  EXPECT_FALSE(registry()->GetExtensionById(shared_module_1->id(),
                                            ExtensionRegistry::EVERYTHING));
  EXPECT_FALSE(registry()->GetExtensionById(shared_module_2->id(),
                                            ExtensionRegistry::EVERYTHING));

}

TEST_F(SharedModuleServiceUnitTest, AllowlistedImports) {
  std::string allowlisted_id = crx_file::id_util::GenerateId("allowlisted");
  std::string nonallowlisted_id =
      crx_file::id_util::GenerateId("nonallowlisted");
  // Create a module which exports to a restricted allowlist.
  std::unique_ptr<base::DictionaryValue> manifest =
      DictionaryBuilder()
          .Set("name", "Shared Module")
          .Set("version", "1.0")
          .Set("manifest_version", 2)
          .Set("export",
               DictionaryBuilder()
                   .Set("allowlist",
                        ListBuilder().Append(allowlisted_id).Build())
                   .Set("resources", ListBuilder().Append("*").Build())
                   .Build())
          .Build();
  scoped_refptr<const Extension> shared_module =
      ExtensionBuilder()
          .SetManifest(std::move(manifest))
          .AddFlags(Extension::FROM_WEBSTORE)
          .SetID(crx_file::id_util::GenerateId("shared_module"))
          .Build();

  EXPECT_TRUE(InstallExtension(shared_module.get(), false));

  // Create and install an extension with the allowlisted ID.
  scoped_refptr<const Extension> allowlisted_extension =
      CreateExtensionImportingModules(
          std::vector<std::string>(1, shared_module->id()), allowlisted_id,
          "1.0");
  EXPECT_TRUE(InstallExtension(allowlisted_extension.get(), false));

  // Try to install an extension with an ID that is not allowlisted.
  scoped_refptr<const Extension> nonallowlisted_extension =
      CreateExtensionImportingModules(
          std::vector<std::string>(1, shared_module->id()), nonallowlisted_id,
          "1.0");
  // This should succeed because only CRX installer (and by extension the
  // WebStore Installer) checks the shared module allowlist.  InstallExtension
  // bypasses the allowlist check because the SharedModuleService does not
  // care about allowlists.
  EXPECT_TRUE(InstallExtension(nonallowlisted_extension.get(), false));
}

TEST_F(SharedModuleServiceUnitTest, PruneMultipleSharedModules) {
  // Create two modules which export a resource each, and install it.
  scoped_refptr<const Extension> shared_module_one =
      CreateSharedModule("shared_module_one");
  EXPECT_TRUE(InstallExtension(shared_module_one.get(), false));
  scoped_refptr<const Extension> shared_module_two =
      CreateSharedModule("shared_module_two");
  EXPECT_TRUE(InstallExtension(shared_module_two.get(), false));

  std::string extension_id = crx_file::id_util::GenerateId("extension_id");
  std::vector<std::string> module_ids;
  module_ids.push_back(shared_module_one->id());
  module_ids.push_back(shared_module_two->id());
  // Create and install an extension that imports both the modules.
  scoped_refptr<const Extension> importing_extension =
      CreateExtensionImportingModules(module_ids, extension_id, "1.0");
  EXPECT_TRUE(InstallExtension(importing_extension.get(), false));

  // Uninstall the extension that imports our modules.
  std::u16string error;
  service()->UninstallExtension(importing_extension->id(),
                                extensions::UNINSTALL_REASON_FOR_TESTING,
                                &error);
  EXPECT_TRUE(error.empty());

  // Since the modules were only referenced by that single extension, they
  // should have been uninstalled as a side-effect of uninstalling the extension
  // that depended upon it.
  EXPECT_FALSE(registry()->GetExtensionById(shared_module_one->id(),
                                            ExtensionRegistry::EVERYTHING));
  EXPECT_FALSE(registry()->GetExtensionById(shared_module_two->id(),
                                            ExtensionRegistry::EVERYTHING));
}

}  // namespace extensions
