1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/base/nsPerformance.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,579 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsPerformance.h" 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsIHttpChannel.h" 1.12 +#include "nsITimedChannel.h" 1.13 +#include "nsDOMNavigationTiming.h" 1.14 +#include "nsContentUtils.h" 1.15 +#include "nsIScriptSecurityManager.h" 1.16 +#include "nsIDOMWindow.h" 1.17 +#include "nsIURI.h" 1.18 +#include "PerformanceEntry.h" 1.19 +#include "PerformanceResourceTiming.h" 1.20 +#include "mozilla/dom/PerformanceBinding.h" 1.21 +#include "mozilla/dom/PerformanceTimingBinding.h" 1.22 +#include "mozilla/dom/PerformanceNavigationBinding.h" 1.23 +#include "mozilla/TimeStamp.h" 1.24 +#include "nsThreadUtils.h" 1.25 + 1.26 +using namespace mozilla; 1.27 + 1.28 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceTiming, mPerformance) 1.29 + 1.30 +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsPerformanceTiming, AddRef) 1.31 +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsPerformanceTiming, Release) 1.32 + 1.33 +nsPerformanceTiming::nsPerformanceTiming(nsPerformance* aPerformance, 1.34 + nsITimedChannel* aChannel, 1.35 + nsIHttpChannel* aHttpChannel, 1.36 + DOMHighResTimeStamp aZeroTime) 1.37 + : mPerformance(aPerformance), 1.38 + mChannel(aChannel), 1.39 + mFetchStart(0.0), 1.40 + mZeroTime(aZeroTime), 1.41 + mReportCrossOriginResources(true) 1.42 +{ 1.43 + MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); 1.44 + SetIsDOMBinding(); 1.45 + 1.46 + if (!nsContentUtils::IsPerformanceTimingEnabled()) { 1.47 + mZeroTime = 0; 1.48 + } 1.49 + 1.50 + // The aHttpChannel argument is null if this nsPerformanceTiming object 1.51 + // is being used for the navigation timing (document) and has a non-null 1.52 + // value for the resource timing (any resources within the page). 1.53 + if (aHttpChannel) { 1.54 + CheckRedirectCrossOrigin(aHttpChannel); 1.55 + } 1.56 +} 1.57 + 1.58 +nsPerformanceTiming::~nsPerformanceTiming() 1.59 +{ 1.60 +} 1.61 + 1.62 +DOMHighResTimeStamp 1.63 +nsPerformanceTiming::FetchStartHighRes() 1.64 +{ 1.65 + if (!mFetchStart) { 1.66 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.67 + return mZeroTime; 1.68 + } 1.69 + TimeStamp stamp; 1.70 + mChannel->GetAsyncOpen(&stamp); 1.71 + MOZ_ASSERT(!stamp.IsNull(), "The fetch start time stamp should always be " 1.72 + "valid if the performance timing is enabled"); 1.73 + mFetchStart = (!stamp.IsNull()) 1.74 + ? TimeStampToDOMHighRes(stamp) 1.75 + : 0.0; 1.76 + } 1.77 + return mFetchStart; 1.78 +} 1.79 + 1.80 +DOMTimeMilliSec 1.81 +nsPerformanceTiming::FetchStart() 1.82 +{ 1.83 + return static_cast<int64_t>(FetchStartHighRes()); 1.84 +} 1.85 + 1.86 +// This method will implement the timing allow check algorithm 1.87 +// http://w3c-test.org/webperf/specs/ResourceTiming/#timing-allow-check 1.88 +// https://bugzilla.mozilla.org/show_bug.cgi?id=936814 1.89 +void 1.90 +nsPerformanceTiming::CheckRedirectCrossOrigin(nsIHttpChannel* aResourceChannel) 1.91 +{ 1.92 + if (!IsInitialized()) { 1.93 + return; 1.94 + } 1.95 + uint16_t redirectCount; 1.96 + mChannel->GetRedirectCount(&redirectCount); 1.97 + if (redirectCount == 0) { 1.98 + return; 1.99 + } 1.100 + nsCOMPtr<nsIURI> resourceURI, referrerURI; 1.101 + aResourceChannel->GetReferrer(getter_AddRefs(referrerURI)); 1.102 + aResourceChannel->GetURI(getter_AddRefs(resourceURI)); 1.103 + nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); 1.104 + nsresult rv = ssm->CheckSameOriginURI(resourceURI, referrerURI, false); 1.105 + if (!NS_SUCCEEDED(rv)) { 1.106 + mReportCrossOriginResources = false; 1.107 + } 1.108 +} 1.109 + 1.110 +bool 1.111 +nsPerformanceTiming::IsSameOriginAsReferral() const 1.112 +{ 1.113 + return mReportCrossOriginResources; 1.114 +} 1.115 + 1.116 +uint16_t 1.117 +nsPerformanceTiming::GetRedirectCount() const 1.118 +{ 1.119 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.120 + return 0; 1.121 + } 1.122 + bool sameOrigin; 1.123 + mChannel->GetAllRedirectsSameOrigin(&sameOrigin); 1.124 + if (!sameOrigin) { 1.125 + return 0; 1.126 + } 1.127 + uint16_t redirectCount; 1.128 + mChannel->GetRedirectCount(&redirectCount); 1.129 + return redirectCount; 1.130 +} 1.131 + 1.132 +/** 1.133 + * RedirectStartHighRes() is used by both the navigation timing and the 1.134 + * resource timing. Since, navigation timing and resource timing check and 1.135 + * interpret cross-domain redirects in a different manner, 1.136 + * RedirectStartHighRes() will make no checks for cross-domain redirect. 1.137 + * It's up to the consumers of this method (nsPerformanceTiming::RedirectStart() 1.138 + * and PerformanceResourceTiming::RedirectStart() to make such verifications. 1.139 + * 1.140 + * @return a valid timing if the Performance Timing is enabled 1.141 + */ 1.142 +DOMHighResTimeStamp 1.143 +nsPerformanceTiming::RedirectStartHighRes() 1.144 +{ 1.145 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.146 + return mZeroTime; 1.147 + } 1.148 + mozilla::TimeStamp stamp; 1.149 + mChannel->GetRedirectStart(&stamp); 1.150 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.151 +} 1.152 + 1.153 +DOMTimeMilliSec 1.154 +nsPerformanceTiming::RedirectStart() 1.155 +{ 1.156 + if (!IsInitialized()) { 1.157 + return mZeroTime; 1.158 + } 1.159 + // We have to check if all the redirect URIs had the same origin (since there 1.160 + // is no check in RedirectStartHighRes()) 1.161 + bool sameOrigin; 1.162 + mChannel->GetAllRedirectsSameOrigin(&sameOrigin); 1.163 + if (sameOrigin) { 1.164 + return static_cast<int64_t>(RedirectStartHighRes()); 1.165 + } 1.166 + return 0; 1.167 +} 1.168 + 1.169 +/** 1.170 + * RedirectEndHighRes() is used by both the navigation timing and the resource 1.171 + * timing. Since, navigation timing and resource timing check and interpret 1.172 + * cross-domain redirects in a different manner, RedirectEndHighRes() will make 1.173 + * no checks for cross-domain redirect. It's up to the consumers of this method 1.174 + * (nsPerformanceTiming::RedirectEnd() and 1.175 + * PerformanceResourceTiming::RedirectEnd() to make such verifications. 1.176 + * 1.177 + * @return a valid timing if the Performance Timing is enabled 1.178 + */ 1.179 +DOMHighResTimeStamp 1.180 +nsPerformanceTiming::RedirectEndHighRes() 1.181 +{ 1.182 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.183 + return mZeroTime; 1.184 + } 1.185 + mozilla::TimeStamp stamp; 1.186 + mChannel->GetRedirectEnd(&stamp); 1.187 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.188 +} 1.189 + 1.190 +DOMTimeMilliSec 1.191 +nsPerformanceTiming::RedirectEnd() 1.192 +{ 1.193 + if (!IsInitialized()) { 1.194 + return mZeroTime; 1.195 + } 1.196 + // We have to check if all the redirect URIs had the same origin (since there 1.197 + // is no check in RedirectEndHighRes()) 1.198 + bool sameOrigin; 1.199 + mChannel->GetAllRedirectsSameOrigin(&sameOrigin); 1.200 + if (sameOrigin) { 1.201 + return static_cast<int64_t>(RedirectEndHighRes()); 1.202 + } 1.203 + return 0; 1.204 +} 1.205 + 1.206 +DOMHighResTimeStamp 1.207 +nsPerformanceTiming::DomainLookupStartHighRes() 1.208 +{ 1.209 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.210 + return mZeroTime; 1.211 + } 1.212 + mozilla::TimeStamp stamp; 1.213 + mChannel->GetDomainLookupStart(&stamp); 1.214 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.215 +} 1.216 + 1.217 +DOMTimeMilliSec 1.218 +nsPerformanceTiming::DomainLookupStart() 1.219 +{ 1.220 + return static_cast<int64_t>(DomainLookupStartHighRes()); 1.221 +} 1.222 + 1.223 +DOMHighResTimeStamp 1.224 +nsPerformanceTiming::DomainLookupEndHighRes() 1.225 +{ 1.226 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.227 + return mZeroTime; 1.228 + } 1.229 + mozilla::TimeStamp stamp; 1.230 + mChannel->GetDomainLookupEnd(&stamp); 1.231 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.232 +} 1.233 + 1.234 +DOMTimeMilliSec 1.235 +nsPerformanceTiming::DomainLookupEnd() 1.236 +{ 1.237 + return static_cast<int64_t>(DomainLookupEndHighRes()); 1.238 +} 1.239 + 1.240 +DOMHighResTimeStamp 1.241 +nsPerformanceTiming::ConnectStartHighRes() 1.242 +{ 1.243 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.244 + return mZeroTime; 1.245 + } 1.246 + mozilla::TimeStamp stamp; 1.247 + mChannel->GetConnectStart(&stamp); 1.248 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.249 +} 1.250 + 1.251 +DOMTimeMilliSec 1.252 +nsPerformanceTiming::ConnectStart() 1.253 +{ 1.254 + return static_cast<int64_t>(ConnectStartHighRes()); 1.255 +} 1.256 + 1.257 +DOMHighResTimeStamp 1.258 +nsPerformanceTiming::ConnectEndHighRes() 1.259 +{ 1.260 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.261 + return mZeroTime; 1.262 + } 1.263 + mozilla::TimeStamp stamp; 1.264 + mChannel->GetConnectEnd(&stamp); 1.265 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.266 +} 1.267 + 1.268 +DOMTimeMilliSec 1.269 +nsPerformanceTiming::ConnectEnd() 1.270 +{ 1.271 + return static_cast<int64_t>(ConnectEndHighRes()); 1.272 +} 1.273 + 1.274 +DOMHighResTimeStamp 1.275 +nsPerformanceTiming::RequestStartHighRes() 1.276 +{ 1.277 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.278 + return mZeroTime; 1.279 + } 1.280 + mozilla::TimeStamp stamp; 1.281 + mChannel->GetRequestStart(&stamp); 1.282 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.283 +} 1.284 + 1.285 +DOMTimeMilliSec 1.286 +nsPerformanceTiming::RequestStart() 1.287 +{ 1.288 + return static_cast<int64_t>(RequestStartHighRes()); 1.289 +} 1.290 + 1.291 +DOMHighResTimeStamp 1.292 +nsPerformanceTiming::ResponseStartHighRes() 1.293 +{ 1.294 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.295 + return mZeroTime; 1.296 + } 1.297 + mozilla::TimeStamp stamp; 1.298 + mChannel->GetResponseStart(&stamp); 1.299 + mozilla::TimeStamp cacheStamp; 1.300 + mChannel->GetCacheReadStart(&cacheStamp); 1.301 + if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) { 1.302 + stamp = cacheStamp; 1.303 + } 1.304 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.305 +} 1.306 + 1.307 +DOMTimeMilliSec 1.308 +nsPerformanceTiming::ResponseStart() 1.309 +{ 1.310 + return static_cast<int64_t>(ResponseStartHighRes()); 1.311 +} 1.312 + 1.313 +DOMHighResTimeStamp 1.314 +nsPerformanceTiming::ResponseEndHighRes() 1.315 +{ 1.316 + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { 1.317 + return mZeroTime; 1.318 + } 1.319 + mozilla::TimeStamp stamp; 1.320 + mChannel->GetResponseEnd(&stamp); 1.321 + mozilla::TimeStamp cacheStamp; 1.322 + mChannel->GetCacheReadEnd(&cacheStamp); 1.323 + if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) { 1.324 + stamp = cacheStamp; 1.325 + } 1.326 + return TimeStampToDOMHighResOrFetchStart(stamp); 1.327 +} 1.328 + 1.329 +DOMTimeMilliSec 1.330 +nsPerformanceTiming::ResponseEnd() 1.331 +{ 1.332 + return static_cast<int64_t>(ResponseEndHighRes()); 1.333 +} 1.334 + 1.335 +bool 1.336 +nsPerformanceTiming::IsInitialized() const 1.337 +{ 1.338 + return !!mChannel; 1.339 +} 1.340 + 1.341 +JSObject* 1.342 +nsPerformanceTiming::WrapObject(JSContext *cx) 1.343 +{ 1.344 + return dom::PerformanceTimingBinding::Wrap(cx, this); 1.345 +} 1.346 + 1.347 + 1.348 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceNavigation, mPerformance) 1.349 + 1.350 +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsPerformanceNavigation, AddRef) 1.351 +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsPerformanceNavigation, Release) 1.352 + 1.353 +nsPerformanceNavigation::nsPerformanceNavigation(nsPerformance* aPerformance) 1.354 + : mPerformance(aPerformance) 1.355 +{ 1.356 + MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); 1.357 + SetIsDOMBinding(); 1.358 +} 1.359 + 1.360 +nsPerformanceNavigation::~nsPerformanceNavigation() 1.361 +{ 1.362 +} 1.363 + 1.364 +JSObject* 1.365 +nsPerformanceNavigation::WrapObject(JSContext *cx) 1.366 +{ 1.367 + return dom::PerformanceNavigationBinding::Wrap(cx, this); 1.368 +} 1.369 + 1.370 + 1.371 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_5(nsPerformance, 1.372 + mWindow, mTiming, 1.373 + mNavigation, mEntries, 1.374 + mParentPerformance) 1.375 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformance) 1.376 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformance) 1.377 + 1.378 +nsPerformance::nsPerformance(nsIDOMWindow* aWindow, 1.379 + nsDOMNavigationTiming* aDOMTiming, 1.380 + nsITimedChannel* aChannel, 1.381 + nsPerformance* aParentPerformance) 1.382 + : mWindow(aWindow), 1.383 + mDOMTiming(aDOMTiming), 1.384 + mChannel(aChannel), 1.385 + mParentPerformance(aParentPerformance), 1.386 + mBufferSizeSet(kDefaultBufferSize), 1.387 + mPrimaryBufferSize(kDefaultBufferSize) 1.388 +{ 1.389 + MOZ_ASSERT(aWindow, "Parent window object should be provided"); 1.390 + SetIsDOMBinding(); 1.391 +} 1.392 + 1.393 +nsPerformance::~nsPerformance() 1.394 +{ 1.395 +} 1.396 + 1.397 +// QueryInterface implementation for nsPerformance 1.398 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformance) 1.399 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.400 + NS_INTERFACE_MAP_ENTRY(nsISupports) 1.401 +NS_INTERFACE_MAP_END 1.402 + 1.403 + 1.404 +nsPerformanceTiming* 1.405 +nsPerformance::Timing() 1.406 +{ 1.407 + if (!mTiming) { 1.408 + // For navigation timing, the third argument (an nsIHtttpChannel) is null 1.409 + // since the cross-domain redirect were already checked. 1.410 + // The last argument (zero time) for performance.timing is the navigation 1.411 + // start value. 1.412 + mTiming = new nsPerformanceTiming(this, mChannel, nullptr, 1.413 + mDOMTiming->GetNavigationStart()); 1.414 + } 1.415 + return mTiming; 1.416 +} 1.417 + 1.418 +nsPerformanceNavigation* 1.419 +nsPerformance::Navigation() 1.420 +{ 1.421 + if (!mNavigation) { 1.422 + mNavigation = new nsPerformanceNavigation(this); 1.423 + } 1.424 + return mNavigation; 1.425 +} 1.426 + 1.427 +DOMHighResTimeStamp 1.428 +nsPerformance::Now() 1.429 +{ 1.430 + return GetDOMTiming()->TimeStampToDOMHighRes(mozilla::TimeStamp::Now()); 1.431 +} 1.432 + 1.433 +JSObject* 1.434 +nsPerformance::WrapObject(JSContext *cx) 1.435 +{ 1.436 + return dom::PerformanceBinding::Wrap(cx, this); 1.437 +} 1.438 + 1.439 +void 1.440 +nsPerformance::GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval) 1.441 +{ 1.442 + MOZ_ASSERT(NS_IsMainThread()); 1.443 + 1.444 + retval.Clear(); 1.445 + uint32_t count = mEntries.Length(); 1.446 + if (count > mPrimaryBufferSize) { 1.447 + count = mPrimaryBufferSize; 1.448 + } 1.449 + retval.AppendElements(mEntries.Elements(), count); 1.450 +} 1.451 + 1.452 +void 1.453 +nsPerformance::GetEntriesByType(const nsAString& entryType, 1.454 + nsTArray<nsRefPtr<PerformanceEntry> >& retval) 1.455 +{ 1.456 + MOZ_ASSERT(NS_IsMainThread()); 1.457 + 1.458 + retval.Clear(); 1.459 + uint32_t count = mEntries.Length(); 1.460 + for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) { 1.461 + if (mEntries[i]->GetEntryType().Equals(entryType)) { 1.462 + retval.AppendElement(mEntries[i]); 1.463 + } 1.464 + } 1.465 +} 1.466 + 1.467 +void 1.468 +nsPerformance::GetEntriesByName(const nsAString& name, 1.469 + const mozilla::dom::Optional<nsAString>& entryType, 1.470 + nsTArray<nsRefPtr<PerformanceEntry> >& retval) 1.471 +{ 1.472 + MOZ_ASSERT(NS_IsMainThread()); 1.473 + 1.474 + retval.Clear(); 1.475 + uint32_t count = mEntries.Length(); 1.476 + for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) { 1.477 + if (mEntries[i]->GetName().Equals(name) && 1.478 + (!entryType.WasPassed() || 1.479 + mEntries[i]->GetEntryType().Equals(entryType.Value()))) { 1.480 + retval.AppendElement(mEntries[i]); 1.481 + } 1.482 + } 1.483 +} 1.484 + 1.485 +void 1.486 +nsPerformance::ClearResourceTimings() 1.487 +{ 1.488 + MOZ_ASSERT(NS_IsMainThread()); 1.489 + mPrimaryBufferSize = mBufferSizeSet; 1.490 + mEntries.Clear(); 1.491 +} 1.492 + 1.493 +void 1.494 +nsPerformance::SetResourceTimingBufferSize(uint64_t maxSize) 1.495 +{ 1.496 + MOZ_ASSERT(NS_IsMainThread()); 1.497 + mBufferSizeSet = maxSize; 1.498 + if (mBufferSizeSet < mEntries.Length()) { 1.499 + // call onresourcetimingbufferfull 1.500 + // https://bugzilla.mozilla.org/show_bug.cgi?id=936813 1.501 + } 1.502 +} 1.503 + 1.504 +/** 1.505 + * An entry should be added only after the resource is loaded. 1.506 + * This method is not thread safe and can only be called on the main thread. 1.507 + */ 1.508 +void 1.509 +nsPerformance::AddEntry(nsIHttpChannel* channel, 1.510 + nsITimedChannel* timedChannel) 1.511 +{ 1.512 + MOZ_ASSERT(NS_IsMainThread()); 1.513 + // Check if resource timing is prefed off. 1.514 + if (!nsContentUtils::IsResourceTimingEnabled()) { 1.515 + return; 1.516 + } 1.517 + if (channel && timedChannel) { 1.518 + nsAutoCString name; 1.519 + nsAutoString initiatorType; 1.520 + nsCOMPtr<nsIURI> originalURI; 1.521 + 1.522 + timedChannel->GetInitiatorType(initiatorType); 1.523 + 1.524 + // According to the spec, "The name attribute must return the resolved URL 1.525 + // of the requested resource. This attribute must not change even if the 1.526 + // fetch redirected to a different URL." 1.527 + channel->GetOriginalURI(getter_AddRefs(originalURI)); 1.528 + originalURI->GetSpec(name); 1.529 + NS_ConvertUTF8toUTF16 entryName(name); 1.530 + 1.531 + // The nsITimedChannel argument will be used to gather all the timings. 1.532 + // The nsIHttpChannel argument will be used to check if any cross-origin 1.533 + // redirects occurred. 1.534 + // The last argument is the "zero time" (offset). Since we don't want 1.535 + // any offset for the resource timing, this will be set to "0" - the 1.536 + // resource timing returns a relative timing (no offset). 1.537 + nsRefPtr<nsPerformanceTiming> performanceTiming = 1.538 + new nsPerformanceTiming(this, timedChannel, channel, 1.539 + 0); 1.540 + 1.541 + // The PerformanceResourceTiming object will use the nsPerformanceTiming 1.542 + // object to get all the required timings. 1.543 + nsRefPtr<dom::PerformanceResourceTiming> performanceEntry = 1.544 + new dom::PerformanceResourceTiming(performanceTiming, this); 1.545 + 1.546 + performanceEntry->SetName(entryName); 1.547 + performanceEntry->SetEntryType(NS_LITERAL_STRING("resource")); 1.548 + // If the initiator type had no valid value, then set it to the default 1.549 + // ("other") value. 1.550 + if (initiatorType.IsEmpty()) { 1.551 + initiatorType = NS_LITERAL_STRING("other"); 1.552 + } 1.553 + performanceEntry->SetInitiatorType(initiatorType); 1.554 + 1.555 + mEntries.InsertElementSorted(performanceEntry, 1.556 + PerformanceEntryComparator()); 1.557 + if (mEntries.Length() > mPrimaryBufferSize) { 1.558 + // call onresourcetimingbufferfull 1.559 + // https://bugzilla.mozilla.org/show_bug.cgi?id=936813 1.560 + } 1.561 + } 1.562 +} 1.563 + 1.564 +bool 1.565 +nsPerformance::PerformanceEntryComparator::Equals( 1.566 + const PerformanceEntry* aElem1, 1.567 + const PerformanceEntry* aElem2) const 1.568 +{ 1.569 + NS_ABORT_IF_FALSE(aElem1 && aElem2, 1.570 + "Trying to compare null performance entries"); 1.571 + return aElem1->StartTime() == aElem2->StartTime(); 1.572 +} 1.573 + 1.574 +bool 1.575 +nsPerformance::PerformanceEntryComparator::LessThan( 1.576 + const PerformanceEntry* aElem1, 1.577 + const PerformanceEntry* aElem2) const 1.578 +{ 1.579 + NS_ABORT_IF_FALSE(aElem1 && aElem2, 1.580 + "Trying to compare null performance entries"); 1.581 + return aElem1->StartTime() < aElem2->StartTime(); 1.582 +}