Commit 366f094b authored by caseq@chromium.org's avatar caseq@chromium.org

DevTools: added support for image url & node in tracing-based timeline

- add trace event for RenderImage::paintIntoRect;
- fix name of decode & resize image events for tracing vs. old timeline;
- add processing of decode/resize/paint/imageref events to TimelineTraceEventBindings;
- generalize handling of additional event properties when building details, so that
    we avoid extra switches over event type by extracting properties relevant for
    details into TraceEvent properties;
- temporary workaround for crash on record stop in tests by cloning an AtomicString
    (see crbug.com/375242 for more details).

BUG=361045,375242

Review URL: https://codereview.chromium.org/308123008

git-svn-id: svn://svn.chromium.org/blink/trunk@175284 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 273dca96
Tests the instrumentation of a DecodeImage and ResizeImage events
event: Decode Image
imageURL: .../inspector/timeline/resources/test.bmp
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/test.gif
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/test.ico
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/test.jpg
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/test.png
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/test.webp
backendNodeId: present
event: Decode Image
imageURL: .../inspector/timeline/resources/big.png
backendNodeId: present
<html>
<head>
<style>
div#img-container {
position: relative;
width: 99px;
height: 99px;
overflow: clip;
}
</style>
<script src="../../../http/tests/inspector/inspector-test.js"></script>
<script src="../../../http/tests/inspector/timeline-test.js"></script>
<script src="../../tracing-test.js"></script>
<script>
var images = [
["../resources/test.bmp", "25", "25"],
["../resources/test.gif", "25", "25"],
["../resources/test.ico", "25", "25"],
["../resources/test.jpg", "25", "25"],
["../resources/test.png", "25", "25"],
["../resources/test.webp", "25", "25"],
["../resources/big.png", "150", "150"]
];
function showImages(callback)
{
var nextImageIndex = 0;
var imgElement = document.getElementById("img-container").firstElementChild;
imgElement.addEventListener("load", imageLoaded);
addImages();
function addImages()
{
if (nextImageIndex >= images.length) {
imgElement.removeEventListener("load", imageLoaded);
callback();
return;
}
var image = images[nextImageIndex++];
imgElement.width = image[1];
imgElement.height = image[2];
imgElement.src = image[0];
}
function imageLoaded()
{
requestAnimationFrame(function() { testRunner.displayAsyncThen(addImages); } );
}
}
function test()
{
var imageCount = 0;
InspectorTest.invokeWithTracing("-*,devtools,disabled-by-default-devtools.timeline*", "showImages", onTracingComplete);
function onTracingComplete()
{
var traceEventBindings = new WebInspector.TimelineTraceEventBindings();
var events = InspectorTest.tracingModel.inspectedTargetEvents();
traceEventBindings.setEvents(events);
for (var i = 0; i < events.length; ++i) {
var event = events[i];
if (events[i].name !== WebInspector.TimelineTraceEventBindings.RecordType.DecodeImage)
continue;
InspectorTest.addResult("event: " + event.name);
InspectorTest.addResult("imageURL: " + InspectorTest.formatters.formatAsURL(event.imageURL));
InspectorTest.addResult("backendNodeId: " + (event.backendNodeId > 0 ? "present" : "absent"));
}
InspectorTest.completeTest();
}
}
</script>
</head>
<body onload="runTest()">
<p>
Tests the instrumentation of a DecodeImage and ResizeImage events
</p>
<div id="img-container"><img></div>
</body>
</html>
...@@ -11,12 +11,12 @@ InspectorTest.invokeWithTracing = function(categoryFilter, functionName, callbac ...@@ -11,12 +11,12 @@ InspectorTest.invokeWithTracing = function(categoryFilter, functionName, callbac
function onTracingStarted(error) function onTracingStarted(error)
{ {
InspectorTest.invokePageFunctionAsync(functionName, onPageActionsDone) InspectorTest.invokePageFunctionAsync(functionName, onPageActionsDone);
} }
function onPageActionsDone() function onPageActionsDone()
{ {
InspectorTest.tracingModel.stop(callback); InspectorTest.tracingModel.stop(InspectorTest.safeWrap(callback));
} }
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "core/inspector/InspectorNodeIds.h" #include "core/inspector/InspectorNodeIds.h"
#include "core/inspector/ScriptCallStack.h" #include "core/inspector/ScriptCallStack.h"
#include "core/page/Page.h" #include "core/page/Page.h"
#include "core/rendering/RenderImage.h"
#include "core/rendering/RenderObject.h" #include "core/rendering/RenderObject.h"
#include "core/xml/XMLHttpRequest.h" #include "core/xml/XMLHttpRequest.h"
#include "platform/JSONValues.h" #include "platform/JSONValues.h"
...@@ -116,7 +117,7 @@ PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveResponseEvent:: ...@@ -116,7 +117,7 @@ PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveResponseEvent::
data->setString("requestId", requestId); data->setString("requestId", requestId);
data->setString("frame", toHexString(frame)); data->setString("frame", toHexString(frame));
data->setNumber("statusCode", response.httpStatusCode()); data->setNumber("statusCode", response.httpStatusCode());
data->setString("mimeType", response.mimeType()); data->setString("mimeType", response.mimeType().string().isolatedCopy());
return TracedValue::fromJSONValue(data); return TracedValue::fromJSONValue(data);
} }
...@@ -295,6 +296,17 @@ PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorFunctionCallEvent::dat ...@@ -295,6 +296,17 @@ PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorFunctionCallEvent::dat
return TracedValue::fromJSONValue(data); return TracedValue::fromJSONValue(data);
} }
PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintImageEvent::data(const RenderImage& renderImage)
{
RefPtr<JSONObject> data = JSONObject::create();
data->setNumber("nodeId", InspectorNodeIds::idForNode(renderImage.generatingNode()));
if (const ImageResource* resource = renderImage.cachedImage())
data->setString("url", resource->url().string());
return TracedValue::fromJSONValue(data);
}
static size_t usedHeapSize() static size_t usedHeapSize()
{ {
HeapInfo info; HeapInfo info;
......
...@@ -20,6 +20,7 @@ class KURL; ...@@ -20,6 +20,7 @@ class KURL;
class LayoutRect; class LayoutRect;
class LocalFrame; class LocalFrame;
class RenderObject; class RenderObject;
class RenderImage;
class ResourceRequest; class ResourceRequest;
class ResourceResponse; class ResourceResponse;
class ScriptSourceCode; class ScriptSourceCode;
...@@ -102,6 +103,11 @@ public: ...@@ -102,6 +103,11 @@ public:
static PassRefPtr<TraceEvent::ConvertableToTraceFormat> data(RenderObject*, const LayoutRect& clipRect, const GraphicsLayer*); static PassRefPtr<TraceEvent::ConvertableToTraceFormat> data(RenderObject*, const LayoutRect& clipRect, const GraphicsLayer*);
}; };
class InspectorPaintImageEvent {
public:
static PassRefPtr<TraceEvent::ConvertableToTraceFormat> data(const RenderImage&);
};
class InspectorMarkLoadEvent { class InspectorMarkLoadEvent {
public: public:
static PassRefPtr<TraceEvent::ConvertableToTraceFormat> data(LocalFrame*); static PassRefPtr<TraceEvent::ConvertableToTraceFormat> data(LocalFrame*);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "core/html/HTMLInputElement.h" #include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMapElement.h" #include "core/html/HTMLMapElement.h"
#include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/rendering/HitTestResult.h" #include "core/rendering/HitTestResult.h"
#include "core/rendering/PaintInfo.h" #include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderView.h" #include "core/rendering/RenderView.h"
...@@ -455,6 +456,8 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect ...@@ -455,6 +456,8 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect
Image* image = m_imageResource->image().get(); Image* image = m_imageResource->image().get();
InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image, image, alignedRect.size()); InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image, image, alignedRect.size());
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(*this));
// FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
InspectorInstrumentation::willPaintImage(this); InspectorInstrumentation::willPaintImage(this);
InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality();
context->setImageInterpolationQuality(interpolationQuality); context->setImageInterpolationQuality(interpolationQuality);
......
...@@ -28,11 +28,10 @@ WebInspector.TimelineTraceEventBindings.RecordType = { ...@@ -28,11 +28,10 @@ WebInspector.TimelineTraceEventBindings.RecordType = {
UpdateLayerTree: "UpdateLayerTree", UpdateLayerTree: "UpdateLayerTree",
PaintSetup: "PaintSetup", PaintSetup: "PaintSetup",
Paint: "Paint", Paint: "Paint",
PaintImage: "PaintImage",
Rasterize: "Rasterize", Rasterize: "Rasterize",
RasterTask: "RasterTask", RasterTask: "RasterTask",
ScrollLayer: "ScrollLayer", ScrollLayer: "ScrollLayer",
DecodeImage: "DecodeImage",
ResizeImage: "ResizeImage",
CompositeLayers: "CompositeLayers", CompositeLayers: "CompositeLayers",
ParseHTML: "ParseHTML", ParseHTML: "ParseHTML",
...@@ -78,6 +77,12 @@ WebInspector.TimelineTraceEventBindings.RecordType = { ...@@ -78,6 +77,12 @@ WebInspector.TimelineTraceEventBindings.RecordType = {
SetLayerTreeId: "SetLayerTreeId", SetLayerTreeId: "SetLayerTreeId",
TracingStartedInPage: "TracingStartedInPage", TracingStartedInPage: "TracingStartedInPage",
DecodeImage: "Decode Image",
ResizeImage: "Resize Image",
DrawLazyPixelRef: "Draw LazyPixelRef",
DecodeLazyPixelRef: "Decode LazyPixelRef",
LazyPixelRef: "LazyPixelRef",
LayerTreeHostImplSnapshot: "cc::LayerTreeHostImpl" LayerTreeHostImplSnapshot: "cc::LayerTreeHostImpl"
}; };
...@@ -105,6 +110,7 @@ WebInspector.TimelineTraceEventBindings.prototype = { ...@@ -105,6 +110,7 @@ WebInspector.TimelineTraceEventBindings.prototype = {
this._layoutInvalidate = {}; this._layoutInvalidate = {};
this._lastScheduleStyleRecalculation = {}; this._lastScheduleStyleRecalculation = {};
this._webSocketCreateEvents = {}; this._webSocketCreateEvents = {};
this._paintImageEventByPixelRefId = {};
this._lastRecalculateStylesEvent = null; this._lastRecalculateStylesEvent = null;
this._currentScriptEvent = null; this._currentScriptEvent = null;
...@@ -154,12 +160,15 @@ WebInspector.TimelineTraceEventBindings.prototype = { ...@@ -154,12 +160,15 @@ WebInspector.TimelineTraceEventBindings.prototype = {
case recordTypes.ResourceSendRequest: case recordTypes.ResourceSendRequest:
this._sendRequestEvents[event.args.data["requestId"]] = event; this._sendRequestEvents[event.args.data["requestId"]] = event;
event.imageURL = event.args.data["url"];
break; break;
case recordTypes.ResourceReceiveResponse: case recordTypes.ResourceReceiveResponse:
case recordTypes.ResourceReceivedData: case recordTypes.ResourceReceivedData:
case recordTypes.ResourceFinish: case recordTypes.ResourceFinish:
event.initiator = this._sendRequestEvents[event.args.data["requestId"]]; event.initiator = this._sendRequestEvents[event.args.data["requestId"]];
if (event.initiator)
event.imageURL = event.initiator.imageURL;
break; break;
case recordTypes.TimerInstall: case recordTypes.TimerInstall:
...@@ -200,6 +209,7 @@ WebInspector.TimelineTraceEventBindings.prototype = { ...@@ -200,6 +209,7 @@ WebInspector.TimelineTraceEventBindings.prototype = {
case recordTypes.Layout: case recordTypes.Layout:
var frameId = event.args["beginData"]["frame"]; var frameId = event.args["beginData"]["frame"];
event.initiator = this._layoutInvalidate[frameId]; event.initiator = this._layoutInvalidate[frameId];
event.backendNodeId = event.args["endData"]["rootNode"];
this._layoutInvalidate[frameId] = null; this._layoutInvalidate[frameId] = null;
if (this._currentScriptEvent) if (this._currentScriptEvent)
event.warning = WebInspector.UIString("Forced synchronous layout is a possible performance bottleneck."); event.warning = WebInspector.UIString("Forced synchronous layout is a possible performance bottleneck.");
...@@ -228,9 +238,55 @@ WebInspector.TimelineTraceEventBindings.prototype = { ...@@ -228,9 +238,55 @@ WebInspector.TimelineTraceEventBindings.prototype = {
case recordTypes.TracingStartedInPage: case recordTypes.TracingStartedInPage:
this._mainThread = event.thread; this._mainThread = event.thread;
break; break;
case recordTypes.Paint:
case recordTypes.ScrollLayer:
event.backendNodeId = event.args["data"]["nodeId"];
break;
case recordTypes.PaintImage:
event.backendNodeId = event.args["data"]["nodeId"];
event.imageURL = event.args["data"]["url"];
break;
case recordTypes.DecodeImage:
case recordTypes.ResizeImage:
var paintImageEvent = this._findAncestorEvent(recordTypes.PaintImage);
if (!paintImageEvent) {
var decodeLazyPixelRefEvent = this._findAncestorEvent(recordTypes.DecodeLazyPixelRef);
paintImageEvent = decodeLazyPixelRefEvent && this._paintImageEventByPixelRefId[decodeLazyPixelRefEvent.args["LazyPixelRef"]];
}
if (!paintImageEvent)
break;
event.backendNodeId = paintImageEvent.backendNodeId;
event.imageURL = paintImageEvent.imageURL;
break;
case recordTypes.DrawLazyPixelRef:
var paintImageEvent = this._findAncestorEvent(recordTypes.PaintImage);
if (!paintImageEvent)
break;
this._paintImageEventByPixelRefId[event.args["LazyPixelRef"]] = paintImageEvent;
event.backendNodeId = paintImageEvent.backendNodeId;
event.imageURL = paintImageEvent.imageURL;
break;
} }
if (this._mainThread === event.thread) if (this._mainThread === event.thread)
this._mainThreadEvents.push(event); this._mainThreadEvents.push(event);
},
/**
* @param {string} name
* @return {?WebInspector.TracingModel.Event}
*/
_findAncestorEvent: function(name)
{
for (var i = this._eventStack.length - 1; i >= 0; --i) {
var event = this._eventStack[i];
if (event.name === name)
return event;
}
return null;
} }
} }
...@@ -296,6 +296,11 @@ WebInspector.TracingModel.Event = function(payload, level, thread) ...@@ -296,6 +296,11 @@ WebInspector.TracingModel.Event = function(payload, level, thread)
this.stackTrace = null; this.stackTrace = null;
/** @type {?Element} */ /** @type {?Element} */
this.previewElement = null; this.previewElement = null;
/** @type {?string} */
this.imageURL = null;
/** @type {number} */
this.backendNodeId = 0;
/** @type {number} */ /** @type {number} */
this.selfTime = 0; this.selfTime = 0;
} }
......
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