// Copyright (c) 2012 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/component_loader.h"

#include <stddef.h>

#include <string>

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace extensions {

namespace {

class MockExtensionService : public TestExtensionService {
 private:
  bool ready_;
  size_t unloaded_count_;
  ExtensionRegistry* registry_;

 public:
  explicit MockExtensionService(Profile* profile)
      : ready_(false),
        unloaded_count_(0),
        registry_(ExtensionRegistry::Get(profile)) {}

  void AddComponentExtension(const Extension* extension) override {
    EXPECT_FALSE(registry_->enabled_extensions().Contains(extension->id()));
    // ExtensionService must become the owner of the extension object.
    registry_->AddEnabled(extension);
  }

  void UnloadExtension(const std::string& extension_id,
                       UnloadedExtensionInfo::Reason reason) override {
    ASSERT_TRUE(registry_->enabled_extensions().Contains(extension_id));
    // Remove the extension with the matching id.
    registry_->RemoveEnabled(extension_id);
    unloaded_count_++;
  }

  void RemoveComponentExtension(const std::string& extension_id) override {
    UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_DISABLE);
  }

  bool is_ready() override { return ready_; }

  void set_ready(bool ready) {
    ready_ = ready;
  }

  size_t unloaded_count() const {
    return unloaded_count_;
  }

  void clear_extensions() { registry_->ClearAll(); }
};

}  // namespace

class ComponentLoaderTest : public testing::Test {
 public:
  ComponentLoaderTest()
      // Note: we pass the same pref service here, to stand in for both
      // user prefs and local state.
      : extension_service_(&profile_),
        component_loader_(&extension_service_,
                          &prefs_,
                          &local_state_,
                          &profile_) {
    component_loader_.set_ignore_whitelist_for_testing(true);
  }

  void SetUp() override {
    extension_path_ =
        GetBasePath().AppendASCII("good")
                     .AppendASCII("Extensions")
                     .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
                     .AppendASCII("1.0.0.0");

    // Read in the extension manifest.
    ASSERT_TRUE(base::ReadFileToString(
        extension_path_.Append(kManifestFilename),
        &manifest_contents_));

    // Register the local state prefs.
#if defined(OS_CHROMEOS)
    local_state_.registry()->RegisterBooleanPref(
        prefs::kAccessibilitySpokenFeedbackEnabled, false);
#endif
  }

 protected:
  content::TestBrowserThreadBundle thread_bundle_;
  TestingProfile profile_;
  MockExtensionService extension_service_;
  sync_preferences::TestingPrefServiceSyncable prefs_;
  TestingPrefServiceSimple local_state_;
  ComponentLoader component_loader_;

  // The root directory of the text extension.
  base::FilePath extension_path_;

  // The contents of the text extension's manifest file.
  std::string manifest_contents_;

  base::FilePath GetBasePath() {
    base::FilePath test_data_dir;
    PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
    return test_data_dir.AppendASCII("extensions");
  }
};

TEST_F(ComponentLoaderTest, ParseManifest) {
  std::unique_ptr<base::DictionaryValue> manifest;

  // Test invalid JSON.
  manifest = component_loader_.ParseManifest("{ 'test': 3 } invalid");
  EXPECT_FALSE(manifest);

  // Test manifests that are valid JSON, but don't have an object literal
  // at the root. ParseManifest() should always return NULL.

  manifest = component_loader_.ParseManifest(std::string());
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("[{ \"foo\": 3 }]");
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("\"Test\"");
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("42");
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("true");
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("false");
  EXPECT_FALSE(manifest);

  manifest = component_loader_.ParseManifest("null");
  EXPECT_FALSE(manifest);

  // Test parsing valid JSON.

  int value = 0;
  manifest = component_loader_.ParseManifest(
      "{ \"test\": { \"one\": 1 }, \"two\": 2 }");
  ASSERT_TRUE(manifest);
  EXPECT_TRUE(manifest->GetInteger("test.one", &value));
  EXPECT_EQ(1, value);
  ASSERT_TRUE(manifest->GetInteger("two", &value));
  EXPECT_EQ(2, value);

  std::string string_value;
  manifest = component_loader_.ParseManifest(manifest_contents_);
  ASSERT_TRUE(manifest->GetString("background.page", &string_value));
  EXPECT_EQ("backgroundpage.html", string_value);
}

