chromium/third_party/blink/renderer/core/dom/document_test.cc

/*
 * Copyright (c) 2014, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/dom/document.h"

#include <algorithm>
#include <memory>

#include "base/time/time.h"
#include "build/build_config.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.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/permissions_policy/document_policy_features.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
#include "third_party/blink/public/web/web_print_page_description.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/css/media_query_list_listener.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
#include "third_party/blink/renderer/core/dom/node_with_index.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/scripted_animation_controller.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_dialog_element.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_animator.h"
#include "third_party/blink/renderer/core/page/validation_message_client.h"
#include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
#include "third_party/blink/renderer/core/testing/mock_policy_container_host.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "url/url_util.h"

namespace blink {

ContentSecurityPolicySource;
ContentSecurityPolicyType;
_;
ElementsAre;
IsEmpty;

class DocumentTest : public PageTestBase {};

void DocumentTest::SetHtmlInnerHTML(const char* html_content) {}

class DocumentSimTest : public SimTest {};

namespace {

class TestSynchronousMutationObserver
    : public GarbageCollected<TestSynchronousMutationObserver>,
      public SynchronousMutationObserver {};

TestSynchronousMutationObserver::TestSynchronousMutationObserver(
    Document& document) {}

void TestSynchronousMutationObserver::ContextDestroyed() {}

void TestSynchronousMutationObserver::DidChangeChildren(
    const ContainerNode& container,
    const ContainerNode::ChildrenChange&) {}

void TestSynchronousMutationObserver::DidMergeTextNodes(
    const Text& node,
    const NodeWithIndex& node_with_index,
    unsigned offset) {}

void TestSynchronousMutationObserver::DidMoveTreeToNewDocument(
    const Node& root) {}

void TestSynchronousMutationObserver::DidSplitTextNode(const Text& node) {}

void TestSynchronousMutationObserver::DidUpdateCharacterData(
    CharacterData* character_data,
    unsigned offset,
    unsigned old_length,
    unsigned new_length) {}

void TestSynchronousMutationObserver::NodeChildrenWillBeRemoved(
    ContainerNode& container) {}

void TestSynchronousMutationObserver::NodeWillBeRemoved(Node& node) {}

void TestSynchronousMutationObserver::Trace(Visitor* visitor) const {}

class MockDocumentValidationMessageClient
    : public GarbageCollected<MockDocumentValidationMessageClient>,
      public ValidationMessageClient {};

class PrefersColorSchemeTestListener final : public MediaQueryListListener {};

bool IsDOMException(ScriptState* script_state,
                    ScriptValue value,
                    DOMExceptionCode code) {}
}  // anonymous namespace

TEST_F(DocumentTest, CreateRangeAdjustedToTreeScopeWithPositionInShadowTree) {}

TEST_F(DocumentTest, DomTreeVersionForRemoval) {}

// This tests that we properly resize and re-layout pages for printing in the
// presence of media queries effecting elements in a subtree layout boundary
TEST_F(DocumentTest, PrintRelayout) {}

// This tests whether we properly set the bits for indicating if a media feature
// has been evaluated.
TEST_F(DocumentTest, MediaFeatureEvaluated) {}

// This test checks that Documunt::linkManifest() returns a value conform to the
// specification.
TEST_F(DocumentTest, LinkManifest) {}

TEST_F(DocumentTest, StyleVersion) {}

TEST_F(DocumentTest, SynchronousMutationNotifier) {}

TEST_F(DocumentTest, SynchronousMutationNotifieAppendChild) {}

TEST_F(DocumentTest, SynchronousMutationNotifieInsertBefore) {}

TEST_F(DocumentTest, SynchronousMutationNotifierMergeTextNodes) {}

TEST_F(DocumentTest, SynchronousMutationNotifierMoveTreeToNewDocument) {}

TEST_F(DocumentTest, SynchronousMutationNotifieRemoveChild) {}

TEST_F(DocumentTest, SynchronousMutationNotifieReplaceChild) {}

TEST_F(DocumentTest, SynchronousMutationNotifierSplitTextNode) {}

TEST_F(DocumentTest, SynchronousMutationNotifierUpdateCharacterData) {}

// This tests that meta-theme-color can be found correctly
TEST_F(DocumentTest, ThemeColor) {}

TEST_F(DocumentTest, ValidationMessageCleanup) {}

// Verifies that calling EnsurePaintLocationDataValidForNode cleans compositor
// inputs only when necessary. We generally want to avoid cleaning the inputs,
// as it is more expensive than just doing layout.
TEST_F(DocumentTest,
       EnsurePaintLocationDataValidForNodeCompositingInputsOnlyWhenNecessary) {}

// Tests that the difference in computed style of direction on the html and body
// elements does not trigger a style recalc for viewport style propagation when
// the computed style for another element in the document is recalculated.
TEST_F(DocumentTest, ViewportPropagationNoRecalc) {}

// A relative url in a sandboxed, srcdoc frame should trigger a usecount.
TEST_F(DocumentTest, SandboxedSrcdocUserCounts_BasicRelativeUrl) {}

// A relative url in a sandboxed, srcdoc frame should not trigger a usecount
// if the srcdoc document has defined a base element.
TEST_F(DocumentTest,
       SandboxedSrcdocUserCounts_BasicRelativeUrlWithBaseElement) {}

// An absolute url in a sandboxed, srcdoc frame should not trigger a usecount.
TEST_F(DocumentTest, SandboxedSrcdocUserCounts_BasicAbsoluteUrl) {}

// As in BasicRelativeUrl, but this time the url is for an iframe.
TEST_F(DocumentTest, SandboxedSrcdocUserCounts_BasicRelativeUrlInIframe) {}

// Non-sandboxed srcdoc frames with relative urls shouldn't trigger the use
// count.
TEST_F(DocumentTest,
       SandboxedSrcdocUserCounts_BasicRelativeUrlInNonSandboxedIframe) {}

// As in BasicAbsoluteUrl, but this time the url is for an iframe.
TEST_F(DocumentTest, SandboxedSrcdocUserCounts_BasicAbsoluteUrlInIframe) {}

TEST_F(DocumentTest, CanExecuteScriptsWithSandboxAndIsolatedWorld) {}

TEST_F(DocumentTest, ElementFromPointOnScrollbar) {}

TEST_F(DocumentTest, ElementFromPointWithPageZoom) {}

TEST_F(DocumentTest, PrefersColorSchemeChanged) {}

TEST_F(DocumentTest, FindInPageUkm) {}

TEST_F(DocumentTest, FindInPageUkmInFrame) {}

TEST_F(DocumentTest, AtPageMarginWithDeviceScaleFactor) {}

TEST_F(DocumentTest, HandlesDisconnectDuringHasPrivateToken) {}

TEST_F(DocumentTest, RejectsHasPrivateTokenCallFromNonHttpNonHttpsDocument) {}

namespace {
class MockTrustTokenQueryAnswerer
    : public network::mojom::blink::TrustTokenQueryAnswerer {};
}  // namespace

TEST_F(DocumentTest, HasPrivateTokenSuccess) {}

TEST_F(DocumentTest, HasPrivateTokenSuccessWithFalseValue) {}

TEST_F(DocumentTest, HasPrivateTokenOperationError) {}

TEST_F(DocumentTest, HasPrivateTokenInvalidArgument) {}

TEST_F(DocumentTest, HasPrivateTokenResourceExhausted) {}

TEST_F(DocumentTest, HasRedemptionRecordSuccess) {}

TEST_F(DocumentTest, HasRedemptionRecordSuccessWithFalseValue) {}

TEST_F(DocumentTest, HasRedemptionRecordOperationError) {}

TEST_F(DocumentTest, HasRedemptionRecordInvalidArgument) {}

TEST_F(DocumentTest, HandlesDisconnectDuringHasRedemptionRecord) {}

TEST_F(DocumentTest,
       RejectsHasRedemptionRecordCallFromNonHttpNonHttpsDocument) {}

/**
 * Tests for viewport-fit propagation.
 */

