// 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/api/declarative_content/content_action.h"

#include <stdint.h>

#include "base/base64.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/values_test_util.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/test_extension_environment.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/value_builder.h"
#include "ipc/ipc_message_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"

namespace extensions {
namespace {

using base::test::ParseJson;
using testing::HasSubstr;

std::unique_ptr<base::DictionaryValue> SimpleManifest() {
  return DictionaryBuilder()
      .Set("name", "extension")
      .Set("manifest_version", 2)
      .Set("version", "1.0")
      .Build();
}

class RequestContentScriptTest : public ExtensionServiceTestBase {
 public:
  RequestContentScriptTest()
      : extension_(ExtensionBuilder().SetManifest(SimpleManifest()).Build()) {}

  // TODO(rdevlin.cronin): This should be SetUp(), but an issues with invoking
  // InitializeEmptyExtensionService() within SetUp() means that we have to
  // call this manually within every test. This can be cleaned up once said
  // issue is fixed.
  virtual void Init() {
    InitializeEmptyExtensionService();
    static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))->
        SetReady();
    base::RunLoop().RunUntilIdle();
  }

  Profile* profile() { return profile_.get(); }
  const Extension* extension() { return extension_.get(); }

 private:
  scoped_refptr<const Extension> extension_;
};

TEST(DeclarativeContentActionTest, InvalidCreation) {
  TestExtensionEnvironment env;
  std::string error;
  std::unique_ptr<const ContentAction> result;
  TestingProfile profile;

  // Test wrong data type passed.
  error.clear();
  result = ContentAction::Create(&profile, nullptr, *ParseJson("[]"), &error);
  EXPECT_THAT(error, HasSubstr("missing instanceType"));
  EXPECT_FALSE(result.get());

  // Test missing instanceType element.
  error.clear();
  result = ContentAction::Create(&profile, nullptr, *ParseJson("{}"), &error);
  EXPECT_THAT(error, HasSubstr("missing instanceType"));
  EXPECT_FALSE(result.get());

  // Test wrong instanceType element.
  error.clear();
  result = ContentAction::Create(
      &profile, nullptr,
      *ParseJson("{\n"
                 "  \"instanceType\": \"declarativeContent.UnknownType\",\n"
                 "}"),
      &error);
  EXPECT_THAT(error, HasSubstr("invalid instanceType"));
  EXPECT_FALSE(result.get());
}

TEST(DeclarativeContentActionTest, ShowPageActionWithoutPageAction) {
  TestExtensionEnvironment env;

  // We install a component extension because all other extensions have a
  // required action.
  DictionaryBuilder manifest;
  manifest.Set("name", "extension")
      .Set("version", "0.1")
      .Set("manifest_version", 2)
      .Set("description", "an extension");
  scoped_refptr<const Extension> extension =
      ExtensionBuilder()
          .SetManifest(manifest.Build())
          .SetLocation(Manifest::COMPONENT)
          .Build();
  env.GetExtensionService()->AddExtension(extension.get());

  TestingProfile profile;
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      &profile, extension.get(),
      *ParseJson("{\n"
                 "  \"instanceType\": \"declarativeContent.ShowPageAction\",\n"
                 "}"),
      &error);
  EXPECT_THAT(error, testing::HasSubstr("without an action"));
  ASSERT_FALSE(result.get());
}

class ParameterizedDeclarativeContentActionTest
    : public ::testing::TestWithParam<ExtensionBuilder::ActionType> {};

