// 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 <stddef.h>

#include <map>
#include <utility>

#include "base/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "chrome/browser/extensions/active_tab_permission_granter.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/navigation_simulator.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/manifest.h"
#include "extensions/common/mojom/injection_type.mojom-shared.h"
#include "extensions/common/mojom/run_location.mojom-shared.h"
#include "extensions/common/user_script.h"
#include "extensions/common/value_builder.h"

namespace extensions {

namespace {

const char kAllHostsPermission[] = "*://*/*";

}  // namespace

// Unittests for the ExtensionActionRunner mostly test the internal logic
// of the runner itself (when to allow/deny extension script injection).
// Testing real injection is allowed/denied as expected (i.e., that the
// ExtensionActionRunner correctly interfaces in the system) is done in the
// ExtensionActionRunnerBrowserTests.
class ExtensionActionRunnerUnitTest : public ChromeRenderViewHostTestHarness {
 public:
  ExtensionActionRunnerUnitTest(const ExtensionActionRunnerUnitTest&) = delete;
  ExtensionActionRunnerUnitTest& operator=(
      const ExtensionActionRunnerUnitTest&) = delete;

 protected:
  ExtensionActionRunnerUnitTest();
  ~ExtensionActionRunnerUnitTest() override;

  // Creates an extension with all hosts permission and adds it to the registry.
  const Extension* AddExtension();

  // Reloads |extension_| by removing it from the registry and recreating it.
  const Extension* ReloadExtension();

  // Returns true if the |extension| requires user consent before injecting
  // a script.
  bool RequiresUserConsent(const Extension* extension) const;

  // Request an injection for the given |extension|.
  void RequestInjection(const Extension* extension);
  void RequestInjection(const Extension* extension,
                        mojom::RunLocation run_location);

  // Returns the number of times a given extension has had a script execute.
  size_t GetExecutionCountForExtension(const std::string& extension_id) const;

  ExtensionActionRunner* runner() const { return extension_action_runner_; }

 private:
  // Returns a closure to use as a script execution for a given extension.
  ExtensionActionRunner::ScriptInjectionCallback
  GetExecutionCallbackForExtension(const std::string& extension_id);

  // Increment the number of executions for the given |extension_id|.
  void IncrementExecutionCount(const std::string& extension_id, bool granted);

  void SetUp() override;

  // The associated ExtensionActionRunner.
  raw_ptr<ExtensionActionRunner> extension_action_runner_ = nullptr;

  // The map of observed executions, keyed by extension id.
  std::map<std::string, int> extension_executions_;

