chromium/chrome/browser/extensions/content_verifier_browsertest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/browser/content_verifier/content_verifier.h"

#include <list>
#include <memory>
#include <set>
#include <string>

#include "base/files/file_util.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/string_split.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/browsertest_util.h"
#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
#include "chrome/browser/extensions/content_verifier_test_utils.h"
#include "chrome/browser/extensions/corrupted_extension_reinstaller.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/crx_file/id_util.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/content_verifier/content_verify_job.h"
#include "extensions/browser/content_verifier/test_utils.h"
#include "extensions/browser/crx_file_info.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/external_install_info.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/mock_external_provider.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/browser/updater/extension_update_data.h"
#include "extensions/browser/updater/manifest_fetch_data.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/file_util.h"
#include "extensions/test/extension_test_message_listener.h"
#include "third_party/zlib/google/compression_utils.h"

#if BUILDFLAG(IS_MAC)
#include "extensions/common/extension_features.h"
#endif

ManifestLocation;

namespace extensions {

namespace {
constexpr char kTenMegResourceExtensionId[] =;
constexpr char kStoragePermissionExtensionId[] =;
constexpr char kStoragePermissionExtensionCrx[] =;

class MockUpdateService : public UpdateService {};

void ExtensionUpdateComplete(base::OnceClosure callback,
                             const std::optional<CrxInstallError>& error) {}

// A helper override to force generation of hashes for all extensions, not just
// those from the webstore.
ChromeContentVerifierDelegate::VerifyInfo GetVerifyInfoAndForceHashes(
    const Extension& extension) {}

}  // namespace

class ContentVerifierTest : public ExtensionBrowserTest {};

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) {}

// Make sure that `VerifierObserver` doesn't crash on destruction.
//
// Regression test for https://crbug.com/353880557.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       VerifierObserverNoCrashOnDestruction) {}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, ContentScripts) {}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, ContentScriptsInLocales) {}

// Tests that a deleted content_script results in content verification failure.
//
// Regression test for crbug.com/1296310.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       DeletedContentScriptFailsContentVerification) {}

// Tests that an unreadable content_script results in content verification
// failure.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       UnreadableContentScriptFailsContentVerification) {}

// A class that forces all installed extensions to generate hashes (normally,
// we'd only generate hashes for policy-installed extensions with the
// appropriate enterprise policy applied). This makes it easier to test the
// relevant bits of content verification (namely, verifying content against an
// expected set) without needing webstore-signed hashes in the test environment.
class ContentVerifierTestWithForcedHashes : public ContentVerifierTest {};

// Tests detection of corruption in an extension's service worker file.
IN_PROC_BROWSER_TEST_F(ContentVerifierTestWithForcedHashes,
                       TestServiceWorkerCorruption_DisableAndEnable) {}

// Tests service worker corruption detection across browser starts.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       PRE_TestServiceWorker_AcrossSession) {}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest, TestServiceWorker_AcrossSession) {}

// Tests the case of a corrupt extension that is force-installed by policy and
// should not be allowed to be manually uninstalled/disabled by the user.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest, PolicyCorrupted) {}

// Tests the case when an extension is first manually installed, then it gets
// corrupted and then it is added to force installed list. The extension should
// get reinstalled and should be enabled.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       ManualInstalledExtensionGotCorruptedThenForceInstalled) {}

class UserInstalledContentVerifierTest : public ContentVerifierTest {};

// Setup a corrupted extension by tampering with one of its source files in
// PRE to verify that it is repaired at startup.
IN_PROC_BROWSER_TEST_F(UserInstalledContentVerifierTest,
                       PRE_UserInstalledCorruptedResourceOnStartup) {}

// Now actually test what happens on the next startup after the PRE test above.
// TODO(crbug.com/40776295): Test is flaky.
IN_PROC_BROWSER_TEST_F(UserInstalledContentVerifierTest,
                       DISABLED_UserInstalledCorruptedResourceOnStartup) {}

// Tests that verification failure during navigating to an extension resource
// correctly disables the extension.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest, VerificationFailureOnNavigate) {}

// Verifies that CRX with verified contents injected into the header is
// successfully installed and verified.
IN_PROC_BROWSER_TEST_F(
    ContentVerifierTest,
    VerificationSuccessfulForCrxWithVerifiedContentsInjectedInHeader) {}

