Commit 2b25d21e authored by Nicolas Pena's avatar Nicolas Pena Committed by Commit Bot

[ElementTiming] Create entries for SVGImageElements

This change adds ElementTiming support for SVGImageElements. It adds a
layout test to verify that the entry is being created in a simple
example.

Bug: 879270
Change-Id: I39ae0a1209f1b299d6a431ac1ba2fcfa94b25b3e
Reviewed-on: https://chromium-review.googlesource.com/c/1467918
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#631923}
parent e9f49910
......@@ -4,11 +4,10 @@
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
......@@ -44,29 +43,27 @@ ImageElementTiming::ImageElementTiming(LocalDOMWindow& window)
DCHECK(origin_trials::ElementTimingEnabled(GetSupplementable()->document()));
}
void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
const LayoutImage* layout_image,
const PaintLayer* painting_layer) {
if (images_notified_.find(layout_image) != images_notified_.end())
void ImageElementTiming::NotifyImagePainted(
const LayoutObject* layout_object,
const ImageResourceContent* cached_image,
const PaintLayer* painting_layer) {
auto result = images_notified_.insert(layout_object);
if (!result.is_new_entry)
return;
images_notified_.insert(layout_image);
LocalFrame* frame = GetSupplementable()->GetFrame();
DCHECK(frame == layout_image->GetDocument().GetFrame());
if (!frame)
DCHECK(frame == layout_object->GetDocument().GetFrame());
if (!frame || !cached_image)
return;
// Skip the computations below if the element is not same origin.
if (!layout_image->CachedImage())
return;
DCHECK(GetSupplementable()->document() == &layout_image->GetDocument());
DCHECK(layout_image->GetDocument().GetSecurityOrigin());
DCHECK(GetSupplementable()->document() == &layout_object->GetDocument());
DCHECK(layout_object->GetDocument().GetSecurityOrigin());
if (!Performance::PassesTimingAllowCheck(
layout_image->CachedImage()->GetResponse(),
*layout_image->GetDocument().GetSecurityOrigin(),
&layout_image->GetDocument()))
cached_image->GetResponse(),
*layout_object->GetDocument().GetSecurityOrigin(),
&layout_object->GetDocument()))
return;
// Compute the viewport rect.
......@@ -78,7 +75,7 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
IntRect viewport = frame->View()->LayoutViewport()->VisibleContentRect();
// Compute the visible part of the image rect.
LayoutRect image_visual_rect = layout_image->FirstFragment().VisualRect();
LayoutRect image_visual_rect = layout_object->FirstFragment().VisualRect();
const auto& local_transform = painting_layer->GetLayoutObject()
.FirstFragment()
.LocalBorderBoxProperties()
......@@ -94,6 +91,7 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
IntRect visible_new_visual_rect = RoundedIntRect(new_visual_rect_abs);
visible_new_visual_rect.Intersect(viewport);
const Element* element = ToElement(layout_object->GetNode());
const AtomicString attr =
element->FastGetAttribute(html_names::kElementtimingAttr);
// Do not create an entry if 'elementtiming' is not present or the image is
......@@ -136,7 +134,7 @@ void ImageElementTiming::ReportImagePaintSwapTime(WebLayerTreeView::SwapResult,
element_timings_.clear();
}
void ImageElementTiming::NotifyWillBeDestroyed(const LayoutImage* image) {
void ImageElementTiming::NotifyWillBeDestroyed(const LayoutObject* image) {
images_notified_.erase(image);
}
......
......@@ -15,7 +15,7 @@
namespace blink {
class HTMLImageElement;
class ImageResourceContent;
class LayoutImage;
// ImageElementTiming is responsible for tracking the paint timings for <img>
......@@ -33,14 +33,14 @@ class CORE_EXPORT ImageElementTiming final
static ImageElementTiming& From(LocalDOMWindow&);
// Called when the LayoutImage has been painted. This method might queue a
// Called when the LayoutObject has been painted. This method might queue a
// swap promise to compute and report paint timestamps.
void NotifyImagePainted(const HTMLImageElement*,
const LayoutImage*,
void NotifyImagePainted(const LayoutObject*,
const ImageResourceContent* cached_image,
const PaintLayer*);
// Called when the LayoutImage will be destroyed.
void NotifyWillBeDestroyed(const LayoutImage*);
void NotifyWillBeDestroyed(const LayoutObject*);
void Trace(blink::Visitor*) override;
......@@ -60,8 +60,8 @@ class CORE_EXPORT ImageElementTiming final
// Vector containing the element timing infos that will be reported during the
// next swap promise callback.
WTF::Vector<ElementTimingInfo> element_timings_;
// Hashmap of LayoutImage objects for which paint has already been notified.
WTF::HashSet<const LayoutImage*> images_notified_;
// Hashmap of LayoutObjects for which paint has already been notified.
WTF::HashSet<const LayoutObject*> images_notified_;
DISALLOW_COPY_AND_ASSIGN(ImageElementTiming);
};
......
......@@ -214,7 +214,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
LocalDOMWindow* window = layout_image_.GetDocument().domWindow();
DCHECK(window);
ImageElementTiming::From(*window).NotifyImagePainted(
ToHTMLImageElement(node), &layout_image_, painting_layer);
&layout_image_, layout_image_.CachedImage(), painting_layer);
}
}
......
......@@ -4,8 +4,11 @@
#include "third_party/blink/renderer/core/paint/svg_image_painter.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_image_resource.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
......@@ -75,6 +78,16 @@ void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) {
Image::ImageDecodingMode decode_mode =
image_element->GetDecodingModeForPainting(image->paint_image_id());
paint_info.context.DrawImage(image.get(), decode_mode, dest_rect, &src_rect);
if (origin_trials::ElementTimingEnabled(&layout_svg_image_.GetDocument()) &&
!paint_info.context.ContextDisabled() && image_resource->CachedImage() &&
image_resource->CachedImage()->IsLoaded()) {
LocalDOMWindow* window = layout_svg_image_.GetDocument().domWindow();
DCHECK(window);
DCHECK(paint_info.PaintContainer());
ImageElementTiming::From(*window).NotifyImagePainted(
&layout_svg_image_, image_resource->CachedImage(),
paint_info.PaintContainer()->Layer());
}
}
FloatSize SVGImagePainter::ComputeImageViewportSize() const {
......
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: observe image inside SVG</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
let beforeRender;
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
checkElement(entry, 'my_svg', beforeRender);
// Assume viewport has size at least 200, so the element is fully visible.
checkRect(entry, [0, 200, 0, 200]);
})
);
observer.observe({entryTypes: ['element']});
beforeRender = performance.now();
}, "Able to observe svg image.");
</script>
<style>
body {
margin: 0;
}
</style>
<svg>
<image href='resources/circle.svg' elementtiming='my_svg'/>
</svg>
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