  scoped_refptr<const Extension> extension_;
};

ExtensionActionRunnerUnitTest::ExtensionActionRunnerUnitTest() = default;
ExtensionActionRunnerUnitTest::~ExtensionActionRunnerUnitTest() = default;

const Extension* ExtensionActionRunnerUnitTest::AddExtension() {
  const std::string kId = crx_file::id_util::GenerateId("all_hosts_extension");
  extension_ =
      ExtensionBuilder()
          .SetManifest(
              DictionaryBuilder()
                  .Set("name", "all_hosts_extension")
                  .Set("description", "an extension")
                  .Set("manifest_version", 2)
                  .Set("version", "1.0.0")
                  .Set("permissions",
                       ListBuilder().Append(kAllHostsPermission).Build())
                  .Build())
          .SetLocation(mojom::ManifestLocation::kInternal)
          .SetID(kId)
          .Build();

  ExtensionRegistry::Get(profile())->AddEnabled(extension_);
  PermissionsUpdater(profile()).InitializePermissions(extension_.get());

  ScriptingPermissionsModifier(profile(), extension_.get())
      .SetWithholdHostPermissions(true);
  return extension_.get();
}

const Extension* ExtensionActionRunnerUnitTest::ReloadExtension() {
  ExtensionRegistry::Get(profile())->RemoveEnabled(extension_->id());
  return AddExtension();
}

bool ExtensionActionRunnerUnitTest::RequiresUserConsent(
    const Extension* extension) const {
  PermissionsData::PageAccess access_type =
      runner()->RequiresUserConsentForScriptInjectionForTesting(
          extension, mojom::InjectionType::kProgrammaticScript);
  // We should never downright refuse access in these tests.
  DCHECK_NE(PermissionsData::PageAccess::kDenied, access_type);
  return access_type == PermissionsData::PageAccess::kWithheld;
}

void ExtensionActionRunnerUnitTest::RequestInjection(
    const Extension* extension) {
  RequestInjection(extension, mojom::RunLocation::kDocumentIdle);
}

void ExtensionActionRunnerUnitTest::RequestInjection(
    const Extension* extension,
    mojom::RunLocation run_location) {
  runner()->RequestScriptInjectionForTesting(
      extension, run_location,
      GetExecutionCallbackForExtension(extension->id()));
}

size_t ExtensionActionRunnerUnitTest::GetExecutionCountForExtension(
    const std::string& extension_id) const {
  auto iter = extension_executions_.find(extension_id);
  if (iter != extension_executions_.end())
    return iter->second;
  return 0u;
}

ExtensionActionRunner::ScriptInjectionCallback
ExtensionActionRunnerUnitTest::GetExecutionCallbackForExtension(
    const std::string& extension_id) {
  // We use base unretained here, but if this ever gets executed outside of
  // this test's lifetime, we have a major problem anyway.
  return base::BindOnce(&ExtensionActionRunnerUnitTest::IncrementExecutionCount,
                        base::Unretained(this), extension_id);
}

void ExtensionActionRunnerUnitTest::IncrementExecutionCount(
    const std::string& extension_id,
    bool granted) {
  if (!granted)
    return;
  ++extension_executions_[extension_id];
}

void ExtensionActionRunnerUnitTest::SetUp() {
  ChromeRenderViewHostTestHarness::SetUp();

  TabHelper::CreateForWebContents(web_contents());
  TabHelper* tab_helper = TabHelper::FromWebContents(web_contents());
  // These should never be null.
  DCHECK(tab_helper);
  extension_action_runner_ = tab_helper->extension_action_runner();
  DCHECK(extension_action_runner_);
}

// Test that extensions with all_hosts require permission to execute, and, once
// that permission is granted, do execute.
TEST_F(ExtensionActionRunnerUnitTest, RequestPermissionAndExecute) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.google.com"));

  // Ensure that there aren't any executions pending.
  ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
  ASSERT_FALSE(runner()->WantsToRun(extension));

  // Since the extension requests all_hosts, we should require user consent.
  EXPECT_TRUE(RequiresUserConsent(extension));

  // Request an injection. The extension should want to run, but should not have
  // executed.
  RequestInjection(extension);
  EXPECT_TRUE(runner()->WantsToRun(extension));
  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Click to accept the extension executing.
  runner()->RunForTesting(extension);

  // The extension should execute, and the extension shouldn't want to run.
  EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));

  // Since we already executed on the given page, we shouldn't need permission
  // for a second time.
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Reloading and same-origin navigations shouldn't clear those permissions,
  // and we shouldn't require user constent again.
  content::NavigationSimulator::Reload(web_contents());
  EXPECT_FALSE(RequiresUserConsent(extension));
  NavigateAndCommit(GURL("https://www.google.com/foo"));
  EXPECT_FALSE(RequiresUserConsent(extension));
  NavigateAndCommit(GURL("https://www.google.com/bar"));
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Cross-origin navigations should clear permissions.
  NavigateAndCommit(GURL("https://otherdomain.google.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));

  // Grant access.
  RequestInjection(extension);
  runner()->RunForTesting(extension);
  EXPECT_EQ(2u, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));

  // Navigating to another site should also clear the permissions.
  NavigateAndCommit(GURL("https://www.foo.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));
}

// Test that injections that are not executed by the time the user navigates are
// ignored and never execute.
TEST_F(ExtensionActionRunnerUnitTest, PendingInjectionsRemovedAtNavigation) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.google.com"));

  ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Request an injection. The extension should want to run, but not execute.
  RequestInjection(extension);
  EXPECT_TRUE(runner()->WantsToRun(extension));
  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Reload. This should remove the pending injection, and we should not
  // execute anything.
  content::NavigationSimulator::Reload(web_contents());
  EXPECT_FALSE(runner()->WantsToRun(extension));
  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Request and accept a new injection.
  RequestInjection(extension);
  runner()->RunForTesting(extension);

  // The extension should only have executed once, even though a grand total
  // of two executions were requested.
  EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));
}

