| Index: third_party/WebKit/Source/core/timing/Performance.cpp
|
| diff --git a/third_party/WebKit/Source/core/timing/Performance.cpp b/third_party/WebKit/Source/core/timing/Performance.cpp
|
| index 2bf1572d39744af76477cc2abd9896f37417d6d7..e8402d527b83e817adafcd38c2ec1c91a1b20a52 100644
|
| --- a/third_party/WebKit/Source/core/timing/Performance.cpp
|
| +++ b/third_party/WebKit/Source/core/timing/Performance.cpp
|
| @@ -35,11 +35,20 @@
|
| #include "bindings/core/v8/V8ObjectBuilder.h"
|
| #include "core/dom/Document.h"
|
| #include "core/frame/LocalFrame.h"
|
| -#include "core/frame/PerformanceMonitor.h"
|
| +#include "core/frame/UseCounter.h"
|
| #include "core/loader/DocumentLoader.h"
|
| #include "core/origin_trials/OriginTrials.h"
|
| #include "core/timing/PerformanceTiming.h"
|
|
|
| +static const double kLongTaskThreshold = 0.05;
|
| +
|
| +static const char kUnknownAttribution[] = "unknown";
|
| +static const char kAmbugiousAttribution[] = "multiple-contexts";
|
| +static const char kSameOriginAttribution[] = "same-origin";
|
| +static const char kAncestorAttribution[] = "cross-origin-ancestor";
|
| +static const char kDescendantAttribution[] = "cross-origin-descendant";
|
| +static const char kCrossOriginAttribution[] = "cross-origin-unreachable";
|
| +
|
| namespace blink {
|
|
|
| static double toTimeOrigin(LocalFrame* frame) {
|
| @@ -62,11 +71,11 @@ Performance::Performance(LocalFrame* frame)
|
|
|
| Performance::~Performance() {
|
| if (frame())
|
| - PerformanceMonitor::performanceObserverRemoved(this);
|
| + frame()->performanceMonitor()->unsubscribeAll(this);
|
| }
|
|
|
| void Performance::frameDestroyed() {
|
| - PerformanceMonitor::performanceObserverRemoved(this);
|
| + frame()->performanceMonitor()->unsubscribeAll(this);
|
| DOMWindowProperty::frameDestroyed();
|
| }
|
|
|
| @@ -99,13 +108,14 @@ void Performance::updateLongTaskInstrumentation() {
|
| if (!frame()->document() ||
|
| !OriginTrials::longTaskObserverEnabled(frame()->document()))
|
| return;
|
| - LocalFrame* localRoot = frame()->localFrameRoot();
|
| - DCHECK(localRoot);
|
|
|
| - if (hasObserverFor(PerformanceEntry::LongTask))
|
| - PerformanceMonitor::performanceObserverAdded(this);
|
| - else
|
| - PerformanceMonitor::performanceObserverRemoved(this);
|
| + if (hasObserverFor(PerformanceEntry::LongTask)) {
|
| + UseCounter::count(frame()->localFrameRoot(), UseCounter::LongTaskObserver);
|
| + frame()->performanceMonitor()->subscribe(PerformanceMonitor::kLongTask,
|
| + kLongTaskThreshold, this);
|
| + } else {
|
| + frame()->performanceMonitor()->unsubscribeAll(this);
|
| + }
|
| }
|
|
|
| ScriptValue Performance::toJSONForBinding(ScriptState* scriptState) const {
|
| @@ -120,6 +130,72 @@ DEFINE_TRACE(Performance) {
|
| visitor->trace(m_timing);
|
| DOMWindowProperty::trace(visitor);
|
| PerformanceBase::trace(visitor);
|
| + PerformanceMonitor::Client::trace(visitor);
|
| +}
|
| +
|
| +static bool canAccessOrigin(Frame* frame1, Frame* frame2) {
|
| + SecurityOrigin* securityOrigin1 =
|
| + frame1->securityContext()->getSecurityOrigin();
|
| + SecurityOrigin* securityOrigin2 =
|
| + frame2->securityContext()->getSecurityOrigin();
|
| + return securityOrigin1->canAccess(securityOrigin2);
|
| +}
|
| +
|
| +/**
|
| + * Report sanitized name based on cross-origin policy.
|
| + * See detailed Security doc here: http://bit.ly/2duD3F7
|
| + */
|
| +// static
|
| +std::pair<String, DOMWindow*> Performance::sanitizedAttribution(
|
| + const HeapHashSet<Member<Frame>>& frames,
|
| + Frame* observerFrame) {
|
| + if (frames.size() == 0) {
|
| + // Unable to attribute as no script was involved.
|
| + return std::make_pair(kUnknownAttribution, nullptr);
|
| + }
|
| + if (frames.size() > 1) {
|
| + // Unable to attribute, multiple script execution contents were involved.
|
| + return std::make_pair(kAmbugiousAttribution, nullptr);
|
| + }
|
| + // Exactly one culprit location, attribute based on origin boundary.
|
| + DCHECK_EQ(1u, frames.size());
|
| + Frame* culpritFrame = *frames.begin();
|
| + DCHECK(culpritFrame);
|
| + if (canAccessOrigin(observerFrame, culpritFrame)) {
|
| + // From accessible frames or same origin, return culprit location URL.
|
| + return std::make_pair(kSameOriginAttribution, culpritFrame->domWindow());
|
| + }
|
| + // For cross-origin, if the culprit is the descendant or ancestor of
|
| + // observer then indicate the *closest* cross-origin frame between
|
| + // the observer and the culprit, in the corresponding direction.
|
| + if (culpritFrame->tree().isDescendantOf(observerFrame)) {
|
| + // If the culprit is a descendant of the observer, then walk up the tree
|
| + // from culprit to observer, and report the *last* cross-origin (from
|
| + // observer) frame. If no intermediate cross-origin frame is found, then
|
| + // report the culprit directly.
|
| + Frame* lastCrossOriginFrame = culpritFrame;
|
| + for (Frame* frame = culpritFrame; frame != observerFrame;
|
| + frame = frame->tree().parent()) {
|
| + if (!canAccessOrigin(observerFrame, frame)) {
|
| + lastCrossOriginFrame = frame;
|
| + }
|
| + }
|
| + return std::make_pair(kDescendantAttribution,
|
| + lastCrossOriginFrame->domWindow());
|
| + }
|
| + if (observerFrame->tree().isDescendantOf(culpritFrame)) {
|
| + return std::make_pair(kAncestorAttribution, nullptr);
|
| + }
|
| + return std::make_pair(kCrossOriginAttribution, nullptr);
|
| +}
|
| +
|
| +void Performance::reportLongTask(
|
| + double startTime,
|
| + double endTime,
|
| + const HeapHashSet<Member<Frame>>& contextFrames) {
|
| + std::pair<String, DOMWindow*> attribution =
|
| + Performance::sanitizedAttribution(contextFrames, frame());
|
| + addLongTaskTiming(startTime, endTime, attribution.first, attribution.second);
|
| }
|
|
|
| } // namespace blink
|
|
|