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 24 matching lines...) Expand all Loading... |
35 #include "core/dom/Document.h" | 35 #include "core/dom/Document.h" |
36 #include "core/dom/DocumentTiming.h" | 36 #include "core/dom/DocumentTiming.h" |
37 #include "core/events/Event.h" | 37 #include "core/events/Event.h" |
38 #include "core/frame/LocalFrame.h" | 38 #include "core/frame/LocalFrame.h" |
39 #include "core/frame/UseCounter.h" | 39 #include "core/frame/UseCounter.h" |
40 #include "core/loader/DocumentLoadTiming.h" | 40 #include "core/loader/DocumentLoadTiming.h" |
41 #include "core/loader/DocumentLoader.h" | 41 #include "core/loader/DocumentLoader.h" |
42 #include "core/timing/PerformanceLongTaskTiming.h" | 42 #include "core/timing/PerformanceLongTaskTiming.h" |
43 #include "core/timing/PerformanceObserver.h" | 43 #include "core/timing/PerformanceObserver.h" |
44 #include "core/timing/PerformanceResourceTiming.h" | 44 #include "core/timing/PerformanceResourceTiming.h" |
45 #include "core/timing/PerformanceServerTiming.h" | |
46 #include "core/timing/PerformanceUserTiming.h" | 45 #include "core/timing/PerformanceUserTiming.h" |
47 #include "platform/RuntimeEnabledFeatures.h" | 46 #include "platform/RuntimeEnabledFeatures.h" |
48 #include "platform/loader/fetch/ResourceResponse.h" | 47 #include "platform/loader/fetch/ResourceResponse.h" |
49 #include "platform/loader/fetch/ResourceTimingInfo.h" | 48 #include "platform/loader/fetch/ResourceTimingInfo.h" |
50 #include "platform/weborigin/SecurityOrigin.h" | 49 #include "platform/weborigin/SecurityOrigin.h" |
51 #include "platform/wtf/CurrentTime.h" | 50 #include "platform/wtf/CurrentTime.h" |
52 | 51 |
53 namespace blink { | 52 namespace blink { |
54 | 53 |
55 namespace { | 54 namespace { |
56 | 55 |
57 SecurityOrigin* GetSecurityOrigin(ExecutionContext* context) { | 56 SecurityOrigin* GetSecurityOrigin(ExecutionContext* context) { |
58 if (context) | 57 if (context) |
59 return context->GetSecurityOrigin(); | 58 return context->GetSecurityOrigin(); |
60 return nullptr; | 59 return nullptr; |
61 } | 60 } |
62 | 61 |
63 } // namespace | 62 } // namespace |
64 | 63 |
65 using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>; | 64 using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>; |
66 | 65 |
67 static const size_t kDefaultResourceTimingBufferSize = 150; | 66 static const size_t kDefaultResourceTimingBufferSize = 150; |
68 static const size_t kDefaultFrameTimingBufferSize = 150; | 67 static const size_t kDefaultFrameTimingBufferSize = 150; |
69 static const size_t kServerTimingBufferSize = 150; | |
70 | 68 |
71 PerformanceBase::PerformanceBase(double time_origin, | 69 PerformanceBase::PerformanceBase(double time_origin, |
72 RefPtr<WebTaskRunner> task_runner) | 70 RefPtr<WebTaskRunner> task_runner) |
73 : frame_timing_buffer_size_(kDefaultFrameTimingBufferSize), | 71 : frame_timing_buffer_size_(kDefaultFrameTimingBufferSize), |
74 resource_timing_buffer_size_(kDefaultResourceTimingBufferSize), | 72 resource_timing_buffer_size_(kDefaultResourceTimingBufferSize), |
75 user_timing_(nullptr), | 73 user_timing_(nullptr), |
76 time_origin_(time_origin), | 74 time_origin_(time_origin), |
77 observer_filter_options_(PerformanceEntry::kInvalid), | 75 observer_filter_options_(PerformanceEntry::kInvalid), |
78 deliver_observations_timer_( | 76 deliver_observations_timer_( |
79 std::move(task_runner), | 77 std::move(task_runner), |
(...skipping 20 matching lines...) Expand all Loading... |
100 // calls this method. | 98 // calls this method. |
101 if (navigation_timing_) | 99 if (navigation_timing_) |
102 entries.push_back(navigation_timing_); | 100 entries.push_back(navigation_timing_); |
103 entries.AppendVector(frame_timing_buffer_); | 101 entries.AppendVector(frame_timing_buffer_); |
104 | 102 |
105 if (user_timing_) { | 103 if (user_timing_) { |
106 entries.AppendVector(user_timing_->GetMarks()); | 104 entries.AppendVector(user_timing_->GetMarks()); |
107 entries.AppendVector(user_timing_->GetMeasures()); | 105 entries.AppendVector(user_timing_->GetMeasures()); |
108 } | 106 } |
109 | 107 |
110 entries.AppendVector(server_timing_buffer_); | |
111 if (first_paint_timing_) | 108 if (first_paint_timing_) |
112 entries.push_back(first_paint_timing_); | 109 entries.push_back(first_paint_timing_); |
113 if (first_contentful_paint_timing_) | 110 if (first_contentful_paint_timing_) |
114 entries.push_back(first_contentful_paint_timing_); | 111 entries.push_back(first_contentful_paint_timing_); |
115 | 112 |
116 std::sort(entries.begin(), entries.end(), | 113 std::sort(entries.begin(), entries.end(), |
117 PerformanceEntry::StartTimeCompareLessThan); | 114 PerformanceEntry::StartTimeCompareLessThan); |
118 return entries; | 115 return entries; |
119 } | 116 } |
120 | 117 |
(...skipping 23 matching lines...) Expand all Loading... |
144 } | 141 } |
145 break; | 142 break; |
146 case PerformanceEntry::kMark: | 143 case PerformanceEntry::kMark: |
147 if (user_timing_) | 144 if (user_timing_) |
148 entries.AppendVector(user_timing_->GetMarks()); | 145 entries.AppendVector(user_timing_->GetMarks()); |
149 break; | 146 break; |
150 case PerformanceEntry::kMeasure: | 147 case PerformanceEntry::kMeasure: |
151 if (user_timing_) | 148 if (user_timing_) |
152 entries.AppendVector(user_timing_->GetMeasures()); | 149 entries.AppendVector(user_timing_->GetMeasures()); |
153 break; | 150 break; |
154 case PerformanceEntry::kServer: | |
155 entries.AppendVector(server_timing_buffer_); | |
156 break; | |
157 case PerformanceEntry::kPaint: | 151 case PerformanceEntry::kPaint: |
158 if (first_paint_timing_) | 152 if (first_paint_timing_) |
159 entries.push_back(first_paint_timing_); | 153 entries.push_back(first_paint_timing_); |
160 if (first_contentful_paint_timing_) | 154 if (first_contentful_paint_timing_) |
161 entries.push_back(first_contentful_paint_timing_); | 155 entries.push_back(first_contentful_paint_timing_); |
162 break; | 156 break; |
163 // Unsupported for LongTask, TaskAttribution. | 157 // Unsupported for LongTask, TaskAttribution. |
164 // Per the spec, these entries can only be accessed via | 158 // Per the spec, these entries can only be accessed via |
165 // Performance Observer. No separate buffer is maintained. | 159 // Performance Observer. No separate buffer is maintained. |
166 case PerformanceEntry::kLongTask: | 160 case PerformanceEntry::kLongTask: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 } | 203 } |
210 } | 204 } |
211 | 205 |
212 if (user_timing_) { | 206 if (user_timing_) { |
213 if (entry_type.IsNull() || type == PerformanceEntry::kMark) | 207 if (entry_type.IsNull() || type == PerformanceEntry::kMark) |
214 entries.AppendVector(user_timing_->GetMarks(name)); | 208 entries.AppendVector(user_timing_->GetMarks(name)); |
215 if (entry_type.IsNull() || type == PerformanceEntry::kMeasure) | 209 if (entry_type.IsNull() || type == PerformanceEntry::kMeasure) |
216 entries.AppendVector(user_timing_->GetMeasures(name)); | 210 entries.AppendVector(user_timing_->GetMeasures(name)); |
217 } | 211 } |
218 | 212 |
219 if (entry_type.IsNull() || type == PerformanceEntry::kServer) { | |
220 // This is inefficient, but this buffer has a max size of | |
221 // 150 entries (controlled by kServerTimingBufferSize). | |
222 for (const auto& entry : server_timing_buffer_) { | |
223 if (entry->name() == name) | |
224 entries.push_back(entry); | |
225 } | |
226 } | |
227 | |
228 std::sort(entries.begin(), entries.end(), | 213 std::sort(entries.begin(), entries.end(), |
229 PerformanceEntry::StartTimeCompareLessThan); | 214 PerformanceEntry::StartTimeCompareLessThan); |
230 return entries; | 215 return entries; |
231 } | 216 } |
232 | 217 |
233 void PerformanceBase::clearResourceTimings() { | 218 void PerformanceBase::clearResourceTimings() { |
234 resource_timing_buffer_.clear(); | 219 resource_timing_buffer_.clear(); |
235 } | 220 } |
236 | 221 |
237 void PerformanceBase::setResourceTimingBufferSize(unsigned size) { | 222 void PerformanceBase::setResourceTimingBufferSize(unsigned size) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 | 284 |
300 for (const ResourceResponse& response : redirect_chain) { | 285 for (const ResourceResponse& response : redirect_chain) { |
301 if (!PassesTimingAllowCheck(response, initiator_security_origin, | 286 if (!PassesTimingAllowCheck(response, initiator_security_origin, |
302 AtomicString(), context)) | 287 AtomicString(), context)) |
303 return false; | 288 return false; |
304 } | 289 } |
305 | 290 |
306 return true; | 291 return true; |
307 } | 292 } |
308 | 293 |
309 void PerformanceBase::AddServerTiming(const ResourceResponse& response, | |
310 ShouldAddToBuffer shouldAddToBuffer) { | |
311 if (shouldAddToBuffer == ShouldAddToBuffer::Never && | |
312 !HasObserverFor(PerformanceEntry::kServer)) { | |
313 return; | |
314 } | |
315 | |
316 ExecutionContext* context = GetExecutionContext(); | |
317 SecurityOrigin* securityOrigin = GetSecurityOrigin(context); | |
318 if (!securityOrigin) { | |
319 return; | |
320 } | |
321 bool allowTimingDetails = PassesTimingAllowCheck( | |
322 response, *securityOrigin, | |
323 response.HttpHeaderField(HTTPNames::Timing_Allow_Origin), context); | |
324 | |
325 std::unique_ptr<ServerTimingHeaderVector> headers = ParseServerTimingHeader( | |
326 response.HttpHeaderField(HTTPNames::Server_Timing)); | |
327 if ((*headers).size() == 0) { | |
328 return; | |
329 } | |
330 | |
331 PerformanceEntryVector entries; | |
332 for (const auto& header : *headers) { | |
333 PerformanceEntry* entry = PerformanceServerTiming::create( | |
334 response.Url().GetString(), header->metric, | |
335 allowTimingDetails ? header->duration : 0.0, | |
336 allowTimingDetails ? header->description : ""); | |
337 entries.push_back(*entry); | |
338 } | |
339 | |
340 NotifyObserversOfEntries(entries); | |
341 if (shouldAddToBuffer == ShouldAddToBuffer::Always && | |
342 server_timing_buffer_.size() + entries.size() <= | |
343 kServerTimingBufferSize) { | |
344 server_timing_buffer_.AppendVector(entries); | |
345 } | |
346 } | |
347 | |
348 void PerformanceBase::AddResourceTiming(const ResourceTimingInfo& info) { | 294 void PerformanceBase::AddResourceTiming(const ResourceTimingInfo& info) { |
349 if (IsResourceTimingBufferFull() && | 295 if (IsResourceTimingBufferFull() && |
350 !HasObserverFor(PerformanceEntry::kResource)) | 296 !HasObserverFor(PerformanceEntry::kResource)) |
351 return; | 297 return; |
352 ExecutionContext* context = GetExecutionContext(); | 298 ExecutionContext* context = GetExecutionContext(); |
353 SecurityOrigin* security_origin = GetSecurityOrigin(context); | 299 SecurityOrigin* security_origin = GetSecurityOrigin(context); |
354 if (!security_origin) | 300 if (!security_origin) |
355 return; | 301 return; |
356 | 302 |
357 const ResourceResponse& final_response = info.FinalResponse(); | 303 const ResourceResponse& final_response = info.FinalResponse(); |
358 bool allow_timing_details = | 304 bool allow_timing_details = |
359 PassesTimingAllowCheck(final_response, *security_origin, | 305 PassesTimingAllowCheck(final_response, *security_origin, |
360 info.OriginalTimingAllowOrigin(), context); | 306 info.OriginalTimingAllowOrigin(), context); |
361 double start_time = info.InitialTime(); | 307 double start_time = info.InitialTime(); |
362 | 308 |
| 309 PerformanceServerTimingVector serverTiming = |
| 310 PerformanceServerTiming::ParseServerTiming( |
| 311 info, allow_timing_details |
| 312 ? PerformanceServerTiming::ShouldAllowTimingDetails::Yes |
| 313 : PerformanceServerTiming::ShouldAllowTimingDetails::No); |
| 314 |
363 if (info.RedirectChain().IsEmpty()) { | 315 if (info.RedirectChain().IsEmpty()) { |
364 PerformanceEntry* entry = PerformanceResourceTiming::Create( | 316 PerformanceEntry* entry = PerformanceResourceTiming::Create( |
365 info, TimeOrigin(), start_time, allow_timing_details); | 317 info, TimeOrigin(), start_time, allow_timing_details, serverTiming); |
366 NotifyObserversOfEntry(*entry); | 318 NotifyObserversOfEntry(*entry); |
367 if (!IsResourceTimingBufferFull()) | 319 if (!IsResourceTimingBufferFull()) |
368 AddResourceTimingBuffer(*entry); | 320 AddResourceTimingBuffer(*entry); |
369 return; | 321 return; |
370 } | 322 } |
371 | 323 |
372 const Vector<ResourceResponse>& redirect_chain = info.RedirectChain(); | 324 const Vector<ResourceResponse>& redirect_chain = info.RedirectChain(); |
373 bool allow_redirect_details = AllowsTimingRedirect( | 325 bool allow_redirect_details = AllowsTimingRedirect( |
374 redirect_chain, final_response, *security_origin, context); | 326 redirect_chain, final_response, *security_origin, context); |
375 | 327 |
376 if (!allow_redirect_details) { | 328 if (!allow_redirect_details) { |
377 ResourceLoadTiming* final_timing = final_response.GetResourceLoadTiming(); | 329 ResourceLoadTiming* final_timing = final_response.GetResourceLoadTiming(); |
378 DCHECK(final_timing); | 330 DCHECK(final_timing); |
379 if (final_timing) | 331 if (final_timing) |
380 start_time = final_timing->RequestTime(); | 332 start_time = final_timing->RequestTime(); |
381 } | 333 } |
382 | 334 |
383 ResourceLoadTiming* last_redirect_timing = | 335 ResourceLoadTiming* last_redirect_timing = |
384 redirect_chain.back().GetResourceLoadTiming(); | 336 redirect_chain.back().GetResourceLoadTiming(); |
385 DCHECK(last_redirect_timing); | 337 DCHECK(last_redirect_timing); |
386 double last_redirect_end_time = last_redirect_timing->ReceiveHeadersEnd(); | 338 double last_redirect_end_time = last_redirect_timing->ReceiveHeadersEnd(); |
387 | 339 |
388 PerformanceEntry* entry = PerformanceResourceTiming::Create( | 340 PerformanceEntry* entry = PerformanceResourceTiming::Create( |
389 info, TimeOrigin(), start_time, last_redirect_end_time, | 341 info, TimeOrigin(), start_time, last_redirect_end_time, |
390 allow_timing_details, allow_redirect_details); | 342 allow_timing_details, allow_redirect_details, serverTiming); |
391 NotifyObserversOfEntry(*entry); | 343 NotifyObserversOfEntry(*entry); |
392 if (!IsResourceTimingBufferFull()) | 344 if (!IsResourceTimingBufferFull()) |
393 AddResourceTimingBuffer(*entry); | 345 AddResourceTimingBuffer(*entry); |
394 } | 346 } |
395 | 347 |
396 // Called after loadEventEnd happens. | 348 // Called after loadEventEnd happens. |
397 void PerformanceBase::NotifyNavigationTimingToObservers() { | 349 void PerformanceBase::NotifyNavigationTimingToObservers() { |
398 if (!navigation_timing_) | 350 if (!navigation_timing_) |
399 navigation_timing_ = CreateNavigationTimingInstance(); | 351 navigation_timing_ = CreateNavigationTimingInstance(); |
400 if (navigation_timing_) | 352 if (navigation_timing_) |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 557 |
606 DOMHighResTimeStamp PerformanceBase::now() const { | 558 DOMHighResTimeStamp PerformanceBase::now() const { |
607 return MonotonicTimeToDOMHighResTimeStamp(MonotonicallyIncreasingTime()); | 559 return MonotonicTimeToDOMHighResTimeStamp(MonotonicallyIncreasingTime()); |
608 } | 560 } |
609 | 561 |
610 DEFINE_TRACE(PerformanceBase) { | 562 DEFINE_TRACE(PerformanceBase) { |
611 visitor->Trace(frame_timing_buffer_); | 563 visitor->Trace(frame_timing_buffer_); |
612 visitor->Trace(resource_timing_buffer_); | 564 visitor->Trace(resource_timing_buffer_); |
613 visitor->Trace(navigation_timing_); | 565 visitor->Trace(navigation_timing_); |
614 visitor->Trace(user_timing_); | 566 visitor->Trace(user_timing_); |
615 visitor->Trace(server_timing_buffer_); | |
616 visitor->Trace(first_paint_timing_); | 567 visitor->Trace(first_paint_timing_); |
617 visitor->Trace(first_contentful_paint_timing_); | 568 visitor->Trace(first_contentful_paint_timing_); |
618 visitor->Trace(observers_); | 569 visitor->Trace(observers_); |
619 visitor->Trace(active_observers_); | 570 visitor->Trace(active_observers_); |
620 visitor->Trace(suspended_observers_); | 571 visitor->Trace(suspended_observers_); |
621 EventTargetWithInlineData::Trace(visitor); | 572 EventTargetWithInlineData::Trace(visitor); |
622 } | 573 } |
623 | 574 |
624 } // namespace blink | 575 } // namespace blink |
OLD | NEW |