chromium/content/browser/loader/cross_site_document_blocking_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 <ostream>
#include <string>
#include <utility>

#include "base/base64.h"
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/browser/site_instance_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.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/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/test_content_browser_client.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.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 "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"

namespace content {

Not;
HasSubstr;

namespace {

enum OrbExpectations {};

constexpr OrbExpectations BlockAsError(const OrbExpectations expectations) {}

// Gets contents of a file at //content/test/data/<dir>/<file>.
std::string GetTestFileContents(const char* dir, const char* file) {}

// Helper for intercepting a resource request to the given URL and capturing the
// response headers and body.
//
// Note that after the request completes, the original requestor (e.g. the
// renderer) will see an injected request failure (this is easier to accomplish
// than forwarding the intercepted response to the original requestor),
class RequestInterceptor {};

}  // namespace

// These tests verify that the browser process blocks cross-site HTML, XML,
// JSON, and some plain text responses when they are not otherwise permitted
// (e.g., by CORS).  This ensures that such responses never end up in the
// renderer process where they might be accessible via a bug.  Careful attention
// is paid to allow other cross-site resources necessary for rendering,
// including cases that may be mislabeled as blocked MIME type.
class CrossSiteDocumentBlockingTestBase : public ContentBrowserTest {};

struct ImgTestParams {};
class CrossSiteDocumentBlockingImgElementTest
    : public CrossSiteDocumentBlockingTestBase,
      public testing::WithParamInterface<ImgTestParams> {};

IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingImgElementTest, Test) {}

// TODO(vogelheim): Consider re-writing these as regular tests, rather than
// as a parameterized test suite.
#define IMG_TEST(tag, resource, expectations)

// The following are files under content/test/data/site_isolation. All
// should be disallowed for cross site XHR under the document blocking policy.
//   valid.*        - Correctly labeled HTML/XML/JSON files.
//   *.txt          - Plain text that sniffs as HTML, XML, or JSON.
//   htmlN_dtd.*    - Various HTML templates to test.
//   json-prefixed* - parser-breaking prefixes
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()

// ORB blocks responses with non-image/audio/video MIME type that don't
// sniff as Javascript (ORBv0.1 blocks ones that sniff as HTML or XML or JSON).
IMG_TEST()
IMG_TEST()

// ORB detects audio/video responses before the final Javascript sniffing (or in
// the case of ORBv0.1, confirmation sniffing for HTML/XML/JSON).  This
// sequencing simplifies the ORB algorithm and implementation because it means
// that the final sniffing step doesn't need to take into account media content.
// OTOH, if ORB detects some audio/video responses based on the MIME type of the
// response, then it may allow some cases that ORB would block - such as a JSON
// response incorrectly labeled as "audio/x-wav".
IMG_TEST()

// These files should be disallowed without sniffing.
//   nosniff.*   - Won't sniff correctly, but blocked because of nosniff.
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()

// These files are allowed for XHR under the document blocking policy because
// the sniffing logic determines they are not actually documents.
//   *js.*   - JavaScript mislabeled as a document.
//   jsonp.* - JSONP (i.e., script) mislabeled as a document.
//   img.*   - Contents that won't match the document label.
//   valid.* - Correctly labeled responses of non-document types.
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()
IMG_TEST()

// ORB allows, because even with 'XCTO: nosniff' ORB will sniff that this is an
// image.
IMG_TEST()
// Like nosniff_png above, except that ORB v0.1 allows because HLS/m3u8 doesn't
// sniff as HTML/XML/JSON.
IMG_TEST()

// This test covers an aspect of Cross-Origin-Resource-Policy (CORP, different
// from ORB) that cannot be covered by wpt/fetch/cross-origin-resource-policy:
// whether blocking occurs *before* the response reaches the renderer process.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       CrossOriginResourcePolicy) {}

// TODO(crbug.com/40269364): Remove support for old header names once API users
// have switched.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       FledgeAuctionOnlySignalsNotReadableFromFetch) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       FledgeAuctionOnlySignalsNotReadableFromFetchNewName) {}