TEST_P(ParameterizedDeclarativeContentActionTest, ShowPageAction) {
  TestExtensionEnvironment env;
  content::RenderViewHostTestEnabler rvh_enabler;

  scoped_refptr<const Extension> extension =
      ExtensionBuilder("extension")
          .SetAction(GetParam())
          .SetLocation(Manifest::INTERNAL)
          .Build();

  env.GetExtensionService()->AddExtension(extension.get());

  std::string error;
  TestingProfile profile;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      nullptr, extension.get(),
      *ParseJson(R"({"instanceType": "declarativeContent.ShowPageAction"})"),
      &error);
  EXPECT_TRUE(error.empty()) << error;
  ASSERT_TRUE(result.get());

  ExtensionAction* action = nullptr;
  auto* action_manager = ExtensionActionManager::Get(env.profile());
  const bool is_browser_action =
      GetParam() == ExtensionBuilder::ActionType::BROWSER_ACTION;
  if (is_browser_action) {
    action = action_manager->GetBrowserAction(*extension);
    ASSERT_TRUE(action);
    // Switch the default so we properly see the action toggling.
    action->SetIsVisible(ExtensionAction::kDefaultTabId, false);
  } else {
    action = action_manager->GetPageAction(*extension);
    ASSERT_TRUE(action);
  }

  std::unique_ptr<content::WebContents> contents = env.MakeTab();
  const int tab_id = ExtensionTabUtil::GetTabId(contents.get());

  // Currently, the action is not visible on the given tab.
  EXPECT_FALSE(action->GetIsVisible(tab_id));
  ContentAction::ApplyInfo apply_info = {extension.get(), env.profile(),
                                         contents.get(), /*priority=*/100};

  // Apply the content action once. The action should be visible on the tab.
  result->Apply(apply_info);
  EXPECT_TRUE(action->GetIsVisible(tab_id));
  // Apply the content action a second time. The extension action should be
  // visible on the tab, with a "count" of 2 (i.e., two different content
  // actions are keeping it visible).
  result->Apply(apply_info);
  EXPECT_TRUE(action->GetIsVisible(tab_id));
  // Revert one of the content actions. Since two content actions caused the
  // extension action to be visible, it should still be visible after reverting
  // only one.
  result->Revert(apply_info);
  EXPECT_TRUE(action->GetIsVisible(tab_id));
  // Revert the final content action. The extension action should now be hidden
  // again.
  result->Revert(apply_info);
  EXPECT_FALSE(action->GetIsVisible(tab_id));
}

INSTANTIATE_TEST_CASE_P(
    ,
    ParameterizedDeclarativeContentActionTest,
    testing::Values(ExtensionBuilder::ActionType::BROWSER_ACTION,
                    ExtensionBuilder::ActionType::PAGE_ACTION));

TEST(DeclarativeContentActionTest, SetIcon) {
  TestExtensionEnvironment env;
  content::RenderViewHostTestEnabler rvh_enabler;

  // Simulate the process of passing ImageData to SetIcon::Create.
  SkBitmap bitmap;
  EXPECT_TRUE(bitmap.tryAllocN32Pixels(19, 19));
  // Fill the bitmap with red pixels.
  bitmap.eraseARGB(255, 255, 0, 0);
  IPC::Message bitmap_pickle;
  IPC::WriteParam(&bitmap_pickle, bitmap);
  std::string binary_data = std::string(
      static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size());
  std::string data64;
  base::Base64Encode(binary_data, &data64);

  std::unique_ptr<base::DictionaryValue> dict =
      DictionaryBuilder()
          .Set("instanceType", "declarativeContent.SetIcon")
          .Set("imageData", DictionaryBuilder().Set("19", data64).Build())
          .Build();

  const Extension* extension = env.MakeExtension(
      *ParseJson("{\"page_action\": { \"default_title\": \"Extension\" } }"));
  base::HistogramTester histogram_tester;
  TestingProfile profile;
  std::string error;
  ContentAction::SetAllowInvisibleIconsForTest(false);
  std::unique_ptr<const ContentAction> result =
      ContentAction::Create(&profile, extension, *dict, &error);
  ContentAction::SetAllowInvisibleIconsForTest(true);
  EXPECT_EQ("", error);
  ASSERT_TRUE(result.get());
  EXPECT_THAT(
      histogram_tester.GetAllSamples("Extensions.DeclarativeSetIconWasVisible"),
      testing::ElementsAre(base::Bucket(1, 1)));
  EXPECT_THAT(histogram_tester.GetAllSamples(
                  "Extensions.DeclarativeSetIconWasVisibleRendered"),
              testing::ElementsAre(base::Bucket(1, 1)));

  ExtensionAction* page_action =
      ExtensionActionManager::Get(env.profile())->GetPageAction(*extension);
  std::unique_ptr<content::WebContents> contents = env.MakeTab();
  const int tab_id = ExtensionTabUtil::GetTabId(contents.get());
  EXPECT_FALSE(page_action->GetIsVisible(tab_id));
  ContentAction::ApplyInfo apply_info = {
    extension, env.profile(), contents.get(), 100
  };

  // The declarative icon shouldn't exist unless the content action is applied.
  EXPECT_TRUE(page_action->GetDeclarativeIcon(tab_id).IsEmpty());
  result->Apply(apply_info);
  EXPECT_FALSE(page_action->GetDeclarativeIcon(tab_id).IsEmpty());
  result->Revert(apply_info);
  EXPECT_TRUE(page_action->GetDeclarativeIcon(tab_id).IsEmpty());
}

