Commit 2780c9b6 authored by Mario Bianucci's avatar Mario Bianucci Committed by Commit Bot

Intersect presentation area with the scrollable area

When determining the presentation area for delegated ink trails, its
possible that the canvas that the user has provided is larger than the
viewport of the browser window. In this case, the presentation area
should intersect with the scrollable area so that it can extend to the
scroll bars, but not beyond them. This change also ensures that the
presentation area is clipped to the edge of iframes as well.

Bug: 1052145
Change-Id: I349616b25a0523e825dffb37c19e14fe737dc3f1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2341949Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDaniel Libby <dlibby@microsoft.com>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#806824}
parent 5c30fbb2
......@@ -10,7 +10,9 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
......@@ -97,14 +99,39 @@ void DelegatedInkTrailPresenter::updateInkTrailStartPoint(
layout_box = layout_view;
}
// TODO(1052145): Move this further into the document lifecycle when layout
// is up to date.
PhysicalRect physical_rect_area = layout_box->LocalToAbsoluteRect(
// Intersect with the visible viewport so that the presentation area can't
// extend beyond the edges of the window or over the scrollbars. The frame
// visual viewport loop accounts for all iframe viewports, and the page visual
// viewport accounts for the full window. Convert everything to root frame
// coordinates in order to make sure offsets aren't lost along the way.
//
// TODO(1052145): Overflow and clip-path clips are ignored here, which results
// in delegated ink trails ignoring the clips and appearing incorrectly in
// some situations. This could also occur due to transformations, as the
// |presenation_area| is currently always a rectilinear bounding box. Ideally
// both of these situations are handled correctly, or the trail doesn't appear
// if we are unable to accurately render it.
PhysicalRect border_box_rect_absolute = layout_box->LocalToAbsoluteRect(
layout_box->PhysicalBorderBoxRect(), kTraverseDocumentBoundaries);
gfx::RectF area(physical_rect_area.X().ToFloat(),
physical_rect_area.Y().ToFloat(),
physical_rect_area.Width().ToFloat(),
physical_rect_area.Height().ToFloat());
while (layout_view->GetFrame()->OwnerLayoutObject()) {
PhysicalRect frame_visual_viewport_absolute =
layout_view->LocalToAbsoluteRect(
PhysicalRect(
layout_view->GetScrollableArea()->VisibleContentRect()),
kTraverseDocumentBoundaries);
border_box_rect_absolute.Intersect(frame_visual_viewport_absolute);
layout_view = layout_view->GetFrame()->OwnerLayoutObject()->View();
}
border_box_rect_absolute.Intersect(PhysicalRect(
local_frame_->GetPage()->GetVisualViewport().VisibleContentRect()));
gfx::RectF area(border_box_rect_absolute.X().ToFloat(),
border_box_rect_absolute.Y().ToFloat(),
border_box_rect_absolute.Width().ToFloat(),
border_box_rect_absolute.Height().ToFloat());
const double diameter_in_physical_pixels = style->diameter() * effective_zoom;
std::unique_ptr<viz::DelegatedInkMetadata> metadata =
......
......@@ -30,6 +30,7 @@ class TestDelegatedInkMetadata {
: area_(area) {
area_.Scale(device_pixel_ratio);
}
TestDelegatedInkMetadata() = default;
void ExpectEqual(TestDelegatedInkMetadata actual) const {
// LayoutUnits cast floats to ints, causing the actual point and area to be
......@@ -64,7 +65,19 @@ DelegatedInkTrailPresenter* CreatePresenter(Element* element,
} // namespace
class DelegatedInkTrailPresenterUnitTest : public SimTest {
protected:
public:
void SetWebViewSize(float width, float height) {
WebView().MainFrameWidget()->Resize(WebSize(width, height));
}
void SetWebViewSizeGreaterThanCanvas(float width, float height) {
// The presentation area is intersected with the visible content rect, so
// make sure that the page size is larger than the canvas to ensure it
// isn't clipped. Adding 1 to the height and width is enough to ensure that
// doesn't happen.
SetWebViewSize(width + 1, height + 1);
}
PointerEvent* CreatePointerMoveEvent(gfx::PointF pt) {
PointerEventInit* init = PointerEventInit::Create();
init->setClientX(pt.x());
......@@ -84,9 +97,29 @@ class DelegatedInkTrailPresenterUnitTest : public SimTest {
}
};
// Test scenarios with the presentation area extending beyond the edges of the
// window to confirm it gets clipped correctly.
class DelegatedInkTrailPresenterCanvasBeyondViewport
: public DelegatedInkTrailPresenterUnitTest,
public testing::WithParamInterface<bool> {
public:
bool CanvasShouldBePastViewport() { return GetParam(); }
float GetViewportWidth() const { return kViewportWidth; }
float GetViewportHeight() const { return kViewportHeight; }
void SetWebViewSize() {
DelegatedInkTrailPresenterUnitTest::SetWebViewSize(kViewportWidth,
kViewportHeight);
}
private:
const float kViewportWidth = 175.f;
const float kViewportHeight = 180.f;
};
// Confirm that all the information is collected and transformed correctly, if
// necessary. Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, CollectAndPropagateMetadata) {
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
CollectAndPropagateMetadata) {
SimRequest main_resource("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
......@@ -108,8 +141,16 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CollectAndPropagateMetadata) {
const float kCanvasWidth = 191.f;
const float kCanvasHeight = 234.f;
TestDelegatedInkMetadata expected_metadata(
gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight));
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kCanvasWidth, kCanvasHeight);
expected_metadata.SetArea(gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight));
} else {
SetWebViewSize();
expected_metadata.SetArea(
gfx::RectF(0, 0, GetViewportWidth(), GetViewportHeight()));
}
DelegatedInkTrailPresenter* presenter = CreatePresenter(
GetDocument().getElementById("canvas"), GetDocument().GetFrame());
......@@ -130,38 +171,10 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CollectAndPropagateMetadata) {
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Confirm that presentation area defaults to the size of the viewport.
// Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, PresentationAreaNotProvided) {
const int kViewportHeight = 555;
const int kViewportWidth = 333;
WebView().MainFrameWidget()->Resize(WebSize(kViewportWidth, kViewportHeight));
DelegatedInkTrailPresenter* presenter =
CreatePresenter(nullptr, GetDocument().GetFrame());
DCHECK(presenter);
TestDelegatedInkMetadata expected_metadata(
gfx::RectF(0, 0, kViewportWidth, kViewportHeight));
InkTrailStyle style;
style.setDiameter(3.6);
style.setColor("yellow");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorYELLOW);
gfx::PointF pt(70, 109);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(pt);
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Confirm that everything is still calculated correctly when the
// DevicePixelRatio is not 1. Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, NotDefaultDevicePixelRatio) {
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
NotDefaultDevicePixelRatio) {
const float kZoom = 1.7;
SetPageZoomFactor(kZoom);
......@@ -186,8 +199,18 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, NotDefaultDevicePixelRatio) {
const float kCanvasWidth = 281.f;
const float kCanvasHeight = 190.f;
TestDelegatedInkMetadata expected_metadata(
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kCanvasWidth * kZoom,
kCanvasHeight * kZoom);
expected_metadata = TestDelegatedInkMetadata(
gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight), kZoom);
} else {
SetWebViewSize();
expected_metadata.SetArea(
gfx::RectF(0, 0, GetViewportWidth(), GetViewportHeight()));
}
DelegatedInkTrailPresenter* presenter = CreatePresenter(
GetDocument().getElementById("canvas"), GetDocument().GetFrame());
......@@ -211,7 +234,7 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, NotDefaultDevicePixelRatio) {
// Confirm that the offset is correct. Numbers and color used were chosen
// arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasNotAtOrigin) {
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasNotAtOrigin) {
SimRequest main_resource("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
......@@ -224,8 +247,8 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasNotAtOrigin) {
width: 250px;
height: 350px;
position: fixed;
top: 375px;
left: 166px;
top: 59px;
left: 16px;
}
</style>
<canvas id='canvas'></canvas>
......@@ -235,11 +258,23 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasNotAtOrigin) {
const float kCanvasWidth = 250.f;
const float kCanvasHeight = 350.f;
const float kCanvasTopOffset = 375.f;
const float kCanvasLeftOffset = 166.f;
const float kCanvasTopOffset = 59.f;
const float kCanvasLeftOffset = 16.f;
TestDelegatedInkMetadata expected_metadata(gfx::RectF(
kCanvasLeftOffset, kCanvasTopOffset, kCanvasWidth, kCanvasHeight));
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kCanvasWidth + kCanvasLeftOffset,
kCanvasHeight + kCanvasTopOffset);
expected_metadata.SetArea(gfx::RectF(kCanvasLeftOffset, kCanvasTopOffset,
kCanvasWidth, kCanvasHeight));
} else {
SetWebViewSize();
expected_metadata.SetArea(
gfx::RectF(kCanvasLeftOffset, kCanvasTopOffset,
GetViewportWidth() - kCanvasLeftOffset,
GetViewportHeight() - kCanvasTopOffset));
}
DelegatedInkTrailPresenter* presenter = CreatePresenter(
GetDocument().getElementById("canvas"), GetDocument().GetFrame());
......@@ -262,7 +297,7 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasNotAtOrigin) {
// Confirm that values, specifically offsets, are transformed correctly when
// the canvas is in an iframe. Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasInIFrame) {
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasInIFrame) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
LoadURL("https://example.com/test.html");
......@@ -272,7 +307,7 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasInIFrame) {
body {
margin: 0;
}
iframe {
#iframe {
width: 500px;
height: 500px;
position: fixed;
......@@ -309,20 +344,35 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasInIFrame) {
const float kIframeBorder = 2.f;
const float kIframeLeftOffset = 57.f + kIframeBorder;
const float kIframeTopOffset = 26.f + kIframeBorder;
const float kIframeHeight = 500.f;
const float kIframeWidth = 500.f;
const float kCanvasLeftOffset = 16.f;
const float kCanvasTopOffset = 33.f;
const float kCanvasHeight = 250.f;
const float kCanvasWidth = 250.f;
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kIframeWidth + kIframeLeftOffset,
kIframeHeight + kIframeTopOffset);
expected_metadata.SetArea(gfx::RectF(kIframeLeftOffset + kCanvasLeftOffset,
kIframeTopOffset + kCanvasTopOffset,
kCanvasWidth, kCanvasHeight));
} else {
SetWebViewSize();
expected_metadata.SetArea(gfx::RectF(
kIframeLeftOffset + kCanvasLeftOffset,
kIframeTopOffset + kCanvasTopOffset,
GetViewportWidth() - (kIframeLeftOffset + kCanvasLeftOffset),
GetViewportHeight() - (kIframeTopOffset + kCanvasTopOffset)));
}
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("iframe"));
auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame());
Document* iframe_document = iframe_element->contentDocument();
TestDelegatedInkMetadata expected_metadata(gfx::RectF(
kIframeLeftOffset + kCanvasLeftOffset,
kIframeTopOffset + kCanvasTopOffset, kCanvasWidth, kCanvasHeight));
DelegatedInkTrailPresenter* presenter = CreatePresenter(
iframe_localframe->GetDocument()->getElementById("canvas"),
iframe_document->GetFrame());
......@@ -344,9 +394,136 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasInIFrame) {
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Confirm that values, specifically offsets, are transformed correctly when
// the canvas is in a nested iframe. Numbers and color used were chosen
// arbitrarily.
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, NestedIframe) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
SimRequest frame2_resource("https://example.com/iframe2.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#OuterIframe {
width: 500px;
height: 500px;
position: fixed;
top: 26px;
left: 57px;
}
</style>
<iframe id='OuterIframe' src='https://example.com/iframe.html'>
</iframe>
)HTML");
frame_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#InnerIframe {
width: 400px;
height: 400px;
position: fixed;
top: 11px;
left: 18px;
}
</style>
<iframe id='InnerIframe' src='https://example.com/iframe2.html'>
</iframe>
)HTML");
frame2_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
canvas {
width: 250px;
height: 250px;
position: fixed;
top: 28px;
left: 6px;
}
</style>
<canvas id='canvas'></canvas>
)HTML");
Compositor().BeginFrame();
// When creating the expected metadata, we have to take into account the
// offsets that are applied to the iframe that the canvas is in, and the 2px
// border around the iframe.
const float kIframeBorder = 2.f;
const float kOuterIframeLeftOffset = 57.f + kIframeBorder;
const float kOuterIframeTopOffset = 26.f + kIframeBorder;
const float kOuterIframeHeight = 500.f;
const float kOuterIframeWidth = 500.f;
const float kInnerIframeLeftOffset =
kOuterIframeLeftOffset + 18.f + kIframeBorder;
const float kInnerIframeTopOffset =
kOuterIframeTopOffset + 11.f + kIframeBorder;
const float kCanvasLeftOffset = 6.f;
const float kCanvasTopOffset = 28.f;
const float kCanvasHeight = 250.f;
const float kCanvasWidth = 250.f;
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kOuterIframeWidth + kOuterIframeLeftOffset,
kOuterIframeHeight + kOuterIframeTopOffset);
expected_metadata.SetArea(gfx::RectF(
kInnerIframeLeftOffset + kCanvasLeftOffset,
kInnerIframeTopOffset + kCanvasTopOffset, kCanvasWidth, kCanvasHeight));
} else {
SetWebViewSize();
expected_metadata.SetArea(gfx::RectF(
kInnerIframeLeftOffset + kCanvasLeftOffset,
kInnerIframeTopOffset + kCanvasTopOffset,
GetViewportWidth() - (kInnerIframeLeftOffset + kCanvasLeftOffset),
GetViewportHeight() - (kInnerIframeTopOffset + kCanvasTopOffset)));
}
auto* outer_iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("OuterIframe"));
auto* inner_iframe_element = To<HTMLIFrameElement>(
outer_iframe_element->contentDocument()->getElementById("InnerIframe"));
auto* iframe_localframe =
To<LocalFrame>(inner_iframe_element->ContentFrame());
Document* iframe_document = inner_iframe_element->contentDocument();
DelegatedInkTrailPresenter* presenter = CreatePresenter(
iframe_localframe->GetDocument()->getElementById("canvas"),
iframe_document->GetFrame());
DCHECK(presenter);
InkTrailStyle style;
style.setDiameter(100000.3);
style.setColor("yellow");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorYELLOW);
gfx::PointF pt(350, 375);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset,
pt.y() + kInnerIframeTopOffset));
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Confirm that values are correct when an iframe is used and presentation area
// isn't provided. Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, IFrameNoPresentationArea) {
TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport,
IFrameNoPresentationArea) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
LoadURL("https://example.com/test.html");
......@@ -356,7 +533,7 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, IFrameNoPresentationArea) {
body {
margin: 0;
}
iframe {
#iframe {
width: 500px;
height: 500px;
position: fixed;
......@@ -387,13 +564,25 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, IFrameNoPresentationArea) {
const float kIframeHeight = 500.f;
const float kIframeWidth = 500.f;
TestDelegatedInkMetadata expected_metadata;
if (!CanvasShouldBePastViewport()) {
SetWebViewSizeGreaterThanCanvas(kIframeWidth + kIframeLeftOffset,
kIframeHeight + kIframeTopOffset);
expected_metadata.SetArea(gfx::RectF(kIframeLeftOffset, kIframeTopOffset,
kIframeWidth, kIframeHeight));
} else {
SetWebViewSize();
expected_metadata.SetArea(
gfx::RectF(kIframeLeftOffset, kIframeTopOffset,
GetViewportWidth() - kIframeLeftOffset,
GetViewportHeight() - kIframeTopOffset));
}
Document* iframe_document =
To<HTMLIFrameElement>(GetDocument().getElementById("iframe"))
->contentDocument();
TestDelegatedInkMetadata expected_metadata(gfx::RectF(
kIframeLeftOffset, kIframeTopOffset, kIframeWidth, kIframeHeight));
DelegatedInkTrailPresenter* presenter =
CreatePresenter(nullptr, iframe_document->GetFrame());
DCHECK(presenter);
......@@ -414,4 +603,333 @@ TEST_F(DelegatedInkTrailPresenterUnitTest, IFrameNoPresentationArea) {
expected_metadata.ExpectEqual(GetActualMetadata());
}
INSTANTIATE_TEST_SUITE_P(,
DelegatedInkTrailPresenterCanvasBeyondViewport,
testing::Bool());
// Confirm that presentation area defaults to the size of the viewport.
// Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, PresentationAreaNotProvided) {
const int kViewportHeight = 555;
const int kViewportWidth = 333;
SetWebViewSize(kViewportWidth, kViewportHeight);
DelegatedInkTrailPresenter* presenter =
CreatePresenter(nullptr, GetDocument().GetFrame());
DCHECK(presenter);
TestDelegatedInkMetadata expected_metadata(
gfx::RectF(0, 0, kViewportWidth, kViewportHeight));
InkTrailStyle style;
style.setDiameter(3.6);
style.setColor("yellow");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorYELLOW);
gfx::PointF pt(70, 109);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(GetDocument().GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(pt);
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Test that the presentation area is clipped correctly by the dimensions of
// the iframe, even when the iframe and canvas each fit entirely within the
// visual viewport.
TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasExtendsOutsideOfIframe) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#iframe {
width: 150px;
height: 150px;
position: fixed;
top: 13px;
left: 19px;
}
</style>
<iframe id='iframe' src='https://example.com/iframe.html'>
</iframe>
)HTML");
frame_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
canvas {
width: 199px;
height: 202px;
}
</style>
<canvas id='canvas'></canvas>
)HTML");
Compositor().BeginFrame();
// When creating the expected metadata, we have to take into account the
// offsets that are applied to the iframe that the canvas is in, and the 2px
// border around the iframe.
const float kIframeBorder = 2.f;
const float kIframeLeftOffset = 19.f + kIframeBorder;
const float kIframeTopOffset = 13.f + kIframeBorder;
const float kIframeHeight = 150.f;
const float kIframeWidth = 150.f;
const float kCanvasHeight = 202.f;
const float kCanvasWidth = 199.f;
// Ensure that the webpage is larger than the iframe and canvas.
SetWebViewSize(kCanvasWidth + kIframeLeftOffset + 1,
kCanvasHeight + kIframeTopOffset + 1);
TestDelegatedInkMetadata expected_metadata(gfx::RectF(
kIframeLeftOffset, kIframeTopOffset, kIframeWidth, kIframeHeight));
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("iframe"));
auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame());
Document* iframe_document = iframe_element->contentDocument();
DelegatedInkTrailPresenter* presenter = CreatePresenter(
iframe_localframe->GetDocument()->getElementById("canvas"),
iframe_document->GetFrame());
DCHECK(presenter);
InkTrailStyle style;
style.setDiameter(99.999);
style.setColor("lime");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorGREEN);
gfx::PointF pt(102, 67);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Test that the presentation area is clipped correctly when it is offset left
// and above the iframe boundaries.
TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasLeftAndAboveIframeBoundaries) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#iframe {
width: 300px;
height: 301px;
position: fixed;
top: 13px;
left: 19px;
}
</style>
<iframe id='iframe' src='https://example.com/iframe.html'>
</iframe>
)HTML");
frame_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
canvas {
width: 189px;
height: 145px;
position: fixed;
top: -70px;
left: -99px;
}
</style>
<canvas id='canvas'></canvas>
)HTML");
Compositor().BeginFrame();
// When creating the expected metadata, we have to take into account the
// offsets that are applied to the iframe that the canvas is in, and the 2px
// border around the iframe.
const float kIframeBorder = 2.f;
const float kIframeLeftOffset = 19.f + kIframeBorder;
const float kIframeTopOffset = 13.f + kIframeBorder;
const float kIframeHeight = 301.f;
const float kIframeWidth = 300.f;
const float kCanvasHeight = 145.f;
const float kCanvasWidth = 189.f;
const float kCanvasLeftOffset = -99.f;
const float kCanvasTopOffset = -70.f;
// Ensure that the webpage is larger than the iframe.
SetWebViewSize(kIframeHeight + kIframeLeftOffset + 1,
kIframeWidth + kIframeTopOffset + 1);
TestDelegatedInkMetadata expected_metadata(gfx::RectF(
kIframeLeftOffset, kIframeTopOffset, kCanvasWidth + kCanvasLeftOffset,
kCanvasHeight + kCanvasTopOffset));
auto* iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("iframe"));
auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame());
Document* iframe_document = iframe_element->contentDocument();
DelegatedInkTrailPresenter* presenter = CreatePresenter(
iframe_localframe->GetDocument()->getElementById("canvas"),
iframe_document->GetFrame());
DCHECK(presenter);
InkTrailStyle style;
style.setDiameter(99.999);
style.setColor("lime");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorGREEN);
gfx::PointF pt(102, 67);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(
gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset));
expected_metadata.ExpectEqual(GetActualMetadata());
}
// Confirm that values, specifically presentation area, are transformed
// correctly when the iframe that the canvas is in is clipped by its parent
// iframe. Numbers and color used were chosen arbitrarily.
TEST_F(DelegatedInkTrailPresenterUnitTest, OuterIframeClipsInnerIframe) {
SimRequest main_resource("https://example.com/test.html", "text/html");
SimRequest frame_resource("https://example.com/iframe.html", "text/html");
SimRequest frame2_resource("https://example.com/iframe2.html", "text/html");
LoadURL("https://example.com/test.html");
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#OuterIframe {
width: 500px;
height: 500px;
position: fixed;
top: 26px;
left: 57px;
}
</style>
<iframe id='OuterIframe' src='https://example.com/iframe.html'>
</iframe>
)HTML");
frame_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
#InnerIframe {
width: 400px;
height: 400px;
position: fixed;
top: 311px;
left: 334px;
}
</style>
<iframe id='InnerIframe' src='https://example.com/iframe2.html'>
</iframe>
)HTML");
frame2_resource.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
margin: 0;
}
canvas {
width: 250px;
height: 250px;
position: fixed;
top: 1px;
left: 2px;
}
</style>
<canvas id='canvas'></canvas>
)HTML");
Compositor().BeginFrame();
// When creating the expected metadata, we have to take into account the
// offsets that are applied to the iframe that the canvas is in, and the 2px
// border around the iframe.
const float kIframeBorder = 2.f;
const float kOuterIframeLeftOffset = 57.f + kIframeBorder;
const float kOuterIframeTopOffset = 26.f + kIframeBorder;
const float kOuterIframeHeight = 500.f;
const float kOuterIframeWidth = 500.f;
const float kInnerIframeLeftOffset =
kOuterIframeLeftOffset + 334.f + kIframeBorder;
const float kInnerIframeTopOffset =
kOuterIframeTopOffset + 311.f + kIframeBorder;
const float kCanvasLeftOffset = 2.f;
const float kCanvasTopOffset = 1.f;
// Ensure that the webpage is larger than the iframe and canvas.
const float kViewportWidth = kOuterIframeWidth + kOuterIframeLeftOffset + 1.f;
const float kViewportHeight =
kOuterIframeHeight + kOuterIframeTopOffset + 1.f;
SetWebViewSize(kViewportWidth, kViewportHeight);
TestDelegatedInkMetadata expected_metadata(
gfx::RectF(kInnerIframeLeftOffset + kCanvasLeftOffset,
kInnerIframeTopOffset + kCanvasTopOffset,
kOuterIframeWidth + kOuterIframeLeftOffset -
kInnerIframeLeftOffset - kCanvasLeftOffset,
kOuterIframeHeight + kOuterIframeTopOffset -
kInnerIframeTopOffset - kCanvasTopOffset));
auto* outer_iframe_element =
To<HTMLIFrameElement>(GetDocument().getElementById("OuterIframe"));
auto* inner_iframe_element = To<HTMLIFrameElement>(
outer_iframe_element->contentDocument()->getElementById("InnerIframe"));
auto* iframe_localframe =
To<LocalFrame>(inner_iframe_element->ContentFrame());
Document* iframe_document = inner_iframe_element->contentDocument();
DelegatedInkTrailPresenter* presenter = CreatePresenter(
iframe_localframe->GetDocument()->getElementById("canvas"),
iframe_document->GetFrame());
DCHECK(presenter);
InkTrailStyle style;
style.setDiameter(19);
style.setColor("red");
expected_metadata.SetDiameter(style.diameter());
expected_metadata.SetColor(SK_ColorRED);
gfx::PointF pt(357, 401);
presenter->updateInkTrailStartPoint(
ToScriptStateForMainWorld(iframe_document->GetFrame()),
CreatePointerMoveEvent(pt), &style);
expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset,
pt.y() + kInnerIframeTopOffset));
expected_metadata.ExpectEqual(GetActualMetadata());
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment