chromium/content/browser/isolated_origin_browsertest.cc

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

#include <sstream>
#include <tuple>
#include <vector>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/origin_agent_cluster_isolation_state.h"
#include "content/browser/process_lock.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/site_info.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/features.h"
#include "content/public/browser/browser_or_resource_context.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/web_exposed_isolation_level.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_navigation_interceptor.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/dom_storage/dom_storage.mojom-test-utils.h"
#include "url/gurl.h"

namespace content {

IsolatedOriginSource;

// This is a base class for all tests in this class.  It does not isolate any
// origins and only provides common helper functions to the other test classes.
class IsolatedOriginTestBase : public ContentBrowserTest {};

class IsolatedOriginTest : public IsolatedOriginTestBase {};

// Tests that verify the header can be used to opt-in to origin isolation.
class OriginIsolationOptInHeaderTest : public IsolatedOriginTestBase {};

// A set of tests that enable OriginAgentCluster by default.
class OriginIsolationDefaultOACTest : public OriginIsolationOptInHeaderTest {};

// A set of tests that enable process-isolated OriginAgentCluster-by-default.
class OriginKeyedProcessByDefaultTest : public OriginIsolationOptInHeaderTest {};

class OriginIsolationPrerenderOptInHeaderTest
    : public OriginIsolationOptInHeaderTest {};  // class OriginIsolationPrerenderOptInHeaderTest

// As in OriginIsolationOptInHeaderTest, but with same-process origin
// isolation.
class SameProcessOriginIsolationOptInHeaderTest
    : public OriginIsolationOptInHeaderTest {};

// As in SameProcessOriginIsolationOptInHeaderTest, but command-line isolate
// foo.com.
class SameProcessOriginIsolationOptInHeaderWithIsolatedOriginTest
    : public SameProcessOriginIsolationOptInHeaderTest {};

// Force WebSecurity off for tests.
class SameProcessNoWebSecurityOriginIsolationOptInHeaderTest
    : public SameProcessOriginIsolationOptInHeaderTest {};

// Used for a few tests that check non-HTTPS secure context behavior.
class OriginIsolationOptInHttpServerHeaderTest : public IsolatedOriginTestBase {};

// This class allows testing the interaction of OptIn isolation and command-line
// isolation for origins. Tests using this class will isolate foo.com and
// bar.com by default using command-line isolation, but any opt-in isolation
// will override this.
class OriginIsolationOptInHeaderCommandLineTest
    : public OriginIsolationOptInHeaderTest {};

// This test verifies that opt-in isolation takes precedence over command-line
// isolation. It loads an opt-in isolated base origin (which would have
// otherwise been isolated via command-line isolation), and then loads a child
// frame sub-origin which should-not be isolated (but would have been if the
// base origin was command-line isolated).
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderCommandLineTest,
                       OptInOverridesCommandLine) {}

// A test to verify that an origin with a trailing dot in the domain name
// doesn't crash when it opts-out of origin isolation when
// kOriginAgentClusterDefaultEnabled is enabled.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       TrailingDotDomainOptOutDoesNotCrash) {}

// A test to confirm that "a.com." is treated as a separate host (and hence
// a separate origin) from "a.com". See example at
// https://url.spec.whatwg.org/#concept-domain.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       TrailingDotDomainIsolatesSeparately1) {}

// A test similar to TrailingDotDomainIsolatesSeparately1, but this time the
// "a.com" domain does not opt-in via a header, and does not get an origin-
// keyed process. Thus, it ends up in a separate process from "a.com.".
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       TrailingDotDomainIsolatesSeparately2) {}

// A test to confirm that if an Origin-Agent-Cluster header is encountered (but
// not committed) as part of a redirect, that it does not opt-in to
// OriginAgentCluster isolation. The setup in this test is subtle, since in
// order for the call to NavigationRequest::OnRequestRedirected() to attempt to
// create a new SiteInstance, we must load the same origin the redirect wants to
// use, and load it without OriginAgentCluster isolation. Prior to the fix for
// https://crbug.com/1329061 the redirect would result in opting the origin into
// OriginAgentCluster isolation since no global walk is present to detect that
// it has already been loaded without.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       RedirectSameSiteWithOACDoesntOptIn) {}

// Same as the preceding test, but the redirect is cross-site.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       RedirectCrossSiteWithOACDoesntOptIn) {}

// This tests that header-based opt-in causes the origin to end up in the
// isolated origins list.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, Basic) {}

