blob: 229a82938eab764b138c1aeb30adc04c249a5d41 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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/platform/platform.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_history_item.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.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/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
namespace blink {
class ProgrammaticScrollTest : public testing::Test {
public:
ProgrammaticScrollTest() : base_url_("http://www.test.com/") {}
void TearDown() override {
Platform::Current()
->GetURLLoaderMockFactory()
->UnregisterAllURLsAndClearMemoryCache();
}
protected:
void RegisterMockedHttpURLLoad(const std::string& file_name) {
url_test_helpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
WebString::FromUTF8(file_name));
}
std::string base_url_;
};
TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithScale) {
RegisterMockedHttpURLLoad("long_scroll.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view =
web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html");
web_view->MainFrameWidget()->Resize(WebSize(1000, 1000));
web_view->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
web_view->SetPageScaleFactor(3.0f);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
false;
loader.GetDocumentLoader()->GetHistoryItem()->SetPageScaleFactor(2);
loader.GetDocumentLoader()->GetHistoryItem()->SetScrollOffset(
ScrollOffset(0, 200));
// Flip back the wasScrolledByUser flag which was set to true by
// setPageScaleFactor because otherwise
// FrameLoader::restoreScrollPositionAndViewState does nothing.
loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
false;
loader.RestoreScrollPositionAndViewState();
// Expect that both scroll and scale were restored.
EXPECT_EQ(2.0f, web_view->PageScaleFactor());
EXPECT_EQ(200, web_view->MainFrameImpl()->GetScrollOffset().height);
}
TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithoutScale) {
RegisterMockedHttpURLLoad("long_scroll.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view =
web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html");
web_view->MainFrameWidget()->Resize(WebSize(1000, 1000));
web_view->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
web_view->SetPageScaleFactor(3.0f);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
false;
loader.GetDocumentLoader()->GetHistoryItem()->SetPageScaleFactor(0);
loader.GetDocumentLoader()->GetHistoryItem()->SetScrollOffset(
ScrollOffset(0, 400));
// FrameLoader::restoreScrollPositionAndViewState flows differently if scale
// is zero.
loader.RestoreScrollPositionAndViewState();
// Expect that only the scroll position was restored.
EXPECT_EQ(3.0f, web_view->PageScaleFactor());
EXPECT_EQ(400, web_view->MainFrameImpl()->GetScrollOffset().height);
}
TEST_F(ProgrammaticScrollTest, SaveScrollStateClearsAnchor) {
RegisterMockedHttpURLLoad("long_scroll.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view =
web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html");
web_view->MainFrameWidget()->Resize(WebSize(1000, 1000));
web_view->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
true;
loader.SaveScrollState();
loader.SaveScrollAnchor();
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 0));
loader.SaveScrollState();
loader.GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user =
false;
loader.RestoreScrollPositionAndViewState();
EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().height);
}
class ProgrammaticScrollSimTest : public SimTest {};
TEST_F(ProgrammaticScrollSimTest, NavigateToHash) {
WebView().MainFrameWidget()->Resize(WebSize(800, 600));
SimRequest main_resource("https://example.com/test.html#target", "text/html");
SimRequest css_resource("https://example.com/test.css", "text/css");
LoadURL("https://example.com/test.html#target");
// Finish loading the main document before the stylesheet is loaded so that
// rendering is blocked when parsing finishes. This will delay closing the
// document until the load event.
main_resource.Start();
main_resource.Write(
"<!DOCTYPE html><link id=link rel=stylesheet href=test.css>");
css_resource.Start();
main_resource.Write(R"HTML(
<style>
body {
height: 4000px;
}
h2 {
position: absolute;
top: 3000px;
}
</style>
<h2 id="target">Target</h2>
)HTML");
main_resource.Finish();
css_resource.Complete();
Compositor().BeginFrame();
// Run pending tasks to fire the load event and close the document. This
// should cause the document to scroll to the hash.
test::RunPendingTasks();
ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(3001, layout_viewport->GetScrollOffset().Height());
}
} // namespace blink