Commit 7598e87a authored by Nicolás Peña Moreno's avatar Nicolás Peña Moreno Committed by Commit Bot

[Longtasks] Fix containerType and containerSrc in attribution

This CL brings the longtasks API up to date with the recent changes on
https://github.com/w3c/longtasks/pull/78. It also adds WPT tests for
those changes. The changes are:

* containerType is "window", "iframe", "embed", etc. depending on the
type of the culprit browsing context container.
* containerSrc is now the 'data' attribute when the container is an
<object>.

Change-Id: I06f661968778e3bec433a1bfe758b4604df01557
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1949146Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721258}
parent 1a7d78d7
......@@ -653,16 +653,17 @@ bool Performance::CanAddResourceTimingEntry() {
void Performance::AddLongTaskTiming(base::TimeTicks start_time,
base::TimeTicks end_time,
const AtomicString& name,
const String& frame_src,
const String& frame_id,
const String& frame_name) {
const AtomicString& container_type,
const String& container_src,
const String& container_id,
const String& container_name) {
if (!HasObserverFor(PerformanceEntry::kLongTask))
return;
auto* entry = MakeGarbageCollected<PerformanceLongTaskTiming>(
MonotonicTimeToDOMHighResTimeStamp(start_time),
MonotonicTimeToDOMHighResTimeStamp(end_time), name, frame_src, frame_id,
frame_name);
MonotonicTimeToDOMHighResTimeStamp(end_time), name, container_type,
container_src, container_id, container_name);
NotifyObserversOfEntry(*entry);
}
......
......@@ -147,9 +147,10 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
void AddLongTaskTiming(base::TimeTicks start_time,
base::TimeTicks end_time,
const AtomicString& name,
const String& culprit_frame_src,
const String& culprit_frame_id,
const String& culprit_frame_name);
const AtomicString& container_type,
const String& container_src,
const String& container_id,
const String& container_name);
// Generates and add a performance entry for the given ResourceTimingInfo.
// |overridden_initiator_type| allows the initiator type to be overridden to
......
......@@ -16,14 +16,13 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming(
double start_time,
double end_time,
const AtomicString& name,
const String& culprit_frame_src,
const String& culprit_frame_id,
const String& culprit_frame_name)
const AtomicString& culprit_type,
const String& culprit_src,
const String& culprit_id,
const String& culprit_name)
: PerformanceEntry(name, start_time, end_time) {
// Only one possible container type exists currently: "iframe".
TaskAttributionTiming* attribution_entry =
TaskAttributionTiming::Create("unknown", "iframe", culprit_frame_src,
culprit_frame_id, culprit_frame_name);
TaskAttributionTiming* attribution_entry = TaskAttributionTiming::Create(
"unknown", culprit_type, culprit_src, culprit_id, culprit_name);
attribution_.push_back(*attribution_entry);
}
......
......@@ -22,9 +22,10 @@ class PerformanceLongTaskTiming final : public PerformanceEntry {
PerformanceLongTaskTiming(double start_time,
double end_time,
const AtomicString& name,
const String& frame_src,
const String& frame_id,
const String& frame_name);
const AtomicString& culprit_type,
const String& culprit_src,
const String& culprit_id,
const String& culprit_name);
AtomicString entryType() const override;
PerformanceEntryType EntryTypeEnum() const override;
......
......@@ -123,8 +123,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) {
// Add a long task entry, but no observer registered.
base_->AddLongTaskTiming(
base::TimeTicks() + base::TimeDelta::FromSecondsD(1234),
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "same-origin",
"www.foo.com/bar", "", "");
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "window",
"same-origin", "www.foo.com/bar", "", "");
EXPECT_FALSE(base_->HasPerformanceObserverFor(PerformanceEntry::kLongTask));
EXPECT_EQ(0, NumPerformanceEntriesInObserver()); // has no effect
......@@ -140,8 +140,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) {
// Add a long task entry
base_->AddLongTaskTiming(
base::TimeTicks() + base::TimeDelta::FromSecondsD(1234),
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "same-origin",
"www.foo.com/bar", "", "");
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "window",
"same-origin", "www.foo.com/bar", "", "");
EXPECT_EQ(1, NumPerformanceEntriesInObserver()); // added an entry
}
......
......@@ -11,7 +11,7 @@
namespace blink {
TaskAttributionTiming::TaskAttributionTiming(const AtomicString& name,
const String& container_type,
const AtomicString& container_type,
const String& container_src,
const String& container_id,
const String& container_name)
......@@ -31,7 +31,7 @@ PerformanceEntryType TaskAttributionTiming::EntryTypeEnum() const {
return PerformanceEntry::EntryType::kTaskAttribution;
}
String TaskAttributionTiming::containerType() const {
AtomicString TaskAttributionTiming::containerType() const {
return container_type_;
}
......
......@@ -17,7 +17,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
public:
static TaskAttributionTiming* Create(const AtomicString& type,
const String& container_type,
const AtomicString& container_type,
const String& container_src,
const String& container_id,
const String& container_name) {
......@@ -28,7 +28,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
AtomicString entryType() const override;
PerformanceEntryType EntryTypeEnum() const override;
String containerType() const;
AtomicString containerType() const;
String containerSrc() const;
String containerId() const;
String containerName() const;
......@@ -36,7 +36,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
void Trace(blink::Visitor*) override;
TaskAttributionTiming(const AtomicString& type,
const String& container_type,
const AtomicString& container_type,
const String& container_src,
const String& container_id,
const String& container_name);
......@@ -45,7 +45,8 @@ class TaskAttributionTiming final : public PerformanceEntry {
private:
void BuildJSONValue(V8ObjectBuilder&) const override;
String container_type_;
AtomicString container_type_;
// TODO(crbug.com/1030396): change the members below to AtomicString.
String container_src_;
String container_id_;
String container_name_;
......
......@@ -77,6 +77,34 @@ String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner,
return attr_value;
}
AtomicString GetFrameOwnerType(HTMLFrameOwnerElement* frame_owner) {
switch (frame_owner->OwnerType()) {
case FrameOwnerElementType::kNone:
return "window";
case FrameOwnerElementType::kIframe:
return "iframe";
case FrameOwnerElementType::kObject:
return "object";
case FrameOwnerElementType::kEmbed:
return "embed";
case FrameOwnerElementType::kFrame:
return "frame";
case FrameOwnerElementType::kPortal:
return "portal";
}
NOTREACHED();
return "";
}
String GetFrameSrc(HTMLFrameOwnerElement* frame_owner) {
switch (frame_owner->OwnerType()) {
case FrameOwnerElementType::kObject:
return GetFrameAttribute(frame_owner, html_names::kDataAttr, false);
default:
return GetFrameAttribute(frame_owner, html_names::kSrcAttr, false);
}
}
const AtomicString& SelfKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, kSelfAttribution, ("self"));
return kSelfAttribution;
......@@ -297,14 +325,14 @@ void WindowPerformance::ReportLongTask(base::TimeTicks start_time,
DOMWindow* culprit_dom_window = attribution.second;
if (!culprit_dom_window || !culprit_dom_window->GetFrame() ||
!culprit_dom_window->GetFrame()->DeprecatedLocalOwner()) {
AddLongTaskTiming(start_time, end_time, attribution.first, g_empty_string,
g_empty_string, g_empty_string);
AddLongTaskTiming(start_time, end_time, attribution.first, "window",
g_empty_string, g_empty_string, g_empty_string);
} else {
HTMLFrameOwnerElement* frame_owner =
culprit_dom_window->GetFrame()->DeprecatedLocalOwner();
AddLongTaskTiming(
start_time, end_time, attribution.first,
GetFrameAttribute(frame_owner, html_names::kSrcAttr, false),
start_time, end_time, attribution.first, GetFrameOwnerType(frame_owner),
GetFrameSrc(frame_owner),
GetFrameAttribute(frame_owner, html_names::kIdAttr, false),
GetFrameAttribute(frame_owner, html_names::kNameAttr, true));
}
......
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>LongTask Timing: long tasks in various containers</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<h1>Longtasks in iframe, frame, object, and embed</h1>
<div id="log"></div>
<script>
function Container(name, src) {
this.name = name;
this.src = src;
}
const Containers = [
new Container('iframe', 'src'),
new Container('frame', 'src'),
new Container('object', 'data'),
new Container('embed', 'src'),
];
Containers.forEach(container => {
promise_test(async t => {
assert_precondition(window.PerformanceLongTaskTiming, 'Longtasks are not supported.');
const initialTime = performance.now();
return new Promise(resolve => {
const observer = new PerformanceObserver(t.step_func(entryList => {
const entries = entryList.getEntries();
assert_equals(entries.length, 1,
'Exactly one entry is expected.');
const longtask = entries[0];
assert_equals(longtask.entryType, 'longtask');
if (longtask.name == 'self' ||
longtask.name == 'multiple-contexts' ||
longtask.name == 'unknown')
return;
assert_equals(longtask.name, 'same-origin-descendant');
assert_greater_than(longtask.duration, 50);
assert_greater_than_equal(longtask.startTime, initialTime);
const currentTime = performance.now();
assert_less_than_equal(longtask.startTime, currentTime);
// Assert the TaskAttributionTiming entry in attribution.
assert_equals(longtask.attribution.length, 1,
'Exactly one attribution entry is expected');
const attribution = longtask.attribution[0];
assert_equals(attribution.entryType, 'taskattribution');
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerId, container.name + '-id');
assert_equals(attribution.containerName, container.name + '-name');
assert_equals(attribution.containerSrc, 'resources/subframe-with-longtask.html');
observer.disconnect();
resolve();
}));
observer.observe({entryTypes: ['longtask']});
const containerObject = document.createElement(container.name);
containerObject.id = container.name + '-id';
containerObject.name = container.name + '-name';
containerObject[container.src] = 'resources/subframe-with-longtask.html';
document.body.appendChild(containerObject);
});
}, `Performance longtask entries in ${container.name} are observable in parent.`);
});
</script>
</body>
......@@ -35,6 +35,7 @@
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, '');
......
......@@ -36,6 +36,7 @@
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'iframe');
assert_equals(attribution.containerId, 'child-iframe-id');
assert_equals(attribution.containerName, 'child-iframe-name');
assert_equals(attribution.containerSrc,
......
......@@ -41,6 +41,7 @@
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'iframe');
assert_equals(attribution.containerId, 'child-iframe-id');
assert_equals(attribution.containerName, 'child-iframe-name');
assert_equals(attribution.containerSrc, 'resources/subframe-with-longtask.html');
......
......@@ -32,6 +32,7 @@
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, '');
......
......@@ -16,6 +16,7 @@
assert_equals(e.data['entryType'], 'longtask');
assert_equals(e.data['frame-attribution'], 'same-origin-ancestor');
assert_equals(e.data['task-attribution'], 'unknown');
assert_equals(e.data['containerType'], 'window');
assert_equals(e.data['containerId'], '');
assert_equals(e.data['containerName'], '');
assert_equals(e.data['containerSrc'], '');
......
......@@ -32,6 +32,7 @@
assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, '');
......
......@@ -16,6 +16,7 @@
assert_equals(e.data['entryType'], 'longtask');
assert_equals(e.data['frame-attribution'], 'cross-origin-unreachable');
assert_equals(e.data['task-attribution'], 'unknown');
assert_equals(e.data['containerType'], 'window');
assert_equals(e.data['containerId'], '');
assert_equals(e.data['containerName'], '');
assert_equals(e.data['containerSrc'], '');
......
......@@ -20,6 +20,7 @@
assert_equals(e.data['frame-attribution'], 'same-origin');
assert_equals(e.data['task-attribution'], 'unknown');
assert_equals(e.data['containerType'], 'iframe');
assert_equals(e.data['containerId'], 'longtask-iframe-id');
assert_equals(e.data['containerName'], 'longtask-iframe-name');
assert_equals(e.data['containerSrc'], 'resources/subframe-with-longtask.html');
......
......@@ -19,6 +19,7 @@
'entryType': longtask.entryType,
'frame-attribution': longtask.name,
'task-attribution': attribution.name,
'containerType': attribution.containerType,
'containerId': attribution.containerId,
'containerName': attribution.containerName,
'containerSrc': attribution.containerSrc
......
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