// A test to ensure that origins whose host has a trailing dot pass the
// validation checks for explicit opt-ins and opt-outs. This is an
// `OriginKeyedProcessByDefaultTest` test in order that the explicit opt-out
// will be tracked. Note: failure for either part of this test will involve
// crashing on a CHECK in
// ChildProcessSecurityPolicyImpl::AddOriginIsolationStateForBrowsingInstance():
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       HostWithTrailingDotAllowed) {}

// A simple test that, when OAC-by-default is enabled with process-isolation, an
// origin that receives default OAC is put in an origin-keyed process.
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       DefaultIsOriginKeyedProcess) {}

// A test to make sure that a renderer-initiated navigation from a default-
// isolated frame to about:blank doesn't crash on a ProcessLock mismatch.
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       RendererInitiatedNavigationToAboutBlankSucceeds) {}

// A test to make sure that a renderer-initiated navigation from a default-
// isolated frame to about:blank doesn't crash on a ProcessLock mismatch.
// This test is similar to RendererInitiatedNavigationToAboutBlankSucceeds
// but with BFCache disabled.
IN_PROC_BROWSER_TEST_F(
    OriginKeyedProcessByDefaultTest,
    RendererInitiatedNavigationToAboutBlankSucceeds_BFCacheDisabled) {}

// The same as for DefaultOptInIsIsolated, but testing on a subframe.
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       SubframeDefaultIsOriginKeyedProcess) {}

// The test ExplicitOptInRespected tests the speculative RFH created before
// receiving the OAC headers. The delay must be set to zero so that the
// speculative RFH is always created before receiving the header.
class OriginKeyedProcessByDefaultTestWithoutSpeculativeRFHDelay
    : public OriginKeyedProcessByDefaultTest {};

// Using origin-keyed processes by default faces a challenge for speculative
// RenderFrameHosts, which are created before any OAC headers arrive.
// Note: the origin is tracked even though the SiteInfo still says it is an
// origin-keyed process by default.
IN_PROC_BROWSER_TEST_F(
    OriginKeyedProcessByDefaultTestWithoutSpeculativeRFHDelay,
    ExplicitOptInRespected) {}

// Process-isolated OAC-by-default should not process isolate a navigation that
// explicitly opts-out. This test is important, in part, for making sure all the
// CanAccessDataForOrigin checks encountered during the navigation pass.
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       ExplicitOptOutRespected) {}

namespace {

void TestDefaultIsolationForFrame(
    FrameTreeNode* ftn,
    const GURL& default_isolated_url,
    bool expect_origin_agent_cluster,
    bool expect_requires_origin_keyed_process,
    bool expect_default_requires_origin_keyed_process) {}

}  // namespace

// This test verifies that locking the definition of default isolation to
// individual BrowsingInstances works correctly when the underlying feature
// is changed dynamically.
IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
                       DynamicEnterprisePolicyChange) {}

IN_PROC_BROWSER_TEST_F(OriginIsolationDefaultOACTest, Basic) {}

// These tests ensure that non-HTTPS secure contexts (see
// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy) are
// able to use origin isolation.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHttpServerHeaderTest, Localhost) {}

IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHttpServerHeaderTest, DotLocalhost) {}

IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHttpServerHeaderTest,
                       OneTwentySeven) {}

// Two tests for basic OAC operation w.r.t. prerendering FrameTrees.

// Basic test to make sure an origin opting-in in a primary FrameTree
// triggers registration of a non-opting-origin in an existing prerendering
// Frametree.
IN_PROC_BROWSER_TEST_F(OriginIsolationPrerenderOptInHeaderTest,
                       SimplePrerenderSubOriginIsolationTest) {}

// Basic test to make sure an origin opting-in in a prerendering FrameTree
// triggers registration of a non-opting-origin in an existing primary
// Frametree.
IN_PROC_BROWSER_TEST_F(OriginIsolationPrerenderOptInHeaderTest,
                       SimplePrerenderSubOriginIsolationTest2) {}

// Further tests deep-dive into various scenarios for the isolation opt-ins.

// In this test the sub-origin is isolated because the header requests it. It
// will have a different site instance than the main frame.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       SimpleSubOriginIsolationTest) {}

// Check that two same-site Origin-Agent-Cluster subframes in unrelated windows
// obey the subframe process reuse policy.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       OriginAgentClusterProcessReuse) {}

// In this test the sub-origin is isolated because the header requests it. It
// will have the same site instance as the main frame, and it will be in the
// same process.
IN_PROC_BROWSER_TEST_F(SameProcessOriginIsolationOptInHeaderTest,
                       SimpleSubOriginIsolationTest) {}

