InternalResponse.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* -*- Mode: C++; tab-width: 8; 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 "InternalResponse.h"
  6. #include "mozilla/Assertions.h"
  7. #include "mozilla/dom/FetchTypes.h"
  8. #include "mozilla/dom/InternalHeaders.h"
  9. #include "mozilla/dom/cache/CacheTypes.h"
  10. #include "mozilla/ipc/PBackgroundSharedTypes.h"
  11. #include "mozilla/ipc/IPCStreamUtils.h"
  12. #include "nsIURI.h"
  13. #include "nsStreamUtils.h"
  14. namespace mozilla {
  15. namespace dom {
  16. InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
  17. : mType(ResponseType::Default)
  18. , mStatus(aStatus)
  19. , mStatusText(aStatusText)
  20. , mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
  21. , mBodySize(UNKNOWN_BODY_SIZE)
  22. {
  23. }
  24. already_AddRefed<InternalResponse>
  25. InternalResponse::FromIPC(const IPCInternalResponse& aIPCResponse)
  26. {
  27. if (aIPCResponse.type() == ResponseType::Error) {
  28. return InternalResponse::NetworkError();
  29. }
  30. RefPtr<InternalResponse> response =
  31. new InternalResponse(aIPCResponse.status(),
  32. aIPCResponse.statusText());
  33. response->SetURLList(aIPCResponse.urlList());
  34. response->mHeaders = new InternalHeaders(aIPCResponse.headers(),
  35. aIPCResponse.headersGuard());
  36. response->InitChannelInfo(aIPCResponse.channelInfo());
  37. if (aIPCResponse.principalInfo().type() == mozilla::ipc::OptionalPrincipalInfo::TPrincipalInfo) {
  38. UniquePtr<mozilla::ipc::PrincipalInfo> info(new mozilla::ipc::PrincipalInfo(aIPCResponse.principalInfo().get_PrincipalInfo()));
  39. response->SetPrincipalInfo(Move(info));
  40. }
  41. nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aIPCResponse.body());
  42. response->SetBody(stream, aIPCResponse.bodySize());
  43. switch (aIPCResponse.type())
  44. {
  45. case ResponseType::Basic:
  46. response = response->BasicResponse();
  47. break;
  48. case ResponseType::Cors:
  49. response = response->CORSResponse();
  50. break;
  51. case ResponseType::Default:
  52. break;
  53. case ResponseType::Opaque:
  54. response = response->OpaqueResponse();
  55. break;
  56. case ResponseType::Opaqueredirect:
  57. response = response->OpaqueRedirectResponse();
  58. break;
  59. default:
  60. MOZ_CRASH("Unexpected ResponseType!");
  61. }
  62. MOZ_ASSERT(response);
  63. return response.forget();
  64. }
  65. InternalResponse::~InternalResponse()
  66. {
  67. }
  68. template void
  69. InternalResponse::ToIPC<PContentParent>
  70. (IPCInternalResponse* aIPCResponse,
  71. PContentParent* aManager,
  72. UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
  73. template void
  74. InternalResponse::ToIPC<nsIContentChild>
  75. (IPCInternalResponse* aIPCResponse,
  76. nsIContentChild* aManager,
  77. UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
  78. template void
  79. InternalResponse::ToIPC<mozilla::ipc::PBackgroundParent>
  80. (IPCInternalResponse* aIPCResponse,
  81. mozilla::ipc::PBackgroundParent* aManager,
  82. UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
  83. template void
  84. InternalResponse::ToIPC<mozilla::ipc::PBackgroundChild>
  85. (IPCInternalResponse* aIPCResponse,
  86. mozilla::ipc::PBackgroundChild* aManager,
  87. UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
  88. template<typename M>
  89. void
  90. InternalResponse::ToIPC(IPCInternalResponse* aIPCResponse,
  91. M* aManager,
  92. UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream)
  93. {
  94. MOZ_ASSERT(aIPCResponse);
  95. aIPCResponse->type() = mType;
  96. aIPCResponse->urlList() = mURLList;
  97. aIPCResponse->status() = GetUnfilteredStatus();
  98. aIPCResponse->statusText() = GetUnfilteredStatusText();
  99. mHeaders->ToIPC(aIPCResponse->headers(), aIPCResponse->headersGuard());
  100. aIPCResponse->channelInfo() = mChannelInfo.AsIPCChannelInfo();
  101. if (mPrincipalInfo) {
  102. aIPCResponse->principalInfo() = *mPrincipalInfo;
  103. } else {
  104. aIPCResponse->principalInfo() = void_t();
  105. }
  106. nsCOMPtr<nsIInputStream> body;
  107. int64_t bodySize;
  108. GetUnfilteredBody(getter_AddRefs(body), &bodySize);
  109. if (body) {
  110. aAutoStream.reset(new mozilla::ipc::AutoIPCStream(aIPCResponse->body()));
  111. aAutoStream->Serialize(body, aManager);
  112. } else {
  113. aIPCResponse->body() = void_t();
  114. }
  115. aIPCResponse->bodySize() = bodySize;
  116. }
  117. already_AddRefed<InternalResponse>
  118. InternalResponse::Clone()
  119. {
  120. RefPtr<InternalResponse> clone = CreateIncompleteCopy();
  121. clone->mHeaders = new InternalHeaders(*mHeaders);
  122. if (mWrappedResponse) {
  123. clone->mWrappedResponse = mWrappedResponse->Clone();
  124. MOZ_ASSERT(!mBody);
  125. return clone.forget();
  126. }
  127. if (!mBody) {
  128. return clone.forget();
  129. }
  130. nsCOMPtr<nsIInputStream> clonedBody;
  131. nsCOMPtr<nsIInputStream> replacementBody;
  132. nsresult rv = NS_CloneInputStream(mBody, getter_AddRefs(clonedBody),
  133. getter_AddRefs(replacementBody));
  134. if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
  135. clone->mBody.swap(clonedBody);
  136. if (replacementBody) {
  137. mBody.swap(replacementBody);
  138. }
  139. return clone.forget();
  140. }
  141. already_AddRefed<InternalResponse>
  142. InternalResponse::BasicResponse()
  143. {
  144. MOZ_ASSERT(!mWrappedResponse, "Can't BasicResponse a already wrapped response");
  145. RefPtr<InternalResponse> basic = CreateIncompleteCopy();
  146. basic->mType = ResponseType::Basic;
  147. basic->mHeaders = InternalHeaders::BasicHeaders(Headers());
  148. basic->mWrappedResponse = this;
  149. return basic.forget();
  150. }
  151. already_AddRefed<InternalResponse>
  152. InternalResponse::CORSResponse()
  153. {
  154. MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
  155. RefPtr<InternalResponse> cors = CreateIncompleteCopy();
  156. cors->mType = ResponseType::Cors;
  157. cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
  158. cors->mWrappedResponse = this;
  159. return cors.forget();
  160. }
  161. void
  162. InternalResponse::SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo)
  163. {
  164. mPrincipalInfo = Move(aPrincipalInfo);
  165. }
  166. LoadTainting
  167. InternalResponse::GetTainting() const
  168. {
  169. switch (mType) {
  170. case ResponseType::Cors:
  171. return LoadTainting::CORS;
  172. case ResponseType::Opaque:
  173. return LoadTainting::Opaque;
  174. default:
  175. return LoadTainting::Basic;
  176. }
  177. }
  178. already_AddRefed<InternalResponse>
  179. InternalResponse::Unfiltered()
  180. {
  181. RefPtr<InternalResponse> ref = mWrappedResponse;
  182. if (!ref) {
  183. ref = this;
  184. }
  185. return ref.forget();
  186. }
  187. already_AddRefed<InternalResponse>
  188. InternalResponse::OpaqueResponse()
  189. {
  190. MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueResponse a already wrapped response");
  191. RefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
  192. response->mType = ResponseType::Opaque;
  193. response->mTerminationReason = mTerminationReason;
  194. response->mChannelInfo = mChannelInfo;
  195. if (mPrincipalInfo) {
  196. response->mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(*mPrincipalInfo);
  197. }
  198. response->mWrappedResponse = this;
  199. return response.forget();
  200. }
  201. already_AddRefed<InternalResponse>
  202. InternalResponse::OpaqueRedirectResponse()
  203. {
  204. MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueRedirectResponse a already wrapped response");
  205. MOZ_ASSERT(!mURLList.IsEmpty(), "URLList should not be emtpy for internalResponse");
  206. RefPtr<InternalResponse> response = OpaqueResponse();
  207. response->mType = ResponseType::Opaqueredirect;
  208. response->mURLList = mURLList;
  209. return response.forget();
  210. }
  211. already_AddRefed<InternalResponse>
  212. InternalResponse::CreateIncompleteCopy()
  213. {
  214. RefPtr<InternalResponse> copy = new InternalResponse(mStatus, mStatusText);
  215. copy->mType = mType;
  216. copy->mTerminationReason = mTerminationReason;
  217. copy->mURLList = mURLList;
  218. copy->mChannelInfo = mChannelInfo;
  219. if (mPrincipalInfo) {
  220. copy->mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(*mPrincipalInfo);
  221. }
  222. return copy.forget();
  223. }
  224. } // namespace dom
  225. } // namespace mozilla