class ViewportFitDocumentTest : public DocumentTest,
                                private ScopedDisplayCutoutAPIForTest {};

// Test meta viewport present but no viewport-fit.
TEST_F(ViewportFitDocumentTest, MetaViewportButNoFit) {}

// Test overriding the viewport fit using SetExpandIntoDisplayCutout.
TEST_F(ViewportFitDocumentTest, ForceExpandIntoCutout) {}

// This is a test case for testing a combination of viewport-fit meta value,
// viewport CSS value and the expected outcome.
ViewportTestCase;

class ParameterizedViewportFitDocumentTest
    : public ViewportFitDocumentTest,
      public testing::WithParamInterface<ViewportTestCase> {};

TEST_P(ParameterizedViewportFitDocumentTest, EffectiveViewportFit) {}

INSTANTIATE_TEST_SUITE_P();

namespace {
class MockReportingContext final : public ReportingContext {};

}  // namespace

TEST_F(DocumentSimTest, LastModified) {}

TEST_F(DocumentSimTest, DuplicatedDocumentPolicyViolationsAreIgnored) {}

// Tests getting the unassociated listed elements.
class UnassociatedListedElementTest : public DocumentTest {};

// Check if the unassociated listed elements are properly extracted.
// Listed elements are: button, fieldset, input, textarea, output, select,
// object and form-associated custom elements.
TEST_F(UnassociatedListedElementTest, GetUnassociatedListedElements) {}

// We extract unassociated listed element in a shadow DOM.
TEST_F(UnassociatedListedElementTest,
       GetUnassociatedListedElementsFromShadowTree) {}

// Check if the dynamically added unassociated listed element is properly
// extracted.
TEST_F(UnassociatedListedElementTest,
       GetDynamicallyAddedUnassociatedListedElements) {}

// Check if the dynamically removed unassociated listed element from the
// Document is no longer extracted.
TEST_F(UnassociatedListedElementTest,
       GetDynamicallyRemovedUnassociatedListedElement) {}

// Check if dynamically assigning an unassociated listed element to a form by
// changing its form attribute is no longer extracted as an unassociated listed
// element.
TEST_F(UnassociatedListedElementTest,
       GetUnassociatedListedElementAfterAddingFormAttr) {}

