#include <memory>
#include <string>
#include "base/json/json_reader.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.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/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/events/event_constants.h"
#include "url/gurl.h"
#if defined(USE_AURA)
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#endif
#define EXPECT_TRUE_OR_FAIL(condition) …
namespace content {
namespace {
enum TestFrameType { … };
enum TestWritingMode { … };
enum TestInvokeMethod { … };
[[maybe_unused]] std::string DescribeFrameType(
const testing::TestParamInfo<TestFrameType>& info) { … }
blink::mojom::FrameWidgetInputHandler* GetInputHandler(FrameTreeNode* node) { … }
class ScopedFocusScrollWaiter { … };
class ScopedSuppressImeEvents { … };
class ScrollRectToVisibleInParentFrameInterceptor
: public blink::mojom::LocalFrameHostInterceptorForTesting { … };
class ScrollIntoViewBrowserTestBase : public ContentBrowserTest { … };
class ScrollIntoViewBrowserTest
: public ScrollIntoViewBrowserTestBase,
public ::testing::WithParamInterface<
std::tuple<TestFrameType, TestWritingMode, TestInvokeMethod>> { … };
IN_PROC_BROWSER_TEST_P(ScrollIntoViewBrowserTest, EditableInSingleNestedFrame) { … }
IN_PROC_BROWSER_TEST_P(ScrollIntoViewBrowserTest, EditableInLocalRoot) { … }
IN_PROC_BROWSER_TEST_P(ScrollIntoViewBrowserTest, EditableInDoublyNestedFrame) { … }
IN_PROC_BROWSER_TEST_P(
ScrollIntoViewBrowserTest,
CrossesEditableInDoublyNestedFrameLocalAndRemoteBoundaries) { … }
INSTANTIATE_TEST_SUITE_P(…);
#if defined(USE_AURA)
class InsetScrollIntoViewBrowserTest
: public ScrollIntoViewBrowserTestBase,
public ::testing::WithParamInterface<TestFrameType> { … };
IN_PROC_BROWSER_TEST_P(InsetScrollIntoViewBrowserTest,
InsetsCauseScrollToFocusedEditable) { … }
INSTANTIATE_TEST_SUITE_P(…);
#endif
#if BUILDFLAG(IS_ANDROID)
constexpr double kMobileMinimumScale = 0.25;
class ZoomScrollIntoViewBrowserTest
: public ScrollIntoViewBrowserTestBase,
public ::testing::WithParamInterface<TestFrameType> {
public:
bool IsForceLocalFrames() const override { return GetParam() == kLocalFrame; }
bool IsWritingModeLTR() const override { return true; }
TestInvokeMethod GetInvokeMethod() const override { return kInputHandler; }
};
IN_PROC_BROWSER_TEST_P(ZoomScrollIntoViewBrowserTest, DesktopViewportMustZoom) {
ASSERT_TRUE(SetupTest("siteA(siteB)"));
EXPECT_EQ(kMobileMinimumScale, GetVisualViewport().scale);
RunTest();
EXPECT_NEAR(1, GetVisualViewport().scale, 0.05);
}
IN_PROC_BROWSER_TEST_P(ZoomScrollIntoViewBrowserTest,
MobileViewportDisablesZoom) {
ASSERT_TRUE(SetupTest("siteA{MobileViewport}(siteB)"));
EXPECT_EQ(kMobileMinimumScale, GetVisualViewport().scale);
RunTest();
EXPECT_EQ(kMobileMinimumScale, GetVisualViewport().scale);
}
IN_PROC_BROWSER_TEST_P(ZoomScrollIntoViewBrowserTest,
TouchActionNoneDisablesZoom) {
ASSERT_TRUE(SetupTest("siteA(siteB{TouchActionNone})"));
EXPECT_EQ(kMobileMinimumScale, GetVisualViewport().scale);
RunTest();
EXPECT_EQ(kMobileMinimumScale, GetVisualViewport().scale);
}
class RootScrollerScrollIntoViewBrowserTest
: public ScrollIntoViewBrowserTestBase {
public:
bool IsForceLocalFrames() const override { return false; }
bool IsWritingModeLTR() const override { return true; }
TestInvokeMethod GetInvokeMethod() const override { return kInputHandler; }
};
IN_PROC_BROWSER_TEST_F(RootScrollerScrollIntoViewBrowserTest,
FocusInRootScroller) {
ASSERT_TRUE(SetupTest("siteA{RootScroller,MobileViewportNoZoom}"));
{
base::RunLoop loop;
shell()->web_contents()->GetPrimaryMainFrame()->InsertVisualStateCallback(
base::BindLambdaForTesting(
[&loop](bool visual_state_updated) { loop.Quit(); }));
loop.Run();
}
ASSERT_EQ(1.0, GetVisualViewport().scale);
ASSERT_EQ(
true,
EvalJs(
InnerMostFrameTreeNode(),
"window.internals.effectiveRootScroller(document).tagName == 'DIV'"));
RunTest();
}
INSTANTIATE_TEST_SUITE_P(,
ZoomScrollIntoViewBrowserTest,
testing::Values(kLocalFrame, kRemoteFrame),
DescribeFrameType);
#endif
class ScrollIntoViewFencedFrameBrowserTest
: public ScrollIntoViewBrowserTestBase { … };
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
SingleFencedFrame) { … }
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
NestedFencedFrames) { … }
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
LocalFrameInFencedFrame) { … }
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
RemoteFrameInFencedFrame) { … }
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
FencedFrameInRemoteFrame) { … }
IN_PROC_BROWSER_TEST_F(ScrollIntoViewFencedFrameBrowserTest,
ProgrammaticScrollIntoViewDoesntCrossFencedFrame) { … }
}
}