// This test is *nearly* the same as SameProcessOriginIsolationOptInHeaderTest.
// SimpleSubOriginIsolationTest, but here we have command-line isolated foo.com
// so it will be in a site instance with a non-empty ProcessLock. But the
// same-process OAC isolated.foo.com will still be in the same SiteInstance,
// and checks on the expected ProcessLock for isolated.foo.com should pass,
// i.e. it should be the same as for the foo.com process.
IN_PROC_BROWSER_TEST_F(
    SameProcessOriginIsolationOptInHeaderWithIsolatedOriginTest,
    SimpleSubOriginIsolationTest) {}

// Verify OAC is calculated using the base URL when using LoadDataWithBaseURL()
// (analogous to Android WebView's loadDataWithBaseURL()) when the actual site
// does not specify an Origin-Agent-Cluster value.
IN_PROC_BROWSER_TEST_F(SameProcessOriginIsolationOptInHeaderTest,
                       LoadDataWithBaseURLNoOAC) {}

// Verify OAC is calculated using the base URL when using LoadDataWithBaseURL()
// (analogous to Android WebView's loadDataWithBaseURL()). Unlike the previous
// test, the actual site specifies an Origin-Agent-Cluster value, which should
// be ignored.
IN_PROC_BROWSER_TEST_F(SameProcessOriginIsolationOptInHeaderTest,
                       LoadDataWithBaseURLWithOAC) {}

// This test checks that same-process OriginAgentCluster won't crash and will
// apply properly when used on a localhost URL.  See https://crbug.com/1276155.
IN_PROC_BROWSER_TEST_F(SameProcessOriginIsolationOptInHeaderTest, Localhost) {}

// This test verifies that --disable-web-security overrides same-process
// OriginAgentCluster (i.e. disables it).
IN_PROC_BROWSER_TEST_F(SameProcessNoWebSecurityOriginIsolationOptInHeaderTest,
                       DisableWebSecurityDisablesOriginAgentCluster) {}

// In this test the sub-origin isn't isolated because no header is set. It will
// have the same site instance as the main frame.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       SimpleSubOriginNonIsolationTest) {}

// This test verifies that renderer-initiated navigations to/from isolated
// sub-origins works as expected.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       RendererInitiatedNavigations) {}

// Check that navigating a main frame from an non-isolated origin to an
// isolated origin and vice versa swaps processes and uses a new SiteInstance,
// both for renderer-initiated and browser-initiated navigations.
// Note: this test is essentially identical to
// IsolatedOriginTest.MainFrameNavigation.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, MainFrameNavigation) {}

// This test ensures that if an origin starts off being isolated in a
// BrowsingInstance, it continues that way within the BrowsingInstance, even
// if a new policy is received that removes the opt-in request.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       OriginIsolationStateRetainedForBrowsingInstance) {}

// This test ensures that if an origin starts off not being isolated in a
// BrowsingInstance, it continues that way within the BrowsingInstance, even
// if the header starts being sent.
// Case #1 where the non-opted-in origin is currently in the frame tree.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       OriginNonIsolationStateRetainedForBrowsingInstance1) {}

// This test ensures that if an origin starts off not being isolated in a
// BrowsingInstance, it continues that way within the BrowsingInstance, even
// if the header starts being sent.
// Case #2 where the non-opted-in origin is currently not in the frame tree.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       OriginNonIsolationStateRetainedForBrowsingInstance2) {}

// This test makes sure that a different tab in the same BrowsingInstance where
// an origin originally did not opt-in respects that state even if the
// server sends a different header.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       OriginNonIsolationStateRetainedForPopup) {}

// This test creates a no-opener popup that is origin-isolated, and has two
// same-sub-origin iframes, one of which requests isolation and one that
// doesn't. The non-isolated child commits first, so the second child shouldn't
// get isolation, but more importantly we shouldn't crash on a NOTREACHED() in
// RenderFrameHostManager that is verifying that the second child frame was
// put in a compatible renderer process.
// https://crbug.com/1099718
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       NoKillForBrowsingInstanceDifferencesInProcess) {}

// Same as NoKillForBrowsingInstanceDifferencesInProcess, except the starting
// page has an isolated iframe that matches the origin that won't get isolation
// in the popup's BrowsingInstance. Since this means that the first
// BrowsingInstance will show sub.foo.com as isolated, then if
// CanAccessDataForOrigin only checks the first BrowsingInstance it will get the
// wrong result.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       NoKillForBrowsingInstanceDifferencesInProcess2) {}