// Check if dynamically removing the form attribute from an associated listed
// element makes it unassociated.
TEST_F(UnassociatedListedElementTest,
       GetUnassociatedListedElementAfterRemovingFormAttr) {}

// Check if after dynamically setting an associated listed element's form
// attribute to a non-existent one, the element becomes unassociated even if
// inside a <form> element.
TEST_F(UnassociatedListedElementTest,
       GetUnassociatedListedElementAfterSettingFormAttrToNonexistent) {}

// Check if dynamically adding an unassociated listed element to an element
// that is not in the Document won't be extracted.
TEST_F(UnassociatedListedElementTest,
       GeDynamicallyAddedUnassociatedListedElementThatIsNotInTheDocument) {}

// Check if an unassociated listed element added as a nested element will be
// extracted.
TEST_F(UnassociatedListedElementTest,
       GetAttachedNestedUnassociatedFormFieldElements) {}

// Check when removing the ancestor element of an unassociated listed element
// won't make the unassociated element extracted.
TEST_F(UnassociatedListedElementTest,
       GetDetachedNestedUnassociatedFormFieldElements) {}

class TopLevelFormsListTest : public DocumentTest {};

// Tests that `GetTopLevelForms` correctly lists forms in the light DOM.
TEST_F(TopLevelFormsListTest, FormsInLightDom) {}

// Tests that `GetTopLevelForms` functions correctly after dynamic form element
// insertion and removal.
TEST_F(TopLevelFormsListTest, FormsInLightDomInsertionAndRemoval) {}

// Tests that top level forms inside shadow DOM are listed correctly and
// insertion and removal updates the cache.
TEST_F(TopLevelFormsListTest, FormsInShadowDomInsertionAndRemoval) {}

// Tests that nested forms across shadow DOM are ignored by `GetTopLevelForms`.
TEST_F(TopLevelFormsListTest, GetTopLevelFormsIgnoresNestedChildren) {}

TEST_F(DocumentTest, DocumentDefiningElementWithMultipleBodies) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterNoStyles) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterExplicitlyHidden) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterExplicitlyVisible) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterExplicitlyVisibleWithObjectFit) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterExplicitlyVisibleLaterHidden) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterIframe) {}

TEST_F(DocumentTest, LayoutReplacedUseCounterSvg) {}

// https://crbug.com/1311370
TEST_F(DocumentSimTest, HeaderPreloadRemoveReaddClient) {}

TEST_F(DocumentTest, ActiveModalDialog) {}

TEST_F(DocumentTest, LifecycleState_DirtyStyle_NoBody) {}

class TestPaymentLinkHandler
    : public payments::facilitated::mojom::blink::PaymentLinkHandler {};

#if BUILDFLAG(IS_ANDROID)
TEST_F(DocumentTest, PaymentLinkHandling_SinglePaymentLink) {
  TestPaymentLinkHandler test_payment_link_handler;
  base::RunLoop run_loop;
  test_payment_link_handler.set_on_link_handled_callback(
      run_loop.QuitClosure());

  GetDocument().GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
      payments::facilitated::mojom::blink::PaymentLinkHandler::Name_,
      base::BindRepeating(&TestPaymentLinkHandler::Bind,
                          base::Unretained(&test_payment_link_handler)));

  ScopedPaymentLinkDetectionForTest payment_link_detection(true);

  SetHtmlInnerHTML(R"HTML(
    <head>
      <link rel="payment" href="upi://payment_link_1">
    </head>
  )HTML");

  // Run the message loop to ensure Mojo messages are dispatched.
  run_loop.Run();

  // Check if the correct payment link was handled.
  EXPECT_EQ(test_payment_link_handler.get_payment_link_handled_counter(), 1);
  EXPECT_EQ(test_payment_link_handler.get_handled_url(),
            KURL("upi://payment_link_1"));
}

TEST_F(DocumentTest, PaymentLinkHandling_MultiplePaymentLink) {
  TestPaymentLinkHandler test_payment_link_handler;
  base::RunLoop run_loop;
  test_payment_link_handler.set_on_link_handled_callback(
      run_loop.QuitClosure());

  GetDocument().GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
      payments::facilitated::mojom::blink::PaymentLinkHandler::Name_,
      base::BindRepeating(&TestPaymentLinkHandler::Bind,
                          base::Unretained(&test_payment_link_handler)));

  ScopedPaymentLinkDetectionForTest payment_link_detection(true);

  SetHtmlInnerHTML(R"HTML(
    <head>
      <link rel="payment" href="upi://payment_link_1">
      <link rel="payment" href="upi://payment_link_2">
    </head>
  )HTML");

  // Run the message loop to ensure Mojo messages are dispatched.
  run_loop.Run();

  // Check if the correct payment link was handled and the payment link handling
  // was invoked only once.
  EXPECT_EQ(test_payment_link_handler.get_payment_link_handled_counter(), 1);
  EXPECT_EQ(test_payment_link_handler.get_handled_url(),
            KURL("upi://payment_link_1"));
}
#endif  // BUILDFLAG(IS_ANDROID)

}  // namespace blink