chromium/chrome/browser/extensions/orb_and_cors_extension_browsertest.cc

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

#include <string>
#include <string_view>
#include <vector>

#include "base/containers/to_vector.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
#include "chrome/browser/extensions/api/permissions/permissions_api.h"
#include "chrome/browser/extensions/api/tabs/tabs_api.h"
#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
#include "chrome/browser/extensions/extension_action_runner.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/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/embedder_support/switches.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/console_message.h"
#include "content/public/browser/network_service_util.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/service_worker_context_observer.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/resource_load_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/browsertest_util.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/permissions_manager.h"
#include "extensions/browser/service_worker/service_worker_test_utils.h"
#include "extensions/browser/url_loader_factory_manager.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/permissions_manager_waiter.h"
#include "extensions/test/test_extension_dir.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom-shared.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace extensions {

namespace {

const char kCorsErrorWhenFetching[] =;

// This is the public key of tools/origin_trials/eftest.key, used to validate
// origin trial tokens generated by tools/origin_trials/generate_token.py.
constexpr char kOriginTrialPublicKeyForTesting[] =;

std::string CreateFetchScript(
    const GURL& resource,
    std::optional<base::Value::Dict> request_init = std::nullopt) {}

std::string PopString(content::DOMMessageQueue* message_queue) {}

}  // namespace

HasSubstr;

class OrbAndCorsExtensionTestBase : public ExtensionBrowserTest {};

class ServiceWorkerConsoleObserver
    : public content::ServiceWorkerContextObserver {};

class OrbAndCorsExtensionBrowserTest : public OrbAndCorsExtensionTestBase {};

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromDeclarativeContentScript_NoSniffXml) {}

// Test that verifies the current, baked-in (but not necessarily desirable
// behavior) where a content script injected by an extension can bypass
// CORS (and ORB) for any hosts the extension has access to.
// See also https://crbug.com/846346.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_NoSniffXml) {}

// Tests that extension permission to bypass CORS is revoked after the extension
// is unloaded.  See also https://crbug.com/843381.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_UnloadedExtension) {}

// Test that <all_urls> permission does not apply to hosts blocked by policy.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ContentScriptVsHostBlockedByPolicy_NoSniffXml) {}

// Test that <all_urls> permission does not apply to hosts blocked by policy.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ContentScriptVsHostBlockedByPolicy_AllowedTextResource) {}

class OrbAndCorsUserHostRestrictionsBrowserTest
    : public OrbAndCorsExtensionBrowserTest {};

IN_PROC_BROWSER_TEST_F(OrbAndCorsUserHostRestrictionsBrowserTest,
                       PolicyVsUserHostRestrictions) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_PermissionToAllUrls) {}
// Verification that granting file access to extensions doesn't relax CORS in
// case of requests to file: URLs (even from content scripts of extensions with
// <all_urls> permission).  See also https://crbug.com/1049604#c14.
IN_PROC_BROWSER_TEST_F(
    OrbAndCorsExtensionBrowserTest,
    FromProgrammaticContentScript_PermissionToAllUrls_FileUrls) {}

// Coverage of *.subdomain.com extension permissions for ORB-eligible fetches
// (via nosniff.xml).
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_SubdomainPermissions) {}

// Test that verifies the current, baked-in (but not necessarily desirable
// behavior) where a content script injected by an extension can bypass
// CORS (and ORB) for any hosts the extension has access to.
// See also https://crbug.com/1034408 and https://crbug.com/846346.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_RedirectToNoSniffXml) {}

// Test that verifies CORS-allowed fetches work for targets that are not
// covered by the extension permissions.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ContentScript_CorsAllowedByServer_NoPermissionToTarget) {}

// Test that verifies that CORS blocks non-ORB-eligible fetches for targets
// that are not covered by the extension permissions.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ContentScript_CorsIgnoredByServer_NoPermissionToTarget) {}

// Tests that same-origin fetches (same-origin relative to the webpage the
// content script is injected into) are allowed.  See also
// https://crbug.com/918660.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_SameOrigin) {}

// Test that responses that would have been allowed by ORB anyway are not
// reported to LogInitiatorSchemeBypassingDocumentBlocking.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_AllowedTextResource) {}

// The private-state-token-redemption Permissions Policy feature, which is
// enabled by default, is required in order to execute a Trust Tokens
// (https://github.com/wicg/trust-token-api) redemption operation alongside a
// subresource request. To enforce this requirement, the browser binds the
// feature's value to a frame's subresource loader.
//
// Ensure that it is being propagated correctly for by verifying that a content
// script can execute a redemption operation.
//
// (Specifically, this makes sure RFHI is passing the correct factory
// parameter to URLLoaderFactoryParamsHelper::CreateForIsolatedWorld.)
class TrustTokenExtensionBrowserTest : public OrbAndCorsExtensionBrowserTest {};