// Test that queueing multiple pending injections, and then accepting, triggers
// them all.
TEST_F(ExtensionActionRunnerUnitTest, MultiplePendingInjection) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);
  NavigateAndCommit(GURL("https://www.google.com"));

  ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  const size_t kNumInjections = 3u;
  // Queue multiple pending injections.
  for (size_t i = 0u; i < kNumInjections; ++i)
    RequestInjection(extension);

  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  runner()->RunForTesting(extension);

  // All pending injections should have executed.
  EXPECT_EQ(kNumInjections, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));
}

TEST_F(ExtensionActionRunnerUnitTest, ActiveScriptsUseActiveTabPermissions) {
  const Extension* extension = AddExtension();
  NavigateAndCommit(GURL("https://www.google.com"));

  ActiveTabPermissionGranter* active_tab_permission_granter =
      TabHelper::FromWebContents(web_contents())
          ->active_tab_permission_granter();
  ASSERT_TRUE(active_tab_permission_granter);
  // Grant the extension active tab permissions. This normally happens, e.g.,
  // if the user clicks on a browser action.
  active_tab_permission_granter->GrantIfRequested(extension);

  // Since we have active tab permissions, we shouldn't need user consent
  // anymore.
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Reloading and other same-origin navigations maintain the permission to
  // execute.
  content::NavigationSimulator::Reload(web_contents());
  EXPECT_FALSE(RequiresUserConsent(extension));
  NavigateAndCommit(GURL("https://www.google.com/foo"));
  EXPECT_FALSE(RequiresUserConsent(extension));
  NavigateAndCommit(GURL("https://www.google.com/bar"));
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Navigating to a different origin will require user consent again.
  NavigateAndCommit(GURL("https://yahoo.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));

  // Back to the original origin should also re-require constent.
  NavigateAndCommit(GURL("https://www.google.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));

  RequestInjection(extension);
  EXPECT_TRUE(runner()->WantsToRun(extension));
  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Grant active tab.
  active_tab_permission_granter->GrantIfRequested(extension);

  // The pending injections should have run since active tab permission was
  // granted.
  EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));
}

TEST_F(ExtensionActionRunnerUnitTest, ActiveScriptsCanHaveAllUrlsPref) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.google.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));

  // Enable the extension on all urls.
  ScriptingPermissionsModifier permissions_modifier(profile(), extension);
  permissions_modifier.SetWithholdHostPermissions(false);

  EXPECT_FALSE(RequiresUserConsent(extension));
  // This should carry across navigations, and websites.
  NavigateAndCommit(GURL("http://www.foo.com"));
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Turning off the preference should have instant effect.
  permissions_modifier.SetWithholdHostPermissions(true);
  EXPECT_TRUE(RequiresUserConsent(extension));

  // And should also persist across navigations and websites.
  NavigateAndCommit(GURL("http://www.bar.com"));
  EXPECT_TRUE(RequiresUserConsent(extension));
}

