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() { ...@@ -653,16 +653,17 @@ bool Performance::CanAddResourceTimingEntry() {
void Performance::AddLongTaskTiming(base::TimeTicks start_time, void Performance::AddLongTaskTiming(base::TimeTicks start_time,
base::TimeTicks end_time, base::TimeTicks end_time,
const AtomicString& name, const AtomicString& name,
const String& frame_src, const AtomicString& container_type,
const String& frame_id, const String& container_src,
const String& frame_name) { const String& container_id,
const String& container_name) {
if (!HasObserverFor(PerformanceEntry::kLongTask)) if (!HasObserverFor(PerformanceEntry::kLongTask))
return; return;
auto* entry = MakeGarbageCollected<PerformanceLongTaskTiming>( auto* entry = MakeGarbageCollected<PerformanceLongTaskTiming>(
MonotonicTimeToDOMHighResTimeStamp(start_time), MonotonicTimeToDOMHighResTimeStamp(start_time),
MonotonicTimeToDOMHighResTimeStamp(end_time), name, frame_src, frame_id, MonotonicTimeToDOMHighResTimeStamp(end_time), name, container_type,
frame_name); container_src, container_id, container_name);
NotifyObserversOfEntry(*entry); NotifyObserversOfEntry(*entry);
} }
......
...@@ -147,9 +147,10 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -147,9 +147,10 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
void AddLongTaskTiming(base::TimeTicks start_time, void AddLongTaskTiming(base::TimeTicks start_time,
base::TimeTicks end_time, base::TimeTicks end_time,
const AtomicString& name, const AtomicString& name,
const String& culprit_frame_src, const AtomicString& container_type,
const String& culprit_frame_id, const String& container_src,
const String& culprit_frame_name); const String& container_id,
const String& container_name);
// Generates and add a performance entry for the given ResourceTimingInfo. // Generates and add a performance entry for the given ResourceTimingInfo.
// |overridden_initiator_type| allows the initiator type to be overridden to // |overridden_initiator_type| allows the initiator type to be overridden to
......
...@@ -16,14 +16,13 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming( ...@@ -16,14 +16,13 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming(
double start_time, double start_time,
double end_time, double end_time,
const AtomicString& name, const AtomicString& name,
const String& culprit_frame_src, const AtomicString& culprit_type,
const String& culprit_frame_id, const String& culprit_src,
const String& culprit_frame_name) const String& culprit_id,
const String& culprit_name)
: PerformanceEntry(name, start_time, end_time) { : PerformanceEntry(name, start_time, end_time) {
// Only one possible container type exists currently: "iframe". TaskAttributionTiming* attribution_entry = TaskAttributionTiming::Create(
TaskAttributionTiming* attribution_entry = "unknown", culprit_type, culprit_src, culprit_id, culprit_name);
TaskAttributionTiming::Create("unknown", "iframe", culprit_frame_src,
culprit_frame_id, culprit_frame_name);
attribution_.push_back(*attribution_entry); attribution_.push_back(*attribution_entry);
} }
......
...@@ -22,9 +22,10 @@ class PerformanceLongTaskTiming final : public PerformanceEntry { ...@@ -22,9 +22,10 @@ class PerformanceLongTaskTiming final : public PerformanceEntry {
PerformanceLongTaskTiming(double start_time, PerformanceLongTaskTiming(double start_time,
double end_time, double end_time,
const AtomicString& name, const AtomicString& name,
const String& frame_src, const AtomicString& culprit_type,
const String& frame_id, const String& culprit_src,
const String& frame_name); const String& culprit_id,
const String& culprit_name);
AtomicString entryType() const override; AtomicString entryType() const override;
PerformanceEntryType EntryTypeEnum() const override; PerformanceEntryType EntryTypeEnum() const override;
......
...@@ -123,8 +123,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) { ...@@ -123,8 +123,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) {
// Add a long task entry, but no observer registered. // Add a long task entry, but no observer registered.
base_->AddLongTaskTiming( base_->AddLongTaskTiming(
base::TimeTicks() + base::TimeDelta::FromSecondsD(1234), base::TimeTicks() + base::TimeDelta::FromSecondsD(1234),
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "same-origin", base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "window",
"www.foo.com/bar", "", ""); "same-origin", "www.foo.com/bar", "", "");
EXPECT_FALSE(base_->HasPerformanceObserverFor(PerformanceEntry::kLongTask)); EXPECT_FALSE(base_->HasPerformanceObserverFor(PerformanceEntry::kLongTask));
EXPECT_EQ(0, NumPerformanceEntriesInObserver()); // has no effect EXPECT_EQ(0, NumPerformanceEntriesInObserver()); // has no effect
...@@ -140,8 +140,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) { ...@@ -140,8 +140,8 @@ TEST_F(PerformanceTest, AddLongTaskTiming) {
// Add a long task entry // Add a long task entry
base_->AddLongTaskTiming( base_->AddLongTaskTiming(
base::TimeTicks() + base::TimeDelta::FromSecondsD(1234), base::TimeTicks() + base::TimeDelta::FromSecondsD(1234),
base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "same-origin", base::TimeTicks() + base::TimeDelta::FromSecondsD(5678), "window",
"www.foo.com/bar", "", ""); "same-origin", "www.foo.com/bar", "", "");
EXPECT_EQ(1, NumPerformanceEntriesInObserver()); // added an entry EXPECT_EQ(1, NumPerformanceEntriesInObserver()); // added an entry
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
namespace blink { namespace blink {
TaskAttributionTiming::TaskAttributionTiming(const AtomicString& name, TaskAttributionTiming::TaskAttributionTiming(const AtomicString& name,
const String& container_type, const AtomicString& container_type,
const String& container_src, const String& container_src,
const String& container_id, const String& container_id,
const String& container_name) const String& container_name)
...@@ -31,7 +31,7 @@ PerformanceEntryType TaskAttributionTiming::EntryTypeEnum() const { ...@@ -31,7 +31,7 @@ PerformanceEntryType TaskAttributionTiming::EntryTypeEnum() const {
return PerformanceEntry::EntryType::kTaskAttribution; return PerformanceEntry::EntryType::kTaskAttribution;
} }
String TaskAttributionTiming::containerType() const { AtomicString TaskAttributionTiming::containerType() const {
return container_type_; return container_type_;
} }
......
...@@ -17,7 +17,7 @@ class TaskAttributionTiming final : public PerformanceEntry { ...@@ -17,7 +17,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
public: public:
static TaskAttributionTiming* Create(const AtomicString& type, static TaskAttributionTiming* Create(const AtomicString& type,
const String& container_type, const AtomicString& container_type,
const String& container_src, const String& container_src,
const String& container_id, const String& container_id,
const String& container_name) { const String& container_name) {
...@@ -28,7 +28,7 @@ class TaskAttributionTiming final : public PerformanceEntry { ...@@ -28,7 +28,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
AtomicString entryType() const override; AtomicString entryType() const override;
PerformanceEntryType EntryTypeEnum() const override; PerformanceEntryType EntryTypeEnum() const override;
String containerType() const; AtomicString containerType() const;
String containerSrc() const; String containerSrc() const;
String containerId() const; String containerId() const;
String containerName() const; String containerName() const;
...@@ -36,7 +36,7 @@ class TaskAttributionTiming final : public PerformanceEntry { ...@@ -36,7 +36,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
TaskAttributionTiming(const AtomicString& type, TaskAttributionTiming(const AtomicString& type,
const String& container_type, const AtomicString& container_type,
const String& container_src, const String& container_src,
const String& container_id, const String& container_id,
const String& container_name); const String& container_name);
...@@ -45,7 +45,8 @@ class TaskAttributionTiming final : public PerformanceEntry { ...@@ -45,7 +45,8 @@ class TaskAttributionTiming final : public PerformanceEntry {
private: private:
void BuildJSONValue(V8ObjectBuilder&) const override; 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_src_;
String container_id_; String container_id_;
String container_name_; String container_name_;
......
...@@ -77,6 +77,34 @@ String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner, ...@@ -77,6 +77,34 @@ String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner,
return attr_value; 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() { const AtomicString& SelfKeyword() {
DEFINE_STATIC_LOCAL(const AtomicString, kSelfAttribution, ("self")); DEFINE_STATIC_LOCAL(const AtomicString, kSelfAttribution, ("self"));
return kSelfAttribution; return kSelfAttribution;
...@@ -297,14 +325,14 @@ void WindowPerformance::ReportLongTask(base::TimeTicks start_time, ...@@ -297,14 +325,14 @@ void WindowPerformance::ReportLongTask(base::TimeTicks start_time,
DOMWindow* culprit_dom_window = attribution.second; DOMWindow* culprit_dom_window = attribution.second;
if (!culprit_dom_window || !culprit_dom_window->GetFrame() || if (!culprit_dom_window || !culprit_dom_window->GetFrame() ||
!culprit_dom_window->GetFrame()->DeprecatedLocalOwner()) { !culprit_dom_window->GetFrame()->DeprecatedLocalOwner()) {
AddLongTaskTiming(start_time, end_time, attribution.first, g_empty_string, AddLongTaskTiming(start_time, end_time, attribution.first, "window",
g_empty_string, g_empty_string); g_empty_string, g_empty_string, g_empty_string);
} else { } else {
HTMLFrameOwnerElement* frame_owner = HTMLFrameOwnerElement* frame_owner =
culprit_dom_window->GetFrame()->DeprecatedLocalOwner(); culprit_dom_window->GetFrame()->DeprecatedLocalOwner();
AddLongTaskTiming( AddLongTaskTiming(
start_time, end_time, attribution.first, start_time, end_time, attribution.first, GetFrameOwnerType(frame_owner),
GetFrameAttribute(frame_owner, html_names::kSrcAttr, false), GetFrameSrc(frame_owner),
GetFrameAttribute(frame_owner, html_names::kIdAttr, false), GetFrameAttribute(frame_owner, html_names::kIdAttr, false),
GetFrameAttribute(frame_owner, html_names::kNameAttr, true)); 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 @@ ...@@ -35,6 +35,7 @@
assert_equals(attribution.name, 'unknown'); assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0); assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0); assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, ''); assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, ''); assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, ''); assert_equals(attribution.containerSrc, '');
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
assert_equals(attribution.name, 'unknown'); assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0); assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0); assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'iframe');
assert_equals(attribution.containerId, 'child-iframe-id'); assert_equals(attribution.containerId, 'child-iframe-id');
assert_equals(attribution.containerName, 'child-iframe-name'); assert_equals(attribution.containerName, 'child-iframe-name');
assert_equals(attribution.containerSrc, assert_equals(attribution.containerSrc,
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
assert_equals(attribution.name, 'unknown'); assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0); assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0); assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'iframe');
assert_equals(attribution.containerId, 'child-iframe-id'); assert_equals(attribution.containerId, 'child-iframe-id');
assert_equals(attribution.containerName, 'child-iframe-name'); assert_equals(attribution.containerName, 'child-iframe-name');
assert_equals(attribution.containerSrc, 'resources/subframe-with-longtask.html'); assert_equals(attribution.containerSrc, 'resources/subframe-with-longtask.html');
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
assert_equals(attribution.name, 'unknown'); assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0); assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0); assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, ''); assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, ''); assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, ''); assert_equals(attribution.containerSrc, '');
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
assert_equals(e.data['entryType'], 'longtask'); assert_equals(e.data['entryType'], 'longtask');
assert_equals(e.data['frame-attribution'], 'same-origin-ancestor'); assert_equals(e.data['frame-attribution'], 'same-origin-ancestor');
assert_equals(e.data['task-attribution'], 'unknown'); assert_equals(e.data['task-attribution'], 'unknown');
assert_equals(e.data['containerType'], 'window');
assert_equals(e.data['containerId'], ''); assert_equals(e.data['containerId'], '');
assert_equals(e.data['containerName'], ''); assert_equals(e.data['containerName'], '');
assert_equals(e.data['containerSrc'], ''); assert_equals(e.data['containerSrc'], '');
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
assert_equals(attribution.name, 'unknown'); assert_equals(attribution.name, 'unknown');
assert_equals(attribution.duration, 0); assert_equals(attribution.duration, 0);
assert_equals(attribution.startTime, 0); assert_equals(attribution.startTime, 0);
assert_equals(attribution.containerType, 'window');
assert_equals(attribution.containerId, ''); assert_equals(attribution.containerId, '');
assert_equals(attribution.containerName, ''); assert_equals(attribution.containerName, '');
assert_equals(attribution.containerSrc, ''); assert_equals(attribution.containerSrc, '');
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
assert_equals(e.data['entryType'], 'longtask'); assert_equals(e.data['entryType'], 'longtask');
assert_equals(e.data['frame-attribution'], 'cross-origin-unreachable'); assert_equals(e.data['frame-attribution'], 'cross-origin-unreachable');
assert_equals(e.data['task-attribution'], 'unknown'); assert_equals(e.data['task-attribution'], 'unknown');
assert_equals(e.data['containerType'], 'window');
assert_equals(e.data['containerId'], ''); assert_equals(e.data['containerId'], '');
assert_equals(e.data['containerName'], ''); assert_equals(e.data['containerName'], '');
assert_equals(e.data['containerSrc'], ''); assert_equals(e.data['containerSrc'], '');
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
assert_equals(e.data['frame-attribution'], 'same-origin'); assert_equals(e.data['frame-attribution'], 'same-origin');
assert_equals(e.data['task-attribution'], 'unknown'); 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['containerId'], 'longtask-iframe-id');
assert_equals(e.data['containerName'], 'longtask-iframe-name'); assert_equals(e.data['containerName'], 'longtask-iframe-name');
assert_equals(e.data['containerSrc'], 'resources/subframe-with-longtask.html'); assert_equals(e.data['containerSrc'], 'resources/subframe-with-longtask.html');
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
'entryType': longtask.entryType, 'entryType': longtask.entryType,
'frame-attribution': longtask.name, 'frame-attribution': longtask.name,
'task-attribution': attribution.name, 'task-attribution': attribution.name,
'containerType': attribution.containerType,
'containerId': attribution.containerId, 'containerId': attribution.containerId,
'containerName': attribution.containerName, 'containerName': attribution.containerName,
'containerSrc': attribution.containerSrc '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