chromium/content/browser/manifest/manifest_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 "third_party/blink/public/common/manifest/manifest.h"

#include <stdint.h>

#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/page.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.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/fenced_frame_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "mojo/public/cpp/bindings/associated_remote.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/is_potentially_trustworthy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"

namespace content {

namespace {

Contains;
HasSubstr;

}  // namespace

class ManifestBrowserTest;

// Mock of a WebContentsDelegate that catches messages sent to the console.
class MockWebContentsDelegate : public WebContentsDelegate {};

class ManifestBrowserTest : public ContentBrowserTest,
                            public WebContentsObserver {};

// The implementation of DidAddMessageToConsole isn't inlined because it needs
// to know about |test_|.
bool MockWebContentsDelegate::DidAddMessageToConsole(
    WebContents* source,
    blink::mojom::ConsoleMessageLevel log_level,
    const std::u16string& message,
    int32_t line_no,
    const std::u16string& source_id) {}

// If a page has no manifest, requesting a manifest should return the empty
// manifest. The URL should be empty.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoManifest) {}

// If a page manifest points to a 404 URL, requesting the manifest should return
// the empty manifest. However, the manifest URL will be non-empty.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, 404Manifest) {}

// If a page has an empty manifest, requesting the manifest should return the
// manifest with default values. The manifest URL should be non-empty.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, EmptyManifest) {}

// If a page's manifest can't be parsed correctly, requesting the manifest
// should return an empty manifest. The manifest URL should be non-empty.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, ParseErrorManifest) {}

// If a page has a manifest that can be fetched and parsed, requesting the
// manifest should return a properly filled manifest. The manifest URL should be
// non-empty.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, SampleManifest) {}

// If a page changes manifest during its life-time, requesting the manifest
// should return the current manifest.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DynamicManifest) {}

// This page has a manifest with only file handlers specified. Asking
// for just the manifest should succeed with a non empty manifest.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, FileHandlerManifest) {}

// If a page's manifest lives in a different origin, it should follow the CORS
// rules and requesting the manifest should return an empty manifest (unless the
// response contains CORS headers).
// Flaky: crbug.com/1122546
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DISABLED_CorsManifest) {}

// If a page's manifest lives in a different origin, it should be accessible if
// it has valid access controls headers.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CorsManifestWithAcessControls) {}

// If a page's manifest is in an insecure origin while the page is in a secure
// origin, requesting the manifest should return the empty manifest.
// TODO(crbug.com/40742592): Flaky test.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DISABLED_MixedContentManifest) {}

// If a page's manifest has some parsing errors, they should show up in the
// developer console.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, ParsingErrorsManifest) {}

// If a page has a manifest and the page is navigated to a page without a
// manifest, the page's manifest should be updated.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, Navigation) {}

// If a page has a manifest and the page is navigated using pushState (ie. same
// page), it should keep its manifest state.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, PushStateNavigation) {}

// If a page has a manifest and is navigated using an anchor (ie. same page), it
// should keep its manifest state.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, AnchorNavigation) {}

namespace {

std::unique_ptr<net::test_server::HttpResponse> CustomHandleRequestForCookies(
    const net::test_server::HttpRequest& request) {}

}  // anonymous namespace

// This tests that when fetching a Manifest with 'use-credentials' set, the
// cookies associated with it are passed along the request.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, UseCredentialsSendCookies) {}

namespace {

std::unique_ptr<net::test_server::HttpResponse> CustomHandleRequestForNoCookies(
    const net::test_server::HttpRequest& request) {}

}  // anonymous namespace

// This tests that when fetching a Manifest without 'use-credentials' set, the
// cookies associated with it are not passed along the request.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoUseCredentialsNoCookies) {}

// This tests that fetching a Manifest from a unique origin always fails,
// regardless of the CORS headers on the manifest. It also tests that no
// manifest change notifications are reported when the origin is unique.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, UniqueOrigin) {}

// This is testing the crash scenario encountered by https://crbug.com/1369363.
// In it a GetManifest() request by WebAppInstallTask was interrupted by a page
// navigation which destructed the internal ManifestManagerHost and forced the
// GetManifest() callback to be invoked during the destruction stack frame. The
// callback, which considered empty manifests valid for proceeding, proceeded to
// read other data on the (not destroyed) WebContents that were also in the
// middle of destruction and triggered a UAF crash.
//
// This test checks that the callback does not get invoked during the
// ManifestManagerHost destruction stack frame and other fields of the
// WebContents are still valid to synchronously access by the callback.
IN_PROC_BROWSER_TEST_F(ManifestBrowserTest,
                       GetManifestInterruptedByDestruction) {}

class ManifestBrowserPrerenderingTest : public ManifestBrowserTest {};

// Tests that GetManifest() returns an empty manifest if it's requested in
// prerendering.
IN_PROC_BROWSER_TEST_F(ManifestBrowserPrerenderingTest,
                       GetManifestInPrerendering) {}

class ManifestFencedFrameBrowserTest : public ManifestBrowserTest {};

// Tests that GetManifest() returns an empty manifest if it's requested in
// a fenced frame.
IN_PROC_BROWSER_TEST_F(ManifestFencedFrameBrowserTest,
                       GetManifestInFencedFrame) {}

}  // namespace content