// Copyright 2016 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/page/page_zoom.h" #include "third_party/blink/public/web/web_console_message.h" #include "third_party/blink/public/web/web_hit_test_result.h" #include "third_party/blink/public/web/web_remote_frame.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_node_string_trustedscript.h" #include "third_party/blink/renderer/core/css/css_default_style_sheets.h" #include "third_party/blink/renderer/core/css/css_style_declaration.h" #include "third_party/blink/renderer/core/frame/browser_controls.h" #include "third_party/blink/renderer/core/frame/dom_visual_viewport.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/root_frame_viewport.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/frame/web_remote_frame_impl.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_view.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/scrolling/root_scroller_controller.h" #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.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/loader/fetch/memory_cache.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/task_environment.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/testing/url_loader_mock_factory.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/vector.h" RunPendingTasks; Mock; namespace blink { namespace { class RootScrollerTest : public testing::Test, private ScopedImplicitRootScrollerForTest { … }; // Test that the document Node should be the default effective root scroller. TEST_F(RootScrollerTest, TestDefaultRootScroller) { … } // Make sure that replacing the documentElement doesn't change the effective // root scroller when no root scroller is set. TEST_F(RootScrollerTest, defaultEffectiveRootScrollerIsDocumentNode) { … } // Tests that a DIV which becomes the implicit root scroller will properly // control url bar and bottom bar hiding and overscroll. TEST_F(RootScrollerTest, BrowserControlsAndOverscroll) { … } // Tests that removing the element that is the root scroller from the DOM tree // changes the effective root scroller. TEST_F(RootScrollerTest, TestRemoveRootScrollerFromDom) { … } // Test that the effective root scroller resets to the document Node when the // current root scroller element becomes invalid as a scroller. TEST_F(RootScrollerTest, TestRootScrollerBecomesInvalid) { … } // Ensures that disconnecting the element currently set as the root scroller // recomputes the effective root scroller, before a lifecycle update. TEST_F(RootScrollerTest, RemoveCurrentRootScroller) { … } // Ensures that the root scroller always gets composited with scrolling layers. // This is necessary since we replace the Frame scrolling layers in CC as the // OuterViewport, we need something to replace them with. TEST_F(RootScrollerTest, AlwaysCreateCompositedScrollingLayers) { … } // Make sure that if an effective root scroller becomes a remote frame, it's // immediately demoted. TEST_F(RootScrollerTest, IFrameSwapToRemote) { … } // Tests that removing the root scroller element from the DOM resets the // effective root scroller without waiting for any lifecycle events. TEST_F(RootScrollerTest, RemoveRootScrollerFromDom) { … } // Tests that we still have a global root scroller layer when the HTML element // has no layout object. crbug.com/637036. TEST_F(RootScrollerTest, DocumentElementHasNoLayoutObject) { … } // On Android, the main scrollbars are owned by the visual viewport and the // LocalFrameView's disabled. This functionality should extend to a rootScroller // that isn't the main LocalFrameView. TEST_F(RootScrollerTest, UseVisualViewportScrollbars) { … } // On Android, the main scrollbars are owned by the visual viewport and the // LocalFrameView's disabled. This functionality should extend to a rootScroller // that's a nested iframe. TEST_F(RootScrollerTest, UseVisualViewportScrollbarsIframe) { … } TEST_F(RootScrollerTest, TopControlsAdjustmentAppliedToRootScroller) { … } TEST_F(RootScrollerTest, RotationAnchoring) { … } // Tests that we don't crash if the default documentElement isn't a valid root // scroller. This can happen in some edge cases where documentElement isn't // <html>. crbug.com/668553. TEST_F(RootScrollerTest, InvalidDefaultRootScroller) { … } // Makes sure that when an iframe becomes the effective root scroller, its // FrameView stops sizing layout to the frame rect and uses its parent's layout // size instead. This allows matching the layout size semantics of the root // FrameView since its layout size can differ from the frame rect due to // resizes by the URL bar. TEST_F(RootScrollerTest, IFrameRootScrollerGetsNonFixedLayoutSize) { … } // Ensure that removing the root scroller element causes an update to the // RootFrameViewport's layout viewport immediately since old layout viewport is // now part of a detached layout hierarchy. TEST_F(RootScrollerTest, ImmediateUpdateOfLayoutViewport) { … } class ImplicitRootScrollerSimTest : public SimTest { … }; // Test that the cached IsEffectiveRootScroller bit on LayoutObject is set // correctly when the Document is the effective root scroller. It becomes the // root scroller before Document has a LayoutView. TEST_F(ImplicitRootScrollerSimTest, DocumentEffectiveSetsCachedBit) { … } // Test that layout from outside a lifecycle wont select a new effective root // scroller. TEST_F(ImplicitRootScrollerSimTest, NonLifecycleLayoutDoesntCauseReselection) { … } // Tests that we don't explode when a layout occurs and the effective // rootScroller no longer has a ContentFrame(). We setup the frame tree such // that the first iframe is the effective root scroller. The second iframe has // an unload handler that reaches back to the common parent and causes a // layout. This will cause us to recalculate the effective root scroller while // the current one is valid in all ways except that it no longer has a content // frame. This test passes if it doesn't crash. https://crbug.com/805317. TEST_F(ImplicitRootScrollerSimTest, RecomputeEffectiveWithNoContentFrame) { … } // Test that the element is considered to be viewport filling only if its // padding box fills the viewport. That means it must have no border. TEST_F(ImplicitRootScrollerSimTest, UsePaddingBoxForViewportFillingCondition) { … } // Tests that the root scroller doesn't affect visualViewport pageLeft and // pageTop. TEST_F(ImplicitRootScrollerSimTest, RootScrollerDoesntAffectVisualViewport) { … } // Tests that we don't crash or violate lifecycle assumptions when we resize // from within layout. TEST_F(ImplicitRootScrollerSimTest, ResizeFromResizeAfterLayout) { … } // Tests basic implicit root scroller mode with a <div>. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScroller) { … } // Test that adding overflow to an element that would otherwise be eligable to // be implicitly pomoted causes promotion. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerAddOverflow) { … } // Tests that we don't crash if an implicit candidate is no longer a box. This // test passes if it doesn't crash. TEST_F(ImplicitRootScrollerSimTest, CandidateLosesLayoutBoxDontCrash) { … } // Ensure that a plugin view being considered for implicit promotion doesn't // cause a crash. https://crbug.com/903440. TEST_F(ImplicitRootScrollerSimTest, ConsiderEmbedCrash) { … } // Test that a valid implicit root scroller wont be promoted/will be demoted if // the main document has overflow. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerDocumentScrollsOverflow) { … } // Test that we'll only implicitly promote an element if its visible. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerVisibilityCondition) { … } // Tests implicit root scroller mode for iframes. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerIframe) { … } // Tests use counter for implicit root scroller. Ensure it's not counted on a // page without an implicit root scroller. TEST_F(ImplicitRootScrollerSimTest, UseCounterNegative) { … } // Tests use counter for implicit root scroller. Ensure it's counted on a // page that loads with an implicit root scroller. TEST_F(ImplicitRootScrollerSimTest, UseCounterPositive) { … } // Tests use counter for implicit root scroller. Ensure it's counted on a // page that loads without an implicit root scroller but later gets one. TEST_F(ImplicitRootScrollerSimTest, UseCounterPositiveAfterLoad) { … } // Test that we correctly recompute the cached bits and thus the root scroller // properties in the event of a layout tree reattachment which causes the // LayoutObject to be disposed and replaced with a new one. TEST_F(ImplicitRootScrollerSimTest, LayoutTreeReplaced) { … } // Tests that if we have multiple valid candidates for implicit promotion, we // don't promote either. TEST_F(ImplicitRootScrollerSimTest, DontPromoteWhenMultipleAreValid) { … } // Test that when a valid iframe becomes loaded and thus should be promoted, it // becomes the root scroller, without needing an intervening layout. TEST_F(ImplicitRootScrollerSimTest, IframeLoadedWithoutLayout) { … } // Ensure that navigating an iframe while it is the effective root scroller, // causes it to remain the effective root scroller after the navigation (to a // page where it remains valid) is finished. TEST_F(ImplicitRootScrollerSimTest, NavigateToValidRemainsRootScroller) { … } // Ensure that scroll restoration logic in the document does not apply // to the implicit root scroller, but rather to the document's LayoutViewport. TEST_F(ImplicitRootScrollerSimTest, ScrollRestorationIgnoresImplicit) { … } // Test that a root scroller is considered to fill the viewport at both the URL // bar shown and URL bar hidden height. TEST_F(ImplicitRootScrollerSimTest, RootScrollerFillsViewportAtBothURLBarStates) { … } // Tests that implicit is continually reevaluating whether to promote or demote // a scroller. TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) { … } // Tests that implicit mode correctly recognizes when an iframe becomes // scrollable. TEST_F(ImplicitRootScrollerSimTest, IframeScrollingAffectsPromotion) { … } // Loads with a larger than the ICB (but otherwise valid) implicit root // scrolling iframe. When the iframe is promoted (which happens at the end of // layout) its layout size is changed which makes it easy to violate lifecycle // assumptions. (e.g. NeedsLayout at the end of layout) TEST_F(ImplicitRootScrollerSimTest, PromotionChangesLayoutSize) { … } // Tests that bottom-fixed objects inside of an iframe root scroller and frame // are marked as being affected by top controls movement. Those inside a // non-rootScroller iframe should not be marked as such. TEST_F(ImplicitRootScrollerSimTest, BottomFixedAffectedByTopControls) { … } // Ensure that we're using the content box for an iframe. Promotion will cause // the content to use the layout size of the parent frame so having padding or // a border would cause us to relayout. TEST_F(ImplicitRootScrollerSimTest, IframeUsesContentBox) { … } // Test that we don't promote any elements implicitly if the main document has // vertical scrolling. TEST_F(ImplicitRootScrollerSimTest, OverflowInMainDocumentRestrictsImplicit) { … } // Test that we overflow in the document allows promotion only so long as the // document isn't scrollable. TEST_F(ImplicitRootScrollerSimTest, OverflowHiddenDoesntRestrictImplicit) { … } // Test that any non-document, clipping ancestor prevents implicit promotion. TEST_F(ImplicitRootScrollerSimTest, ClippingAncestorPreventsPromotion) { … } TEST_F(ImplicitRootScrollerSimTest, AppliedAtFractionalZoom) { … } // Ensure that a scrollable fieldset doesn't get promoted to root scroller. // With FieldsetNG, a scrollable fieldset creates an anonymous LayoutBox that // doesn't have an associated Node. RootScroller is premised on the fact that a // scroller is associated with a Node. It'd be non-trivial work to make this // work without a clear benefit so for now ensure it doesn't get promoted and // doesn't cause any crashes. https://crbug.com/1125621. TEST_F(ImplicitRootScrollerSimTest, FieldsetNGCantBeRootScroller) { … } class RootScrollerHitTest : public ImplicitRootScrollerSimTest { … }; // Test that hit testing in the area revealed at the bottom of the screen // revealed by hiding the URL bar works properly when using a root scroller // when the target and scroller are in the same PaintLayer. TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarSameLayer) { … } // Test that hit testing in the area revealed at the bottom of the screen // revealed by hiding the URL bar works properly when using a root scroller // when the target and scroller are in different PaintLayers. TEST_F(RootScrollerHitTest, HitTestInAreaRevealedByURLBarDifferentLayer) { … } } // namespace } // namespace blink