nsLoadGroup.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/DebugOnly.h"
  6. #include "nsLoadGroup.h"
  7. #include "nsArrayEnumerator.h"
  8. #include "nsCOMArray.h"
  9. #include "nsCOMPtr.h"
  10. #include "mozilla/Logging.h"
  11. #include "nsString.h"
  12. #include "nsTArray.h"
  13. #include "nsITimedChannel.h"
  14. #include "nsIInterfaceRequestor.h"
  15. #include "nsIRequestObserver.h"
  16. #include "nsIRequestContext.h"
  17. #include "CacheObserver.h"
  18. #include "MainThreadUtils.h"
  19. #include "mozilla/net/NeckoChild.h"
  20. namespace mozilla {
  21. namespace net {
  22. //
  23. // Log module for nsILoadGroup logging...
  24. //
  25. // To enable logging (see prlog.h for full details):
  26. //
  27. // set MOZ_LOG=LoadGroup:5
  28. // set MOZ_LOG_FILE=network.log
  29. //
  30. // This enables LogLevel::Debug level information and places all output in
  31. // the file network.log.
  32. //
  33. static LazyLogModule gLoadGroupLog("LoadGroup");
  34. #undef LOG
  35. #define LOG(args) MOZ_LOG(gLoadGroupLog, mozilla::LogLevel::Debug, args)
  36. ////////////////////////////////////////////////////////////////////////////////
  37. class RequestMapEntry : public PLDHashEntryHdr
  38. {
  39. public:
  40. explicit RequestMapEntry(nsIRequest *aRequest) :
  41. mKey(aRequest)
  42. {
  43. }
  44. nsCOMPtr<nsIRequest> mKey;
  45. };
  46. static bool
  47. RequestHashMatchEntry(const PLDHashEntryHdr *entry, const void *key)
  48. {
  49. const RequestMapEntry *e =
  50. static_cast<const RequestMapEntry *>(entry);
  51. const nsIRequest *request = static_cast<const nsIRequest *>(key);
  52. return e->mKey == request;
  53. }
  54. static void
  55. RequestHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
  56. {
  57. RequestMapEntry *e = static_cast<RequestMapEntry *>(entry);
  58. // An entry is being cleared, let the entry do its own cleanup.
  59. e->~RequestMapEntry();
  60. }
  61. static void
  62. RequestHashInitEntry(PLDHashEntryHdr *entry, const void *key)
  63. {
  64. const nsIRequest *const_request = static_cast<const nsIRequest *>(key);
  65. nsIRequest *request = const_cast<nsIRequest *>(const_request);
  66. // Initialize the entry with placement new
  67. new (entry) RequestMapEntry(request);
  68. }
  69. static const PLDHashTableOps sRequestHashOps =
  70. {
  71. PLDHashTable::HashVoidPtrKeyStub,
  72. RequestHashMatchEntry,
  73. PLDHashTable::MoveEntryStub,
  74. RequestHashClearEntry,
  75. RequestHashInitEntry
  76. };
  77. static void
  78. RescheduleRequest(nsIRequest *aRequest, int32_t delta)
  79. {
  80. nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aRequest);
  81. if (p)
  82. p->AdjustPriority(delta);
  83. }
  84. nsLoadGroup::nsLoadGroup(nsISupports* outer)
  85. : mForegroundCount(0)
  86. , mLoadFlags(LOAD_NORMAL)
  87. , mDefaultLoadFlags(0)
  88. , mRequests(&sRequestHashOps, sizeof(RequestMapEntry))
  89. , mStatus(NS_OK)
  90. , mPriority(PRIORITY_NORMAL)
  91. , mIsCanceling(false)
  92. , mDefaultLoadIsTimed(false)
  93. , mTimedRequests(0)
  94. , mCachedRequests(0)
  95. , mTimedNonCachedRequestsUntilOnEndPageLoad(0)
  96. {
  97. NS_INIT_AGGREGATED(outer);
  98. LOG(("LOADGROUP [%x]: Created.\n", this));
  99. }
  100. nsLoadGroup::~nsLoadGroup()
  101. {
  102. DebugOnly<nsresult> rv = Cancel(NS_BINDING_ABORTED);
  103. NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed");
  104. mDefaultLoadRequest = nullptr;
  105. if (mRequestContext) {
  106. nsID rcid;
  107. mRequestContext->GetID(&rcid);
  108. if (IsNeckoChild() && gNeckoChild) {
  109. char rcid_str[NSID_LENGTH];
  110. rcid.ToProvidedString(rcid_str);
  111. nsCString rcid_nscs;
  112. rcid_nscs.AssignASCII(rcid_str);
  113. gNeckoChild->SendRemoveRequestContext(rcid_nscs);
  114. } else {
  115. mRequestContextService->RemoveRequestContext(rcid);
  116. }
  117. }
  118. LOG(("LOADGROUP [%x]: Destroyed.\n", this));
  119. }
  120. ////////////////////////////////////////////////////////////////////////////////
  121. // nsISupports methods:
  122. NS_IMPL_AGGREGATED(nsLoadGroup)
  123. NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsLoadGroup)
  124. NS_INTERFACE_MAP_ENTRY(nsILoadGroup)
  125. NS_INTERFACE_MAP_ENTRY(nsPILoadGroupInternal)
  126. NS_INTERFACE_MAP_ENTRY(nsILoadGroupChild)
  127. NS_INTERFACE_MAP_ENTRY(nsIRequest)
  128. NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
  129. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  130. NS_INTERFACE_MAP_END
  131. ////////////////////////////////////////////////////////////////////////////////
  132. // nsIRequest methods:
  133. NS_IMETHODIMP
  134. nsLoadGroup::GetName(nsACString &result)
  135. {
  136. // XXX is this the right "name" for a load group?
  137. if (!mDefaultLoadRequest) {
  138. result.Truncate();
  139. return NS_OK;
  140. }
  141. return mDefaultLoadRequest->GetName(result);
  142. }
  143. NS_IMETHODIMP
  144. nsLoadGroup::IsPending(bool *aResult)
  145. {
  146. *aResult = (mForegroundCount > 0) ? true : false;
  147. return NS_OK;
  148. }
  149. NS_IMETHODIMP
  150. nsLoadGroup::GetStatus(nsresult *status)
  151. {
  152. if (NS_SUCCEEDED(mStatus) && mDefaultLoadRequest)
  153. return mDefaultLoadRequest->GetStatus(status);
  154. *status = mStatus;
  155. return NS_OK;
  156. }
  157. static bool
  158. AppendRequestsToArray(PLDHashTable* aTable, nsTArray<nsIRequest*> *aArray)
  159. {
  160. for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
  161. auto e = static_cast<RequestMapEntry*>(iter.Get());
  162. nsIRequest *request = e->mKey;
  163. NS_ASSERTION(request, "What? Null key in PLDHashTable entry?");
  164. bool ok = !!aArray->AppendElement(request);
  165. if (!ok) {
  166. break;
  167. }
  168. NS_ADDREF(request);
  169. }
  170. if (aArray->Length() != aTable->EntryCount()) {
  171. for (uint32_t i = 0, len = aArray->Length(); i < len; ++i) {
  172. NS_RELEASE((*aArray)[i]);
  173. }
  174. return false;
  175. }
  176. return true;
  177. }
  178. NS_IMETHODIMP
  179. nsLoadGroup::Cancel(nsresult status)
  180. {
  181. MOZ_ASSERT(NS_IsMainThread());
  182. NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
  183. nsresult rv;
  184. uint32_t count = mRequests.EntryCount();
  185. AutoTArray<nsIRequest*, 8> requests;
  186. if (!AppendRequestsToArray(&mRequests, &requests)) {
  187. return NS_ERROR_OUT_OF_MEMORY;
  188. }
  189. // set the load group status to our cancel status while we cancel
  190. // all our requests...once the cancel is done, we'll reset it...
  191. //
  192. mStatus = status;
  193. // Set the flag indicating that the loadgroup is being canceled... This
  194. // prevents any new channels from being added during the operation.
  195. //
  196. mIsCanceling = true;
  197. nsresult firstError = NS_OK;
  198. while (count > 0) {
  199. nsIRequest* request = requests.ElementAt(--count);
  200. NS_ASSERTION(request, "NULL request found in list.");
  201. if (!mRequests.Search(request)) {
  202. // |request| was removed already
  203. NS_RELEASE(request);
  204. continue;
  205. }
  206. if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
  207. nsAutoCString nameStr;
  208. request->GetName(nameStr);
  209. LOG(("LOADGROUP [%x]: Canceling request %x %s.\n",
  210. this, request, nameStr.get()));
  211. }
  212. //
  213. // Remove the request from the load group... This may cause
  214. // the OnStopRequest notification to fire...
  215. //
  216. // XXX: What should the context be?
  217. //
  218. (void)RemoveRequest(request, nullptr, status);
  219. // Cancel the request...
  220. rv = request->Cancel(status);
  221. // Remember the first failure and return it...
  222. if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
  223. firstError = rv;
  224. NS_RELEASE(request);
  225. }
  226. #if defined(DEBUG)
  227. NS_ASSERTION(mRequests.EntryCount() == 0, "Request list is not empty.");
  228. NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
  229. #endif
  230. mStatus = NS_OK;
  231. mIsCanceling = false;
  232. return firstError;
  233. }
  234. NS_IMETHODIMP
  235. nsLoadGroup::Suspend()
  236. {
  237. nsresult rv, firstError;
  238. uint32_t count = mRequests.EntryCount();
  239. AutoTArray<nsIRequest*, 8> requests;
  240. if (!AppendRequestsToArray(&mRequests, &requests)) {
  241. return NS_ERROR_OUT_OF_MEMORY;
  242. }
  243. firstError = NS_OK;
  244. //
  245. // Operate the elements from back to front so that if items get
  246. // get removed from the list it won't affect our iteration
  247. //
  248. while (count > 0) {
  249. nsIRequest* request = requests.ElementAt(--count);
  250. NS_ASSERTION(request, "NULL request found in list.");
  251. if (!request)
  252. continue;
  253. if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
  254. nsAutoCString nameStr;
  255. request->GetName(nameStr);
  256. LOG(("LOADGROUP [%x]: Suspending request %x %s.\n",
  257. this, request, nameStr.get()));
  258. }
  259. // Suspend the request...
  260. rv = request->Suspend();
  261. // Remember the first failure and return it...
  262. if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
  263. firstError = rv;
  264. NS_RELEASE(request);
  265. }
  266. return firstError;
  267. }
  268. NS_IMETHODIMP
  269. nsLoadGroup::Resume()
  270. {
  271. nsresult rv, firstError;
  272. uint32_t count = mRequests.EntryCount();
  273. AutoTArray<nsIRequest*, 8> requests;
  274. if (!AppendRequestsToArray(&mRequests, &requests)) {
  275. return NS_ERROR_OUT_OF_MEMORY;
  276. }
  277. firstError = NS_OK;
  278. //
  279. // Operate the elements from back to front so that if items get
  280. // get removed from the list it won't affect our iteration
  281. //
  282. while (count > 0) {
  283. nsIRequest* request = requests.ElementAt(--count);
  284. NS_ASSERTION(request, "NULL request found in list.");
  285. if (!request)
  286. continue;
  287. if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
  288. nsAutoCString nameStr;
  289. request->GetName(nameStr);
  290. LOG(("LOADGROUP [%x]: Resuming request %x %s.\n",
  291. this, request, nameStr.get()));
  292. }
  293. // Resume the request...
  294. rv = request->Resume();
  295. // Remember the first failure and return it...
  296. if (NS_FAILED(rv) && NS_SUCCEEDED(firstError))
  297. firstError = rv;
  298. NS_RELEASE(request);
  299. }
  300. return firstError;
  301. }
  302. NS_IMETHODIMP
  303. nsLoadGroup::GetLoadFlags(uint32_t *aLoadFlags)
  304. {
  305. *aLoadFlags = mLoadFlags;
  306. return NS_OK;
  307. }
  308. NS_IMETHODIMP
  309. nsLoadGroup::SetLoadFlags(uint32_t aLoadFlags)
  310. {
  311. mLoadFlags = aLoadFlags;
  312. return NS_OK;
  313. }
  314. NS_IMETHODIMP
  315. nsLoadGroup::GetLoadGroup(nsILoadGroup **loadGroup)
  316. {
  317. *loadGroup = mLoadGroup;
  318. NS_IF_ADDREF(*loadGroup);
  319. return NS_OK;
  320. }
  321. NS_IMETHODIMP
  322. nsLoadGroup::SetLoadGroup(nsILoadGroup *loadGroup)
  323. {
  324. mLoadGroup = loadGroup;
  325. return NS_OK;
  326. }
  327. ////////////////////////////////////////////////////////////////////////////////
  328. // nsILoadGroup methods:
  329. NS_IMETHODIMP
  330. nsLoadGroup::GetDefaultLoadRequest(nsIRequest * *aRequest)
  331. {
  332. *aRequest = mDefaultLoadRequest;
  333. NS_IF_ADDREF(*aRequest);
  334. return NS_OK;
  335. }
  336. NS_IMETHODIMP
  337. nsLoadGroup::SetDefaultLoadRequest(nsIRequest *aRequest)
  338. {
  339. mDefaultLoadRequest = aRequest;
  340. // Inherit the group load flags from the default load request
  341. if (mDefaultLoadRequest) {
  342. mDefaultLoadRequest->GetLoadFlags(&mLoadFlags);
  343. //
  344. // Mask off any bits that are not part of the nsIRequest flags.
  345. // in particular, nsIChannel::LOAD_DOCUMENT_URI...
  346. //
  347. mLoadFlags &= nsIRequest::LOAD_REQUESTMASK;
  348. nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(aRequest);
  349. mDefaultLoadIsTimed = timedChannel != nullptr;
  350. if (mDefaultLoadIsTimed) {
  351. timedChannel->SetTimingEnabled(true);
  352. }
  353. }
  354. // Else, do not change the group's load flags (see bug 95981)
  355. return NS_OK;
  356. }
  357. NS_IMETHODIMP
  358. nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
  359. {
  360. nsresult rv;
  361. if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
  362. nsAutoCString nameStr;
  363. request->GetName(nameStr);
  364. LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n",
  365. this, request, nameStr.get(), mRequests.EntryCount()));
  366. }
  367. NS_ASSERTION(!mRequests.Search(request),
  368. "Entry added to loadgroup twice, don't do that");
  369. //
  370. // Do not add the channel, if the loadgroup is being canceled...
  371. //
  372. if (mIsCanceling) {
  373. LOG(("LOADGROUP [%x]: AddChannel() ABORTED because LoadGroup is"
  374. " being canceled!!\n", this));
  375. return NS_BINDING_ABORTED;
  376. }
  377. nsLoadFlags flags;
  378. // if the request is the default load request or if the default load
  379. // request is null, then the load group should inherit its load flags from
  380. // the request, but also we need to enforce defaultLoadFlags.
  381. if (mDefaultLoadRequest == request || !mDefaultLoadRequest) {
  382. rv = MergeDefaultLoadFlags(request, flags);
  383. } else {
  384. rv = MergeLoadFlags(request, flags);
  385. }
  386. if (NS_FAILED(rv)) return rv;
  387. //
  388. // Add the request to the list of active requests...
  389. //
  390. auto entry =
  391. static_cast<RequestMapEntry*>(mRequests.Add(request, fallible));
  392. if (!entry) {
  393. return NS_ERROR_OUT_OF_MEMORY;
  394. }
  395. if (mPriority != 0)
  396. RescheduleRequest(request, mPriority);
  397. nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(request);
  398. if (timedChannel)
  399. timedChannel->SetTimingEnabled(true);
  400. if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
  401. // Update the count of foreground URIs..
  402. mForegroundCount += 1;
  403. //
  404. // Fire the OnStartRequest notification out to the observer...
  405. //
  406. // If the notification fails then DO NOT add the request to
  407. // the load group.
  408. //
  409. nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
  410. if (observer) {
  411. LOG(("LOADGROUP [%x]: Firing OnStartRequest for request %x."
  412. "(foreground count=%d).\n", this, request, mForegroundCount));
  413. rv = observer->OnStartRequest(request, ctxt);
  414. if (NS_FAILED(rv)) {
  415. LOG(("LOADGROUP [%x]: OnStartRequest for request %x FAILED.\n",
  416. this, request));
  417. //
  418. // The URI load has been canceled by the observer. Clean up
  419. // the damage...
  420. //
  421. mRequests.Remove(request);
  422. rv = NS_OK;
  423. mForegroundCount -= 1;
  424. }
  425. }
  426. // Ensure that we're part of our loadgroup while pending
  427. if (mForegroundCount == 1 && mLoadGroup) {
  428. mLoadGroup->AddRequest(this, nullptr);
  429. }
  430. }
  431. return rv;
  432. }
  433. NS_IMETHODIMP
  434. nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
  435. nsresult aStatus)
  436. {
  437. NS_ENSURE_ARG_POINTER(request);
  438. nsresult rv;
  439. if (MOZ_LOG_TEST(gLoadGroupLog, LogLevel::Debug)) {
  440. nsAutoCString nameStr;
  441. request->GetName(nameStr);
  442. LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n",
  443. this, request, nameStr.get(), aStatus, mRequests.EntryCount() - 1));
  444. }
  445. // Make sure we have a owning reference to the request we're about
  446. // to remove.
  447. nsCOMPtr<nsIRequest> kungFuDeathGrip(request);
  448. //
  449. // Remove the request from the group. If this fails, it means that
  450. // the request was *not* in the group so do not update the foreground
  451. // count or it will get messed up...
  452. //
  453. auto entry = static_cast<RequestMapEntry*>(mRequests.Search(request));
  454. if (!entry) {
  455. LOG(("LOADGROUP [%x]: Unable to remove request %x. Not in group!\n",
  456. this, request));
  457. return NS_ERROR_FAILURE;
  458. }
  459. mRequests.RemoveEntry(entry);
  460. // Undo any group priority delta...
  461. if (mPriority != 0)
  462. RescheduleRequest(request, -mPriority);
  463. nsLoadFlags flags;
  464. rv = request->GetLoadFlags(&flags);
  465. if (NS_FAILED(rv)) return rv;
  466. if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
  467. NS_ASSERTION(mForegroundCount > 0, "ForegroundCount messed up");
  468. mForegroundCount -= 1;
  469. // Fire the OnStopRequest out to the observer...
  470. nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
  471. if (observer) {
  472. LOG(("LOADGROUP [%x]: Firing OnStopRequest for request %x."
  473. "(foreground count=%d).\n", this, request, mForegroundCount));
  474. rv = observer->OnStopRequest(request, ctxt, aStatus);
  475. if (NS_FAILED(rv)) {
  476. LOG(("LOADGROUP [%x]: OnStopRequest for request %x FAILED.\n",
  477. this, request));
  478. }
  479. }
  480. // If that was the last request -> remove ourselves from loadgroup
  481. if (mForegroundCount == 0 && mLoadGroup) {
  482. mLoadGroup->RemoveRequest(this, nullptr, aStatus);
  483. }
  484. }
  485. return rv;
  486. }
  487. NS_IMETHODIMP
  488. nsLoadGroup::GetRequests(nsISimpleEnumerator * *aRequests)
  489. {
  490. nsCOMArray<nsIRequest> requests;
  491. requests.SetCapacity(mRequests.EntryCount());
  492. for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
  493. auto e = static_cast<RequestMapEntry*>(iter.Get());
  494. requests.AppendObject(e->mKey);
  495. }
  496. return NS_NewArrayEnumerator(aRequests, requests);
  497. }
  498. NS_IMETHODIMP
  499. nsLoadGroup::SetGroupObserver(nsIRequestObserver* aObserver)
  500. {
  501. mObserver = do_GetWeakReference(aObserver);
  502. return NS_OK;
  503. }
  504. NS_IMETHODIMP
  505. nsLoadGroup::GetGroupObserver(nsIRequestObserver* *aResult)
  506. {
  507. nsCOMPtr<nsIRequestObserver> observer = do_QueryReferent(mObserver);
  508. *aResult = observer;
  509. NS_IF_ADDREF(*aResult);
  510. return NS_OK;
  511. }
  512. NS_IMETHODIMP
  513. nsLoadGroup::GetActiveCount(uint32_t* aResult)
  514. {
  515. *aResult = mForegroundCount;
  516. return NS_OK;
  517. }
  518. NS_IMETHODIMP
  519. nsLoadGroup::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
  520. {
  521. NS_ENSURE_ARG_POINTER(aCallbacks);
  522. *aCallbacks = mCallbacks;
  523. NS_IF_ADDREF(*aCallbacks);
  524. return NS_OK;
  525. }
  526. NS_IMETHODIMP
  527. nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
  528. {
  529. mCallbacks = aCallbacks;
  530. return NS_OK;
  531. }
  532. NS_IMETHODIMP
  533. nsLoadGroup::GetRequestContextID(nsID *aRCID)
  534. {
  535. if (!mRequestContext) {
  536. return NS_ERROR_NOT_AVAILABLE;
  537. }
  538. return mRequestContext->GetID(aRCID);
  539. }
  540. ////////////////////////////////////////////////////////////////////////////////
  541. // nsILoadGroupChild methods:
  542. NS_IMETHODIMP
  543. nsLoadGroup::GetParentLoadGroup(nsILoadGroup * *aParentLoadGroup)
  544. {
  545. *aParentLoadGroup = nullptr;
  546. nsCOMPtr<nsILoadGroup> parent = do_QueryReferent(mParentLoadGroup);
  547. if (!parent)
  548. return NS_OK;
  549. parent.forget(aParentLoadGroup);
  550. return NS_OK;
  551. }
  552. NS_IMETHODIMP
  553. nsLoadGroup::SetParentLoadGroup(nsILoadGroup *aParentLoadGroup)
  554. {
  555. mParentLoadGroup = do_GetWeakReference(aParentLoadGroup);
  556. return NS_OK;
  557. }
  558. NS_IMETHODIMP
  559. nsLoadGroup::GetChildLoadGroup(nsILoadGroup * *aChildLoadGroup)
  560. {
  561. NS_ADDREF(*aChildLoadGroup = this);
  562. return NS_OK;
  563. }
  564. NS_IMETHODIMP
  565. nsLoadGroup::GetRootLoadGroup(nsILoadGroup * *aRootLoadGroup)
  566. {
  567. // first recursively try the root load group of our parent
  568. nsCOMPtr<nsILoadGroupChild> ancestor = do_QueryReferent(mParentLoadGroup);
  569. if (ancestor)
  570. return ancestor->GetRootLoadGroup(aRootLoadGroup);
  571. // next recursively try the root load group of our own load grop
  572. ancestor = do_QueryInterface(mLoadGroup);
  573. if (ancestor)
  574. return ancestor->GetRootLoadGroup(aRootLoadGroup);
  575. // finally just return this
  576. NS_ADDREF(*aRootLoadGroup = this);
  577. return NS_OK;
  578. }
  579. ////////////////////////////////////////////////////////////////////////////////
  580. // nsPILoadGroupInternal methods:
  581. NS_IMETHODIMP
  582. nsLoadGroup::OnEndPageLoad(nsIChannel *aDefaultChannel)
  583. {
  584. // for the moment, nothing to do here.
  585. return NS_OK;
  586. }
  587. ////////////////////////////////////////////////////////////////////////////////
  588. // nsISupportsPriority methods:
  589. NS_IMETHODIMP
  590. nsLoadGroup::GetPriority(int32_t *aValue)
  591. {
  592. *aValue = mPriority;
  593. return NS_OK;
  594. }
  595. NS_IMETHODIMP
  596. nsLoadGroup::SetPriority(int32_t aValue)
  597. {
  598. return AdjustPriority(aValue - mPriority);
  599. }
  600. NS_IMETHODIMP
  601. nsLoadGroup::AdjustPriority(int32_t aDelta)
  602. {
  603. // Update the priority for each request that supports nsISupportsPriority
  604. if (aDelta != 0) {
  605. mPriority += aDelta;
  606. for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
  607. auto e = static_cast<RequestMapEntry*>(iter.Get());
  608. RescheduleRequest(e->mKey, aDelta);
  609. }
  610. }
  611. return NS_OK;
  612. }
  613. NS_IMETHODIMP
  614. nsLoadGroup::GetDefaultLoadFlags(uint32_t *aFlags)
  615. {
  616. *aFlags = mDefaultLoadFlags;
  617. return NS_OK;
  618. }
  619. NS_IMETHODIMP
  620. nsLoadGroup::SetDefaultLoadFlags(uint32_t aFlags)
  621. {
  622. mDefaultLoadFlags = aFlags;
  623. return NS_OK;
  624. }
  625. ////////////////////////////////////////////////////////////////////////////////
  626. nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest,
  627. nsLoadFlags& outFlags)
  628. {
  629. nsresult rv;
  630. nsLoadFlags flags, oldFlags;
  631. rv = aRequest->GetLoadFlags(&flags);
  632. if (NS_FAILED(rv)) {
  633. return rv;
  634. }
  635. oldFlags = flags;
  636. // Inherit the following bits...
  637. flags |= (mLoadFlags & (LOAD_BACKGROUND |
  638. LOAD_BYPASS_CACHE |
  639. LOAD_FROM_CACHE |
  640. VALIDATE_ALWAYS |
  641. VALIDATE_ONCE_PER_SESSION |
  642. VALIDATE_NEVER));
  643. // ... and force the default flags.
  644. flags |= mDefaultLoadFlags;
  645. if (flags != oldFlags) {
  646. rv = aRequest->SetLoadFlags(flags);
  647. }
  648. outFlags = flags;
  649. return rv;
  650. }
  651. nsresult nsLoadGroup::MergeDefaultLoadFlags(nsIRequest *aRequest,
  652. nsLoadFlags& outFlags)
  653. {
  654. nsresult rv;
  655. nsLoadFlags flags, oldFlags;
  656. rv = aRequest->GetLoadFlags(&flags);
  657. if (NS_FAILED(rv)) {
  658. return rv;
  659. }
  660. oldFlags = flags;
  661. // ... and force the default flags.
  662. flags |= mDefaultLoadFlags;
  663. if (flags != oldFlags) {
  664. rv = aRequest->SetLoadFlags(flags);
  665. }
  666. outFlags = flags;
  667. return rv;
  668. }
  669. nsresult nsLoadGroup::Init()
  670. {
  671. mRequestContextService = do_GetService("@mozilla.org/network/request-context-service;1");
  672. if (mRequestContextService) {
  673. nsID requestContextID;
  674. if (NS_SUCCEEDED(mRequestContextService->NewRequestContextID(&requestContextID))) {
  675. mRequestContextService->GetRequestContext(requestContextID,
  676. getter_AddRefs(mRequestContext));
  677. }
  678. }
  679. return NS_OK;
  680. }
  681. } // namespace net
  682. } // namespace mozilla
  683. #undef LOG