// Test that the extension isn't loaded if the extension service isn't ready.
TEST_F(ComponentLoaderTest, AddWhenNotReady) {
  extension_service_.set_ready(false);
  std::string extension_id =
      component_loader_.Add(manifest_contents_, extension_path_);
  EXPECT_NE("", extension_id);
  ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
  EXPECT_EQ(0u, registry->enabled_extensions().size());
}

// Test that it *is* loaded when the extension service *is* ready.
TEST_F(ComponentLoaderTest, AddWhenReady) {
  extension_service_.set_ready(true);
  std::string extension_id =
      component_loader_.Add(manifest_contents_, extension_path_);
  EXPECT_NE("", extension_id);
  ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
  EXPECT_EQ(1u, registry->enabled_extensions().size());
  EXPECT_TRUE(registry->enabled_extensions().GetByID(extension_id));
}

TEST_F(ComponentLoaderTest, Remove) {
  extension_service_.set_ready(false);
  ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);

  // Removing an extension that was never added should be ok.
  component_loader_.Remove(extension_path_);
  EXPECT_EQ(0u, registry->enabled_extensions().size());

  // Try adding and removing before LoadAll() is called.
  component_loader_.Add(manifest_contents_, extension_path_);
  component_loader_.Remove(extension_path_);
  component_loader_.LoadAll();
  EXPECT_EQ(0u, registry->enabled_extensions().size());

  // Load an extension, and check that it's unloaded when Remove() is called.
  extension_service_.set_ready(true);
  std::string extension_id =
      component_loader_.Add(manifest_contents_, extension_path_);
  EXPECT_EQ(1u, registry->enabled_extensions().size());
  component_loader_.Remove(extension_path_);
  EXPECT_EQ(0u, registry->enabled_extensions().size());

  // And after calling LoadAll(), it shouldn't get loaded.
  component_loader_.LoadAll();
  EXPECT_EQ(0u, registry->enabled_extensions().size());
}

TEST_F(ComponentLoaderTest, LoadAll) {
  extension_service_.set_ready(false);
  ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);

  // No extensions should be loaded if none were added.
  component_loader_.LoadAll();
  EXPECT_EQ(0u, registry->enabled_extensions().size());

  // Use LoadAll() to load the default extensions.
  component_loader_.AddDefaultComponentExtensions(false);
  component_loader_.LoadAll();
  unsigned int default_count = registry->enabled_extensions().size();

  // Clear the list of loaded extensions, and reload with one more.
  extension_service_.clear_extensions();
  component_loader_.Add(manifest_contents_, extension_path_);
  component_loader_.LoadAll();

  EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
}

TEST_F(ComponentLoaderTest, AddOrReplace) {
  EXPECT_EQ(0u, component_loader_.registered_extensions_count());
  component_loader_.AddDefaultComponentExtensions(false);
  size_t const default_count = component_loader_.registered_extensions_count();
  base::FilePath known_extension = GetBasePath()
      .AppendASCII("override_component_extension");
  base::FilePath unknow_extension = extension_path_;
  base::FilePath invalid_extension = GetBasePath()
      .AppendASCII("this_path_does_not_exist");

  // Replace a default component extension.
  component_loader_.AddOrReplace(known_extension);
  EXPECT_EQ(default_count,
            component_loader_.registered_extensions_count());

  // Add a new component extension.
  component_loader_.AddOrReplace(unknow_extension);
  EXPECT_EQ(default_count + 1,
            component_loader_.registered_extensions_count());

  extension_service_.set_ready(true);
  component_loader_.LoadAll();
  ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);

  EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
  EXPECT_EQ(0u, extension_service_.unloaded_count());

  // replace loaded component extension.
  component_loader_.AddOrReplace(known_extension);
  EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
  EXPECT_EQ(1u, extension_service_.unloaded_count());

  // Add an invalid component extension.
  std::string extension_id = component_loader_.AddOrReplace(invalid_extension);
  EXPECT_TRUE(extension_id.empty());
}

}  // namespace extensions