TEST_F(ExtensionActionRunnerUnitTest, TestAlwaysRun) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.google.com/?gws_rd=ssl"));

  // Ensure that there aren't any executions pending.
  ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
  ASSERT_FALSE(runner()->WantsToRun(extension));

  // Since the extension requests all_hosts, we should require user consent.
  EXPECT_TRUE(RequiresUserConsent(extension));

  // Request an injection. The extension should want to run, but not execute.
  RequestInjection(extension);
  EXPECT_TRUE(runner()->WantsToRun(extension));
  EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));

  // Allow the extension to always run on this origin.
  ScriptingPermissionsModifier modifier(profile(), extension);
  modifier.GrantHostPermission(web_contents()->GetLastCommittedURL());
  runner()->RunForTesting(extension);

  // The extension should execute, and the extension shouldn't want to run.
  EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
  EXPECT_FALSE(runner()->WantsToRun(extension));

  // Since we already executed on the given page, we shouldn't need permission
  // for a second time.
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Navigating to another site that hasn't been granted a persisted permission
  // should necessitate user consent.
  NavigateAndCommit(GURL("https://www.foo.com/bar"));
  EXPECT_TRUE(RequiresUserConsent(extension));

  // We shouldn't need user permission upon returning to the original origin.
  NavigateAndCommit(GURL("https://www.google.com/foo/bar"));
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Reloading the extension should not clear any granted host permissions.
  extension = ReloadExtension();
  content::NavigationSimulator::Reload(web_contents());
  EXPECT_FALSE(RequiresUserConsent(extension));

  // Different host...
  NavigateAndCommit(GURL("https://www.foo.com/bar"));
  EXPECT_TRUE(RequiresUserConsent(extension));
  // Different scheme...
  NavigateAndCommit(GURL("http://www.google.com/foo/bar"));
  EXPECT_TRUE(RequiresUserConsent(extension));
  // Different subdomain...
  NavigateAndCommit(GURL("https://en.google.com/foo/bar"));
  EXPECT_TRUE(RequiresUserConsent(extension));
  // Only the "always run" origin should be allowed to run without user consent.
  NavigateAndCommit(GURL("https://www.google.com/foo/bar"));
  EXPECT_FALSE(RequiresUserConsent(extension));
}

TEST_F(ExtensionActionRunnerUnitTest, TestDifferentScriptRunLocations) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.foo.com"));

  EXPECT_EQ(BLOCKED_ACTION_NONE, runner()->GetBlockedActions(extension));

  RequestInjection(extension, mojom::RunLocation::kDocumentEnd);
  EXPECT_EQ(BLOCKED_ACTION_SCRIPT_OTHER,
            runner()->GetBlockedActions(extension));
  RequestInjection(extension, mojom::RunLocation::kDocumentIdle);
  EXPECT_EQ(BLOCKED_ACTION_SCRIPT_OTHER,
            runner()->GetBlockedActions(extension));
  RequestInjection(extension, mojom::RunLocation::kDocumentStart);
  EXPECT_EQ(BLOCKED_ACTION_SCRIPT_AT_START | BLOCKED_ACTION_SCRIPT_OTHER,
            runner()->GetBlockedActions(extension));

  runner()->RunForTesting(extension);
  EXPECT_EQ(BLOCKED_ACTION_NONE, runner()->GetBlockedActions(extension));
}

TEST_F(ExtensionActionRunnerUnitTest, TestWebRequestBlocked) {
  const Extension* extension = AddExtension();
  ASSERT_TRUE(extension);

  NavigateAndCommit(GURL("https://www.foo.com"));

  EXPECT_EQ(BLOCKED_ACTION_NONE, runner()->GetBlockedActions(extension));
  EXPECT_FALSE(runner()->WantsToRun(extension));

  runner()->OnWebRequestBlocked(extension);
  EXPECT_EQ(BLOCKED_ACTION_WEB_REQUEST, runner()->GetBlockedActions(extension));
  EXPECT_TRUE(runner()->WantsToRun(extension));

  RequestInjection(extension);
  EXPECT_EQ(BLOCKED_ACTION_WEB_REQUEST | BLOCKED_ACTION_SCRIPT_OTHER,
            runner()->GetBlockedActions(extension));
  EXPECT_TRUE(runner()->WantsToRun(extension));

  NavigateAndCommit(GURL("https://www.bar.com"));
  EXPECT_EQ(BLOCKED_ACTION_NONE, runner()->GetBlockedActions(extension));
  EXPECT_FALSE(runner()->WantsToRun(extension));
}

}  // namespace extensions
