| 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 |