// TODO(crbug.com/40221677): Have trust tokens handle the existence, or not, of
// PrivacySandboxSettings3.
IN_PROC_BROWSER_TEST_F(
    TrustTokenExtensionBrowserTest,
    DISABLED_FromProgrammaticContentScript_TrustTokenRedemptionAllowed) {}

// Coverage of *.subdomain.com extension permissions for non-ORB eligible
// fetches (via save_page/text.txt).
IN_PROC_BROWSER_TEST_F(
    OrbAndCorsExtensionBrowserTest,
    FromProgrammaticContentScript_AllowedTextResource_SubdomainPermissions) {}

// Test that responses that would have been allowed by ORB after sniffing are
// included in the AllowedByOrbButNotCors UMA.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_AllowedAfterSniffing) {}

// Test that responses are blocked by ORB, but have empty response body are not
// reported to LogInitiatorSchemeBypassingDocumentBlocking.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromProgrammaticContentScript_EmptyAndBlocked) {}

// Test that requests from an extension background page use relaxed CORS
// processing.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_NoSniffXml) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_NoSniffXml_OriginAccessList) {}

// Test that requests from an extension background page use relaxed ORB
// processing in `no-cors` mode.  See also https://crbug.com/1252173.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_NoSniffXml_NoCors) {}

// Test that requests from an extension background page use relaxed ORB
// processing.  This test covers split-mode extensions - see:
// https://developer.chrome.com/docs/extensions/mv2/manifest/incognito/#split)
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_IncognitoSplitMode) {}

// Test that ORB+CORS are enforced for extensions with no permissions to
// http/https origins.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ExtensionWithNoHttpPermissions) {}

// Test that ORB+CORS are enforced for extensions with optional permissions to
// http/https origins.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ExtensionWithOptionalHttpPermissions) {}

// Test that requests from an extension page hosted in a foreground tab use
// relaxed ORB processing.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromForegroundPage_NoSniffXml) {}

// Test that requests from an extension page hosted in a foreground tab use
// relaxed ORB processing.  This test covers split-mode extensions - see:
// https://developer.chrome.com/docs/extensions/mv2/manifest/incognito/#split
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromForegroundPage_IncognitoSplitMode) {}

// Test that requests from an extension's service worker to the network use
// relaxed ORB processing (both in the case of requests that 1) are initiated
// by the service worker and/or 2) are ignored by the service worker and fall
// back to the network).
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromRegisteredServiceWorker_NoSniffXml) {}

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \
    BUILDFLAG(IS_MAC)
// Flaky on Linux, especially under sanitizers: https://crbug.com/1073052
// Flaky UAF on Mac under ASAN: https://crbug.com/1082355
#define MAYBE_FromBackgroundServiceWorker_NoSniffXml
#else
#define MAYBE_FromBackgroundServiceWorker_NoSniffXml
#endif

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       MAYBE_FromBackgroundServiceWorker_NoSniffXml) {}

class ReadyToCommitWaiter : public content::WebContentsObserver {};

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       ProgrammaticContentScriptVsWebUI) {}

class OrbAndCorsAppBrowserTest : public PlatformAppBrowserTest {};

IN_PROC_BROWSER_TEST_F(OrbAndCorsAppBrowserTest, WebViewContentScript) {}

OriginHeaderExtensionBrowserTest;

IN_PROC_BROWSER_TEST_F(OriginHeaderExtensionBrowserTest,
                       OriginHeaderInCrossOriginGetRequest) {}

IN_PROC_BROWSER_TEST_F(OriginHeaderExtensionBrowserTest,
                       OriginHeaderInCrossOriginPostRequest) {}

IN_PROC_BROWSER_TEST_F(OriginHeaderExtensionBrowserTest,
                       OriginHeaderInSameOriginPostRequest) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       RequestHeaders_InSameOriginFetch_FromContentScript) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       RequestHeaders_InSameOriginXhr_FromContentScript) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest, CorsFromContentScript) {}

IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_ActiveTabPermission) {}

// Similar to FromBackgroundPage_ActiveTabPermission, but focues on interaction
// between the regular background page and the separate incognito background
// page in "split" mode.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_ActiveTabPermission_SplitMode) {}

// Similar to FromBackgroundPage_ActiveTabPermission_SplitMode, but goes through
// steps that (at one point) forced additional, persistent leaking of incognito
// permission into the regular profile's background page.  See also
// https://crbug.com/1167262.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_ActiveTabPermission_SplitMode2) {}

// Similar to FromBackgroundPage_ActiveTabPermission, but focues on behavior
// of the background page when it is shared between the regular and the
// incognito profiles in "spanning" mode.
IN_PROC_BROWSER_TEST_F(OrbAndCorsExtensionBrowserTest,
                       FromBackgroundPage_ActiveTabPermission_SpanningMode) {}

}  // namespace extensions