// This test handles the case where the base origin is isolated, but a
// sub-origin isn't. In this case we need to place the sub-origin in a site-
// keyed SiteInstance with the same site URL as the origin-keyed SiteInstance
// used for the isolated base origin. Note: only the isolated base origin will
// have a port in this test, as the non-isolated sub-origin will have its port
// value stripped. The test IsolatedBaseOriginNoPorts tests the case where
// neither the isolated base origin nor the non-isolated sub-origin has a port
// value.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, IsolatedBaseOrigin) {}

// This test is the same as OriginIsolationOptInHeaderTest
// .IsolatedBaseOrigin except it uses port-free URLs. This is critical since we
// can have two SiteInstances with the same SiteURL as long as one is
// origin-keyed and the other isn't. Site URLs used to be used as map-keys but
// with opt-in origin isolation we need to also consider the keying flag.
// When the URLs all have non-default ports, we will never have duplicate
// site URLs since the site-keyed one will have the port stripped.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       IsolatedBaseOriginNoPorts) {}

IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       SeparateBrowserContextTest) {}

// This test creates a scenario where we have a frame that is on the initial
// NavigationEntry, and then we created another frame with the same origin
// that opts-in to isolation. The opt-in triggers a walk of the session history
// and the frame tree ... the session history won't pick up the first frame, but
// the frame-tree walk should.
// TODO(crbug.com/40467594): Once every created frame is guaranteed to
// have a FrameNavigationEntry and thus represented in the sesion history, we
// probably can remove the frame-tree walk.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, FrameTreeTest) {}

// Similar to FrameTreeTest, but we stop the navigation that's not requesting
// isolation at the pending commit state in tab2, then verify that the FrameTree
// walk has correctly registered the origin as non-isolated in tab2, but
// isolated in tab1.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       FrameTreeTestPendingCommit) {}

// Helper class to navigate a second tab to a specified URL that requests opt-in
// origin isolation just before the first tab processes the next
// DidCommitProvisionalLoad message.
class InjectIsolationRequestingNavigation
    : public DidCommitNavigationInterceptor {};

// TODO(crbug.com/40708791): flaky on Android builders since 2020-07-28.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_FrameTreeTestBeforeDidCommit
#else
#define MAYBE_FrameTreeTestBeforeDidCommit
#endif
// This test is similar to the one above, but exercises the pending navigation
// when it's at a different stage, namely between the CommitNavigation and
// DidCommitProvisionalLoad, rather than at WillProcessResponse.
IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest,
                       MAYBE_FrameTreeTestBeforeDidCommit) {}

class StrictOriginIsolationTest : public IsolatedOriginTestBase {};

IN_PROC_BROWSER_TEST_F(StrictOriginIsolationTest, SubframesAreIsolated) {}

IN_PROC_BROWSER_TEST_F(StrictOriginIsolationTest, MainframesAreIsolated) {}

// Ensure that navigations across two URLs that resolve to the same effective
// URL won't result in a renderer kill with strict origin isolation. See
// https://crbug.com/961386.
IN_PROC_BROWSER_TEST_F(StrictOriginIsolationTest,
                       NavigateToURLsWithSameEffectiveURL) {}

// Check that navigating a main frame from an non-isolated origin to an
// isolated origin and vice versa swaps processes and uses a new SiteInstance,
// both for renderer-initiated and browser-initiated navigations.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, MainFrameNavigation) {}

// Check that opening a popup for an isolated origin puts it into a new process
// and its own SiteInstance.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Popup) {}

// Check that navigating a subframe to an isolated origin puts the subframe
// into an OOPIF and its own SiteInstance.  Also check that the isolated
// frame's subframes also end up in correct SiteInstance.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Subframe) {}

// Check that when an non-isolated origin foo.com embeds a subframe from an
// isolated origin, which then navigates to a non-isolated origin bar.com,
// bar.com goes back to the main frame's SiteInstance.  See
// https://crbug.com/711006.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       NoOOPIFWhenIsolatedOriginNavigatesToNonIsolatedOrigin) {}

// Check that a new isolated origin subframe will attempt to reuse an existing
// process for that isolated origin, even across BrowsingInstances.  Also check
// that main frame navigations to an isolated origin keep using the default
// process model and do not reuse existing processes.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, SubframeReusesExistingProcess) {}