// Verifies that CRX with malformed verified contents injected into the header
// is not installed.
IN_PROC_BROWSER_TEST_F(
    ContentVerifierTest,
    InstallationFailureForCrxWithMalformedVerifiedContentsInjectedInHeader) {}

// Verifies that CRX with missing verified contents is successfully installed
// but not verified due to missing hashes.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       VerificationFailureForMissingVerifiedContents) {}

// Tests that tampering with a large resource fails content verification as
// expected. The size of the resource is such that it would trigger
// FileLoaderObserver::OnSeekComplete in extension_protocols.cc.
//
// Regression test for: http://crbug.com/965043.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest, TamperLargeSizedResource) {}

// Tests that a resource reading failure due to FileURLLoader cancellation
// does not incorrectly result in content verificaton failure.
// Regression test for: http://crbug.com/977805.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       PRE_ResourceReadCancellationDoesNotFailVerification) {}

IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       ResourceReadCancellationDoesNotFailVerification) {}

// Tests that navigating to an extension resource with '/' at end does not
// disable the extension.
//
// Regression test for: https://crbug.com/929578.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       RemainsEnabledOnNavigateToPathEndingWithSlash) {}

#if BUILDFLAG(IS_MAC)
class ContentVerifierTestWithSeparatorFlagDisabled
    : public ContentVerifierTest {
 protected:
  ContentVerifierTestWithSeparatorFlagDisabled() {
    feature_list_.InitAndDisableFeature(
        extensions_features::kMacRejectFilePathsEndingWithSeparator);
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

// Same as ContentVerifierTest.RemainsEnabledOnNavigateToPathEndingWithSlash,
// but with the MacRejectFilePathsEndingWithSeparator flag disabled. See
// https://crbug.com/356878412.
// TODO(crbug.com/357636604): Remove after the flag is removed in M132.
IN_PROC_BROWSER_TEST_F(ContentVerifierTestWithSeparatorFlagDisabled,
                       RemainsEnabledOnNavigateToPathEndingWithSlash) {
  const Extension* extension = InstallExtensionFromWebstore(
      test_data_dir_.AppendASCII("content_verifier/dot_slash_paths.crx"), 1);
  ASSERT_TRUE(extension);
  const ExtensionId kExtensionId = extension->id();

  GURL page_url = extension->GetResourceURL("page.html/");
  ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
      browser(), page_url, 1, WindowOpenDisposition::CURRENT_TAB,
      ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
  int reasons = prefs->GetDisableReasons(kExtensionId);
  EXPECT_EQ(0, reasons);
}
#endif  // BUILDFLAG(IS_MAC)

// Tests that navigating to an extension resource with '.' at end does not
// disable the extension.
//
// Regression test for https://crbug.com/696208.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       RemainsEnabledOnNavigateToPathEndingWithDot) {}

// Tests that navigating to an extension resource with incorrect case does not
// disable the extension, both in case-sensitive and case-insensitive systems.
//
// Regression test for https://crbug.com/1033294.
IN_PROC_BROWSER_TEST_F(ContentVerifierTest,
                       RemainsEnabledOnNavigateToPathWithIncorrectCase) {}

class ContentVerifierPolicyTest : public ContentVerifierTest {};

// We want to test what happens at startup with a corroption-disabled policy
// force installed extension. So we set that up in the PRE test here.
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest,
                       PRE_PolicyCorruptedOnStartup) {}

// Now actually test what happens on the next startup after the PRE test above.
// TODO(crbug.com/40805905): Flaky on mac arm64.
#if BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)
#define MAYBE_PolicyCorruptedOnStartup
#else
#define MAYBE_PolicyCorruptedOnStartup
#endif
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest,
                       MAYBE_PolicyCorruptedOnStartup) {}

IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest, Backoff) {}

// Tests that if CheckForExternalUpdates() fails, then we retry reinstalling
// corrupted policy extensions. For example: if network is unavailable,
// CheckForExternalUpdates() will fail.
IN_PROC_BROWSER_TEST_F(ContentVerifierPolicyTest, FailedUpdateRetries) {}

}  // namespace extensions