TEST(DeclarativeContentActionTest, SetInvisibleIcon) {
  TestExtensionEnvironment env;

  // Simulate the process of passing ImageData to SetIcon::Create.
  SkBitmap bitmap;
  EXPECT_TRUE(bitmap.tryAllocN32Pixels(19, 19));
  bitmap.eraseARGB(0, 0, 0, 0);
  uint32_t* pixels = bitmap.getAddr32(0, 0);
  // Set a single pixel, which isn't enough to consider the icon visible.
  pixels[0] = SkColorSetARGB(255, 255, 0, 0);
  IPC::Message bitmap_pickle;
  IPC::WriteParam(&bitmap_pickle, bitmap);
  std::string binary_data = std::string(
      static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size());
  std::string data64;
  base::Base64Encode(binary_data, &data64);

  std::unique_ptr<base::DictionaryValue> dict =
      DictionaryBuilder()
          .Set("instanceType", "declarativeContent.SetIcon")
          .Set("imageData", DictionaryBuilder().Set("19", data64).Build())
          .Build();

  // Expect an error and no instance to be created.
  const Extension* extension = env.MakeExtension(
      *ParseJson(R"({"page_action": {"default_title": "Extension"}})"));
  base::HistogramTester histogram_tester;
  TestingProfile profile;
  std::string error;
  ContentAction::SetAllowInvisibleIconsForTest(false);
  std::unique_ptr<const ContentAction> result =
      ContentAction::Create(&profile, extension, *dict, &error);
  ContentAction::SetAllowInvisibleIconsForTest(true);
  EXPECT_EQ("The specified icon is not sufficiently visible", error);
  EXPECT_FALSE(result);
  EXPECT_THAT(
      histogram_tester.GetAllSamples("Extensions.DeclarativeSetIconWasVisible"),
      testing::ElementsAre(base::Bucket(0, 1)));
  EXPECT_THAT(histogram_tester.GetAllSamples(
                  "Extensions.DeclarativeSetIconWasVisibleRendered"),
              testing::ElementsAre(base::Bucket(0, 1)));
}

TEST_F(RequestContentScriptTest, MissingScripts) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"allFrames\": true,\n"
          "  \"matchAboutBlank\": true\n"
          "}"),
      &error);
  EXPECT_THAT(error, testing::HasSubstr("Missing parameter is required"));
  ASSERT_FALSE(result.get());
}

TEST_F(RequestContentScriptTest, CSS) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"css\": [\"style.css\"]\n"
          "}"),
      &error);
  EXPECT_EQ("", error);
  ASSERT_TRUE(result.get());
}

TEST_F(RequestContentScriptTest, JS) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": [\"script.js\"]\n"
          "}"),
      &error);
  EXPECT_EQ("", error);
  ASSERT_TRUE(result.get());
}

TEST_F(RequestContentScriptTest, CSSBadType) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"css\": \"style.css\"\n"
          "}"),
      &error);
  ASSERT_FALSE(result.get());
}

TEST_F(RequestContentScriptTest, JSBadType) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": \"script.js\"\n"
          "}"),
      &error);
  ASSERT_FALSE(result.get());
}

TEST_F(RequestContentScriptTest, AllFrames) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": [\"script.js\"],\n"
          "  \"allFrames\": true\n"
          "}"),
      &error);
  EXPECT_EQ("", error);
  ASSERT_TRUE(result.get());
}

TEST_F(RequestContentScriptTest, MatchAboutBlank) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": [\"script.js\"],\n"
          "  \"matchAboutBlank\": true\n"
          "}"),
      &error);
  EXPECT_EQ("", error);
  ASSERT_TRUE(result.get());
}

TEST_F(RequestContentScriptTest, AllFramesBadType) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": [\"script.js\"],\n"
          "  \"allFrames\": null\n"
          "}"),
      &error);
  ASSERT_FALSE(result.get());
}

TEST_F(RequestContentScriptTest, MatchAboutBlankBadType) {
  Init();
  std::string error;
  std::unique_ptr<const ContentAction> result = ContentAction::Create(
      profile(), extension(),
      *ParseJson(
          "{\n"
          "  \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
          "  \"js\": [\"script.js\"],\n"
          "  \"matchAboutBlank\": null\n"
          "}"),
      &error);
  ASSERT_FALSE(result.get());
}

}  // namespace
}  // namespace extensions