// Check that when a cross-site, non-isolated-origin iframe opens a popup,
// navigates it to an isolated origin, and then the popup navigates back to its
// opener iframe's site, the popup and the opener iframe end up in the same
// process and can script each other.  See https://crbug.com/796912.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       PopupNavigatesToIsolatedOriginAndBack) {}

// Check that when a non-isolated-origin page opens a popup, navigates it
// to an isolated origin, and then the popup navigates to a third non-isolated
// origin and finally back to its opener's origin, the popup and the opener
// iframe end up in the same process and can script each other:
//
//   foo.com
//      |
//  window.open()
//      |
//      V
//  about:blank -> isolated.foo.com -> bar.com -> foo.com
//
// This is a variant of PopupNavigatesToIsolatedOriginAndBack where the popup
// navigates to a third site before coming back to the opener's site. See
// https://crbug.com/807184.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       PopupNavigatesToIsolatedOriginThenToAnotherSiteAndBack) {}

// Check that with an ABA hierarchy, where B is an isolated origin, the root
// and grandchild frames end up in the same process and can script each other.
// See https://crbug.com/796912.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       IsolatedOriginSubframeCreatesGrandchildInRootSite) {}

// Check that isolated origins can access cookies.  This requires cookie checks
// on the IO thread to be aware of isolated origins.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, Cookies) {}

// Check that isolated origins won't be placed into processes for other sites
// when over the process limit.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, ProcessLimit) {}

// Verify that a navigation to an non-isolated origin does not reuse a process
// from a pending navigation to an isolated origin.  See
// https://crbug.com/738634.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       ProcessReuseWithResponseStartedFromIsolatedOrigin) {}

// When a navigation uses a siteless SiteInstance, and a second navigation
// commits an isolated origin which reuses the siteless SiteInstance's process
// before the first navigation's response is received, ensure that the first
// navigation can still finish properly and transfer to a new process, without
// an origin lock mismatch. See https://crbug.com/773809.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       ProcessReuseWithLazilyAssignedSiteInstance) {}

// Same as ProcessReuseWithLazilyAssignedSiteInstance above, but here the
// navigation with a siteless SiteInstance is for an isolated origin, and the
// unrelated tab loads an unisolated URL which reuses the siteless
// SiteInstance's process.  Although the unisolated URL won't lock that process
// to an origin (except when running with --site-per-process), it should still
// mark it as used and cause the isolated origin to transfer when it receives a
// response. See https://crbug.com/773809.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       ProcessReuseWithLazilyAssignedIsolatedSiteInstance) {}

// Verify that a navigation to an unisolated origin cannot reuse a process from
// a pending navigation to an isolated origin.  Similar to
// ProcessReuseWithResponseStartedFromIsolatedOrigin, but here the non-isolated
// URL is the first to reach OnResponseStarted, which should mark the process
// as "used", so that the isolated origin can't reuse it. See
// https://crbug.com/738634.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       ProcessReuseWithResponseStartedFromUnisolatedOrigin) {}

// Verify that when a process has a pending SiteProcessCountTracker entry for
// an isolated origin, and a navigation to a non-isolated origin reuses that
// process, future isolated origin subframe navigations do not reuse that
// process. See https://crbug.com/780661.
IN_PROC_BROWSER_TEST_F(
    IsolatedOriginTest,
    IsolatedSubframeDoesNotReuseUnsuitableProcessWithPendingSiteEntry) {}

// Similar to the test above, but for a ServiceWorker.  When a process has a
// pending SiteProcessCountTracker entry for an isolated origin, and a
// navigation to a non-isolated origin reuses that process, a ServiceWorker
// subsequently created for that isolated origin shouldn't reuse that process.
// See https://crbug.com/780661 and https://crbug.com/780089.
IN_PROC_BROWSER_TEST_F(
    IsolatedOriginTest,
    IsolatedServiceWorkerDoesNotReuseUnsuitableProcessWithPendingSiteEntry) {}

// Check that subdomains on an isolated origin (e.g., bar.isolated.foo.com)
// also end up in the isolated origin's SiteInstance.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, IsolatedOriginWithSubdomain) {}

// This class allows intercepting the BindStorageArea and OpenLocalStorage
// methods in order to test what happens when parameters are changed.
class StoragePartitonInterceptor
    : public blink::mojom::DomStorageInterceptorForTesting,
      public RenderProcessHostObserver {};

std::optional<blink::LocalFrameToken>
    StoragePartitonInterceptor::saved_first_local_frame_token_ =;

