Commit 83de5fce authored by Long Ly's avatar Long Ly Committed by Commit Bot

Add additional DOM Rects to DOMSnapshot.captureSnapshot

Adding offsetRects, clientRects and offsetRects into
DOMSnapshot.captureSnapshot using an experimental flags includeDOMRects.

Change-Id: Ie2c0af41c94fc1eeb9a6a371193182791a744719
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1612105
Commit-Queue: Long Ly <loly@microsoft.com>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#666362}
parent 687a3b4c
...@@ -2416,6 +2416,12 @@ experimental domain DOMSnapshot ...@@ -2416,6 +2416,12 @@ experimental domain DOMSnapshot
array of StringIndex text array of StringIndex text
# Stacking context information. # Stacking context information.
RareBooleanData stackingContexts RareBooleanData stackingContexts
# The offset rect of nodes. Only available when includeDOMRects is set to true
optional array of Rectangle offsetRects
# The scroll rect of nodes. Only available when includeDOMRects is set to true
optional array of Rectangle scrollRects
# The client rect of nodes. Only available when includeDOMRects is set to true
optional array of Rectangle clientRects
# Table of details of the post layout rendered text positions. The exact layout should not be regarded as # Table of details of the post layout rendered text positions. The exact layout should not be regarded as
# stable and may change between versions. # stable and may change between versions.
...@@ -2468,6 +2474,8 @@ experimental domain DOMSnapshot ...@@ -2468,6 +2474,8 @@ experimental domain DOMSnapshot
parameters parameters
# Whitelist of computed styles to return. # Whitelist of computed styles to return.
array of string computedStyles array of string computedStyles
# Whether to include DOM rectangles (offsetRects, clientRects, scrollRects) into the snapshot
optional boolean includeDOMRects
returns returns
# The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document. # The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document.
array of DocumentSnapshot documents array of DocumentSnapshot documents
......
...@@ -69,6 +69,19 @@ std::unique_ptr<protocol::Array<double>> BuildRectForLayoutRect2( ...@@ -69,6 +69,19 @@ std::unique_ptr<protocol::Array<double>> BuildRectForLayoutRect2(
return result; return result;
} }
std::unique_ptr<protocol::Array<double>> BuildRectForLayout(const int x,
const int y,
const int width,
const int height) {
std::unique_ptr<protocol::Array<double>> result =
protocol::Array<double>::create();
result->addItem(x);
result->addItem(y);
result->addItem(width);
result->addItem(height);
return result;
}
// Returns |layout_object|'s bounding box in document coordinates. // Returns |layout_object|'s bounding box in document coordinates.
LayoutRect RectInDocument(const LayoutObject* layout_object) { LayoutRect RectInDocument(const LayoutObject* layout_object) {
LayoutRect rect_in_absolute(layout_object->AbsoluteBoundingBoxFloatRect()); LayoutRect rect_in_absolute(layout_object->AbsoluteBoundingBoxFloatRect());
...@@ -290,6 +303,7 @@ Response InspectorDOMSnapshotAgent::getSnapshot( ...@@ -290,6 +303,7 @@ Response InspectorDOMSnapshotAgent::getSnapshot(
protocol::Response InspectorDOMSnapshotAgent::captureSnapshot( protocol::Response InspectorDOMSnapshotAgent::captureSnapshot(
std::unique_ptr<protocol::Array<String>> computed_styles, std::unique_ptr<protocol::Array<String>> computed_styles,
protocol::Maybe<bool> include_dom_rects,
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>* std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>*
documents, documents,
std::unique_ptr<protocol::Array<String>>* strings) { std::unique_ptr<protocol::Array<String>>* strings) {
...@@ -307,6 +321,8 @@ protocol::Response InspectorDOMSnapshotAgent::captureSnapshot( ...@@ -307,6 +321,8 @@ protocol::Response InspectorDOMSnapshotAgent::captureSnapshot(
std::make_pair(computed_styles->get(i), property_id)); std::make_pair(computed_styles->get(i), property_id));
} }
include_snapshot_dom_rects_ = include_dom_rects.fromMaybe(false);
for (LocalFrame* frame : *inspected_frames_) { for (LocalFrame* frame : *inspected_frames_) {
if (Document* document = frame->GetDocument()) if (Document* document = frame->GetDocument())
document_order_map_.Set(document, document_order_map_.size()); document_order_map_.Set(document, document_order_map_.size());
...@@ -578,6 +594,15 @@ void InspectorDOMSnapshotAgent::VisitDocument2(Document* document) { ...@@ -578,6 +594,15 @@ void InspectorDOMSnapshotAgent::VisitDocument2(Document* document) {
document_->setScrollOffsetY(offset.Height()); document_->setScrollOffsetY(offset.Height());
} }
if (include_snapshot_dom_rects_) {
document_->getLayout()->setOffsetRects(
protocol::Array<protocol::Array<double>>::create());
document_->getLayout()->setClientRects(
protocol::Array<protocol::Array<double>>::create());
document_->getLayout()->setScrollRects(
protocol::Array<protocol::Array<double>>::create());
}
VisitNode2(document, -1); VisitNode2(document, -1);
documents_->addItem(std::move(document_)); documents_->addItem(std::move(document_));
} }
...@@ -896,6 +921,39 @@ int InspectorDOMSnapshotAgent::BuildLayoutTreeNode(LayoutObject* layout_object, ...@@ -896,6 +921,39 @@ int InspectorDOMSnapshotAgent::BuildLayoutTreeNode(LayoutObject* layout_object,
layout_tree_snapshot->getBounds()->addItem( layout_tree_snapshot->getBounds()->addItem(
BuildRectForLayoutRect2(RectInDocument(layout_object))); BuildRectForLayoutRect2(RectInDocument(layout_object)));
if (include_snapshot_dom_rects_) {
protocol::Array<protocol::Array<double>>* offsetRects =
layout_tree_snapshot->getOffsetRects(nullptr);
DCHECK(offsetRects);
protocol::Array<protocol::Array<double>>* clientRects =
layout_tree_snapshot->getClientRects(nullptr);
DCHECK(clientRects);
protocol::Array<protocol::Array<double>>* scrollRects =
layout_tree_snapshot->getScrollRects(nullptr);
DCHECK(scrollRects);
if (node->IsElementNode()) {
auto* element = ToElement(node);
offsetRects->addItem(
BuildRectForLayout(element->OffsetLeft(), element->OffsetTop(),
element->OffsetWidth(), element->OffsetHeight()));
clientRects->addItem(
BuildRectForLayout(element->clientLeft(), element->clientTop(),
element->clientWidth(), element->clientHeight()));
scrollRects->addItem(
BuildRectForLayout(element->scrollLeft(), element->scrollTop(),
element->scrollWidth(), element->scrollHeight()));
} else {
offsetRects->addItem(protocol::Array<double>::create());
clientRects->addItem(protocol::Array<double>::create());
scrollRects->addItem(protocol::Array<double>::create());
}
}
if (layout_object->Style() && layout_object->Style()->IsStackingContext()) if (layout_object->Style() && layout_object->Style()->IsStackingContext())
SetRare(layout_tree_snapshot->getStackingContexts(), layout_index); SetRare(layout_tree_snapshot->getStackingContexts(), layout_index);
......
...@@ -53,6 +53,7 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final ...@@ -53,6 +53,7 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
computed_styles) override; computed_styles) override;
protocol::Response captureSnapshot( protocol::Response captureSnapshot(
std::unique_ptr<protocol::Array<String>> computed_styles, std::unique_ptr<protocol::Array<String>> computed_styles,
protocol::Maybe<bool> include_dom_rects,
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>* std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>*
documents, documents,
std::unique_ptr<protocol::Array<String>>* strings) override; std::unique_ptr<protocol::Array<String>>* strings) override;
...@@ -156,6 +157,7 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final ...@@ -156,6 +157,7 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
// Maps a style string vector to an index in |computed_styles_|. Used to avoid // Maps a style string vector to an index in |computed_styles_|. Used to avoid
// duplicate entries in |computed_styles_|. // duplicate entries in |computed_styles_|.
std::unique_ptr<ComputedStylesMap> computed_styles_map_; std::unique_ptr<ComputedStylesMap> computed_styles_map_;
bool include_snapshot_dom_rects_ = false;
std::unique_ptr<CSSPropertyFilter> css_property_filter_; std::unique_ptr<CSSPropertyFilter> css_property_filter_;
// Maps a PaintLayer to its paint order index. // Maps a PaintLayer to its paint order index.
std::unique_ptr<PaintOrderMap> paint_order_map_; std::unique_ptr<PaintOrderMap> paint_order_map_;
......
Tests DOMSnapshot.getSnapshot reports offset, scroll, and client rects of each node.
{
"documents": [
{
"documentURL": 0,
"baseURL": 0,
"contentLanguage": -1,
"encodingName": 1,
"publicId": -1,
"systemId": -1,
"frameId": 2,
"nodes": "<object>",
"layout": {
"nodeIndex": "<object>",
"styles": "<object>",
"bounds": [
[
0,
0,
800,
600
],
[
0,
0,
800,
0
],
[
0,
0,
800,
0
],
[
100,
100,
100,
100
],
[
100,
100,
96,
16
]
],
"text": "<object>",
"stackingContexts": "<object>",
"offsetRects": [
[],
[
0,
0,
800,
0
],
[
0,
0,
800,
0
],
[
100,
100,
100,
100
],
[]
],
"scrollRects": [
[],
[
0,
0,
800,
600
],
[
0,
0,
800,
0
],
[
0,
0,
100,
100
],
[]
],
"clientRects": [
[],
[
0,
0,
800,
600
],
[
0,
0,
800,
0
],
[
0,
0,
100,
100
],
[]
]
},
"textBoxes": "<object>",
"scrollOffsetX": 0,
"scrollOffsetY": 0
}
],
"strings": "<object>"
}
(async function(testRunner) {
const {dp} = await testRunner.startURL('../resources/dom-snapshot-includeDOMRects.html', 'Tests DOMSnapshot.getSnapshot reports offset, scroll, and client rects of each node.');
function stabilize(key, value) {
const unstableKeys = new Set(['strings', 'textBoxes', 'nodes', 'nodeIndex', 'styles', 'text', 'stackingContexts']);
if (unstableKeys.has(key))
return '<' + typeof(value) + '>';
return value;
}
const response = await dp.DOMSnapshot.captureSnapshot({'computedStyles': [], 'includeDOMRects': true});
if (response.error)
testRunner.log(response);
else
testRunner.log(JSON.stringify(response.result, stabilize, 2));
testRunner.completeTest();
})
<!DOCTYPE html>
<!-- domSnapshot test for a document to include offsetRects, clientRects, and scrollRects. -->
<style>
@font-face {
font-family: 'ahem';
src: url(../../resources/Ahem.ttf);
}
</style>
<style>
* {
margin: 0;
padding: 0;
}
div {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
}
</style>
<!-- The div's box should have size and position of 100x100 to match the
computed style, even though it's visually scaled by the viewport. The
text's box should also be inside the div's box, not outside it. -->
<div style='font-family: ahem;' id='100x100'>Boxes!</div>
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