nsStreamLoader.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  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 "nsStreamLoader.h"
  6. #include "nsIInputStream.h"
  7. #include "nsIChannel.h"
  8. #include "nsError.h"
  9. #include "GeckoProfiler.h"
  10. #include <limits>
  11. namespace mozilla {
  12. namespace net {
  13. nsStreamLoader::nsStreamLoader()
  14. : mData()
  15. {
  16. }
  17. nsStreamLoader::~nsStreamLoader()
  18. {
  19. }
  20. NS_IMETHODIMP
  21. nsStreamLoader::Init(nsIStreamLoaderObserver* aStreamObserver,
  22. nsIRequestObserver* aRequestObserver)
  23. {
  24. NS_ENSURE_ARG_POINTER(aStreamObserver);
  25. mObserver = aStreamObserver;
  26. mRequestObserver = aRequestObserver;
  27. return NS_OK;
  28. }
  29. nsresult
  30. nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
  31. {
  32. if (aOuter) return NS_ERROR_NO_AGGREGATION;
  33. nsStreamLoader* it = new nsStreamLoader();
  34. if (it == nullptr)
  35. return NS_ERROR_OUT_OF_MEMORY;
  36. NS_ADDREF(it);
  37. nsresult rv = it->QueryInterface(aIID, aResult);
  38. NS_RELEASE(it);
  39. return rv;
  40. }
  41. NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader,
  42. nsIRequestObserver, nsIStreamListener,
  43. nsIThreadRetargetableStreamListener)
  44. NS_IMETHODIMP
  45. nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes)
  46. {
  47. *aNumBytes = mBytesRead;
  48. return NS_OK;
  49. }
  50. NS_IMETHODIMP
  51. nsStreamLoader::GetRequest(nsIRequest **aRequest)
  52. {
  53. NS_IF_ADDREF(*aRequest = mRequest);
  54. return NS_OK;
  55. }
  56. NS_IMETHODIMP
  57. nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
  58. {
  59. nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
  60. if (chan) {
  61. int64_t contentLength = -1;
  62. chan->GetContentLength(&contentLength);
  63. if (contentLength >= 0) {
  64. if (uint64_t(contentLength) > std::numeric_limits<size_t>::max()) {
  65. // Too big to fit into size_t, so let's bail.
  66. return NS_ERROR_OUT_OF_MEMORY;
  67. }
  68. // preallocate buffer
  69. if (!mData.initCapacity(contentLength)) {
  70. return NS_ERROR_OUT_OF_MEMORY;
  71. }
  72. }
  73. }
  74. mContext = ctxt;
  75. if (mRequestObserver) {
  76. mRequestObserver->OnStartRequest(request, ctxt);
  77. }
  78. return NS_OK;
  79. }
  80. NS_IMETHODIMP
  81. nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
  82. nsresult aStatus)
  83. {
  84. PROFILER_LABEL("nsStreamLoader", "OnStopRequest",
  85. js::ProfileEntry::Category::NETWORK);
  86. if (mObserver) {
  87. // provide nsIStreamLoader::request during call to OnStreamComplete
  88. mRequest = request;
  89. size_t length = mData.length();
  90. uint8_t* elems = mData.extractOrCopyRawBuffer();
  91. nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
  92. length, elems);
  93. if (rv != NS_SUCCESS_ADOPTED_DATA) {
  94. // The observer didn't take ownership of the extracted data buffer, so
  95. // put it back into mData.
  96. mData.replaceRawBuffer(elems, length);
  97. }
  98. // done.. cleanup
  99. ReleaseData();
  100. mRequest = nullptr;
  101. mObserver = nullptr;
  102. mContext = nullptr;
  103. }
  104. if (mRequestObserver) {
  105. mRequestObserver->OnStopRequest(request, ctxt, aStatus);
  106. mRequestObserver = nullptr;
  107. }
  108. return NS_OK;
  109. }
  110. nsresult
  111. nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
  112. void *closure,
  113. const char *fromSegment,
  114. uint32_t toOffset,
  115. uint32_t count,
  116. uint32_t *writeCount)
  117. {
  118. nsStreamLoader *self = (nsStreamLoader *) closure;
  119. if (!self->mData.append(fromSegment, count)) {
  120. self->mData.clearAndFree();
  121. return NS_ERROR_OUT_OF_MEMORY;
  122. }
  123. *writeCount = count;
  124. return NS_OK;
  125. }
  126. NS_IMETHODIMP
  127. nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
  128. nsIInputStream *inStr,
  129. uint64_t sourceOffset, uint32_t count)
  130. {
  131. uint32_t countRead;
  132. nsresult rv = inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
  133. NS_ENSURE_SUCCESS(rv, rv);
  134. mBytesRead += countRead;
  135. return NS_OK;
  136. }
  137. void
  138. nsStreamLoader::ReleaseData()
  139. {
  140. mData.clearAndFree();
  141. }
  142. NS_IMETHODIMP
  143. nsStreamLoader::CheckListenerChain()
  144. {
  145. return NS_OK;
  146. }
  147. } // namespace net
  148. } // namespace mozilla