// Save the first LocalFrameToken seen and inject it into future calls.
void CreateTestDomStorageBackendToSaveFirstFrame(
    RenderProcessHostImpl* rph,
    mojo::PendingReceiver<blink::mojom::DomStorage> receiver) {}

// Inject (or not if null) a StorageKey and LocalFrameToken.
void CreateTestDomStorageBackendToInjectValues(
    std::optional<blink::StorageKey> storage_key_to_inject,
    std::optional<blink::LocalFrameToken> local_frame_token_to_inject,
    RenderProcessHostImpl* rph,
    mojo::PendingReceiver<blink::mojom::DomStorage> receiver) {}

// Verify that a renderer process cannot read sessionStorage of another origin.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, SessionStorage_WrongOrigin) {}

// Verify not fatal if the renderer reads sessionStorage from an empty
// LocalFrameToken.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       SessionStorage_EmptyLocalFrameToken) {}

// Verify fatal error if the renderer reads sessionStorage from the wrong
// LocalFrameToken.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       SessionStorage_WrongLocalFrameToken) {}

// Verify not fatal if the renderer reads localStorage from an empty
// LocalFrameToken.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, LocalStorage_EmptyLocalFrameToken) {}

// Verify fatal error if the renderer reads localStorage from the wrong
// LocalFrameToken.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, LocalStorage_WrongLocalFrameToken) {}

// Verify that an isolated renderer process cannot read localStorage of an
// origin outside of its isolated site.
IN_PROC_BROWSER_TEST_F(
    IsolatedOriginTest,
    LocalStorageOriginEnforcement_IsolatedAccessingNonIsolated) {}

#if BUILDFLAG(IS_ANDROID)
#define MAYBE_LocalStorageOriginEnforcement_NonIsolatedAccessingIsolated
#else
// TODO(lukasza): https://crbug.com/566091: Once remote NTP is capable of
// embedding OOPIFs, start enforcing citadel-style checks on desktop
// platforms.
#define MAYBE_LocalStorageOriginEnforcement_NonIsolatedAccessingIsolated
#endif
// Verify that a non-isolated renderer process cannot read localStorage of an
// isolated origin.
//
// TODO(alexmos, lukasza): https://crbug.com/764958: Replicate this test for
// the IO-thread case.
IN_PROC_BROWSER_TEST_F(
    IsolatedOriginTest,
    MAYBE_LocalStorageOriginEnforcement_NonIsolatedAccessingIsolated) {}

// Verify that an IPC request for reading localStorage of an *opaque* origin
// will be rejected.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest,
                       LocalStorageOriginEnforcement_OpaqueOrigin) {}

class IsolatedOriginFieldTrialTest : public IsolatedOriginTestBase {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginFieldTrialTest, Test) {}

class IsolatedOriginCommandLineAndFieldTrialTest
    : public IsolatedOriginFieldTrialTest {};

// Verify that the lists of isolated origins specified via --isolate-origins
// and via field trials are merged.  See https://crbug.com/894535.
IN_PROC_BROWSER_TEST_F(IsolatedOriginCommandLineAndFieldTrialTest, Test) {}

// This is a regression test for https://crbug.com/793350 - the long list of
// origins to isolate used to be unnecessarily propagated to the renderer
// process, trigerring a crash due to exceeding kZygoteMaxMessageLength.
class IsolatedOriginLongListTest : public IsolatedOriginTestBase {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginLongListTest, Test) {}

// Check that navigating a subframe to an isolated origin error page puts the
// subframe into an OOPIF and its own SiteInstance.  Also check that the error
// page in a subframe ends up in the correct SiteInstance.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, SubframeErrorPages) {}

namespace {
bool HasDefaultSiteInstance(RenderFrameHost* rfh) {}
}  // namespace

// Verify process assignment behavior for the case where a site that does not
// require isolation embeds a frame that does require isolation, which in turn
// embeds another site that does not require isolation.
// A  (Does not require isolation)
// +-> B (requires isolation)
//     +-> C (different site from A that does not require isolation.)
//         +-> A (same site as top-level which also does not require isolation.)
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, AIsolatedCA) {}

IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, NavigateToBlobURL) {}

// Test that same-site cross-origin navigations keep user activation even when
// origin isolation is enabled.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, UserActivationSameSite) {}

// Ensure that --disable-site-isolation-trials disables origin isolation.
class IsolatedOriginTrialOverrideTest : public IsolatedOriginFieldTrialTest {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginTrialOverrideTest, Test) {}

