dom/base/nsPerformance.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsPerformance.h"
michael@0 7 #include "nsCOMPtr.h"
michael@0 8 #include "nsIHttpChannel.h"
michael@0 9 #include "nsITimedChannel.h"
michael@0 10 #include "nsDOMNavigationTiming.h"
michael@0 11 #include "nsContentUtils.h"
michael@0 12 #include "nsIScriptSecurityManager.h"
michael@0 13 #include "nsIDOMWindow.h"
michael@0 14 #include "nsIURI.h"
michael@0 15 #include "PerformanceEntry.h"
michael@0 16 #include "PerformanceResourceTiming.h"
michael@0 17 #include "mozilla/dom/PerformanceBinding.h"
michael@0 18 #include "mozilla/dom/PerformanceTimingBinding.h"
michael@0 19 #include "mozilla/dom/PerformanceNavigationBinding.h"
michael@0 20 #include "mozilla/TimeStamp.h"
michael@0 21 #include "nsThreadUtils.h"
michael@0 22
michael@0 23 using namespace mozilla;
michael@0 24
michael@0 25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceTiming, mPerformance)
michael@0 26
michael@0 27 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsPerformanceTiming, AddRef)
michael@0 28 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsPerformanceTiming, Release)
michael@0 29
michael@0 30 nsPerformanceTiming::nsPerformanceTiming(nsPerformance* aPerformance,
michael@0 31 nsITimedChannel* aChannel,
michael@0 32 nsIHttpChannel* aHttpChannel,
michael@0 33 DOMHighResTimeStamp aZeroTime)
michael@0 34 : mPerformance(aPerformance),
michael@0 35 mChannel(aChannel),
michael@0 36 mFetchStart(0.0),
michael@0 37 mZeroTime(aZeroTime),
michael@0 38 mReportCrossOriginResources(true)
michael@0 39 {
michael@0 40 MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
michael@0 41 SetIsDOMBinding();
michael@0 42
michael@0 43 if (!nsContentUtils::IsPerformanceTimingEnabled()) {
michael@0 44 mZeroTime = 0;
michael@0 45 }
michael@0 46
michael@0 47 // The aHttpChannel argument is null if this nsPerformanceTiming object
michael@0 48 // is being used for the navigation timing (document) and has a non-null
michael@0 49 // value for the resource timing (any resources within the page).
michael@0 50 if (aHttpChannel) {
michael@0 51 CheckRedirectCrossOrigin(aHttpChannel);
michael@0 52 }
michael@0 53 }
michael@0 54
michael@0 55 nsPerformanceTiming::~nsPerformanceTiming()
michael@0 56 {
michael@0 57 }
michael@0 58
michael@0 59 DOMHighResTimeStamp
michael@0 60 nsPerformanceTiming::FetchStartHighRes()
michael@0 61 {
michael@0 62 if (!mFetchStart) {
michael@0 63 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 64 return mZeroTime;
michael@0 65 }
michael@0 66 TimeStamp stamp;
michael@0 67 mChannel->GetAsyncOpen(&stamp);
michael@0 68 MOZ_ASSERT(!stamp.IsNull(), "The fetch start time stamp should always be "
michael@0 69 "valid if the performance timing is enabled");
michael@0 70 mFetchStart = (!stamp.IsNull())
michael@0 71 ? TimeStampToDOMHighRes(stamp)
michael@0 72 : 0.0;
michael@0 73 }
michael@0 74 return mFetchStart;
michael@0 75 }
michael@0 76
michael@0 77 DOMTimeMilliSec
michael@0 78 nsPerformanceTiming::FetchStart()
michael@0 79 {
michael@0 80 return static_cast<int64_t>(FetchStartHighRes());
michael@0 81 }
michael@0 82
michael@0 83 // This method will implement the timing allow check algorithm
michael@0 84 // http://w3c-test.org/webperf/specs/ResourceTiming/#timing-allow-check
michael@0 85 // https://bugzilla.mozilla.org/show_bug.cgi?id=936814
michael@0 86 void
michael@0 87 nsPerformanceTiming::CheckRedirectCrossOrigin(nsIHttpChannel* aResourceChannel)
michael@0 88 {
michael@0 89 if (!IsInitialized()) {
michael@0 90 return;
michael@0 91 }
michael@0 92 uint16_t redirectCount;
michael@0 93 mChannel->GetRedirectCount(&redirectCount);
michael@0 94 if (redirectCount == 0) {
michael@0 95 return;
michael@0 96 }
michael@0 97 nsCOMPtr<nsIURI> resourceURI, referrerURI;
michael@0 98 aResourceChannel->GetReferrer(getter_AddRefs(referrerURI));
michael@0 99 aResourceChannel->GetURI(getter_AddRefs(resourceURI));
michael@0 100 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
michael@0 101 nsresult rv = ssm->CheckSameOriginURI(resourceURI, referrerURI, false);
michael@0 102 if (!NS_SUCCEEDED(rv)) {
michael@0 103 mReportCrossOriginResources = false;
michael@0 104 }
michael@0 105 }
michael@0 106
michael@0 107 bool
michael@0 108 nsPerformanceTiming::IsSameOriginAsReferral() const
michael@0 109 {
michael@0 110 return mReportCrossOriginResources;
michael@0 111 }
michael@0 112
michael@0 113 uint16_t
michael@0 114 nsPerformanceTiming::GetRedirectCount() const
michael@0 115 {
michael@0 116 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 117 return 0;
michael@0 118 }
michael@0 119 bool sameOrigin;
michael@0 120 mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
michael@0 121 if (!sameOrigin) {
michael@0 122 return 0;
michael@0 123 }
michael@0 124 uint16_t redirectCount;
michael@0 125 mChannel->GetRedirectCount(&redirectCount);
michael@0 126 return redirectCount;
michael@0 127 }
michael@0 128
michael@0 129 /**
michael@0 130 * RedirectStartHighRes() is used by both the navigation timing and the
michael@0 131 * resource timing. Since, navigation timing and resource timing check and
michael@0 132 * interpret cross-domain redirects in a different manner,
michael@0 133 * RedirectStartHighRes() will make no checks for cross-domain redirect.
michael@0 134 * It's up to the consumers of this method (nsPerformanceTiming::RedirectStart()
michael@0 135 * and PerformanceResourceTiming::RedirectStart() to make such verifications.
michael@0 136 *
michael@0 137 * @return a valid timing if the Performance Timing is enabled
michael@0 138 */
michael@0 139 DOMHighResTimeStamp
michael@0 140 nsPerformanceTiming::RedirectStartHighRes()
michael@0 141 {
michael@0 142 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 143 return mZeroTime;
michael@0 144 }
michael@0 145 mozilla::TimeStamp stamp;
michael@0 146 mChannel->GetRedirectStart(&stamp);
michael@0 147 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 148 }
michael@0 149
michael@0 150 DOMTimeMilliSec
michael@0 151 nsPerformanceTiming::RedirectStart()
michael@0 152 {
michael@0 153 if (!IsInitialized()) {
michael@0 154 return mZeroTime;
michael@0 155 }
michael@0 156 // We have to check if all the redirect URIs had the same origin (since there
michael@0 157 // is no check in RedirectStartHighRes())
michael@0 158 bool sameOrigin;
michael@0 159 mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
michael@0 160 if (sameOrigin) {
michael@0 161 return static_cast<int64_t>(RedirectStartHighRes());
michael@0 162 }
michael@0 163 return 0;
michael@0 164 }
michael@0 165
michael@0 166 /**
michael@0 167 * RedirectEndHighRes() is used by both the navigation timing and the resource
michael@0 168 * timing. Since, navigation timing and resource timing check and interpret
michael@0 169 * cross-domain redirects in a different manner, RedirectEndHighRes() will make
michael@0 170 * no checks for cross-domain redirect. It's up to the consumers of this method
michael@0 171 * (nsPerformanceTiming::RedirectEnd() and
michael@0 172 * PerformanceResourceTiming::RedirectEnd() to make such verifications.
michael@0 173 *
michael@0 174 * @return a valid timing if the Performance Timing is enabled
michael@0 175 */
michael@0 176 DOMHighResTimeStamp
michael@0 177 nsPerformanceTiming::RedirectEndHighRes()
michael@0 178 {
michael@0 179 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 180 return mZeroTime;
michael@0 181 }
michael@0 182 mozilla::TimeStamp stamp;
michael@0 183 mChannel->GetRedirectEnd(&stamp);
michael@0 184 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 185 }
michael@0 186
michael@0 187 DOMTimeMilliSec
michael@0 188 nsPerformanceTiming::RedirectEnd()
michael@0 189 {
michael@0 190 if (!IsInitialized()) {
michael@0 191 return mZeroTime;
michael@0 192 }
michael@0 193 // We have to check if all the redirect URIs had the same origin (since there
michael@0 194 // is no check in RedirectEndHighRes())
michael@0 195 bool sameOrigin;
michael@0 196 mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
michael@0 197 if (sameOrigin) {
michael@0 198 return static_cast<int64_t>(RedirectEndHighRes());
michael@0 199 }
michael@0 200 return 0;
michael@0 201 }
michael@0 202
michael@0 203 DOMHighResTimeStamp
michael@0 204 nsPerformanceTiming::DomainLookupStartHighRes()
michael@0 205 {
michael@0 206 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 207 return mZeroTime;
michael@0 208 }
michael@0 209 mozilla::TimeStamp stamp;
michael@0 210 mChannel->GetDomainLookupStart(&stamp);
michael@0 211 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 212 }
michael@0 213
michael@0 214 DOMTimeMilliSec
michael@0 215 nsPerformanceTiming::DomainLookupStart()
michael@0 216 {
michael@0 217 return static_cast<int64_t>(DomainLookupStartHighRes());
michael@0 218 }
michael@0 219
michael@0 220 DOMHighResTimeStamp
michael@0 221 nsPerformanceTiming::DomainLookupEndHighRes()
michael@0 222 {
michael@0 223 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 224 return mZeroTime;
michael@0 225 }
michael@0 226 mozilla::TimeStamp stamp;
michael@0 227 mChannel->GetDomainLookupEnd(&stamp);
michael@0 228 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 229 }
michael@0 230
michael@0 231 DOMTimeMilliSec
michael@0 232 nsPerformanceTiming::DomainLookupEnd()
michael@0 233 {
michael@0 234 return static_cast<int64_t>(DomainLookupEndHighRes());
michael@0 235 }
michael@0 236
michael@0 237 DOMHighResTimeStamp
michael@0 238 nsPerformanceTiming::ConnectStartHighRes()
michael@0 239 {
michael@0 240 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 241 return mZeroTime;
michael@0 242 }
michael@0 243 mozilla::TimeStamp stamp;
michael@0 244 mChannel->GetConnectStart(&stamp);
michael@0 245 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 246 }
michael@0 247
michael@0 248 DOMTimeMilliSec
michael@0 249 nsPerformanceTiming::ConnectStart()
michael@0 250 {
michael@0 251 return static_cast<int64_t>(ConnectStartHighRes());
michael@0 252 }
michael@0 253
michael@0 254 DOMHighResTimeStamp
michael@0 255 nsPerformanceTiming::ConnectEndHighRes()
michael@0 256 {
michael@0 257 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 258 return mZeroTime;
michael@0 259 }
michael@0 260 mozilla::TimeStamp stamp;
michael@0 261 mChannel->GetConnectEnd(&stamp);
michael@0 262 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 263 }
michael@0 264
michael@0 265 DOMTimeMilliSec
michael@0 266 nsPerformanceTiming::ConnectEnd()
michael@0 267 {
michael@0 268 return static_cast<int64_t>(ConnectEndHighRes());
michael@0 269 }
michael@0 270
michael@0 271 DOMHighResTimeStamp
michael@0 272 nsPerformanceTiming::RequestStartHighRes()
michael@0 273 {
michael@0 274 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 275 return mZeroTime;
michael@0 276 }
michael@0 277 mozilla::TimeStamp stamp;
michael@0 278 mChannel->GetRequestStart(&stamp);
michael@0 279 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 280 }
michael@0 281
michael@0 282 DOMTimeMilliSec
michael@0 283 nsPerformanceTiming::RequestStart()
michael@0 284 {
michael@0 285 return static_cast<int64_t>(RequestStartHighRes());
michael@0 286 }
michael@0 287
michael@0 288 DOMHighResTimeStamp
michael@0 289 nsPerformanceTiming::ResponseStartHighRes()
michael@0 290 {
michael@0 291 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 292 return mZeroTime;
michael@0 293 }
michael@0 294 mozilla::TimeStamp stamp;
michael@0 295 mChannel->GetResponseStart(&stamp);
michael@0 296 mozilla::TimeStamp cacheStamp;
michael@0 297 mChannel->GetCacheReadStart(&cacheStamp);
michael@0 298 if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
michael@0 299 stamp = cacheStamp;
michael@0 300 }
michael@0 301 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 302 }
michael@0 303
michael@0 304 DOMTimeMilliSec
michael@0 305 nsPerformanceTiming::ResponseStart()
michael@0 306 {
michael@0 307 return static_cast<int64_t>(ResponseStartHighRes());
michael@0 308 }
michael@0 309
michael@0 310 DOMHighResTimeStamp
michael@0 311 nsPerformanceTiming::ResponseEndHighRes()
michael@0 312 {
michael@0 313 if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
michael@0 314 return mZeroTime;
michael@0 315 }
michael@0 316 mozilla::TimeStamp stamp;
michael@0 317 mChannel->GetResponseEnd(&stamp);
michael@0 318 mozilla::TimeStamp cacheStamp;
michael@0 319 mChannel->GetCacheReadEnd(&cacheStamp);
michael@0 320 if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
michael@0 321 stamp = cacheStamp;
michael@0 322 }
michael@0 323 return TimeStampToDOMHighResOrFetchStart(stamp);
michael@0 324 }
michael@0 325
michael@0 326 DOMTimeMilliSec
michael@0 327 nsPerformanceTiming::ResponseEnd()
michael@0 328 {
michael@0 329 return static_cast<int64_t>(ResponseEndHighRes());
michael@0 330 }
michael@0 331
michael@0 332 bool
michael@0 333 nsPerformanceTiming::IsInitialized() const
michael@0 334 {
michael@0 335 return !!mChannel;
michael@0 336 }
michael@0 337
michael@0 338 JSObject*
michael@0 339 nsPerformanceTiming::WrapObject(JSContext *cx)
michael@0 340 {
michael@0 341 return dom::PerformanceTimingBinding::Wrap(cx, this);
michael@0 342 }
michael@0 343
michael@0 344
michael@0 345 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPerformanceNavigation, mPerformance)
michael@0 346
michael@0 347 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsPerformanceNavigation, AddRef)
michael@0 348 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsPerformanceNavigation, Release)
michael@0 349
michael@0 350 nsPerformanceNavigation::nsPerformanceNavigation(nsPerformance* aPerformance)
michael@0 351 : mPerformance(aPerformance)
michael@0 352 {
michael@0 353 MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
michael@0 354 SetIsDOMBinding();
michael@0 355 }
michael@0 356
michael@0 357 nsPerformanceNavigation::~nsPerformanceNavigation()
michael@0 358 {
michael@0 359 }
michael@0 360
michael@0 361 JSObject*
michael@0 362 nsPerformanceNavigation::WrapObject(JSContext *cx)
michael@0 363 {
michael@0 364 return dom::PerformanceNavigationBinding::Wrap(cx, this);
michael@0 365 }
michael@0 366
michael@0 367
michael@0 368 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_5(nsPerformance,
michael@0 369 mWindow, mTiming,
michael@0 370 mNavigation, mEntries,
michael@0 371 mParentPerformance)
michael@0 372 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPerformance)
michael@0 373 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPerformance)
michael@0 374
michael@0 375 nsPerformance::nsPerformance(nsIDOMWindow* aWindow,
michael@0 376 nsDOMNavigationTiming* aDOMTiming,
michael@0 377 nsITimedChannel* aChannel,
michael@0 378 nsPerformance* aParentPerformance)
michael@0 379 : mWindow(aWindow),
michael@0 380 mDOMTiming(aDOMTiming),
michael@0 381 mChannel(aChannel),
michael@0 382 mParentPerformance(aParentPerformance),
michael@0 383 mBufferSizeSet(kDefaultBufferSize),
michael@0 384 mPrimaryBufferSize(kDefaultBufferSize)
michael@0 385 {
michael@0 386 MOZ_ASSERT(aWindow, "Parent window object should be provided");
michael@0 387 SetIsDOMBinding();
michael@0 388 }
michael@0 389
michael@0 390 nsPerformance::~nsPerformance()
michael@0 391 {
michael@0 392 }
michael@0 393
michael@0 394 // QueryInterface implementation for nsPerformance
michael@0 395 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPerformance)
michael@0 396 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 397 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 398 NS_INTERFACE_MAP_END
michael@0 399
michael@0 400
michael@0 401 nsPerformanceTiming*
michael@0 402 nsPerformance::Timing()
michael@0 403 {
michael@0 404 if (!mTiming) {
michael@0 405 // For navigation timing, the third argument (an nsIHtttpChannel) is null
michael@0 406 // since the cross-domain redirect were already checked.
michael@0 407 // The last argument (zero time) for performance.timing is the navigation
michael@0 408 // start value.
michael@0 409 mTiming = new nsPerformanceTiming(this, mChannel, nullptr,
michael@0 410 mDOMTiming->GetNavigationStart());
michael@0 411 }
michael@0 412 return mTiming;
michael@0 413 }
michael@0 414
michael@0 415 nsPerformanceNavigation*
michael@0 416 nsPerformance::Navigation()
michael@0 417 {
michael@0 418 if (!mNavigation) {
michael@0 419 mNavigation = new nsPerformanceNavigation(this);
michael@0 420 }
michael@0 421 return mNavigation;
michael@0 422 }
michael@0 423
michael@0 424 DOMHighResTimeStamp
michael@0 425 nsPerformance::Now()
michael@0 426 {
michael@0 427 return GetDOMTiming()->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
michael@0 428 }
michael@0 429
michael@0 430 JSObject*
michael@0 431 nsPerformance::WrapObject(JSContext *cx)
michael@0 432 {
michael@0 433 return dom::PerformanceBinding::Wrap(cx, this);
michael@0 434 }
michael@0 435
michael@0 436 void
michael@0 437 nsPerformance::GetEntries(nsTArray<nsRefPtr<PerformanceEntry> >& retval)
michael@0 438 {
michael@0 439 MOZ_ASSERT(NS_IsMainThread());
michael@0 440
michael@0 441 retval.Clear();
michael@0 442 uint32_t count = mEntries.Length();
michael@0 443 if (count > mPrimaryBufferSize) {
michael@0 444 count = mPrimaryBufferSize;
michael@0 445 }
michael@0 446 retval.AppendElements(mEntries.Elements(), count);
michael@0 447 }
michael@0 448
michael@0 449 void
michael@0 450 nsPerformance::GetEntriesByType(const nsAString& entryType,
michael@0 451 nsTArray<nsRefPtr<PerformanceEntry> >& retval)
michael@0 452 {
michael@0 453 MOZ_ASSERT(NS_IsMainThread());
michael@0 454
michael@0 455 retval.Clear();
michael@0 456 uint32_t count = mEntries.Length();
michael@0 457 for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) {
michael@0 458 if (mEntries[i]->GetEntryType().Equals(entryType)) {
michael@0 459 retval.AppendElement(mEntries[i]);
michael@0 460 }
michael@0 461 }
michael@0 462 }
michael@0 463
michael@0 464 void
michael@0 465 nsPerformance::GetEntriesByName(const nsAString& name,
michael@0 466 const mozilla::dom::Optional<nsAString>& entryType,
michael@0 467 nsTArray<nsRefPtr<PerformanceEntry> >& retval)
michael@0 468 {
michael@0 469 MOZ_ASSERT(NS_IsMainThread());
michael@0 470
michael@0 471 retval.Clear();
michael@0 472 uint32_t count = mEntries.Length();
michael@0 473 for (uint32_t i = 0 ; i < count && i < mPrimaryBufferSize ; i++) {
michael@0 474 if (mEntries[i]->GetName().Equals(name) &&
michael@0 475 (!entryType.WasPassed() ||
michael@0 476 mEntries[i]->GetEntryType().Equals(entryType.Value()))) {
michael@0 477 retval.AppendElement(mEntries[i]);
michael@0 478 }
michael@0 479 }
michael@0 480 }
michael@0 481
michael@0 482 void
michael@0 483 nsPerformance::ClearResourceTimings()
michael@0 484 {
michael@0 485 MOZ_ASSERT(NS_IsMainThread());
michael@0 486 mPrimaryBufferSize = mBufferSizeSet;
michael@0 487 mEntries.Clear();
michael@0 488 }
michael@0 489
michael@0 490 void
michael@0 491 nsPerformance::SetResourceTimingBufferSize(uint64_t maxSize)
michael@0 492 {
michael@0 493 MOZ_ASSERT(NS_IsMainThread());
michael@0 494 mBufferSizeSet = maxSize;
michael@0 495 if (mBufferSizeSet < mEntries.Length()) {
michael@0 496 // call onresourcetimingbufferfull
michael@0 497 // https://bugzilla.mozilla.org/show_bug.cgi?id=936813
michael@0 498 }
michael@0 499 }
michael@0 500
michael@0 501 /**
michael@0 502 * An entry should be added only after the resource is loaded.
michael@0 503 * This method is not thread safe and can only be called on the main thread.
michael@0 504 */
michael@0 505 void
michael@0 506 nsPerformance::AddEntry(nsIHttpChannel* channel,
michael@0 507 nsITimedChannel* timedChannel)
michael@0 508 {
michael@0 509 MOZ_ASSERT(NS_IsMainThread());
michael@0 510 // Check if resource timing is prefed off.
michael@0 511 if (!nsContentUtils::IsResourceTimingEnabled()) {
michael@0 512 return;
michael@0 513 }
michael@0 514 if (channel && timedChannel) {
michael@0 515 nsAutoCString name;
michael@0 516 nsAutoString initiatorType;
michael@0 517 nsCOMPtr<nsIURI> originalURI;
michael@0 518
michael@0 519 timedChannel->GetInitiatorType(initiatorType);
michael@0 520
michael@0 521 // According to the spec, "The name attribute must return the resolved URL
michael@0 522 // of the requested resource. This attribute must not change even if the
michael@0 523 // fetch redirected to a different URL."
michael@0 524 channel->GetOriginalURI(getter_AddRefs(originalURI));
michael@0 525 originalURI->GetSpec(name);
michael@0 526 NS_ConvertUTF8toUTF16 entryName(name);
michael@0 527
michael@0 528 // The nsITimedChannel argument will be used to gather all the timings.
michael@0 529 // The nsIHttpChannel argument will be used to check if any cross-origin
michael@0 530 // redirects occurred.
michael@0 531 // The last argument is the "zero time" (offset). Since we don't want
michael@0 532 // any offset for the resource timing, this will be set to "0" - the
michael@0 533 // resource timing returns a relative timing (no offset).
michael@0 534 nsRefPtr<nsPerformanceTiming> performanceTiming =
michael@0 535 new nsPerformanceTiming(this, timedChannel, channel,
michael@0 536 0);
michael@0 537
michael@0 538 // The PerformanceResourceTiming object will use the nsPerformanceTiming
michael@0 539 // object to get all the required timings.
michael@0 540 nsRefPtr<dom::PerformanceResourceTiming> performanceEntry =
michael@0 541 new dom::PerformanceResourceTiming(performanceTiming, this);
michael@0 542
michael@0 543 performanceEntry->SetName(entryName);
michael@0 544 performanceEntry->SetEntryType(NS_LITERAL_STRING("resource"));
michael@0 545 // If the initiator type had no valid value, then set it to the default
michael@0 546 // ("other") value.
michael@0 547 if (initiatorType.IsEmpty()) {
michael@0 548 initiatorType = NS_LITERAL_STRING("other");
michael@0 549 }
michael@0 550 performanceEntry->SetInitiatorType(initiatorType);
michael@0 551
michael@0 552 mEntries.InsertElementSorted(performanceEntry,
michael@0 553 PerformanceEntryComparator());
michael@0 554 if (mEntries.Length() > mPrimaryBufferSize) {
michael@0 555 // call onresourcetimingbufferfull
michael@0 556 // https://bugzilla.mozilla.org/show_bug.cgi?id=936813
michael@0 557 }
michael@0 558 }
michael@0 559 }
michael@0 560
michael@0 561 bool
michael@0 562 nsPerformance::PerformanceEntryComparator::Equals(
michael@0 563 const PerformanceEntry* aElem1,
michael@0 564 const PerformanceEntry* aElem2) const
michael@0 565 {
michael@0 566 NS_ABORT_IF_FALSE(aElem1 && aElem2,
michael@0 567 "Trying to compare null performance entries");
michael@0 568 return aElem1->StartTime() == aElem2->StartTime();
michael@0 569 }
michael@0 570
michael@0 571 bool
michael@0 572 nsPerformance::PerformanceEntryComparator::LessThan(
michael@0 573 const PerformanceEntry* aElem1,
michael@0 574 const PerformanceEntry* aElem2) const
michael@0 575 {
michael@0 576 NS_ABORT_IF_FALSE(aElem1 && aElem2,
michael@0 577 "Trying to compare null performance entries");
michael@0 578 return aElem1->StartTime() < aElem2->StartTime();
michael@0 579 }

mercurial