Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2012 Intel Inc. All rights reserved. | 3 * Copyright (C) 2012 Intel Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "core/timing/Performance.h" | 32 #include "core/timing/Performance.h" |
| 33 | 33 |
| 34 #include "bindings/core/v8/ScriptValue.h" | 34 #include "bindings/core/v8/ScriptValue.h" |
| 35 #include "bindings/core/v8/V8ObjectBuilder.h" | 35 #include "bindings/core/v8/V8ObjectBuilder.h" |
| 36 #include "core/dom/Document.h" | 36 #include "core/dom/Document.h" |
| 37 #include "core/frame/LocalFrame.h" | 37 #include "core/frame/LocalFrame.h" |
| 38 #include "core/frame/PerformanceMonitor.h" | 38 #include "core/frame/UseCounter.h" |
| 39 #include "core/loader/DocumentLoader.h" | 39 #include "core/loader/DocumentLoader.h" |
| 40 #include "core/origin_trials/OriginTrials.h" | 40 #include "core/origin_trials/OriginTrials.h" |
| 41 #include "core/timing/PerformanceTiming.h" | 41 #include "core/timing/PerformanceTiming.h" |
| 42 | 42 |
| 43 static const double kLongTaskThreshold = 0.05; | |
| 44 | |
| 45 static const char kUnknownAttribution[] = "unknown"; | |
| 46 static const char kAmbugiousAttribution[] = "multiple-contexts"; | |
| 47 static const char kSameOriginAttribution[] = "same-origin"; | |
| 48 static const char kAncestorAttribution[] = "cross-origin-ancestor"; | |
| 49 static const char kDescendantAttribution[] = "cross-origin-descendant"; | |
| 50 static const char kCrossOriginAttribution[] = "cross-origin-unreachable"; | |
| 51 | |
| 43 namespace blink { | 52 namespace blink { |
| 44 | 53 |
| 45 static double toTimeOrigin(LocalFrame* frame) { | 54 static double toTimeOrigin(LocalFrame* frame) { |
| 46 if (!frame) | 55 if (!frame) |
| 47 return 0.0; | 56 return 0.0; |
| 48 | 57 |
| 49 Document* document = frame->document(); | 58 Document* document = frame->document(); |
| 50 if (!document) | 59 if (!document) |
| 51 return 0.0; | 60 return 0.0; |
| 52 | 61 |
| 53 DocumentLoader* loader = document->loader(); | 62 DocumentLoader* loader = document->loader(); |
| 54 if (!loader) | 63 if (!loader) |
| 55 return 0.0; | 64 return 0.0; |
| 56 | 65 |
| 57 return loader->timing().referenceMonotonicTime(); | 66 return loader->timing().referenceMonotonicTime(); |
| 58 } | 67 } |
| 59 | 68 |
| 60 Performance::Performance(LocalFrame* frame) | 69 Performance::Performance(LocalFrame* frame) |
| 61 : PerformanceBase(toTimeOrigin(frame)), DOMWindowProperty(frame) {} | 70 : PerformanceBase(toTimeOrigin(frame)), DOMWindowProperty(frame) {} |
| 62 | 71 |
| 63 Performance::~Performance() { | 72 Performance::~Performance() {} |
| 64 if (frame()) | |
| 65 PerformanceMonitor::performanceObserverRemoved(this); | |
| 66 } | |
| 67 | |
| 68 void Performance::frameDestroyed() { | |
|
caseq
2016/11/09 00:41:11
Shouldn't you unsubscribe when frame is gone?
pfeldman
2016/11/09 01:39:14
Done.
pfeldman
2016/11/09 01:39:14
Done.
| |
| 69 PerformanceMonitor::performanceObserverRemoved(this); | |
| 70 DOMWindowProperty::frameDestroyed(); | |
| 71 } | |
| 72 | 73 |
| 73 ExecutionContext* Performance::getExecutionContext() const { | 74 ExecutionContext* Performance::getExecutionContext() const { |
| 74 if (!frame()) | 75 if (!frame()) |
| 75 return nullptr; | 76 return nullptr; |
| 76 return frame()->document(); | 77 return frame()->document(); |
| 77 } | 78 } |
| 78 | 79 |
| 79 MemoryInfo* Performance::memory() { | 80 MemoryInfo* Performance::memory() { |
| 80 return MemoryInfo::create(); | 81 return MemoryInfo::create(); |
| 81 } | 82 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 92 m_timing = PerformanceTiming::create(frame()); | 93 m_timing = PerformanceTiming::create(frame()); |
| 93 | 94 |
| 94 return m_timing.get(); | 95 return m_timing.get(); |
| 95 } | 96 } |
| 96 | 97 |
| 97 void Performance::updateLongTaskInstrumentation() { | 98 void Performance::updateLongTaskInstrumentation() { |
| 98 DCHECK(frame()); | 99 DCHECK(frame()); |
| 99 if (!frame()->document() || | 100 if (!frame()->document() || |
| 100 !OriginTrials::longTaskObserverEnabled(frame()->document())) | 101 !OriginTrials::longTaskObserverEnabled(frame()->document())) |
| 101 return; | 102 return; |
| 102 LocalFrame* localRoot = frame()->localFrameRoot(); | |
| 103 DCHECK(localRoot); | |
| 104 | 103 |
| 105 if (hasObserverFor(PerformanceEntry::LongTask)) | 104 if (hasObserverFor(PerformanceEntry::LongTask)) { |
| 106 PerformanceMonitor::performanceObserverAdded(this); | 105 UseCounter::count(frame()->localFrameRoot(), UseCounter::LongTaskObserver); |
| 107 else | 106 frame()->performanceMonitor()->subscribe(PerformanceMonitor::kLongTask, |
| 108 PerformanceMonitor::performanceObserverRemoved(this); | 107 kLongTaskThreshold, this); |
| 108 } else { | |
| 109 frame()->performanceMonitor()->unsubscribeAll(this); | |
| 110 } | |
| 109 } | 111 } |
| 110 | 112 |
| 111 ScriptValue Performance::toJSONForBinding(ScriptState* scriptState) const { | 113 ScriptValue Performance::toJSONForBinding(ScriptState* scriptState) const { |
| 112 V8ObjectBuilder result(scriptState); | 114 V8ObjectBuilder result(scriptState); |
| 113 result.add("timing", timing()->toJSONForBinding(scriptState)); | 115 result.add("timing", timing()->toJSONForBinding(scriptState)); |
| 114 result.add("navigation", navigation()->toJSONForBinding(scriptState)); | 116 result.add("navigation", navigation()->toJSONForBinding(scriptState)); |
| 115 return result.scriptValue(); | 117 return result.scriptValue(); |
| 116 } | 118 } |
| 117 | 119 |
| 118 DEFINE_TRACE(Performance) { | 120 DEFINE_TRACE(Performance) { |
| 119 visitor->trace(m_navigation); | 121 visitor->trace(m_navigation); |
| 120 visitor->trace(m_timing); | 122 visitor->trace(m_timing); |
| 121 DOMWindowProperty::trace(visitor); | 123 DOMWindowProperty::trace(visitor); |
| 122 PerformanceBase::trace(visitor); | 124 PerformanceBase::trace(visitor); |
| 125 PerformanceMonitor::Client::trace(visitor); | |
| 126 } | |
| 127 | |
| 128 static bool canAccessOrigin(Frame* frame1, Frame* frame2) { | |
| 129 SecurityOrigin* securityOrigin1 = | |
| 130 frame1->securityContext()->getSecurityOrigin(); | |
| 131 SecurityOrigin* securityOrigin2 = | |
| 132 frame2->securityContext()->getSecurityOrigin(); | |
| 133 return securityOrigin1->canAccess(securityOrigin2); | |
| 134 } | |
| 135 | |
| 136 /** | |
| 137 * Report sanitized name based on cross-origin policy. | |
| 138 * See detailed Security doc here: http://bit.ly/2duD3F7 | |
| 139 */ | |
| 140 // static | |
| 141 std::pair<String, DOMWindow*> Performance::sanitizedAttribution( | |
| 142 const HeapHashSet<Member<Frame>>& frames, | |
| 143 Frame* observerFrame) { | |
| 144 if (frames.size() == 0) { | |
| 145 // Unable to attribute as no script was involved. | |
| 146 return std::make_pair(kUnknownAttribution, nullptr); | |
| 147 } | |
| 148 if (frames.size() > 1) { | |
| 149 // Unable to attribute, multiple script execution contents were involved. | |
| 150 return std::make_pair(kAmbugiousAttribution, nullptr); | |
| 151 } | |
| 152 // Exactly one culprit location, attribute based on origin boundary. | |
| 153 DCHECK_EQ(1u, frames.size()); | |
| 154 Frame* culpritFrame = *frames.begin(); | |
| 155 DCHECK(culpritFrame); | |
| 156 if (canAccessOrigin(observerFrame, culpritFrame)) { | |
| 157 // From accessible frames or same origin, return culprit location URL. | |
| 158 return std::make_pair(kSameOriginAttribution, culpritFrame->domWindow()); | |
| 159 } | |
| 160 // For cross-origin, if the culprit is the descendant or ancestor of | |
| 161 // observer then indicate the *closest* cross-origin frame between | |
| 162 // the observer and the culprit, in the corresponding direction. | |
| 163 if (culpritFrame->tree().isDescendantOf(observerFrame)) { | |
| 164 // If the culprit is a descendant of the observer, then walk up the tree | |
| 165 // from culprit to observer, and report the *last* cross-origin (from | |
| 166 // observer) frame. If no intermediate cross-origin frame is found, then | |
| 167 // report the culprit directly. | |
| 168 Frame* lastCrossOriginFrame = culpritFrame; | |
| 169 for (Frame* frame = culpritFrame; frame != observerFrame; | |
| 170 frame = frame->tree().parent()) { | |
| 171 if (!canAccessOrigin(observerFrame, frame)) { | |
| 172 lastCrossOriginFrame = frame; | |
| 173 } | |
| 174 } | |
| 175 return std::make_pair(kDescendantAttribution, | |
| 176 lastCrossOriginFrame->domWindow()); | |
| 177 } | |
| 178 if (observerFrame->tree().isDescendantOf(culpritFrame)) { | |
| 179 return std::make_pair(kAncestorAttribution, nullptr); | |
| 180 } | |
| 181 return std::make_pair(kCrossOriginAttribution, nullptr); | |
| 182 } | |
| 183 | |
| 184 void Performance::reportLongTask( | |
| 185 double startTime, | |
| 186 double endTime, | |
| 187 const HeapHashSet<Member<Frame>>& contextFrames) { | |
| 188 std::pair<String, DOMWindow*> attribution = | |
| 189 Performance::sanitizedAttribution(contextFrames, frame()); | |
|
caseq
2016/11/09 00:41:12
frame() can be null here, right?
pfeldman
2016/11/09 01:39:14
Not anymore.
| |
| 190 addLongTaskTiming(startTime, endTime, attribution.first, attribution.second); | |
| 123 } | 191 } |
| 124 | 192 |
| 125 } // namespace blink | 193 } // namespace blink |
| OLD | NEW |