// Ensure that --disable-site-isolation-trials and/or
// --disable-site-isolation-for-policy do not override the flag.
class IsolatedOriginPolicyOverrideTest : public IsolatedOriginFieldTrialTest {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginPolicyOverrideTest, Test) {}

// Ensure that --disable-site-isolation-trials and/or
// --disable-site-isolation-for-policy do not override the flag.
class IsolatedOriginNoFlagOverrideTest : public IsolatedOriginTest {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginNoFlagOverrideTest, Test) {}

// Verify that main frame's origin isolation still keeps all same-origin frames
// in the same process.  When allocating processes for a(b(c),d(c)), we should
// ensure that "c" frames are in the same process.
//
// This is a regression test for https://crbug.com/787576.
IN_PROC_BROWSER_TEST_F(IsolatedOriginNoFlagOverrideTest,
                       SameOriginSubframesProcessSharing) {}

// Helper class for testing dynamically-added isolated origins.  Tests that use
// this run without full --site-per-process, but with two isolated origins that
// are configured at startup (isolated.foo.com and isolated.bar.com).
class DynamicIsolatedOriginTest : public IsolatedOriginTest {};

// Check that dynamically added isolated origins take effect for future
// BrowsingInstances only.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest,
                       IsolationAppliesToFutureBrowsingInstances) {}

// Check that dynamically added isolated origins take effect for future
// BrowsingInstances only, focusing on various main frame navigations.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, MainFrameNavigations) {}

// Check that dynamically added isolated origins do not prevent older processes
// for the same origin from accessing cookies.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, OldProcessCanAccessCookies) {}

// Verify that when isolating sub.foo.com dynamically, foo.com and sub.foo.com
// start to be treated as cross-site for process model decisions.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, IsolatedSubdomain) {}

// Check that when an isolated origin takes effect in BrowsingInstance 1, a new
// BrowsingInstance 2, which reuses an old process from BrowsingInstance 1 for
// its main frame, still applies the isolated origin to its subframe.  This
// demonstrates that isolated origins can't be scoped purely based on process
// IDs.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest,
                       NewBrowsingInstanceInOldProcess) {}

// Verify that a process locked to foo.com is not reused for a navigation to
// foo.com that does not require a dedicated process.  See
// https://crbug.com/950453.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest,
                       LockedProcessNotReusedForNonisolatedSameSiteNavigation) {}

// Checks that isolated origins can be added only for a specific profile,
// and that they don't apply to other profiles.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, PerProfileIsolation) {}

// Check that a dynamically added isolated origin can take effect on the next
// main frame navigation by forcing a BrowsingInstance swap, in the case that
// there are no script references to the frame being navigated.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest, ForceBrowsingInstanceSwap) {}

// Same as the test above, but using a renderer-initiated navigation.  Check
// that a dynamically added isolated origin can take effect on the next main
// frame navigation by forcing a BrowsingInstance swap, in the case that there
// are no script references to the frame being navigated.
IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest,
                       ForceBrowsingInstanceSwap_RendererInitiated) {}

IN_PROC_BROWSER_TEST_F(DynamicIsolatedOriginTest,
                       DontForceBrowsingInstanceSwapWhenScriptReferencesExist) {}

// This test ensures that when a page becomes isolated in the middle of
// creating and navigating a new window, the new window prevents a
// BrowsingInstance swap.
IN_PROC_BROWSER_TEST_F(
    DynamicIsolatedOriginTest,
    DontForceBrowsingInstanceSwapWithPendingNavigationInNewWindow) {}

class IsolatedOriginTestWithStrictSiteInstances : public IsolatedOriginTest {};

IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithStrictSiteInstances,
                       NonIsolatedFramesCanShareDefaultProcess) {}

// Creates a non-isolated main frame with an isolated child and non-isolated
// grandchild. With strict site isolation disabled and
// kProcessSharingWithStrictSiteInstances enabled, the main frame and the
// grandchild should be in the same process even though they have different
// SiteInstances.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithStrictSiteInstances,
                       IsolatedChildWithNonIsolatedGrandchild) {}

// Navigate a frame into and out of an isolated origin. This should not
// confuse BrowsingInstance into holding onto a stale default_process_.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithStrictSiteInstances,
                       SubframeNavigatesOutofIsolationThenToIsolation) {}

// Ensure a popup and its opener can go in the same process, even though
// they have different SiteInstances with kProcessSharingWithStrictSiteInstances
// enabled.
IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithStrictSiteInstances,
                       NonIsolatedPopup) {}

class WildcardOriginIsolationTest : public IsolatedOriginTestBase {};

