1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsLoadGroup.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1179 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set sw=4 ts=4 sts=4 et cin: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/DebugOnly.h" 1.11 + 1.12 +#include "nsLoadGroup.h" 1.13 + 1.14 +#include "nsArrayEnumerator.h" 1.15 +#include "nsCOMArray.h" 1.16 +#include "nsCOMPtr.h" 1.17 +#include "prlog.h" 1.18 +#include "nsString.h" 1.19 +#include "nsTArray.h" 1.20 +#include "mozilla/Atomics.h" 1.21 +#include "mozilla/Telemetry.h" 1.22 +#include "nsAutoPtr.h" 1.23 +#include "mozilla/net/PSpdyPush.h" 1.24 +#include "nsITimedChannel.h" 1.25 +#include "nsIInterfaceRequestor.h" 1.26 +#include "nsIRequestObserver.h" 1.27 +#include "CacheObserver.h" 1.28 +#include "MainThreadUtils.h" 1.29 + 1.30 +using namespace mozilla; 1.31 +using namespace mozilla::net; 1.32 + 1.33 +#if defined(PR_LOGGING) 1.34 +// 1.35 +// Log module for nsILoadGroup logging... 1.36 +// 1.37 +// To enable logging (see prlog.h for full details): 1.38 +// 1.39 +// set NSPR_LOG_MODULES=LoadGroup:5 1.40 +// set NSPR_LOG_FILE=nspr.log 1.41 +// 1.42 +// this enables PR_LOG_DEBUG level information and places all output in 1.43 +// the file nspr.log 1.44 +// 1.45 +static PRLogModuleInfo* gLoadGroupLog = nullptr; 1.46 +#endif 1.47 + 1.48 +#undef LOG 1.49 +#define LOG(args) PR_LOG(gLoadGroupLog, PR_LOG_DEBUG, args) 1.50 + 1.51 +//////////////////////////////////////////////////////////////////////////////// 1.52 + 1.53 +class RequestMapEntry : public PLDHashEntryHdr 1.54 +{ 1.55 +public: 1.56 + RequestMapEntry(nsIRequest *aRequest) : 1.57 + mKey(aRequest) 1.58 + { 1.59 + } 1.60 + 1.61 + nsCOMPtr<nsIRequest> mKey; 1.62 +}; 1.63 + 1.64 +static bool 1.65 +RequestHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, 1.66 + const void *key) 1.67 +{ 1.68 + const RequestMapEntry *e = 1.69 + static_cast<const RequestMapEntry *>(entry); 1.70 + const nsIRequest *request = static_cast<const nsIRequest *>(key); 1.71 + 1.72 + return e->mKey == request; 1.73 +} 1.74 + 1.75 +static void 1.76 +RequestHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) 1.77 +{ 1.78 + RequestMapEntry *e = static_cast<RequestMapEntry *>(entry); 1.79 + 1.80 + // An entry is being cleared, let the entry do its own cleanup. 1.81 + e->~RequestMapEntry(); 1.82 +} 1.83 + 1.84 +static bool 1.85 +RequestHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, 1.86 + const void *key) 1.87 +{ 1.88 + const nsIRequest *const_request = static_cast<const nsIRequest *>(key); 1.89 + nsIRequest *request = const_cast<nsIRequest *>(const_request); 1.90 + 1.91 + // Initialize the entry with placement new 1.92 + new (entry) RequestMapEntry(request); 1.93 + return true; 1.94 +} 1.95 + 1.96 + 1.97 +static void 1.98 +RescheduleRequest(nsIRequest *aRequest, int32_t delta) 1.99 +{ 1.100 + nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aRequest); 1.101 + if (p) 1.102 + p->AdjustPriority(delta); 1.103 +} 1.104 + 1.105 +static PLDHashOperator 1.106 +RescheduleRequests(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.107 + uint32_t number, void *arg) 1.108 +{ 1.109 + RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr); 1.110 + int32_t *delta = static_cast<int32_t *>(arg); 1.111 + 1.112 + RescheduleRequest(e->mKey, *delta); 1.113 + return PL_DHASH_NEXT; 1.114 +} 1.115 + 1.116 + 1.117 +nsLoadGroup::nsLoadGroup(nsISupports* outer) 1.118 + : mForegroundCount(0) 1.119 + , mLoadFlags(LOAD_NORMAL) 1.120 + , mDefaultLoadFlags(0) 1.121 + , mStatus(NS_OK) 1.122 + , mPriority(PRIORITY_NORMAL) 1.123 + , mIsCanceling(false) 1.124 + , mDefaultLoadIsTimed(false) 1.125 + , mTimedRequests(0) 1.126 + , mCachedRequests(0) 1.127 + , mTimedNonCachedRequestsUntilOnEndPageLoad(0) 1.128 +{ 1.129 + NS_INIT_AGGREGATED(outer); 1.130 + 1.131 +#if defined(PR_LOGGING) 1.132 + // Initialize the global PRLogModule for nsILoadGroup logging 1.133 + if (nullptr == gLoadGroupLog) 1.134 + gLoadGroupLog = PR_NewLogModule("LoadGroup"); 1.135 +#endif 1.136 + 1.137 + LOG(("LOADGROUP [%x]: Created.\n", this)); 1.138 + 1.139 + // Initialize the ops in the hash to null to make sure we get 1.140 + // consistent errors if someone fails to call ::Init() on an 1.141 + // nsLoadGroup. 1.142 + mRequests.ops = nullptr; 1.143 +} 1.144 + 1.145 +nsLoadGroup::~nsLoadGroup() 1.146 +{ 1.147 + DebugOnly<nsresult> rv = Cancel(NS_BINDING_ABORTED); 1.148 + NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed"); 1.149 + 1.150 + if (mRequests.ops) { 1.151 + PL_DHashTableFinish(&mRequests); 1.152 + } 1.153 + 1.154 + mDefaultLoadRequest = 0; 1.155 + 1.156 + LOG(("LOADGROUP [%x]: Destroyed.\n", this)); 1.157 +} 1.158 + 1.159 + 1.160 +//////////////////////////////////////////////////////////////////////////////// 1.161 +// nsISupports methods: 1.162 + 1.163 +NS_IMPL_AGGREGATED(nsLoadGroup) 1.164 +NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsLoadGroup) 1.165 + NS_INTERFACE_MAP_ENTRY(nsILoadGroup) 1.166 + NS_INTERFACE_MAP_ENTRY(nsPILoadGroupInternal) 1.167 + NS_INTERFACE_MAP_ENTRY(nsILoadGroupChild) 1.168 + NS_INTERFACE_MAP_ENTRY(nsIRequest) 1.169 + NS_INTERFACE_MAP_ENTRY(nsISupportsPriority) 1.170 + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 1.171 +NS_INTERFACE_MAP_END 1.172 + 1.173 +//////////////////////////////////////////////////////////////////////////////// 1.174 +// nsIRequest methods: 1.175 + 1.176 +NS_IMETHODIMP 1.177 +nsLoadGroup::GetName(nsACString &result) 1.178 +{ 1.179 + // XXX is this the right "name" for a load group? 1.180 + 1.181 + if (!mDefaultLoadRequest) { 1.182 + result.Truncate(); 1.183 + return NS_OK; 1.184 + } 1.185 + 1.186 + return mDefaultLoadRequest->GetName(result); 1.187 +} 1.188 + 1.189 +NS_IMETHODIMP 1.190 +nsLoadGroup::IsPending(bool *aResult) 1.191 +{ 1.192 + *aResult = (mForegroundCount > 0) ? true : false; 1.193 + return NS_OK; 1.194 +} 1.195 + 1.196 +NS_IMETHODIMP 1.197 +nsLoadGroup::GetStatus(nsresult *status) 1.198 +{ 1.199 + if (NS_SUCCEEDED(mStatus) && mDefaultLoadRequest) 1.200 + return mDefaultLoadRequest->GetStatus(status); 1.201 + 1.202 + *status = mStatus; 1.203 + return NS_OK; 1.204 +} 1.205 + 1.206 +// PLDHashTable enumeration callback that appends strong references to 1.207 +// all nsIRequest to an nsTArray<nsIRequest*>. 1.208 +static PLDHashOperator 1.209 +AppendRequestsToArray(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.210 + uint32_t number, void *arg) 1.211 +{ 1.212 + RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr); 1.213 + nsTArray<nsIRequest*> *array = static_cast<nsTArray<nsIRequest*> *>(arg); 1.214 + 1.215 + nsIRequest *request = e->mKey; 1.216 + NS_ASSERTION(request, "What? Null key in pldhash entry?"); 1.217 + 1.218 + bool ok = array->AppendElement(request) != nullptr; 1.219 + 1.220 + if (!ok) { 1.221 + return PL_DHASH_STOP; 1.222 + } 1.223 + 1.224 + NS_ADDREF(request); 1.225 + 1.226 + return PL_DHASH_NEXT; 1.227 +} 1.228 + 1.229 +NS_IMETHODIMP 1.230 +nsLoadGroup::Cancel(nsresult status) 1.231 +{ 1.232 + MOZ_ASSERT(NS_IsMainThread()); 1.233 + 1.234 + NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code"); 1.235 + nsresult rv; 1.236 + uint32_t count = mRequests.entryCount; 1.237 + 1.238 + nsAutoTArray<nsIRequest*, 8> requests; 1.239 + 1.240 + PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray, 1.241 + static_cast<nsTArray<nsIRequest*> *>(&requests)); 1.242 + 1.243 + if (requests.Length() != count) { 1.244 + for (uint32_t i = 0, len = requests.Length(); i < len; ++i) { 1.245 + NS_RELEASE(requests[i]); 1.246 + } 1.247 + 1.248 + return NS_ERROR_OUT_OF_MEMORY; 1.249 + } 1.250 + 1.251 + // set the load group status to our cancel status while we cancel 1.252 + // all our requests...once the cancel is done, we'll reset it... 1.253 + // 1.254 + mStatus = status; 1.255 + 1.256 + // Set the flag indicating that the loadgroup is being canceled... This 1.257 + // prevents any new channels from being added during the operation. 1.258 + // 1.259 + mIsCanceling = true; 1.260 + 1.261 + nsresult firstError = NS_OK; 1.262 + 1.263 + while (count > 0) { 1.264 + nsIRequest* request = requests.ElementAt(--count); 1.265 + 1.266 + NS_ASSERTION(request, "NULL request found in list."); 1.267 + 1.268 + RequestMapEntry *entry = 1.269 + static_cast<RequestMapEntry *> 1.270 + (PL_DHashTableOperate(&mRequests, request, 1.271 + PL_DHASH_LOOKUP)); 1.272 + 1.273 + if (PL_DHASH_ENTRY_IS_FREE(entry)) { 1.274 + // |request| was removed already 1.275 + 1.276 + NS_RELEASE(request); 1.277 + 1.278 + continue; 1.279 + } 1.280 + 1.281 +#if defined(PR_LOGGING) 1.282 + nsAutoCString nameStr; 1.283 + request->GetName(nameStr); 1.284 + LOG(("LOADGROUP [%x]: Canceling request %x %s.\n", 1.285 + this, request, nameStr.get())); 1.286 +#endif 1.287 + 1.288 + // 1.289 + // Remove the request from the load group... This may cause 1.290 + // the OnStopRequest notification to fire... 1.291 + // 1.292 + // XXX: What should the context be? 1.293 + // 1.294 + (void)RemoveRequest(request, nullptr, status); 1.295 + 1.296 + // Cancel the request... 1.297 + rv = request->Cancel(status); 1.298 + 1.299 + // Remember the first failure and return it... 1.300 + if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) 1.301 + firstError = rv; 1.302 + 1.303 + NS_RELEASE(request); 1.304 + } 1.305 + 1.306 +#if defined(DEBUG) 1.307 + NS_ASSERTION(mRequests.entryCount == 0, "Request list is not empty."); 1.308 + NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active."); 1.309 +#endif 1.310 + 1.311 + mStatus = NS_OK; 1.312 + mIsCanceling = false; 1.313 + 1.314 + return firstError; 1.315 +} 1.316 + 1.317 + 1.318 +NS_IMETHODIMP 1.319 +nsLoadGroup::Suspend() 1.320 +{ 1.321 + nsresult rv, firstError; 1.322 + uint32_t count = mRequests.entryCount; 1.323 + 1.324 + nsAutoTArray<nsIRequest*, 8> requests; 1.325 + 1.326 + PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray, 1.327 + static_cast<nsTArray<nsIRequest*> *>(&requests)); 1.328 + 1.329 + if (requests.Length() != count) { 1.330 + for (uint32_t i = 0, len = requests.Length(); i < len; ++i) { 1.331 + NS_RELEASE(requests[i]); 1.332 + } 1.333 + 1.334 + return NS_ERROR_OUT_OF_MEMORY; 1.335 + } 1.336 + 1.337 + firstError = NS_OK; 1.338 + // 1.339 + // Operate the elements from back to front so that if items get 1.340 + // get removed from the list it won't affect our iteration 1.341 + // 1.342 + while (count > 0) { 1.343 + nsIRequest* request = requests.ElementAt(--count); 1.344 + 1.345 + NS_ASSERTION(request, "NULL request found in list."); 1.346 + if (!request) 1.347 + continue; 1.348 + 1.349 +#if defined(PR_LOGGING) 1.350 + nsAutoCString nameStr; 1.351 + request->GetName(nameStr); 1.352 + LOG(("LOADGROUP [%x]: Suspending request %x %s.\n", 1.353 + this, request, nameStr.get())); 1.354 +#endif 1.355 + 1.356 + // Suspend the request... 1.357 + rv = request->Suspend(); 1.358 + 1.359 + // Remember the first failure and return it... 1.360 + if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) 1.361 + firstError = rv; 1.362 + 1.363 + NS_RELEASE(request); 1.364 + } 1.365 + 1.366 + return firstError; 1.367 +} 1.368 + 1.369 + 1.370 +NS_IMETHODIMP 1.371 +nsLoadGroup::Resume() 1.372 +{ 1.373 + nsresult rv, firstError; 1.374 + uint32_t count = mRequests.entryCount; 1.375 + 1.376 + nsAutoTArray<nsIRequest*, 8> requests; 1.377 + 1.378 + PL_DHashTableEnumerate(&mRequests, AppendRequestsToArray, 1.379 + static_cast<nsTArray<nsIRequest*> *>(&requests)); 1.380 + 1.381 + if (requests.Length() != count) { 1.382 + for (uint32_t i = 0, len = requests.Length(); i < len; ++i) { 1.383 + NS_RELEASE(requests[i]); 1.384 + } 1.385 + 1.386 + return NS_ERROR_OUT_OF_MEMORY; 1.387 + } 1.388 + 1.389 + firstError = NS_OK; 1.390 + // 1.391 + // Operate the elements from back to front so that if items get 1.392 + // get removed from the list it won't affect our iteration 1.393 + // 1.394 + while (count > 0) { 1.395 + nsIRequest* request = requests.ElementAt(--count); 1.396 + 1.397 + NS_ASSERTION(request, "NULL request found in list."); 1.398 + if (!request) 1.399 + continue; 1.400 + 1.401 +#if defined(PR_LOGGING) 1.402 + nsAutoCString nameStr; 1.403 + request->GetName(nameStr); 1.404 + LOG(("LOADGROUP [%x]: Resuming request %x %s.\n", 1.405 + this, request, nameStr.get())); 1.406 +#endif 1.407 + 1.408 + // Resume the request... 1.409 + rv = request->Resume(); 1.410 + 1.411 + // Remember the first failure and return it... 1.412 + if (NS_FAILED(rv) && NS_SUCCEEDED(firstError)) 1.413 + firstError = rv; 1.414 + 1.415 + NS_RELEASE(request); 1.416 + } 1.417 + 1.418 + return firstError; 1.419 +} 1.420 + 1.421 +NS_IMETHODIMP 1.422 +nsLoadGroup::GetLoadFlags(uint32_t *aLoadFlags) 1.423 +{ 1.424 + *aLoadFlags = mLoadFlags; 1.425 + return NS_OK; 1.426 +} 1.427 + 1.428 +NS_IMETHODIMP 1.429 +nsLoadGroup::SetLoadFlags(uint32_t aLoadFlags) 1.430 +{ 1.431 + mLoadFlags = aLoadFlags; 1.432 + return NS_OK; 1.433 +} 1.434 + 1.435 +NS_IMETHODIMP 1.436 +nsLoadGroup::GetLoadGroup(nsILoadGroup **loadGroup) 1.437 +{ 1.438 + *loadGroup = mLoadGroup; 1.439 + NS_IF_ADDREF(*loadGroup); 1.440 + return NS_OK; 1.441 +} 1.442 + 1.443 +NS_IMETHODIMP 1.444 +nsLoadGroup::SetLoadGroup(nsILoadGroup *loadGroup) 1.445 +{ 1.446 + mLoadGroup = loadGroup; 1.447 + return NS_OK; 1.448 +} 1.449 + 1.450 +//////////////////////////////////////////////////////////////////////////////// 1.451 +// nsILoadGroup methods: 1.452 + 1.453 +NS_IMETHODIMP 1.454 +nsLoadGroup::GetDefaultLoadRequest(nsIRequest * *aRequest) 1.455 +{ 1.456 + *aRequest = mDefaultLoadRequest; 1.457 + NS_IF_ADDREF(*aRequest); 1.458 + return NS_OK; 1.459 +} 1.460 + 1.461 +NS_IMETHODIMP 1.462 +nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest) 1.463 +{ 1.464 + mDefaultLoadRequest = aRequest; 1.465 + // Inherit the group load flags from the default load request 1.466 + if (mDefaultLoadRequest) { 1.467 + mDefaultLoadRequest->GetLoadFlags(&mLoadFlags); 1.468 + // 1.469 + // Mask off any bits that are not part of the nsIRequest flags. 1.470 + // in particular, nsIChannel::LOAD_DOCUMENT_URI... 1.471 + // 1.472 + mLoadFlags &= nsIRequest::LOAD_REQUESTMASK; 1.473 + 1.474 + nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(aRequest); 1.475 + mDefaultLoadIsTimed = timedChannel != nullptr; 1.476 + if (mDefaultLoadIsTimed) { 1.477 + timedChannel->GetChannelCreation(&mDefaultRequestCreationTime); 1.478 + timedChannel->SetTimingEnabled(true); 1.479 + } 1.480 + } 1.481 + // Else, do not change the group's load flags (see bug 95981) 1.482 + return NS_OK; 1.483 +} 1.484 + 1.485 +NS_IMETHODIMP 1.486 +nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt) 1.487 +{ 1.488 + nsresult rv; 1.489 + 1.490 +#if defined(PR_LOGGING) 1.491 + { 1.492 + nsAutoCString nameStr; 1.493 + request->GetName(nameStr); 1.494 + LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n", 1.495 + this, request, nameStr.get(), mRequests.entryCount)); 1.496 + } 1.497 +#endif /* PR_LOGGING */ 1.498 + 1.499 +#ifdef DEBUG 1.500 + { 1.501 + RequestMapEntry *entry = 1.502 + static_cast<RequestMapEntry *> 1.503 + (PL_DHashTableOperate(&mRequests, request, 1.504 + PL_DHASH_LOOKUP)); 1.505 + 1.506 + NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(entry), 1.507 + "Entry added to loadgroup twice, don't do that"); 1.508 + } 1.509 +#endif 1.510 + 1.511 + // 1.512 + // Do not add the channel, if the loadgroup is being canceled... 1.513 + // 1.514 + if (mIsCanceling) { 1.515 + 1.516 +#if defined(PR_LOGGING) 1.517 + LOG(("LOADGROUP [%x]: AddChannel() ABORTED because LoadGroup is" 1.518 + " being canceled!!\n", this)); 1.519 +#endif /* PR_LOGGING */ 1.520 + 1.521 + return NS_BINDING_ABORTED; 1.522 + } 1.523 + 1.524 + nsLoadFlags flags; 1.525 + // if the request is the default load request or if the default 1.526 + // load request is null, then the load group should inherit its 1.527 + // load flags from the request. 1.528 + if (mDefaultLoadRequest == request || !mDefaultLoadRequest) 1.529 + rv = request->GetLoadFlags(&flags); 1.530 + else 1.531 + rv = MergeLoadFlags(request, flags); 1.532 + if (NS_FAILED(rv)) return rv; 1.533 + 1.534 + // 1.535 + // Add the request to the list of active requests... 1.536 + // 1.537 + 1.538 + RequestMapEntry *entry = 1.539 + static_cast<RequestMapEntry *> 1.540 + (PL_DHashTableOperate(&mRequests, request, 1.541 + PL_DHASH_ADD)); 1.542 + 1.543 + if (!entry) { 1.544 + return NS_ERROR_OUT_OF_MEMORY; 1.545 + } 1.546 + 1.547 + if (mPriority != 0) 1.548 + RescheduleRequest(request, mPriority); 1.549 + 1.550 + nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request); 1.551 + if (timedChannel) 1.552 + timedChannel->SetTimingEnabled(true); 1.553 + 1.554 + if (!(flags & nsIRequest::LOAD_BACKGROUND)) { 1.555 + // Update the count of foreground URIs.. 1.556 + mForegroundCount += 1; 1.557 + 1.558 + // 1.559 + // Fire the OnStartRequest notification out to the observer... 1.560 + // 1.561 + // If the notification fails then DO NOT add the request to 1.562 + // the load group. 1.563 + // 1.564 + nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); 1.565 + if (observer) { 1.566 + LOG(("LOADGROUP [%x]: Firing OnStartRequest for request %x." 1.567 + "(foreground count=%d).\n", this, request, mForegroundCount)); 1.568 + 1.569 + rv = observer->OnStartRequest(request, ctxt); 1.570 + if (NS_FAILED(rv)) { 1.571 + LOG(("LOADGROUP [%x]: OnStartRequest for request %x FAILED.\n", 1.572 + this, request)); 1.573 + // 1.574 + // The URI load has been canceled by the observer. Clean up 1.575 + // the damage... 1.576 + // 1.577 + 1.578 + PL_DHashTableOperate(&mRequests, request, PL_DHASH_REMOVE); 1.579 + 1.580 + rv = NS_OK; 1.581 + 1.582 + mForegroundCount -= 1; 1.583 + } 1.584 + } 1.585 + 1.586 + // Ensure that we're part of our loadgroup while pending 1.587 + if (mForegroundCount == 1 && mLoadGroup) { 1.588 + mLoadGroup->AddRequest(this, nullptr); 1.589 + } 1.590 + 1.591 + } 1.592 + 1.593 + return rv; 1.594 +} 1.595 + 1.596 +NS_IMETHODIMP 1.597 +nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt, 1.598 + nsresult aStatus) 1.599 +{ 1.600 + NS_ENSURE_ARG_POINTER(request); 1.601 + nsresult rv; 1.602 + 1.603 +#if defined(PR_LOGGING) 1.604 + { 1.605 + nsAutoCString nameStr; 1.606 + request->GetName(nameStr); 1.607 + LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n", 1.608 + this, request, nameStr.get(), aStatus, mRequests.entryCount-1)); 1.609 + } 1.610 +#endif 1.611 + 1.612 + // Make sure we have a owning reference to the request we're about 1.613 + // to remove. 1.614 + 1.615 + nsCOMPtr<nsIRequest> kungFuDeathGrip(request); 1.616 + 1.617 + // 1.618 + // Remove the request from the group. If this fails, it means that 1.619 + // the request was *not* in the group so do not update the foreground 1.620 + // count or it will get messed up... 1.621 + // 1.622 + RequestMapEntry *entry = 1.623 + static_cast<RequestMapEntry *> 1.624 + (PL_DHashTableOperate(&mRequests, request, 1.625 + PL_DHASH_LOOKUP)); 1.626 + 1.627 + if (PL_DHASH_ENTRY_IS_FREE(entry)) { 1.628 + LOG(("LOADGROUP [%x]: Unable to remove request %x. Not in group!\n", 1.629 + this, request)); 1.630 + 1.631 + return NS_ERROR_FAILURE; 1.632 + } 1.633 + 1.634 + PL_DHashTableRawRemove(&mRequests, entry); 1.635 + 1.636 + // Collect telemetry stats only when default request is a timed channel. 1.637 + // Don't include failed requests in the timing statistics. 1.638 + if (mDefaultLoadIsTimed && NS_SUCCEEDED(aStatus)) { 1.639 + nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request); 1.640 + if (timedChannel) { 1.641 + // Figure out if this request was served from the cache 1.642 + ++mTimedRequests; 1.643 + TimeStamp timeStamp; 1.644 + rv = timedChannel->GetCacheReadStart(&timeStamp); 1.645 + if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { 1.646 + ++mCachedRequests; 1.647 + } 1.648 + else { 1.649 + mTimedNonCachedRequestsUntilOnEndPageLoad++; 1.650 + } 1.651 + 1.652 + rv = timedChannel->GetAsyncOpen(&timeStamp); 1.653 + if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { 1.654 + Telemetry::AccumulateTimeDelta( 1.655 + Telemetry::HTTP_SUBITEM_OPEN_LATENCY_TIME, 1.656 + mDefaultRequestCreationTime, timeStamp); 1.657 + } 1.658 + 1.659 + rv = timedChannel->GetResponseStart(&timeStamp); 1.660 + if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { 1.661 + Telemetry::AccumulateTimeDelta( 1.662 + Telemetry::HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME, 1.663 + mDefaultRequestCreationTime, timeStamp); 1.664 + } 1.665 + 1.666 + TelemetryReportChannel(timedChannel, false); 1.667 + } 1.668 + } 1.669 + 1.670 + if (mRequests.entryCount == 0) { 1.671 + TelemetryReport(); 1.672 + } 1.673 + 1.674 + // Undo any group priority delta... 1.675 + if (mPriority != 0) 1.676 + RescheduleRequest(request, -mPriority); 1.677 + 1.678 + nsLoadFlags flags; 1.679 + rv = request->GetLoadFlags(&flags); 1.680 + if (NS_FAILED(rv)) return rv; 1.681 + 1.682 + if (!(flags & nsIRequest::LOAD_BACKGROUND)) { 1.683 + NS_ASSERTION(mForegroundCount > 0, "ForegroundCount messed up"); 1.684 + mForegroundCount -= 1; 1.685 + 1.686 + // Fire the OnStopRequest out to the observer... 1.687 + nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); 1.688 + if (observer) { 1.689 + LOG(("LOADGROUP [%x]: Firing OnStopRequest for request %x." 1.690 + "(foreground count=%d).\n", this, request, mForegroundCount)); 1.691 + 1.692 + rv = observer->OnStopRequest(request, ctxt, aStatus); 1.693 + 1.694 +#if defined(PR_LOGGING) 1.695 + if (NS_FAILED(rv)) { 1.696 + LOG(("LOADGROUP [%x]: OnStopRequest for request %x FAILED.\n", 1.697 + this, request)); 1.698 + } 1.699 +#endif 1.700 + } 1.701 + 1.702 + // If that was the last request -> remove ourselves from loadgroup 1.703 + if (mForegroundCount == 0 && mLoadGroup) { 1.704 + mLoadGroup->RemoveRequest(this, nullptr, aStatus); 1.705 + } 1.706 + } 1.707 + 1.708 + return rv; 1.709 +} 1.710 + 1.711 +// PLDHashTable enumeration callback that appends all items in the 1.712 +// hash to an nsCOMArray 1.713 +static PLDHashOperator 1.714 +AppendRequestsToCOMArray(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.715 + uint32_t number, void *arg) 1.716 +{ 1.717 + RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr); 1.718 + static_cast<nsCOMArray<nsIRequest>*>(arg)->AppendObject(e->mKey); 1.719 + return PL_DHASH_NEXT; 1.720 +} 1.721 + 1.722 +NS_IMETHODIMP 1.723 +nsLoadGroup::GetRequests(nsISimpleEnumerator * *aRequests) 1.724 +{ 1.725 + nsCOMArray<nsIRequest> requests; 1.726 + requests.SetCapacity(mRequests.entryCount); 1.727 + 1.728 + PL_DHashTableEnumerate(&mRequests, AppendRequestsToCOMArray, &requests); 1.729 + 1.730 + return NS_NewArrayEnumerator(aRequests, requests); 1.731 +} 1.732 + 1.733 +NS_IMETHODIMP 1.734 +nsLoadGroup::SetGroupObserver(nsIRequestObserver* aObserver) 1.735 +{ 1.736 + mObserver = do_GetWeakReference(aObserver); 1.737 + return NS_OK; 1.738 +} 1.739 + 1.740 +NS_IMETHODIMP 1.741 +nsLoadGroup::GetGroupObserver(nsIRequestObserver* *aResult) 1.742 +{ 1.743 + nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); 1.744 + *aResult = observer; 1.745 + NS_IF_ADDREF(*aResult); 1.746 + return NS_OK; 1.747 +} 1.748 + 1.749 +NS_IMETHODIMP 1.750 +nsLoadGroup::GetActiveCount(uint32_t* aResult) 1.751 +{ 1.752 + *aResult = mForegroundCount; 1.753 + return NS_OK; 1.754 +} 1.755 + 1.756 +NS_IMETHODIMP 1.757 +nsLoadGroup::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks) 1.758 +{ 1.759 + NS_ENSURE_ARG_POINTER(aCallbacks); 1.760 + *aCallbacks = mCallbacks; 1.761 + NS_IF_ADDREF(*aCallbacks); 1.762 + return NS_OK; 1.763 +} 1.764 + 1.765 +NS_IMETHODIMP 1.766 +nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks) 1.767 +{ 1.768 + mCallbacks = aCallbacks; 1.769 + return NS_OK; 1.770 +} 1.771 + 1.772 +NS_IMETHODIMP 1.773 +nsLoadGroup::GetConnectionInfo(nsILoadGroupConnectionInfo **aCI) 1.774 +{ 1.775 + NS_ENSURE_ARG_POINTER(aCI); 1.776 + *aCI = mConnectionInfo; 1.777 + NS_IF_ADDREF(*aCI); 1.778 + return NS_OK; 1.779 +} 1.780 + 1.781 +//////////////////////////////////////////////////////////////////////////////// 1.782 +// nsILoadGroupChild methods: 1.783 + 1.784 +/* attribute nsILoadGroup parentLoadGroup; */ 1.785 +NS_IMETHODIMP 1.786 +nsLoadGroup::GetParentLoadGroup(nsILoadGroup * *aParentLoadGroup) 1.787 +{ 1.788 + *aParentLoadGroup = nullptr; 1.789 + nsCOMPtr<nsILoadGroup> parent = do_QueryReferent(mParentLoadGroup); 1.790 + if (!parent) 1.791 + return NS_OK; 1.792 + parent.forget(aParentLoadGroup); 1.793 + return NS_OK; 1.794 +} 1.795 + 1.796 +NS_IMETHODIMP 1.797 +nsLoadGroup::SetParentLoadGroup(nsILoadGroup *aParentLoadGroup) 1.798 +{ 1.799 + mParentLoadGroup = do_GetWeakReference(aParentLoadGroup); 1.800 + return NS_OK; 1.801 +} 1.802 + 1.803 +/* readonly attribute nsILoadGroup childLoadGroup; */ 1.804 +NS_IMETHODIMP 1.805 +nsLoadGroup::GetChildLoadGroup(nsILoadGroup * *aChildLoadGroup) 1.806 +{ 1.807 + NS_ADDREF(*aChildLoadGroup = this); 1.808 + return NS_OK; 1.809 +} 1.810 + 1.811 +/* readonly attribute nsILoadGroup rootLoadGroup; */ 1.812 +NS_IMETHODIMP 1.813 +nsLoadGroup::GetRootLoadGroup(nsILoadGroup * *aRootLoadGroup) 1.814 +{ 1.815 + // first recursively try the root load group of our parent 1.816 + nsCOMPtr<nsILoadGroupChild> ancestor = do_QueryReferent(mParentLoadGroup); 1.817 + if (ancestor) 1.818 + return ancestor->GetRootLoadGroup(aRootLoadGroup); 1.819 + 1.820 + // next recursively try the root load group of our own load grop 1.821 + ancestor = do_QueryInterface(mLoadGroup); 1.822 + if (ancestor) 1.823 + return ancestor->GetRootLoadGroup(aRootLoadGroup); 1.824 + 1.825 + // finally just return this 1.826 + NS_ADDREF(*aRootLoadGroup = this); 1.827 + return NS_OK; 1.828 +} 1.829 + 1.830 +//////////////////////////////////////////////////////////////////////////////// 1.831 +// nsPILoadGroupInternal methods: 1.832 + 1.833 +NS_IMETHODIMP 1.834 +nsLoadGroup::OnEndPageLoad(nsIChannel *aDefaultChannel) 1.835 +{ 1.836 + // for the moment, nothing to do here. 1.837 + return NS_OK; 1.838 +} 1.839 + 1.840 +//////////////////////////////////////////////////////////////////////////////// 1.841 +// nsISupportsPriority methods: 1.842 + 1.843 +NS_IMETHODIMP 1.844 +nsLoadGroup::GetPriority(int32_t *aValue) 1.845 +{ 1.846 + *aValue = mPriority; 1.847 + return NS_OK; 1.848 +} 1.849 + 1.850 +NS_IMETHODIMP 1.851 +nsLoadGroup::SetPriority(int32_t aValue) 1.852 +{ 1.853 + return AdjustPriority(aValue - mPriority); 1.854 +} 1.855 + 1.856 +NS_IMETHODIMP 1.857 +nsLoadGroup::AdjustPriority(int32_t aDelta) 1.858 +{ 1.859 + // Update the priority for each request that supports nsISupportsPriority 1.860 + if (aDelta != 0) { 1.861 + mPriority += aDelta; 1.862 + PL_DHashTableEnumerate(&mRequests, RescheduleRequests, &aDelta); 1.863 + } 1.864 + return NS_OK; 1.865 +} 1.866 + 1.867 +NS_IMETHODIMP 1.868 +nsLoadGroup::GetDefaultLoadFlags(uint32_t *aFlags) 1.869 +{ 1.870 + *aFlags = mDefaultLoadFlags; 1.871 + return NS_OK; 1.872 +} 1.873 + 1.874 +NS_IMETHODIMP 1.875 +nsLoadGroup::SetDefaultLoadFlags(uint32_t aFlags) 1.876 +{ 1.877 + mDefaultLoadFlags = aFlags; 1.878 + return NS_OK; 1.879 +} 1.880 + 1.881 + 1.882 +//////////////////////////////////////////////////////////////////////////////// 1.883 + 1.884 +void 1.885 +nsLoadGroup::TelemetryReport() 1.886 +{ 1.887 + if (mDefaultLoadIsTimed) { 1.888 + Telemetry::Accumulate(Telemetry::HTTP_REQUEST_PER_PAGE, mTimedRequests); 1.889 + if (mTimedRequests) { 1.890 + Telemetry::Accumulate(Telemetry::HTTP_REQUEST_PER_PAGE_FROM_CACHE, 1.891 + mCachedRequests * 100 / mTimedRequests); 1.892 + } 1.893 + 1.894 + nsCOMPtr<nsITimedChannel> timedChannel = 1.895 + do_QueryInterface(mDefaultLoadRequest); 1.896 + if (timedChannel) 1.897 + TelemetryReportChannel(timedChannel, true); 1.898 + } 1.899 + 1.900 + mTimedRequests = 0; 1.901 + mCachedRequests = 0; 1.902 + mDefaultLoadIsTimed = false; 1.903 +} 1.904 + 1.905 +void 1.906 +nsLoadGroup::TelemetryReportChannel(nsITimedChannel *aTimedChannel, 1.907 + bool aDefaultRequest) 1.908 +{ 1.909 + nsresult rv; 1.910 + bool timingEnabled; 1.911 + rv = aTimedChannel->GetTimingEnabled(&timingEnabled); 1.912 + if (NS_FAILED(rv) || !timingEnabled) 1.913 + return; 1.914 + 1.915 + TimeStamp asyncOpen; 1.916 + rv = aTimedChannel->GetAsyncOpen(&asyncOpen); 1.917 + // We do not check !asyncOpen.IsNull() bellow, prevent ASSERTIONs this way 1.918 + if (NS_FAILED(rv) || asyncOpen.IsNull()) 1.919 + return; 1.920 + 1.921 + TimeStamp cacheReadStart; 1.922 + rv = aTimedChannel->GetCacheReadStart(&cacheReadStart); 1.923 + if (NS_FAILED(rv)) 1.924 + return; 1.925 + 1.926 + TimeStamp cacheReadEnd; 1.927 + rv = aTimedChannel->GetCacheReadEnd(&cacheReadEnd); 1.928 + if (NS_FAILED(rv)) 1.929 + return; 1.930 + 1.931 + TimeStamp domainLookupStart; 1.932 + rv = aTimedChannel->GetDomainLookupStart(&domainLookupStart); 1.933 + if (NS_FAILED(rv)) 1.934 + return; 1.935 + 1.936 + TimeStamp domainLookupEnd; 1.937 + rv = aTimedChannel->GetDomainLookupEnd(&domainLookupEnd); 1.938 + if (NS_FAILED(rv)) 1.939 + return; 1.940 + 1.941 + TimeStamp connectStart; 1.942 + rv = aTimedChannel->GetConnectStart(&connectStart); 1.943 + if (NS_FAILED(rv)) 1.944 + return; 1.945 + 1.946 + TimeStamp connectEnd; 1.947 + rv = aTimedChannel->GetConnectEnd(&connectEnd); 1.948 + if (NS_FAILED(rv)) 1.949 + return; 1.950 + 1.951 + TimeStamp requestStart; 1.952 + rv = aTimedChannel->GetRequestStart(&requestStart); 1.953 + if (NS_FAILED(rv)) 1.954 + return; 1.955 + 1.956 + TimeStamp responseStart; 1.957 + rv = aTimedChannel->GetResponseStart(&responseStart); 1.958 + if (NS_FAILED(rv)) 1.959 + return; 1.960 + 1.961 + TimeStamp responseEnd; 1.962 + rv = aTimedChannel->GetResponseEnd(&responseEnd); 1.963 + if (NS_FAILED(rv)) 1.964 + return; 1.965 + 1.966 +#define HTTP_REQUEST_HISTOGRAMS(prefix) \ 1.967 + if (!domainLookupStart.IsNull()) { \ 1.968 + Telemetry::AccumulateTimeDelta( \ 1.969 + Telemetry::HTTP_##prefix##_DNS_ISSUE_TIME, \ 1.970 + asyncOpen, domainLookupStart); \ 1.971 + } \ 1.972 + \ 1.973 + if (!domainLookupStart.IsNull() && !domainLookupEnd.IsNull()) { \ 1.974 + Telemetry::AccumulateTimeDelta( \ 1.975 + Telemetry::HTTP_##prefix##_DNS_LOOKUP_TIME, \ 1.976 + domainLookupStart, domainLookupEnd); \ 1.977 + } \ 1.978 + \ 1.979 + if (!connectStart.IsNull() && !connectEnd.IsNull()) { \ 1.980 + Telemetry::AccumulateTimeDelta( \ 1.981 + Telemetry::HTTP_##prefix##_TCP_CONNECTION, \ 1.982 + connectStart, connectEnd); \ 1.983 + } \ 1.984 + \ 1.985 + \ 1.986 + if (!requestStart.IsNull() && !responseEnd.IsNull()) { \ 1.987 + Telemetry::AccumulateTimeDelta( \ 1.988 + Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_SENT, \ 1.989 + asyncOpen, requestStart); \ 1.990 + \ 1.991 + Telemetry::AccumulateTimeDelta( \ 1.992 + Telemetry::HTTP_##prefix##_FIRST_SENT_TO_LAST_RECEIVED, \ 1.993 + requestStart, responseEnd); \ 1.994 + \ 1.995 + if (cacheReadStart.IsNull() && !responseStart.IsNull()) { \ 1.996 + Telemetry::AccumulateTimeDelta( \ 1.997 + Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_RECEIVED, \ 1.998 + asyncOpen, responseStart); \ 1.999 + } \ 1.1000 + } \ 1.1001 + \ 1.1002 + if (!cacheReadStart.IsNull() && !cacheReadEnd.IsNull()) { \ 1.1003 + if (!CacheObserver::UseNewCache()) { \ 1.1004 + Telemetry::AccumulateTimeDelta( \ 1.1005 + Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_FROM_CACHE, \ 1.1006 + asyncOpen, cacheReadStart); \ 1.1007 + } else { \ 1.1008 + Telemetry::AccumulateTimeDelta( \ 1.1009 + Telemetry::HTTP_##prefix##_OPEN_TO_FIRST_FROM_CACHE_V2, \ 1.1010 + asyncOpen, cacheReadStart); \ 1.1011 + } \ 1.1012 + \ 1.1013 + if (!CacheObserver::UseNewCache()) { \ 1.1014 + Telemetry::AccumulateTimeDelta( \ 1.1015 + Telemetry::HTTP_##prefix##_CACHE_READ_TIME, \ 1.1016 + cacheReadStart, cacheReadEnd); \ 1.1017 + } else { \ 1.1018 + Telemetry::AccumulateTimeDelta( \ 1.1019 + Telemetry::HTTP_##prefix##_CACHE_READ_TIME_V2, \ 1.1020 + cacheReadStart, cacheReadEnd); \ 1.1021 + } \ 1.1022 + \ 1.1023 + if (!requestStart.IsNull() && !responseEnd.IsNull()) { \ 1.1024 + Telemetry::AccumulateTimeDelta( \ 1.1025 + Telemetry::HTTP_##prefix##_REVALIDATION, \ 1.1026 + requestStart, responseEnd); \ 1.1027 + } \ 1.1028 + } \ 1.1029 + \ 1.1030 + if (!cacheReadEnd.IsNull()) { \ 1.1031 + Telemetry::AccumulateTimeDelta( \ 1.1032 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD, \ 1.1033 + asyncOpen, cacheReadEnd); \ 1.1034 + \ 1.1035 + if (!CacheObserver::UseNewCache()) { \ 1.1036 + Telemetry::AccumulateTimeDelta( \ 1.1037 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD_CACHED, \ 1.1038 + asyncOpen, cacheReadEnd); \ 1.1039 + } else { \ 1.1040 + Telemetry::AccumulateTimeDelta( \ 1.1041 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD_CACHED_V2, \ 1.1042 + asyncOpen, cacheReadEnd); \ 1.1043 + } \ 1.1044 + } \ 1.1045 + else if (!responseEnd.IsNull()) { \ 1.1046 + if (!CacheObserver::UseNewCache()) { \ 1.1047 + Telemetry::AccumulateTimeDelta( \ 1.1048 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD, \ 1.1049 + asyncOpen, responseEnd); \ 1.1050 + Telemetry::AccumulateTimeDelta( \ 1.1051 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD_NET, \ 1.1052 + asyncOpen, responseEnd); \ 1.1053 + } else { \ 1.1054 + Telemetry::AccumulateTimeDelta( \ 1.1055 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD_V2, \ 1.1056 + asyncOpen, responseEnd); \ 1.1057 + Telemetry::AccumulateTimeDelta( \ 1.1058 + Telemetry::HTTP_##prefix##_COMPLETE_LOAD_NET_V2, \ 1.1059 + asyncOpen, responseEnd); \ 1.1060 + } \ 1.1061 + } 1.1062 + 1.1063 + if (aDefaultRequest) { 1.1064 + HTTP_REQUEST_HISTOGRAMS(PAGE) 1.1065 + } else { 1.1066 + HTTP_REQUEST_HISTOGRAMS(SUB) 1.1067 + } 1.1068 +#undef HTTP_REQUEST_HISTOGRAMS 1.1069 +} 1.1070 + 1.1071 +nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags) 1.1072 +{ 1.1073 + nsresult rv; 1.1074 + nsLoadFlags flags, oldFlags; 1.1075 + 1.1076 + rv = aRequest->GetLoadFlags(&flags); 1.1077 + if (NS_FAILED(rv)) 1.1078 + return rv; 1.1079 + 1.1080 + oldFlags = flags; 1.1081 + 1.1082 + // Inherit the following bits... 1.1083 + flags |= (mLoadFlags & (LOAD_BACKGROUND | 1.1084 + LOAD_BYPASS_CACHE | 1.1085 + LOAD_FROM_CACHE | 1.1086 + VALIDATE_ALWAYS | 1.1087 + VALIDATE_ONCE_PER_SESSION | 1.1088 + VALIDATE_NEVER)); 1.1089 + 1.1090 + // ... and force the default flags. 1.1091 + flags |= mDefaultLoadFlags; 1.1092 + 1.1093 + if (flags != oldFlags) 1.1094 + rv = aRequest->SetLoadFlags(flags); 1.1095 + 1.1096 + outFlags = flags; 1.1097 + return rv; 1.1098 +} 1.1099 + 1.1100 +// nsLoadGroupConnectionInfo 1.1101 + 1.1102 +class nsLoadGroupConnectionInfo MOZ_FINAL : public nsILoadGroupConnectionInfo 1.1103 +{ 1.1104 +public: 1.1105 + NS_DECL_THREADSAFE_ISUPPORTS 1.1106 + NS_DECL_NSILOADGROUPCONNECTIONINFO 1.1107 + 1.1108 + nsLoadGroupConnectionInfo(); 1.1109 +private: 1.1110 + Atomic<uint32_t> mBlockingTransactionCount; 1.1111 + nsAutoPtr<mozilla::net::SpdyPushCache> mSpdyCache; 1.1112 +}; 1.1113 + 1.1114 +NS_IMPL_ISUPPORTS(nsLoadGroupConnectionInfo, nsILoadGroupConnectionInfo) 1.1115 + 1.1116 +nsLoadGroupConnectionInfo::nsLoadGroupConnectionInfo() 1.1117 + : mBlockingTransactionCount(0) 1.1118 +{ 1.1119 +} 1.1120 + 1.1121 +NS_IMETHODIMP 1.1122 +nsLoadGroupConnectionInfo::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount) 1.1123 +{ 1.1124 + NS_ENSURE_ARG_POINTER(aBlockingTransactionCount); 1.1125 + *aBlockingTransactionCount = mBlockingTransactionCount; 1.1126 + return NS_OK; 1.1127 +} 1.1128 + 1.1129 +NS_IMETHODIMP 1.1130 +nsLoadGroupConnectionInfo::AddBlockingTransaction() 1.1131 +{ 1.1132 + mBlockingTransactionCount++; 1.1133 + return NS_OK; 1.1134 +} 1.1135 + 1.1136 +NS_IMETHODIMP 1.1137 +nsLoadGroupConnectionInfo::RemoveBlockingTransaction(uint32_t *_retval) 1.1138 +{ 1.1139 + NS_ENSURE_ARG_POINTER(_retval); 1.1140 + mBlockingTransactionCount--; 1.1141 + *_retval = mBlockingTransactionCount; 1.1142 + return NS_OK; 1.1143 +} 1.1144 + 1.1145 +/* [noscript] attribute SpdyPushCachePtr spdyPushCache; */ 1.1146 +NS_IMETHODIMP 1.1147 +nsLoadGroupConnectionInfo::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache) 1.1148 +{ 1.1149 + *aSpdyPushCache = mSpdyCache.get(); 1.1150 + return NS_OK; 1.1151 +} 1.1152 + 1.1153 +NS_IMETHODIMP 1.1154 +nsLoadGroupConnectionInfo::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache) 1.1155 +{ 1.1156 + mSpdyCache = aSpdyPushCache; 1.1157 + return NS_OK; 1.1158 +} 1.1159 + 1.1160 +nsresult nsLoadGroup::Init() 1.1161 +{ 1.1162 + static const PLDHashTableOps hash_table_ops = 1.1163 + { 1.1164 + PL_DHashAllocTable, 1.1165 + PL_DHashFreeTable, 1.1166 + PL_DHashVoidPtrKeyStub, 1.1167 + RequestHashMatchEntry, 1.1168 + PL_DHashMoveEntryStub, 1.1169 + RequestHashClearEntry, 1.1170 + PL_DHashFinalizeStub, 1.1171 + RequestHashInitEntry 1.1172 + }; 1.1173 + 1.1174 + PL_DHashTableInit(&mRequests, &hash_table_ops, nullptr, 1.1175 + sizeof(RequestMapEntry), 16); 1.1176 + 1.1177 + mConnectionInfo = new nsLoadGroupConnectionInfo(); 1.1178 + 1.1179 + return NS_OK; 1.1180 +} 1.1181 + 1.1182 +#undef LOG