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