IN_PROC_BROWSER_TEST_F(WildcardOriginIsolationTest, MainFrameNavigation) {}

IN_PROC_BROWSER_TEST_F(WildcardOriginIsolationTest, SubFrameNavigation) {}

// Helper class for testing site isolation triggered by
// Cross-Origin-Opener-Policy headers.  These tests disable strict site
// isolation by default, so that we can check whether a site becomes isolated
// due to COOP on both desktop and Android.
class COOPIsolationTest : public IsolatedOriginTestBase {};

// Check that a main frame navigation to a COOP site (with no subsequent user
// gesture) triggers isolation for that site within the current
// BrowsingInstance.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, SameOrigin) {}

// Verify that the same-origin-allow-popups COOP header value triggers
// isolation, and that this behaves sanely with window.open().
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, SameOriginAllowPopups) {}

// Verify that the `noopener-allow-popups COOP header value triggers isolation,
// and that this behaves sanely with window.open().
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, NoopenerAllowPopups) {}

// Verify that COOP isolation applies at a site (and not origin) granularity.
//
// Isolating sites rather than origins may seem counterintuitive, considering
// the COOP header value that triggers isolation is "same-origin".  However,
// process isolation granularity that we can infer from COOP is quite different
// from what that actual COOP value controls. The COOP "same-origin" value
// specifies when to sever opener relationships and create a new
// BrowsingInstance; a COOP "same-origin" main frame document may only stay in
// the same BrowsingInstance as other same-origin COOP documents.  However,
// this does not apply to iframes, and it's possible to have a
// foo.bar.coop.com(baz.coop.com) hierarchy where the main frame has COOP
// "same-origin" but both frames set document.domain to coop.com and
// synchronously script each other (*).  Hence, in this case, we must isolate
// the coop.com site and place the two frames in the same process. This test
// covers that precise scenario.
//
// (*) In the future, COOP may disallow document.domain, in which case we may
// need to revisit this.  See https://github.com/whatwg/html/issues/6177.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, SiteGranularity) {}

// Verify that COOP isolation applies when both COOP and COEP headers are set
// (i.e., for a cross-origin-isolated page).  This results in a different COOP
// header value (kSameOriginPlusCoep) which should still trigger isolation.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, COOPAndCOEP) {}

// Check that when a site triggers both COOP isolation and OriginAgentCluster,
// both mechanisms take effect.  This test uses a URL with default ports so
// that we can exercise the site URL being the same with both COOP and OAC.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, COOPAndOriginAgentClusterNoPorts) {}

// Check that when a site triggers both COOP isolation and OriginAgentCluster,
// both mechanisms take effect.  Similar to the test above, but starts on a URL
// where the origin doesn't match the site.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest,
                       COOPAndOriginAgentClusterOnSubdomain) {}

// Verify that if strict site isolation is in place, COOP isolation does not
// add redundant isolated origins to ChildProcessSecurityPolicy.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, SiteAlreadyRequiresDedicatedProcess) {}

// Verify that seeing a user activation on a COOP document triggers isolation
// of that document's site in future BrowsingInstances, but doesn't affect any
// existing BrowsingInstances.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, UserActivation) {}

// Similar to the test above, but verify that a user activation on a same-site
// subframe also triggers isolation of a COOP site in the main frame for future
// BrowsingInstances.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, UserActivationInSubframe) {}

// Similar to the test above, but verify that a user activation on a
// same-origin about:blank subframe triggers isolation of a COOP site in the
// main frame for future BrowsingInstances.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, UserActivationInAboutBlankSubframe) {}

// Ensure that navigating to http://localhost which has COOP+COEP headers, and
// hence will attempt to trigger COOP isolation, will not crash.  See
// https://crbug.com/1276155.
IN_PROC_BROWSER_TEST_F(COOPIsolationTest, Localhost) {}

// Helper class for testing site isolation triggered by different JIT policies
// being applied.
class JITIsolationTest : public IsolatedOriginTest,
                         public ::testing::WithParamInterface<bool> {};

IN_PROC_BROWSER_TEST_P(JITIsolationTest, MainFrameTest) {}

IN_PROC_BROWSER_TEST_P(JITIsolationTest, DefaultSiteTest) {}

INSTANTIATE_TEST_SUITE_P();
INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_F(JITIsolationTest, SubFrameTest) {}

// Check that jitless subframes obey process reuse policies.
IN_PROC_BROWSER_TEST_F(JITIsolationTest, SubFrameProcessReuse) {}

}  // namespace content