static PLDHashOperator RescheduleRequests(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg) { RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr); PRInt32 *delta = static_cast<PRInt32 *>(arg); RescheduleRequest(e->mKey, *delta); return PL_DHASH_NEXT; }
NS_IMETHODIMP nsLoadGroup::AdjustPriority(int32_t aDelta) { // Update the priority for each request that supports nsISupportsPriority if (aDelta != 0) { mPriority += aDelta; for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) { auto e = static_cast<RequestMapEntry*>(iter.Get()); RescheduleRequest(e->mKey, aDelta); } } return NS_OK; }
NS_IMETHODIMP nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt, nsresult aStatus) { NS_ENSURE_ARG_POINTER(request); nsresult rv; #if defined(PR_LOGGING) { nsCAutoString nameStr; request->GetName(nameStr); LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n", this, request, nameStr.get(), aStatus, mRequests.entryCount-1)); } #endif // Make sure we have a owning reference to the request we're about // to remove. nsCOMPtr<nsIRequest> kungFuDeathGrip(request); // // Remove the request from the group. If this fails, it means that // the request was *not* in the group so do not update the foreground // count or it will get messed up... // RequestMapEntry *entry = static_cast<RequestMapEntry *> (PL_DHashTableOperate(&mRequests, request, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_FREE(entry)) { LOG(("LOADGROUP [%x]: Unable to remove request %x. Not in group!\n", this, request)); return NS_ERROR_FAILURE; } PL_DHashTableRawRemove(&mRequests, entry); // Undo any group priority delta... if (mPriority != 0) RescheduleRequest(request, -mPriority); nsLoadFlags flags; rv = request->GetLoadFlags(&flags); if (NS_FAILED(rv)) return rv; if (!(flags & nsIRequest::LOAD_BACKGROUND)) { NS_ASSERTION(mForegroundCount > 0, "ForegroundCount messed up"); mForegroundCount -= 1; // Fire the OnStopRequest out to the observer... nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); if (observer) { LOG(("LOADGROUP [%x]: Firing OnStopRequest for request %x." "(foreground count=%d).\n", this, request, mForegroundCount)); rv = observer->OnStopRequest(request, ctxt, aStatus); #if defined(PR_LOGGING) if (NS_FAILED(rv)) { LOG(("LOADGROUP [%x]: OnStopRequest for request %x FAILED.\n", this, request)); } #endif } // If that was the last request -> remove ourselves from loadgroup if (mForegroundCount == 0 && mLoadGroup) { mLoadGroup->RemoveRequest(this, nsnull, aStatus); } } return rv; }
NS_IMETHODIMP nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt) { nsresult rv; #if defined(PR_LOGGING) { nsCAutoString nameStr; request->GetName(nameStr); LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n", this, request, nameStr.get(), mRequests.entryCount)); } #endif /* PR_LOGGING */ #ifdef DEBUG { RequestMapEntry *entry = static_cast<RequestMapEntry *> (PL_DHashTableOperate(&mRequests, request, PL_DHASH_LOOKUP)); NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(entry), "Entry added to loadgroup twice, don't do that"); } #endif // // Do not add the channel, if the loadgroup is being canceled... // if (mIsCanceling) { #if defined(PR_LOGGING) LOG(("LOADGROUP [%x]: AddChannel() ABORTED because LoadGroup is" " being canceled!!\n", this)); #endif /* PR_LOGGING */ return NS_BINDING_ABORTED; } nsLoadFlags flags; // if the request is the default load request or if the default // load request is null, then the load group should inherit its // load flags from the request. if (mDefaultLoadRequest == request || !mDefaultLoadRequest) rv = request->GetLoadFlags(&flags); else rv = MergeLoadFlags(request, flags); if (NS_FAILED(rv)) return rv; // // Add the request to the list of active requests... // RequestMapEntry *entry = static_cast<RequestMapEntry *> (PL_DHashTableOperate(&mRequests, request, PL_DHASH_ADD)); if (!entry) { return NS_ERROR_OUT_OF_MEMORY; } if (mPriority != 0) RescheduleRequest(request, mPriority); if (!(flags & nsIRequest::LOAD_BACKGROUND)) { // Update the count of foreground URIs.. mForegroundCount += 1; // // Fire the OnStartRequest notification out to the observer... // // If the notification fails then DO NOT add the request to // the load group. // nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); if (observer) { LOG(("LOADGROUP [%x]: Firing OnStartRequest for request %x." "(foreground count=%d).\n", this, request, mForegroundCount)); rv = observer->OnStartRequest(request, ctxt); if (NS_FAILED(rv)) { LOG(("LOADGROUP [%x]: OnStartRequest for request %x FAILED.\n", this, request)); // // The URI load has been canceled by the observer. Clean up // the damage... // PL_DHashTableOperate(&mRequests, request, PL_DHASH_REMOVE); rv = NS_OK; mForegroundCount -= 1; } } // Ensure that we're part of our loadgroup while pending if (mForegroundCount == 1 && mLoadGroup) { mLoadGroup->AddRequest(this, nsnull); } } return rv; }
NS_IMETHODIMP nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt, nsresult aStatus) { NS_ENSURE_ARG_POINTER(request); nsresult rv; if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) { nsAutoCString nameStr; request->GetName(nameStr); LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n", this, request, nameStr.get(), aStatus, mRequests.EntryCount() - 1)); } // Make sure we have a owning reference to the request we're about // to remove. nsCOMPtr<nsIRequest> kungFuDeathGrip(request); // // Remove the request from the group. If this fails, it means that // the request was *not* in the group so do not update the foreground // count or it will get messed up... // auto entry = static_cast<RequestMapEntry*>(mRequests.Search(request)); if (!entry) { LOG(("LOADGROUP [%x]: Unable to remove request %x. Not in group!\n", this, request)); return NS_ERROR_FAILURE; } mRequests.RemoveEntry(entry); // Collect telemetry stats only when default request is a timed channel. // Don't include failed requests in the timing statistics. if (mDefaultLoadIsTimed && NS_SUCCEEDED(aStatus)) { nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request); if (timedChannel) { // Figure out if this request was served from the cache ++mTimedRequests; TimeStamp timeStamp; rv = timedChannel->GetCacheReadStart(&timeStamp); if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { ++mCachedRequests; } else { mTimedNonCachedRequestsUntilOnEndPageLoad++; } rv = timedChannel->GetAsyncOpen(&timeStamp); if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { Telemetry::AccumulateTimeDelta( Telemetry::HTTP_SUBITEM_OPEN_LATENCY_TIME, mDefaultRequestCreationTime, timeStamp); } rv = timedChannel->GetResponseStart(&timeStamp); if (NS_SUCCEEDED(rv) && !timeStamp.IsNull()) { Telemetry::AccumulateTimeDelta( Telemetry::HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME, mDefaultRequestCreationTime, timeStamp); } TelemetryReportChannel(timedChannel, false); } } if (mRequests.EntryCount() == 0) { TelemetryReport(); } // Undo any group priority delta... if (mPriority != 0) RescheduleRequest(request, -mPriority); nsLoadFlags flags; rv = request->GetLoadFlags(&flags); if (NS_FAILED(rv)) return rv; if (!(flags & nsIRequest::LOAD_BACKGROUND)) { NS_ASSERTION(mForegroundCount > 0, "ForegroundCount messed up"); mForegroundCount -= 1; // Fire the OnStopRequest out to the observer... nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); if (observer) { LOG(("LOADGROUP [%x]: Firing OnStopRequest for request %x." "(foreground count=%d).\n", this, request, mForegroundCount)); rv = observer->OnStopRequest(request, ctxt, aStatus); if (NS_FAILED(rv)) { LOG(("LOADGROUP [%x]: OnStopRequest for request %x FAILED.\n", this, request)); } } // If that was the last request -> remove ourselves from loadgroup if (mForegroundCount == 0 && mLoadGroup) { mLoadGroup->RemoveRequest(this, nullptr, aStatus); } } return rv; }
NS_IMETHODIMP nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt) { nsresult rv; if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) { nsAutoCString nameStr; request->GetName(nameStr); LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n", this, request, nameStr.get(), mRequests.EntryCount())); } NS_ASSERTION(!mRequests.Search(request), "Entry added to loadgroup twice, don't do that"); // // Do not add the channel, if the loadgroup is being canceled... // if (mIsCanceling) { LOG(("LOADGROUP [%x]: AddChannel() ABORTED because LoadGroup is" " being canceled!!\n", this)); return NS_BINDING_ABORTED; } nsLoadFlags flags; // if the request is the default load request or if the default load // request is null, then the load group should inherit its load flags from // the request, but also we need to enforce defaultLoadFlags. if (mDefaultLoadRequest == request || !mDefaultLoadRequest) { rv = MergeDefaultLoadFlags(request, flags); } else { rv = MergeLoadFlags(request, flags); } if (NS_FAILED(rv)) return rv; // // Add the request to the list of active requests... // auto entry = static_cast<RequestMapEntry*>(mRequests.Add(request, fallible)); if (!entry) { return NS_ERROR_OUT_OF_MEMORY; } if (mPriority != 0) RescheduleRequest(request, mPriority); nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request); if (timedChannel) timedChannel->SetTimingEnabled(true); if (!(flags & nsIRequest::LOAD_BACKGROUND)) { // Update the count of foreground URIs.. mForegroundCount += 1; // // Fire the OnStartRequest notification out to the observer... // // If the notification fails then DO NOT add the request to // the load group. // nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver); if (observer) { LOG(("LOADGROUP [%x]: Firing OnStartRequest for request %x." "(foreground count=%d).\n", this, request, mForegroundCount)); rv = observer->OnStartRequest(request, ctxt); if (NS_FAILED(rv)) { LOG(("LOADGROUP [%x]: OnStartRequest for request %x FAILED.\n", this, request)); // // The URI load has been canceled by the observer. Clean up // the damage... // mRequests.Remove(request); rv = NS_OK; mForegroundCount -= 1; } } // Ensure that we're part of our loadgroup while pending if (mForegroundCount == 1 && mLoadGroup) { mLoadGroup->AddRequest(this, nullptr); } } return rv; }