IN_PROC_BROWSER_TEST_F(
    CrossSiteDocumentBlockingTestBase,
    FledgeAuctionOnlySignalsNotReadableFromFetchBothNewAndOldNames) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase, AllowCorsFetches) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       AllowSameOriginFetchFromLoadDataWithBaseUrl) {}

// Regression test for https://crbug.com/958421.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase, BackToAboutBlank) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       BlockForVariousTargets) {}

// Checks to see that ORB blocking applies to processes hosting error pages.
// Regression test for https://crbug.com/814913.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       BlockRequestFromErrorPage) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       HeadersBlockedInResponseBlockedByCorb) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       HeadersSanitizedInCrossOriginResponseAllowedByCorb) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       HeadersSanitizedInSameOriginResponseAllowedByCorb) {}

// TODO(lukasza): https://crbug.com/154571: Enable this test on Android once
// SharedWorkers are also enabled on Android.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase, SharedWorker) {}
#endif  // !BUILDFLAG(IS_ANDROID)

// https://crbug.com/1218723 this is broken by SplitCacheByNetworkIsolationKey.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTestBase,
                       DISABLED_PrefetchIsNotImpacted) {}

// This test class sets up a service worker that can be used to try to respond
// to same-origin requests with cross-origin responses.
class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {};

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest,
                       NetworkToServiceWorkerResponse) {}

// Test class to verify that --disable-web-security turns off ORB.
class CrossSiteDocumentBlockingDisableWebSecurityTest
    : public CrossSiteDocumentBlockingTestBase {};

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableWebSecurityTest,
                       DisableBlocking) {}

// Test class to verify that documents are blocked for sandboxed iframes (opaque
// origins) as well.
class CrossSiteDocumentBlockingSandboxedIframeTest
    : public CrossSiteDocumentBlockingTestBase,
      public ::testing::WithParamInterface<bool> {};

// Tests that documents are blocked from an opaque origin in a sandboxed iframe
// whose precursor is the same as the parent frame's origin.
IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingSandboxedIframeTest,
                       BlockDocumentsFromOpaqueOriginInSameOriginEmbedder) {}

INSTANTIATE_TEST_SUITE_P();

// Test class to verify that documents are blocked for isolated origins as well.
class CrossSiteDocumentBlockingIsolatedOriginTest
    : public CrossSiteDocumentBlockingTestBase {};

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingIsolatedOriginTest,
                       BlockDocumentsFromIsolatedOrigin) {}

IN_PROC_BROWSER_TEST_F(ContentBrowserTest, CorpVsBrowserInitiatedRequest) {}

// This test class sets up a script element for webbundle subresource loading.
// e.g. <script type=webbundle>...</script>
class CrossSiteDocumentBlockingWebBundleTest : public ContentBrowserTest {};

// CrossSiteDocumentBlockingWebBundleTest has 4 tests; a cartesian product of
// 1) cross-origin bundle, 2) same-origin bundle
// X
// A). ORB-protected MIME type (e.g. text/json), B) other type (e.g. image/png)
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest,
                       CrossOriginWebBundleSubresoruceJson) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest,
                       CrossOriginWebBundleSubresorucePng) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest,
                       SameOriginWebBundleSubresoruceJson) {}

IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest,
                       SameOriginWebBundleSubresorucePng) {}

// TODO(crbug.com/40269364): Remove support for old header names once API users
// have switched.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest,
                       FledgeAuctionOnlySignalsNotReadableFromFetchWebBundle) {}

IN_PROC_BROWSER_TEST_F(
    CrossSiteDocumentBlockingWebBundleTest,
    FledgeAuctionOnlySignalsNotReadableFromFetchWebBundleNewName) {}

IN_PROC_BROWSER_TEST_F(
    CrossSiteDocumentBlockingWebBundleTest,
    FledgeAuctionOnlySignalsNotReadableFromFetchWebBundleBothNewAndOldNames) {}

}  // namespace content