netwerk/base/src/nsLoadGroup.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim: set sw=4 ts=4 sts=4 et cin: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "mozilla/DebugOnly.h"
michael@0 8
michael@0 9 #include "nsLoadGroup.h"
michael@0 10
michael@0 11 #include "nsArrayEnumerator.h"
michael@0 12 #include "nsCOMArray.h"
michael@0 13 #include "nsCOMPtr.h"
michael@0 14 #include "prlog.h"
michael@0 15 #include "nsString.h"
michael@0 16 #include "nsTArray.h"
michael@0 17 #include "mozilla/Atomics.h"
michael@0 18 #include "mozilla/Telemetry.h"
michael@0 19 #include "nsAutoPtr.h"
michael@0 20 #include "mozilla/net/PSpdyPush.h"
michael@0 21 #include "nsITimedChannel.h"
michael@0 22 #include "nsIInterfaceRequestor.h"
michael@0 23 #include "nsIRequestObserver.h"
michael@0 24 #include "CacheObserver.h"
michael@0 25 #include "MainThreadUtils.h"
michael@0 26
michael@0 27 using namespace mozilla;
michael@0 28 using namespace mozilla::net;
michael@0 29
michael@0 30 #if defined(PR_LOGGING)
michael@0 31 //
michael@0 32 // Log module for nsILoadGroup logging...
michael@0 33 //
michael@0 34 // To enable logging (see prlog.h for full details):
michael@0 35 //
michael@0 36 // set NSPR_LOG_MODULES=LoadGroup:5
michael@0 37 // set NSPR_LOG_FILE=nspr.log
michael@0 38 //
michael@0 39 // this enables PR_LOG_DEBUG level information and places all output in
michael@0 40 // the file nspr.log
michael@0 41 //
michael@0 42 static PRLogModuleInfo* gLoadGroupLog = nullptr;
michael@0 43 #endif
michael@0 44
michael@0 45 #undef LOG
michael@0 46 #define LOG(args) PR_LOG(gLoadGroupLog, PR_LOG_DEBUG, args)
michael@0 47
michael@0 48 ////////////////////////////////////////////////////////////////////////////////
michael@0 49
michael@0 50 class RequestMapEntry : public PLDHashEntryHdr
michael@0 51 {
michael@0 52 public:
michael@0 53 RequestMapEntry(nsIRequest *aRequest) :
michael@0 54 mKey(aRequest)
michael@0 55 {
michael@0 56 }
michael@0 57
michael@0 58 nsCOMPtr<nsIRequest> mKey;
michael@0 59 };
michael@0 60
michael@0 61 static bool
michael@0 62 RequestHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
michael@0 63 const void *key)
michael@0 64 {
michael@0 65 const RequestMapEntry *e =
michael@0 66 static_cast<const RequestMapEntry *>(entry);
michael@0 67 const nsIRequest *request = static_cast<const nsIRequest *>(key);
michael@0 68
michael@0 69 return e->mKey == request;
michael@0 70 }
michael@0 71
michael@0 72 static void
michael@0 73 RequestHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
michael@0 74 {
michael@0 75 RequestMapEntry *e = static_cast<RequestMapEntry *>(entry);
michael@0 76
michael@0 77 // An entry is being cleared, let the entry do its own cleanup.
michael@0 78 e->~RequestMapEntry();
michael@0 79 }
michael@0 80
michael@0 81 static bool
michael@0 82 RequestHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
michael@0 83 const void *key)
michael@0 84 {
michael@0 85 const nsIRequest *const_request = static_cast<const nsIRequest *>(key);
michael@0 86 nsIRequest *request = const_cast<nsIRequest *>(const_request);
michael@0 87
michael@0 88 // Initialize the entry with placement new
michael@0 89 new (entry) RequestMapEntry(request);
michael@0 90 return true;
michael@0 91 }
michael@0 92
michael@0 93
michael@0 94 static void
michael@0 95 RescheduleRequest(nsIRequest *aRequest, int32_t delta)
michael@0 96 {
michael@0 97 nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aRequest);
michael@0 98 if (p)
michael@0 99 p->AdjustPriority(delta);
michael@0 100 }
michael@0 101
michael@0 102 static PLDHashOperator
michael@0 103 RescheduleRequests(PLDHashTable *table, PLDHashEntryHdr *hdr,
michael@0 104 uint32_t number, void *arg)
michael@0 105 {
michael@0 106 RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr);
michael@0 107 int32_t *delta = static_cast<int32_t *>(arg);
michael@0 108
michael@0 109 RescheduleRequest(e->mKey, *delta);
michael@0 110 return PL_DHASH_NEXT;
michael@0 111 }
michael@0 112
michael@0 113
michael@0 114 nsLoadGroup::nsLoadGroup(nsISupports* outer)
michael@0 115 : mForegroundCount(0)
michael@0 116 , mLoadFlags(LOAD_NORMAL)
michael@0 117 , mDefaultLoadFlags(0)
michael@0 118 , mStatus(NS_OK)
michael@0 119 , mPriority(PRIORITY_NORMAL)
michael@0 120 , mIsCanceling(false)
michael@0 121 , mDefaultLoadIsTimed(false)
michael@0 122 , mTimedRequests(0)
michael@0 123 , mCachedRequests(0)
michael@0 124 , mTimedNonCachedRequestsUntilOnEndPageLoad(0)
michael@0 125 {
michael@0 126 NS_INIT_AGGREGATED(outer);
michael@0 127
michael@0 128 #if defined(PR_LOGGING)
michael@0 129 // Initialize the global PRLogModule for nsILoadGroup logging
michael@0 130 if (nullptr == gLoadGroupLog)
michael@0 131 gLoadGroupLog = PR_NewLogModule("LoadGroup");
michael@0 132 #endif
michael@0 133
michael@0 134 LOG(("LOADGROUP [%x]: Created.\n", this));
michael@0 135
michael@0 136 // Initialize the ops in the hash to null to make sure we get
michael@0 137 // consistent errors if someone fails to call ::Init() on an
michael@0 138 // nsLoadGroup.
michael@0 139 mRequests.ops = nullptr;
michael@0 140 }
michael@0 141
michael@0 142 nsLoadGroup::~nsLoadGroup()
michael@0 143 {
michael@0 144 DebugOnly<nsresult> rv = Cancel(NS_BINDING_ABORTED);
michael@0 145 NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed");
michael@0 146
michael@0 147 if (mRequests.ops) {
michael@0 148 PL_DHashTableFinish(&mRequests);
michael@0 149 }
michael@0 150
michael@0 151 mDefaultLoadRequest = 0;
michael@0 152
michael@0 153 LOG(("LOADGROUP [%x]: Destroyed.\n", this));
michael@0 154 }
michael@0 155
michael@0 156
michael@0 157 ////////////////////////////////////////////////////////////////////////////////
michael@0 158 // nsISupports methods:
michael@0 159
michael@0 160 NS_IMPL_AGGREGATED(nsLoadGroup)
michael@0 161 NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsLoadGroup)
michael@0 162 NS_INTERFACE_MAP_ENTRY(nsILoadGroup)
michael@0 163 NS_INTERFACE_MAP_ENTRY(nsPILoadGroupInternal)
michael@0 164 NS_INTERFACE_MAP_ENTRY(nsILoadGroupChild)
michael@0 165 NS_INTERFACE_MAP_ENTRY(nsIRequest)
michael@0 166 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
michael@0 167 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 168 NS_INTERFACE_MAP_END
michael@0 169
michael@0 170 ////////////////////////////////////////////////////////////////////////////////
michael@0 171 // nsIRequest methods:
michael@0 172
michael@0 173 NS_IMETHODIMP
michael@0 174 nsLoadGroup::GetName(nsACString &result)
michael@0 175 {
michael@0 176 // XXX is this the right "name" for a load group?
michael@0 177
michael@0 178 if (!mDefaultLoadRequest) {
michael@0 179 result.Truncate();
michael@0 180 return NS_OK;
michael@0 181 }
michael@0 182
michael@0 183 return mDefaultLoadRequest->GetName(result);
michael@0 184 }
michael@0 185
michael@0 186 NS_IMETHODIMP
michael@0 187 nsLoadGroup::IsPending(bool *aResult)
michael@0 188 {
michael@0 189 *aResult = (mForegroundCount > 0) ? true : false;
michael@0 190 return NS_OK;
michael@0 191 }
michael@0 192
michael@0 193 NS_IMETHODIMP
michael@0 194 nsLoadGroup::GetStatus(nsresult *status)
michael@0 195 {
michael@0 196 if (NS_SUCCEEDED(mStatus) && mDefaultLoadRequest)
michael@0 197 return mDefaultLoadRequest->GetStatus(status);
michael@0 198
michael@0 199 *status = mStatus;
michael@0 200 return NS_OK;
michael@0 201 }
michael@0 202
michael@0 203 // PLDHashTable enumeration callback that appends strong references to
michael@0 204 // all nsIRequest to an nsTArray<nsIRequest*>.
michael@0 205 static PLDHashOperator
michael@0 206 AppendRequestsToArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
michael@0 207 uint32_t number, void *arg)
michael@0 208 {
michael@0 209 RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr);
michael@0 210 nsTArray<nsIRequest*> *array = static_cast<nsTArray<nsIRequest*> *>(arg);
michael@0 211
michael@0 212 nsIRequest *request = e->mKey;
michael@0 213 NS_ASSERTION(request, "What? Null key in pldhash entry?");
michael@0 214
michael@0 215 bool ok = array->AppendElement(request) != nullptr;
michael@0 216
michael@0 217 if (!ok) {
michael@0 218 return PL_DHASH_STOP;
michael@0 219 }
michael@0 220
michael@0 221 NS_ADDREF(request);
michael@0 222
michael@0 223 return PL_DHASH_NEXT;
michael@0 224 }
michael@0 225
michael@0 226 NS_IMETHODIMP
michael@0 227 nsLoadGroup::Cancel(nsresult status)
michael@0 228 {
michael@0 229 MOZ_ASSERT(NS_IsMainThread());
michael@0 230
michael@0 231 NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
michael@0 232 nsresult rv;
michael@0 233 uint32_t count = mRequests.entryCount;
michael@0 234
michael@0 235 nsAutoTArray<nsIRequest*, 8> requests;
michael@0 236
michael@0 237 PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray,
michael@0 238 static_cast<nsTArray<nsIRequest*> *>(&requests));
michael@0 239
michael@0 240 if (requests.Length() != count) {
michael@0 241 for (uint32_t i = 0, len = requests.Length(); i < len; ++i) {
michael@0 242 NS_RELEASE(requests[i]);
michael@0 243 }
michael@0 244
michael@0 245 return NS_ERROR_OUT_OF_MEMORY;
michael@0 246 }
michael@0 247
michael@0 248 // set the load group status to our cancel status while we cancel
michael@0 249 // all our requests...once the cancel is done, we'll reset it...
michael@0 250 //
michael@0 251 mStatus = status;
michael@0 252
michael@0 253 // Set the flag indicating that the loadgroup is being canceled... This
michael@0 254 // prevents any new channels from being added during the operation.
michael@0 255 //
michael@0 256 mIsCanceling = true;
michael@0 257
michael@0 258 nsresult firstError = NS_OK;
michael@0 259
michael@0 260 while (count > 0) {
michael@0 261 nsIRequest* request = requests.ElementAt(--count);
michael@0 262
michael@0 263 NS_ASSERTION(request, "NULL request found in list.");
michael@0 264
michael@0 265 RequestMapEntry *entry =
michael@0 266 static_cast<RequestMapEntry *>
michael@0 267 (PL_DHashTableOperate(&mRequests, request,
michael@0 268 PL_DHASH_LOOKUP));
michael@0 269
michael@0 270 if (PL_DHASH_ENTRY_IS_FREE(entry)) {
michael@0 271 // |request| was removed already
michael@0 272
michael@0 273 NS_RELEASE(request);
michael@0 274
michael@0 275 continue;
michael@0 276 }
michael@0 277
michael@0 278 #if defined(PR_LOGGING)
michael@0 279 nsAutoCString nameStr;
michael@0 280 request->GetName(nameStr);
michael@0 281 LOG(("LOADGROUP [%x]: Canceling request %x %s.\n",
michael@0 282 this, request, nameStr.get()));
michael@0 283 #endif
michael@0 284
michael@0 285 //
michael@0 286 // Remove the request from the load group... This may cause
michael@0 287 // the OnStopRequest notification to fire...
michael@0 288 //
michael@0 289 // XXX: What should the context be?
michael@0 290 //
michael@0 291 (void)RemoveRequest(request, nullptr, status);
michael@0 292
michael@0 293 // Cancel the request...
michael@0 294 rv = request->Cancel(status);
michael@0 295
michael@0 296 // Remember the first failure and return it...
michael@0 297 if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
michael@0 298 firstError = rv;
michael@0 299
michael@0 300 NS_RELEASE(request);
michael@0 301 }
michael@0 302
michael@0 303 #if defined(DEBUG)
michael@0 304 NS_ASSERTION(mRequests.entryCount == 0, "Request list is not empty.");
michael@0 305 NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
michael@0 306 #endif
michael@0 307
michael@0 308 mStatus = NS_OK;
michael@0 309 mIsCanceling = false;
michael@0 310
michael@0 311 return firstError;
michael@0 312 }
michael@0 313
michael@0 314
michael@0 315 NS_IMETHODIMP
michael@0 316 nsLoadGroup::Suspend()
michael@0 317 {
michael@0 318 nsresult rv, firstError;
michael@0 319 uint32_t count = mRequests.entryCount;
michael@0 320
michael@0 321 nsAutoTArray<nsIRequest*, 8> requests;
michael@0 322
michael@0 323 PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray,
michael@0 324 static_cast<nsTArray<nsIRequest*> *>(&requests));
michael@0 325
michael@0 326 if (requests.Length() != count) {
michael@0 327 for (uint32_t i = 0, len = requests.Length(); i < len; ++i) {
michael@0 328 NS_RELEASE(requests[i]);
michael@0 329 }
michael@0 330
michael@0 331 return NS_ERROR_OUT_OF_MEMORY;
michael@0 332 }
michael@0 333
michael@0 334 firstError = NS_OK;
michael@0 335 //
michael@0 336 // Operate the elements from back to front so that if items get
michael@0 337 // get removed from the list it won't affect our iteration
michael@0 338 //
michael@0 339 while (count > 0) {
michael@0 340 nsIRequest* request = requests.ElementAt(--count);
michael@0 341
michael@0 342 NS_ASSERTION(request, "NULL request found in list.");
michael@0 343 if (!request)
michael@0 344 continue;
michael@0 345
michael@0 346 #if defined(PR_LOGGING)
michael@0 347 nsAutoCString nameStr;
michael@0 348 request->GetName(nameStr);
michael@0 349 LOG(("LOADGROUP [%x]: Suspending request %x %s.\n",
michael@0 350 this, request, nameStr.get()));
michael@0 351 #endif
michael@0 352
michael@0 353 // Suspend the request...
michael@0 354 rv = request->Suspend();
michael@0 355
michael@0 356 // Remember the first failure and return it...
michael@0 357 if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
michael@0 358 firstError = rv;
michael@0 359
michael@0 360 NS_RELEASE(request);
michael@0 361 }
michael@0 362
michael@0 363 return firstError;
michael@0 364 }
michael@0 365
michael@0 366
michael@0 367 NS_IMETHODIMP
michael@0 368 nsLoadGroup::Resume()
michael@0 369 {
michael@0 370 nsresult rv, firstError;
michael@0 371 uint32_t count = mRequests.entryCount;
michael@0 372
michael@0 373 nsAutoTArray<nsIRequest*, 8> requests;
michael@0 374
michael@0 375 PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray,
michael@0 376 static_cast<nsTArray<nsIRequest*> *>(&requests));
michael@0 377
michael@0 378 if (requests.Length() != count) {
michael@0 379 for (uint32_t i = 0, len = requests.Length(); i < len; ++i) {
michael@0 380 NS_RELEASE(requests[i]);
michael@0 381 }
michael@0 382
michael@0 383 return NS_ERROR_OUT_OF_MEMORY;
michael@0 384 }
michael@0 385
michael@0 386 firstError = NS_OK;
michael@0 387 //
michael@0 388 // Operate the elements from back to front so that if items get
michael@0 389 // get removed from the list it won't affect our iteration
michael@0 390 //
michael@0 391 while (count > 0) {
michael@0 392 nsIRequest* request = requests.ElementAt(--count);
michael@0 393
michael@0 394 NS_ASSERTION(request, "NULL request found in list.");
michael@0 395 if (!request)
michael@0 396 continue;
michael@0 397
michael@0 398 #if defined(PR_LOGGING)
michael@0 399 nsAutoCString nameStr;
michael@0 400 request->GetName(nameStr);
michael@0 401 LOG(("LOADGROUP [%x]: Resuming request %x %s.\n",
michael@0 402 this, request, nameStr.get()));
michael@0 403 #endif
michael@0 404
michael@0 405 // Resume the request...
michael@0 406 rv = request->Resume();
michael@0 407
michael@0 408 // Remember the first failure and return it...
michael@0 409 if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
michael@0 410 firstError = rv;
michael@0 411
michael@0 412 NS_RELEASE(request);
michael@0 413 }
michael@0 414
michael@0 415 return firstError;
michael@0 416 }
michael@0 417
michael@0 418 NS_IMETHODIMP
michael@0 419 nsLoadGroup::GetLoadFlags(uint32_t *aLoadFlags)
michael@0 420 {
michael@0 421 *aLoadFlags = mLoadFlags;
michael@0 422 return NS_OK;
michael@0 423 }
michael@0 424
michael@0 425 NS_IMETHODIMP
michael@0 426 nsLoadGroup::SetLoadFlags(uint32_t aLoadFlags)
michael@0 427 {
michael@0 428 mLoadFlags = aLoadFlags;
michael@0 429 return NS_OK;
michael@0 430 }
michael@0 431
michael@0 432 NS_IMETHODIMP
michael@0 433 nsLoadGroup::GetLoadGroup(nsILoadGroup **loadGroup)
michael@0 434 {
michael@0 435 *loadGroup = mLoadGroup;
michael@0 436 NS_IF_ADDREF(*loadGroup);
michael@0 437 return NS_OK;
michael@0 438 }
michael@0 439
michael@0 440 NS_IMETHODIMP
michael@0 441 nsLoadGroup::SetLoadGroup(nsILoadGroup *loadGroup)
michael@0 442 {
michael@0 443 mLoadGroup = loadGroup;
michael@0 444 return NS_OK;
michael@0 445 }
michael@0 446
michael@0 447 ////////////////////////////////////////////////////////////////////////////////
michael@0 448 // nsILoadGroup methods:
michael@0 449
michael@0 450 NS_IMETHODIMP
michael@0 451 nsLoadGroup::GetDefaultLoadRequest(nsIRequest * *aRequest)
michael@0 452 {
michael@0 453 *aRequest = mDefaultLoadRequest;
michael@0 454 NS_IF_ADDREF(*aRequest);
michael@0 455 return NS_OK;
michael@0 456 }
michael@0 457
michael@0 458 NS_IMETHODIMP
michael@0 459 nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest)
michael@0 460 {
michael@0 461 mDefaultLoadRequest = aRequest;
michael@0 462 // Inherit the group load flags from the default load request
michael@0 463 if (mDefaultLoadRequest) {
michael@0 464 mDefaultLoadRequest->GetLoadFlags(&mLoadFlags);
michael@0 465 //
michael@0 466 // Mask off any bits that are not part of the nsIRequest flags.
michael@0 467 // in particular, nsIChannel::LOAD_DOCUMENT_URI...
michael@0 468 //
michael@0 469 mLoadFlags &= nsIRequest::LOAD_REQUESTMASK;
michael@0 470
michael@0 471 nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(aRequest);
michael@0 472 mDefaultLoadIsTimed = timedChannel != nullptr;
michael@0 473 if (mDefaultLoadIsTimed) {
michael@0 474 timedChannel->GetChannelCreation(&mDefaultRequestCreationTime);
michael@0 475 timedChannel->SetTimingEnabled(true);
michael@0 476 }
michael@0 477 }
michael@0 478 // Else, do not change the group's load flags (see bug 95981)
michael@0 479 return NS_OK;
michael@0 480 }
michael@0 481
michael@0 482 NS_IMETHODIMP
michael@0 483 nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
michael@0 484 {
michael@0 485 nsresult rv;
michael@0 486
michael@0 487 #if defined(PR_LOGGING)
michael@0 488 {
michael@0 489 nsAutoCString nameStr;
michael@0 490 request->GetName(nameStr);
michael@0 491 LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n",
michael@0 492 this, request, nameStr.get(), mRequests.entryCount));
michael@0 493 }
michael@0 494 #endif /* PR_LOGGING */
michael@0 495
michael@0 496 #ifdef DEBUG
michael@0 497 {
michael@0 498 RequestMapEntry *entry =
michael@0 499 static_cast<RequestMapEntry *>
michael@0 500 (PL_DHashTableOperate(&mRequests, request,
michael@0 501 PL_DHASH_LOOKUP));
michael@0 502
michael@0 503 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(entry),
michael@0 504 "Entry added to loadgroup twice, don't do that");
michael@0 505 }
michael@0 506 #endif
michael@0 507
michael@0 508 //
michael@0 509 // Do not add the channel, if the loadgroup is being canceled...
michael@0 510 //
michael@0 511 if (mIsCanceling) {
michael@0 512
michael@0 513 #if defined(PR_LOGGING)
michael@0 514 LOG(("LOADGROUP [%x]: AddChannel() ABORTED because LoadGroup is"
michael@0 515 " being canceled!!\n", this));
michael@0 516 #endif /* PR_LOGGING */
michael@0 517
michael@0 518 return NS_BINDING_ABORTED;
michael@0 519 }
michael@0 520
michael@0 521 nsLoadFlags flags;
michael@0 522 // if the request is the default load request or if the default
michael@0 523 // load request is null, then the load group should inherit its
michael@0 524 // load flags from the request.
michael@0 525 if (mDefaultLoadRequest == request || !mDefaultLoadRequest)
michael@0 526 rv = request->GetLoadFlags(&flags);
michael@0 527 else
michael@0 528 rv = MergeLoadFlags(request, flags);
michael@0 529 if (NS_FAILED(rv)) return rv;
michael@0 530
michael@0 531 //
michael@0 532 // Add the request to the list of active requests...
michael@0 533 //
michael@0 534
michael@0 535 RequestMapEntry *entry =
michael@0 536 static_cast<RequestMapEntry *>
michael@0 537 (PL_DHashTableOperate(&mRequests, request,
michael@0 538 PL_DHASH_ADD));
michael@0 539
michael@0 540 if (!entry) {
michael@0 541 return NS_ERROR_OUT_OF_MEMORY;
michael@0 542 }
michael@0 543
michael@0 544 if (mPriority != 0)
michael@0 545 RescheduleRequest(request, mPriority);
michael@0 546
michael@0 547 nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request);
michael@0 548 if (timedChannel)
michael@0 549 timedChannel->SetTimingEnabled(true);
michael@0 550
michael@0 551 if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
michael@0 552 // Update the count of foreground URIs..
michael@0 553 mForegroundCount += 1;
michael@0 554
michael@0 555 //
michael@0 556 // Fire the OnStartRequest notification out to the observer...
michael@0 557 //
michael@0 558 // If the notification fails then DO NOT add the request to
michael@0 559 // the load group.
michael@0 560 //
michael@0 561 nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
michael@0 562 if (observer) {
michael@0 563 LOG(("LOADGROUP [%x]: Firing OnStartRequest for request %x."
michael@0 564 "(foreground count=%d).\n", this, request, mForegroundCount));
michael@0 565
michael@0 566 rv = observer->OnStartRequest(request, ctxt);
michael@0 567 if (NS_FAILED(rv)) {
michael@0 568 LOG(("LOADGROUP [%x]: OnStartRequest for request %x FAILED.\n",
michael@0 569 this, request));
michael@0 570 //
michael@0 571 // The URI load has been canceled by the observer. Clean up
michael@0 572 // the damage...
michael@0 573 //
michael@0 574
michael@0 575 PL_DHashTableOperate(&mRequests, request, PL_DHASH_REMOVE);
michael@0 576
michael@0 577 rv = NS_OK;
michael@0 578
michael@0 579 mForegroundCount -= 1;
michael@0 580 }
michael@0 581 }
michael@0 582
michael@0 583 // Ensure that we're part of our loadgroup while pending
michael@0 584 if (mForegroundCount == 1 && mLoadGroup) {
michael@0 585 mLoadGroup->AddRequest(this, nullptr);
michael@0 586 }
michael@0 587
michael@0 588 }
michael@0 589
michael@0 590 return rv;
michael@0 591 }
michael@0 592
michael@0 593 NS_IMETHODIMP
michael@0 594 nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
michael@0 595 nsresult aStatus)
michael@0 596 {
michael@0 597 NS_ENSURE_ARG_POINTER(request);
michael@0 598 nsresult rv;
michael@0 599
michael@0 600 #if defined(PR_LOGGING)
michael@0 601 {
michael@0 602 nsAutoCString nameStr;
michael@0 603 request->GetName(nameStr);
michael@0 604 LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n",
michael@0 605 this, request, nameStr.get(), aStatus, mRequests.entryCount-1));
michael@0 606 }
michael@0 607 #endif
michael@0 608
michael@0 609 // Make sure we have a owning reference to the request we're about
michael@0 610 // to remove.
michael@0 611
michael@0 612 nsCOMPtr<nsIRequest> kungFuDeathGrip(request);
michael@0 613
michael@0 614 //
michael@0 615 // Remove the request from the group. If this fails, it means that
michael@0 616 // the request was *not* in the group so do not update the foreground
michael@0 617 // count or it will get messed up...
michael@0 618 //
michael@0 619 RequestMapEntry *entry =
michael@0 620 static_cast<RequestMapEntry *>
michael@0 621 (PL_DHashTableOperate(&mRequests, request,
michael@0 622 PL_DHASH_LOOKUP));
michael@0 623
michael@0 624 if (PL_DHASH_ENTRY_IS_FREE(entry)) {
michael@0 625 LOG(("LOADGROUP [%x]: Unable to remove request %x. Not in group!\n",
michael@0 626 this, request));
michael@0 627
michael@0 628 return NS_ERROR_FAILURE;
michael@0 629 }
michael@0 630
michael@0 631 PL_DHashTableRawRemove(&mRequests, entry);
michael@0 632
michael@0 633 // Collect telemetry stats only when default request is a timed channel.
michael@0 634 // Don't include failed requests in the timing statistics.
michael@0 635 if (mDefaultLoadIsTimed && NS_SUCCEEDED(aStatus)) {
michael@0 636 nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request);
michael@0 637 if (timedChannel) {
michael@0 638 // Figure out if this request was served from the cache
michael@0 639 ++mTimedRequests;
michael@0 640 TimeStamp timeStamp;
michael@0 641 rv = timedChannel->GetCacheReadStart(&timeStamp);
michael@0 642 if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) {
michael@0 643 ++mCachedRequests;
michael@0 644 }
michael@0 645 else {
michael@0 646 mTimedNonCachedRequestsUntilOnEndPageLoad++;
michael@0 647 }
michael@0 648
michael@0 649 rv = timedChannel->GetAsyncOpen(&timeStamp);
michael@0 650 if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) {
michael@0 651 Telemetry::AccumulateTimeDelta(
michael@0 652 Telemetry::HTTP_SUBITEM_OPEN_LATENCY_TIME,
michael@0 653 mDefaultRequestCreationTime, timeStamp);
michael@0 654 }
michael@0 655
michael@0 656 rv = timedChannel->GetResponseStart(&timeStamp);
michael@0 657 if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) {
michael@0 658 Telemetry::AccumulateTimeDelta(
michael@0 659 Telemetry::HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME,
michael@0 660 mDefaultRequestCreationTime, timeStamp);
michael@0 661 }
michael@0 662
michael@0 663 TelemetryReportChannel(timedChannel, false);
michael@0 664 }
michael@0 665 }
michael@0 666
michael@0 667 if (mRequests.entryCount == 0) {
michael@0 668 TelemetryReport();
michael@0 669 }
michael@0 670
michael@0 671 // Undo any group priority delta...
michael@0 672 if (mPriority != 0)
michael@0 673 RescheduleRequest(request, -mPriority);
michael@0 674
michael@0 675 nsLoadFlags flags;
michael@0 676 rv = request->GetLoadFlags(&flags);
michael@0 677 if (NS_FAILED(rv)) return rv;
michael@0 678
michael@0 679 if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
michael@0 680 NS_ASSERTION(mForegroundCount > 0, "ForegroundCount messed up");
michael@0 681 mForegroundCount -= 1;
michael@0 682
michael@0 683 // Fire the OnStopRequest out to the observer...
michael@0 684 nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
michael@0 685 if (observer) {
michael@0 686 LOG(("LOADGROUP [%x]: Firing OnStopRequest for request %x."
michael@0 687 "(foreground count=%d).\n", this, request, mForegroundCount));
michael@0 688
michael@0 689 rv = observer->OnStopRequest(request, ctxt, aStatus);
michael@0 690
michael@0 691 #if defined(PR_LOGGING)
michael@0 692 if (NS_FAILED(rv)) {
michael@0 693 LOG(("LOADGROUP [%x]: OnStopRequest for request %x FAILED.\n",
michael@0 694 this, request));
michael@0 695 }
michael@0 696 #endif
michael@0 697 }
michael@0 698
michael@0 699 // If that was the last request -> remove ourselves from loadgroup
michael@0 700 if (mForegroundCount == 0 && mLoadGroup) {
michael@0 701 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
michael@0 702 }
michael@0 703 }
michael@0 704
michael@0 705 return rv;
michael@0 706 }
michael@0 707
michael@0 708 // PLDHashTable enumeration callback that appends all items in the
michael@0 709 // hash to an nsCOMArray
michael@0 710 static PLDHashOperator
michael@0 711 AppendRequestsToCOMArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
michael@0 712 uint32_t number, void *arg)
michael@0 713 {
michael@0 714 RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr);
michael@0 715 static_cast<nsCOMArray<nsIRequest>*>(arg)->AppendObject(e->mKey);
michael@0 716 return PL_DHASH_NEXT;
michael@0 717 }
michael@0 718
michael@0 719 NS_IMETHODIMP
michael@0 720 nsLoadGroup::GetRequests(nsISimpleEnumerator * *aRequests)
michael@0 721 {
michael@0 722 nsCOMArray<nsIRequest> requests;
michael@0 723 requests.SetCapacity(mRequests.entryCount);
michael@0 724
michael@0 725 PL_DHashTableEnumerate(&mRequests, AppendRequestsToCOMArray, &requests);
michael@0 726
michael@0 727 return NS_NewArrayEnumerator(aRequests, requests);
michael@0 728 }
michael@0 729
michael@0 730 NS_IMETHODIMP
michael@0 731 nsLoadGroup::SetGroupObserver(nsIRequestObserver* aObserver)
michael@0 732 {
michael@0 733 mObserver = do_GetWeakReference(aObserver);
michael@0 734 return NS_OK;
michael@0 735 }
michael@0 736
michael@0 737 NS_IMETHODIMP
michael@0 738 nsLoadGroup::GetGroupObserver(nsIRequestObserver* *aResult)
michael@0 739 {
michael@0 740 nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
michael@0 741 *aResult = observer;
michael@0 742 NS_IF_ADDREF(*aResult);
michael@0 743 return NS_OK;
michael@0 744 }
michael@0 745
michael@0 746 NS_IMETHODIMP
michael@0 747 nsLoadGroup::GetActiveCount(uint32_t* aResult)
michael@0 748 {
michael@0 749 *aResult = mForegroundCount;
michael@0 750 return NS_OK;
michael@0 751 }
michael@0 752
michael@0 753 NS_IMETHODIMP
michael@0 754 nsLoadGroup::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
michael@0 755 {
michael@0 756 NS_ENSURE_ARG_POINTER(aCallbacks);
michael@0 757 *aCallbacks = mCallbacks;
michael@0 758 NS_IF_ADDREF(*aCallbacks);
michael@0 759 return NS_OK;
michael@0 760 }
michael@0 761
michael@0 762 NS_IMETHODIMP
michael@0 763 nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
michael@0 764 {
michael@0 765 mCallbacks = aCallbacks;
michael@0 766 return NS_OK;
michael@0 767 }
michael@0 768
michael@0 769 NS_IMETHODIMP
michael@0 770 nsLoadGroup::GetConnectionInfo(nsILoadGroupConnectionInfo **aCI)
michael@0 771 {
michael@0 772 NS_ENSURE_ARG_POINTER(aCI);
michael@0 773 *aCI = mConnectionInfo;
michael@0 774 NS_IF_ADDREF(*aCI);
michael@0 775 return NS_OK;
michael@0 776 }
michael@0 777
michael@0 778 ////////////////////////////////////////////////////////////////////////////////
michael@0 779 // nsILoadGroupChild methods:
michael@0 780
michael@0 781 /* attribute nsILoadGroup parentLoadGroup; */
michael@0 782 NS_IMETHODIMP
michael@0 783 nsLoadGroup::GetParentLoadGroup(nsILoadGroup * *aParentLoadGroup)
michael@0 784 {
michael@0 785 *aParentLoadGroup = nullptr;
michael@0 786 nsCOMPtr<nsILoadGroup> parent = do_QueryReferent(mParentLoadGroup);
michael@0 787 if (!parent)
michael@0 788 return NS_OK;
michael@0 789 parent.forget(aParentLoadGroup);
michael@0 790 return NS_OK;
michael@0 791 }
michael@0 792
michael@0 793 NS_IMETHODIMP
michael@0 794 nsLoadGroup::SetParentLoadGroup(nsILoadGroup *aParentLoadGroup)
michael@0 795 {
michael@0 796 mParentLoadGroup = do_GetWeakReference(aParentLoadGroup);
michael@0 797 return NS_OK;
michael@0 798 }
michael@0 799
michael@0 800 /* readonly attribute nsILoadGroup childLoadGroup; */
michael@0 801 NS_IMETHODIMP
michael@0 802 nsLoadGroup::GetChildLoadGroup(nsILoadGroup * *aChildLoadGroup)
michael@0 803 {
michael@0 804 NS_ADDREF(*aChildLoadGroup = this);
michael@0 805 return NS_OK;
michael@0 806 }
michael@0 807
michael@0 808 /* readonly attribute nsILoadGroup rootLoadGroup; */
michael@0 809 NS_IMETHODIMP
michael@0 810 nsLoadGroup::GetRootLoadGroup(nsILoadGroup * *aRootLoadGroup)
michael@0 811 {
michael@0 812 // first recursively try the root load group of our parent
michael@0 813 nsCOMPtr<nsILoadGroupChild> ancestor = do_QueryReferent(mParentLoadGroup);
michael@0 814 if (ancestor)
michael@0 815 return ancestor->GetRootLoadGroup(aRootLoadGroup);
michael@0 816
michael@0 817 // next recursively try the root load group of our own load grop
michael@0 818 ancestor = do_QueryInterface(mLoadGroup);
michael@0 819 if (ancestor)
michael@0 820 return ancestor->GetRootLoadGroup(aRootLoadGroup);
michael@0 821
michael@0 822 // finally just return this
michael@0 823 NS_ADDREF(*aRootLoadGroup = this);
michael@0 824 return NS_OK;
michael@0 825 }
michael@0 826
michael@0 827 ////////////////////////////////////////////////////////////////////////////////
michael@0 828 // nsPILoadGroupInternal methods:
michael@0 829
michael@0 830 NS_IMETHODIMP
michael@0 831 nsLoadGroup::OnEndPageLoad(nsIChannel *aDefaultChannel)
michael@0 832 {
michael@0 833 // for the moment, nothing to do here.
michael@0 834 return NS_OK;
michael@0 835 }
michael@0 836
michael@0 837 ////////////////////////////////////////////////////////////////////////////////
michael@0 838 // nsISupportsPriority methods:
michael@0 839
michael@0 840 NS_IMETHODIMP
michael@0 841 nsLoadGroup::GetPriority(int32_t *aValue)
michael@0 842 {
michael@0 843 *aValue = mPriority;
michael@0 844 return NS_OK;
michael@0 845 }
michael@0 846
michael@0 847 NS_IMETHODIMP
michael@0 848 nsLoadGroup::SetPriority(int32_t aValue)
michael@0 849 {
michael@0 850 return AdjustPriority(aValue - mPriority);
michael@0 851 }
michael@0 852
michael@0 853 NS_IMETHODIMP
michael@0 854 nsLoadGroup::AdjustPriority(int32_t aDelta)
michael@0 855 {
michael@0 856 // Update the priority for each request that supports nsISupportsPriority
michael@0 857 if (aDelta != 0) {
michael@0 858 mPriority += aDelta;
michael@0 859 PL_DHashTableEnumerate(&mRequests, RescheduleRequests, &aDelta);
michael@0 860 }
michael@0 861 return NS_OK;
michael@0 862 }
michael@0 863
michael@0 864 NS_IMETHODIMP
michael@0 865 nsLoadGroup::GetDefaultLoadFlags(uint32_t *aFlags)
michael@0 866 {
michael@0 867 *aFlags = mDefaultLoadFlags;
michael@0 868 return NS_OK;
michael@0 869 }
michael@0 870
michael@0 871 NS_IMETHODIMP
michael@0 872 nsLoadGroup::SetDefaultLoadFlags(uint32_t aFlags)
michael@0 873 {
michael@0 874 mDefaultLoadFlags = aFlags;
michael@0 875 return NS_OK;
michael@0 876 }
michael@0 877
michael@0 878
michael@0 879 ////////////////////////////////////////////////////////////////////////////////
michael@0 880
michael@0 881 void
michael@0 882 nsLoadGroup::TelemetryReport()
michael@0 883 {
michael@0 884 if (mDefaultLoadIsTimed) {
michael@0 885 Telemetry::Accumulate(Telemetry::HTTP_REQUEST_PER_PAGE, mTimedRequests);
michael@0 886 if (mTimedRequests) {
michael@0 887 Telemetry::Accumulate(Telemetry::HTTP_REQUEST_PER_PAGE_FROM_CACHE,
michael@0 888 mCachedRequests * 100 / mTimedRequests);
michael@0 889 }
michael@0 890
michael@0 891 nsCOMPtr<nsITimedChannel> timedChannel =
michael@0 892 do_QueryInterface(mDefaultLoadRequest);
michael@0 893 if (timedChannel)
michael@0 894 TelemetryReportChannel(timedChannel, true);
michael@0 895 }
michael@0 896
michael@0 897 mTimedRequests = 0;
michael@0 898 mCachedRequests = 0;
michael@0 899 mDefaultLoadIsTimed = false;
michael@0 900 }
michael@0 901
michael@0 902 void
michael@0 903 nsLoadGroup::TelemetryReportChannel(nsITimedChannel *aTimedChannel,
michael@0 904 bool aDefaultRequest)
michael@0 905 {
michael@0 906 nsresult rv;
michael@0 907 bool timingEnabled;
michael@0 908 rv = aTimedChannel->GetTimingEnabled(&timingEnabled);
michael@0 909 if (NS_FAILED(rv) || !timingEnabled)
michael@0 910 return;
michael@0 911
michael@0 912 TimeStamp asyncOpen;
michael@0 913 rv = aTimedChannel->GetAsyncOpen(&asyncOpen);
michael@0 914 // We do not check !asyncOpen.IsNull() bellow, prevent ASSERTIONs this way
michael@0 915 if (NS_FAILED(rv) || asyncOpen.IsNull())
michael@0 916 return;
michael@0 917
michael@0 918 TimeStamp cacheReadStart;
michael@0 919 rv = aTimedChannel->GetCacheReadStart(&cacheReadStart);
michael@0 920 if (NS_FAILED(rv))
michael@0 921 return;
michael@0 922
michael@0 923 TimeStamp cacheReadEnd;
michael@0 924 rv = aTimedChannel->GetCacheReadEnd(&cacheReadEnd);
michael@0 925 if (NS_FAILED(rv))
michael@0 926 return;
michael@0 927
michael@0 928 TimeStamp domainLookupStart;
michael@0 929 rv = aTimedChannel->GetDomainLookupStart(&domainLookupStart);
michael@0 930 if (NS_FAILED(rv))
michael@0 931 return;
michael@0 932
michael@0 933 TimeStamp domainLookupEnd;
michael@0 934 rv = aTimedChannel->GetDomainLookupEnd(&domainLookupEnd);
michael@0 935 if (NS_FAILED(rv))
michael@0 936 return;
michael@0 937
michael@0 938 TimeStamp connectStart;
michael@0 939 rv = aTimedChannel->GetConnectStart(&connectStart);
michael@0 940 if (NS_FAILED(rv))
michael@0 941 return;
michael@0 942
michael@0 943 TimeStamp connectEnd;
michael@0 944 rv = aTimedChannel->GetConnectEnd(&connectEnd);
michael@0 945 if (NS_FAILED(rv))
michael@0 946 return;
michael@0 947
michael@0 948 TimeStamp requestStart;
michael@0 949 rv = aTimedChannel->GetRequestStart(&requestStart);
michael@0 950 if (NS_FAILED(rv))
michael@0 951 return;
michael@0 952
michael@0 953 TimeStamp responseStart;
michael@0 954 rv = aTimedChannel->GetResponseStart(&responseStart);
michael@0 955 if (NS_FAILED(rv))
michael@0 956 return;
michael@0 957
michael@0 958 TimeStamp responseEnd;
michael@0 959 rv = aTimedChannel->GetResponseEnd(&responseEnd);
michael@0 960 if (NS_FAILED(rv))
michael@0 961 return;
michael@0 962
michael@0 963 #define HTTP_REQUEST_HISTOGRAMS(prefix) \
michael@0 964 if (!domainLookupStart.IsNull()) { \
michael@0 965 Telemetry::AccumulateTimeDelta( \
michael@0 966 Telemetry::HTTP_##prefix##_DNS_ISSUE_TIME, \
michael@0 967 asyncOpen, domainLookupStart); \
michael@0 968 } \
michael@0 969 \
michael@0 970 if (!domainLookupStart.IsNull() && !domainLookupEnd.IsNull()) { \
michael@0 971 Telemetry::AccumulateTimeDelta( \
michael@0 972 Telemetry::HTTP_##prefix##_DNS_LOOKUP_TIME, \
michael@0 973 domainLookupStart, domainLookupEnd); \
michael@0 974 } \
michael@0 975 \
michael@0 976 if (!connectStart.IsNull() && !connectEnd.IsNull()) { \
michael@0 977 Telemetry::AccumulateTimeDelta( \
michael@0 978 Telemetry::HTTP_##prefix##_TCP_CONNECTION, \
michael@0 979 connectStart, connectEnd); \
michael@0 980 } \
michael@0 981 \
michael@0 982 \
michael@0 983 if (!requestStart.IsNull() && !responseEnd.IsNull()) { \
michael@0 984 Telemetry::AccumulateTimeDelta( \
michael@0 985 Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_SENT, \
michael@0 986 asyncOpen, requestStart); \
michael@0 987 \
michael@0 988 Telemetry::AccumulateTimeDelta( \
michael@0 989 Telemetry::HTTP_##prefix##_FIRST_SENT_TO_LAST_RECEIVED, \
michael@0 990 requestStart, responseEnd); \
michael@0 991 \
michael@0 992 if (cacheReadStart.IsNull() && !responseStart.IsNull()) { \
michael@0 993 Telemetry::AccumulateTimeDelta( \
michael@0 994 Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_RECEIVED, \
michael@0 995 asyncOpen, responseStart); \
michael@0 996 } \
michael@0 997 } \
michael@0 998 \
michael@0 999 if (!cacheReadStart.IsNull() && !cacheReadEnd.IsNull()) { \
michael@0 1000 if (!CacheObserver::UseNewCache()) { \
michael@0 1001 Telemetry::AccumulateTimeDelta( \
michael@0 1002 Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_FROM_CACHE, \
michael@0 1003 asyncOpen, cacheReadStart); \
michael@0 1004 } else { \
michael@0 1005 Telemetry::AccumulateTimeDelta( \
michael@0 1006 Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_FROM_CACHE_V2, \
michael@0 1007 asyncOpen, cacheReadStart); \
michael@0 1008 } \
michael@0 1009 \
michael@0 1010 if (!CacheObserver::UseNewCache()) { \
michael@0 1011 Telemetry::AccumulateTimeDelta( \
michael@0 1012 Telemetry::HTTP_##prefix##_CACHE_READ_TIME, \
michael@0 1013 cacheReadStart, cacheReadEnd); \
michael@0 1014 } else { \
michael@0 1015 Telemetry::AccumulateTimeDelta( \
michael@0 1016 Telemetry::HTTP_##prefix##_CACHE_READ_TIME_V2, \
michael@0 1017 cacheReadStart, cacheReadEnd); \
michael@0 1018 } \
michael@0 1019 \
michael@0 1020 if (!requestStart.IsNull() && !responseEnd.IsNull()) { \
michael@0 1021 Telemetry::AccumulateTimeDelta( \
michael@0 1022 Telemetry::HTTP_##prefix##_REVALIDATION, \
michael@0 1023 requestStart, responseEnd); \
michael@0 1024 } \
michael@0 1025 } \
michael@0 1026 \
michael@0 1027 if (!cacheReadEnd.IsNull()) { \
michael@0 1028 Telemetry::AccumulateTimeDelta( \
michael@0 1029 Telemetry::HTTP_##prefix##_COMPLETE_LOAD, \
michael@0 1030 asyncOpen, cacheReadEnd); \
michael@0 1031 \
michael@0 1032 if (!CacheObserver::UseNewCache()) { \
michael@0 1033 Telemetry::AccumulateTimeDelta( \
michael@0 1034 Telemetry::HTTP_##prefix##_COMPLETE_LOAD_CACHED, \
michael@0 1035 asyncOpen, cacheReadEnd); \
michael@0 1036 } else { \
michael@0 1037 Telemetry::AccumulateTimeDelta( \
michael@0 1038 Telemetry::HTTP_##prefix##_COMPLETE_LOAD_CACHED_V2, \
michael@0 1039 asyncOpen, cacheReadEnd); \
michael@0 1040 } \
michael@0 1041 } \
michael@0 1042 else if (!responseEnd.IsNull()) { \
michael@0 1043 if (!CacheObserver::UseNewCache()) { \
michael@0 1044 Telemetry::AccumulateTimeDelta( \
michael@0 1045 Telemetry::HTTP_##prefix##_COMPLETE_LOAD, \
michael@0 1046 asyncOpen, responseEnd); \
michael@0 1047 Telemetry::AccumulateTimeDelta( \
michael@0 1048 Telemetry::HTTP_##prefix##_COMPLETE_LOAD_NET, \
michael@0 1049 asyncOpen, responseEnd); \
michael@0 1050 } else { \
michael@0 1051 Telemetry::AccumulateTimeDelta( \
michael@0 1052 Telemetry::HTTP_##prefix##_COMPLETE_LOAD_V2, \
michael@0 1053 asyncOpen, responseEnd); \
michael@0 1054 Telemetry::AccumulateTimeDelta( \
michael@0 1055 Telemetry::HTTP_##prefix##_COMPLETE_LOAD_NET_V2, \
michael@0 1056 asyncOpen, responseEnd); \
michael@0 1057 } \
michael@0 1058 }
michael@0 1059
michael@0 1060 if (aDefaultRequest) {
michael@0 1061 HTTP_REQUEST_HISTOGRAMS(PAGE)
michael@0 1062 } else {
michael@0 1063 HTTP_REQUEST_HISTOGRAMS(SUB)
michael@0 1064 }
michael@0 1065 #undef HTTP_REQUEST_HISTOGRAMS
michael@0 1066 }
michael@0 1067
michael@0 1068 nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags)
michael@0 1069 {
michael@0 1070 nsresult rv;
michael@0 1071 nsLoadFlags flags, oldFlags;
michael@0 1072
michael@0 1073 rv = aRequest->GetLoadFlags(&flags);
michael@0 1074 if (NS_FAILED(rv))
michael@0 1075 return rv;
michael@0 1076
michael@0 1077 oldFlags = flags;
michael@0 1078
michael@0 1079 // Inherit the following bits...
michael@0 1080 flags |= (mLoadFlags & (LOAD_BACKGROUND |
michael@0 1081 LOAD_BYPASS_CACHE |
michael@0 1082 LOAD_FROM_CACHE |
michael@0 1083 VALIDATE_ALWAYS |
michael@0 1084 VALIDATE_ONCE_PER_SESSION |
michael@0 1085 VALIDATE_NEVER));
michael@0 1086
michael@0 1087 // ... and force the default flags.
michael@0 1088 flags |= mDefaultLoadFlags;
michael@0 1089
michael@0 1090 if (flags != oldFlags)
michael@0 1091 rv = aRequest->SetLoadFlags(flags);
michael@0 1092
michael@0 1093 outFlags = flags;
michael@0 1094 return rv;
michael@0 1095 }
michael@0 1096
michael@0 1097 // nsLoadGroupConnectionInfo
michael@0 1098
michael@0 1099 class nsLoadGroupConnectionInfo MOZ_FINAL : public nsILoadGroupConnectionInfo
michael@0 1100 {
michael@0 1101 public:
michael@0 1102 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 1103 NS_DECL_NSILOADGROUPCONNECTIONINFO
michael@0 1104
michael@0 1105 nsLoadGroupConnectionInfo();
michael@0 1106 private:
michael@0 1107 Atomic<uint32_t> mBlockingTransactionCount;
michael@0 1108 nsAutoPtr<mozilla::net::SpdyPushCache> mSpdyCache;
michael@0 1109 };
michael@0 1110
michael@0 1111 NS_IMPL_ISUPPORTS(nsLoadGroupConnectionInfo, nsILoadGroupConnectionInfo)
michael@0 1112
michael@0 1113 nsLoadGroupConnectionInfo::nsLoadGroupConnectionInfo()
michael@0 1114 : mBlockingTransactionCount(0)
michael@0 1115 {
michael@0 1116 }
michael@0 1117
michael@0 1118 NS_IMETHODIMP
michael@0 1119 nsLoadGroupConnectionInfo::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount)
michael@0 1120 {
michael@0 1121 NS_ENSURE_ARG_POINTER(aBlockingTransactionCount);
michael@0 1122 *aBlockingTransactionCount = mBlockingTransactionCount;
michael@0 1123 return NS_OK;
michael@0 1124 }
michael@0 1125
michael@0 1126 NS_IMETHODIMP
michael@0 1127 nsLoadGroupConnectionInfo::AddBlockingTransaction()
michael@0 1128 {
michael@0 1129 mBlockingTransactionCount++;
michael@0 1130 return NS_OK;
michael@0 1131 }
michael@0 1132
michael@0 1133 NS_IMETHODIMP
michael@0 1134 nsLoadGroupConnectionInfo::RemoveBlockingTransaction(uint32_t *_retval)
michael@0 1135 {
michael@0 1136 NS_ENSURE_ARG_POINTER(_retval);
michael@0 1137 mBlockingTransactionCount--;
michael@0 1138 *_retval = mBlockingTransactionCount;
michael@0 1139 return NS_OK;
michael@0 1140 }
michael@0 1141
michael@0 1142 /* [noscript] attribute SpdyPushCachePtr spdyPushCache; */
michael@0 1143 NS_IMETHODIMP
michael@0 1144 nsLoadGroupConnectionInfo::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
michael@0 1145 {
michael@0 1146 *aSpdyPushCache = mSpdyCache.get();
michael@0 1147 return NS_OK;
michael@0 1148 }
michael@0 1149
michael@0 1150 NS_IMETHODIMP
michael@0 1151 nsLoadGroupConnectionInfo::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
michael@0 1152 {
michael@0 1153 mSpdyCache = aSpdyPushCache;
michael@0 1154 return NS_OK;
michael@0 1155 }
michael@0 1156
michael@0 1157 nsresult nsLoadGroup::Init()
michael@0 1158 {
michael@0 1159 static const PLDHashTableOps hash_table_ops =
michael@0 1160 {
michael@0 1161 PL_DHashAllocTable,
michael@0 1162 PL_DHashFreeTable,
michael@0 1163 PL_DHashVoidPtrKeyStub,
michael@0 1164 RequestHashMatchEntry,
michael@0 1165 PL_DHashMoveEntryStub,
michael@0 1166 RequestHashClearEntry,
michael@0 1167 PL_DHashFinalizeStub,
michael@0 1168 RequestHashInitEntry
michael@0 1169 };
michael@0 1170
michael@0 1171 PL_DHashTableInit(&mRequests, &hash_table_ops, nullptr,
michael@0 1172 sizeof(RequestMapEntry), 16);
michael@0 1173
michael@0 1174 mConnectionInfo = new nsLoadGroupConnectionInfo();
michael@0 1175
michael@0 1176 return NS_OK;
michael@0 1177 }
michael@0 1178
michael@0 1179 #undef LOG

mercurial