WyciwygChannelParent.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "nsWyciwyg.h"
  5. #include "mozilla/net/WyciwygChannelParent.h"
  6. #include "nsWyciwygChannel.h"
  7. #include "nsNetUtil.h"
  8. #include "nsCharsetSource.h"
  9. #include "nsISerializable.h"
  10. #include "nsSerializationHelper.h"
  11. #include "mozilla/ipc/URIUtils.h"
  12. #include "mozilla/net/NeckoParent.h"
  13. #include "SerializedLoadContext.h"
  14. #include "nsIContentPolicy.h"
  15. #include "mozilla/ipc/BackgroundUtils.h"
  16. using namespace mozilla::ipc;
  17. namespace mozilla {
  18. namespace net {
  19. WyciwygChannelParent::WyciwygChannelParent()
  20. : mIPCClosed(false)
  21. , mReceivedAppData(false)
  22. {
  23. }
  24. WyciwygChannelParent::~WyciwygChannelParent()
  25. {
  26. }
  27. void
  28. WyciwygChannelParent::ActorDestroy(ActorDestroyReason why)
  29. {
  30. // We may still have refcount>0 if the channel hasn't called OnStopRequest
  31. // yet, but we must not send any more msgs to child.
  32. mIPCClosed = true;
  33. // We need to force the cycle to break here
  34. if (mChannel) {
  35. mChannel->SetNotificationCallbacks(nullptr);
  36. }
  37. }
  38. //-----------------------------------------------------------------------------
  39. // WyciwygChannelParent::nsISupports
  40. //-----------------------------------------------------------------------------
  41. NS_IMPL_ISUPPORTS(WyciwygChannelParent,
  42. nsIStreamListener,
  43. nsIInterfaceRequestor,
  44. nsIRequestObserver)
  45. //-----------------------------------------------------------------------------
  46. // WyciwygChannelParent::PWyciwygChannelParent
  47. //-----------------------------------------------------------------------------
  48. bool
  49. WyciwygChannelParent::RecvInit(const URIParams& aURI,
  50. const ipc::PrincipalInfo& aRequestingPrincipalInfo,
  51. const ipc::PrincipalInfo& aTriggeringPrincipalInfo,
  52. const ipc::PrincipalInfo& aPrincipalToInheritInfo,
  53. const uint32_t& aSecurityFlags,
  54. const uint32_t& aContentPolicyType)
  55. {
  56. nsresult rv;
  57. nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
  58. if (!uri)
  59. return false;
  60. LOG(("WyciwygChannelParent RecvInit [this=%p uri=%s]\n",
  61. this, uri->GetSpecOrDefault().get()));
  62. nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
  63. if (NS_FAILED(rv))
  64. return SendCancelEarly(rv);
  65. nsCOMPtr<nsIPrincipal> requestingPrincipal =
  66. mozilla::ipc::PrincipalInfoToPrincipal(aRequestingPrincipalInfo, &rv);
  67. if (NS_FAILED(rv)) {
  68. return SendCancelEarly(rv);
  69. }
  70. nsCOMPtr<nsIPrincipal> triggeringPrincipal =
  71. mozilla::ipc::PrincipalInfoToPrincipal(aTriggeringPrincipalInfo, &rv);
  72. if (NS_FAILED(rv)) {
  73. return SendCancelEarly(rv);
  74. }
  75. nsCOMPtr<nsIPrincipal> principalToInherit =
  76. mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalToInheritInfo, &rv);
  77. if (NS_FAILED(rv)) {
  78. return SendCancelEarly(rv);
  79. }
  80. nsCOMPtr<nsIChannel> chan;
  81. rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(chan),
  82. uri,
  83. requestingPrincipal,
  84. triggeringPrincipal,
  85. aSecurityFlags,
  86. aContentPolicyType,
  87. nullptr, // loadGroup
  88. nullptr, // aCallbacks
  89. nsIRequest::LOAD_NORMAL,
  90. ios);
  91. if (NS_FAILED(rv))
  92. return SendCancelEarly(rv);
  93. nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
  94. rv = loadInfo->SetPrincipalToInherit(principalToInherit);
  95. if (NS_FAILED(rv)) {
  96. return SendCancelEarly(rv);
  97. }
  98. mChannel = do_QueryInterface(chan, &rv);
  99. if (NS_FAILED(rv))
  100. return SendCancelEarly(rv);
  101. return true;
  102. }
  103. bool
  104. WyciwygChannelParent::RecvAppData(const IPC::SerializedLoadContext& loadContext,
  105. const PBrowserOrId &parent)
  106. {
  107. LOG(("WyciwygChannelParent RecvAppData [this=%p]\n", this));
  108. if (!SetupAppData(loadContext, parent))
  109. return false;
  110. mChannel->SetNotificationCallbacks(this);
  111. return true;
  112. }
  113. bool
  114. WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext,
  115. const PBrowserOrId &aParent)
  116. {
  117. if (!mChannel)
  118. return true;
  119. const char* error = NeckoParent::CreateChannelLoadContext(aParent,
  120. Manager()->Manager(),
  121. loadContext,
  122. nullptr,
  123. mLoadContext);
  124. if (error) {
  125. printf_stderr("WyciwygChannelParent::SetupAppData: FATAL ERROR: %s\n",
  126. error);
  127. return false;
  128. }
  129. if (!mLoadContext && loadContext.IsPrivateBitValid()) {
  130. nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
  131. if (pbChannel)
  132. pbChannel->SetPrivate(loadContext.mOriginAttributes.mPrivateBrowsingId > 0);
  133. }
  134. mReceivedAppData = true;
  135. return true;
  136. }
  137. bool
  138. WyciwygChannelParent::RecvAsyncOpen(const URIParams& aOriginal,
  139. const uint32_t& aLoadFlags,
  140. const IPC::SerializedLoadContext& loadContext,
  141. const PBrowserOrId &aParent)
  142. {
  143. nsCOMPtr<nsIURI> original = DeserializeURI(aOriginal);
  144. if (!original)
  145. return false;
  146. LOG(("WyciwygChannelParent RecvAsyncOpen [this=%p]\n", this));
  147. if (!mChannel)
  148. return true;
  149. nsresult rv;
  150. rv = mChannel->SetOriginalURI(original);
  151. if (NS_FAILED(rv))
  152. return SendCancelEarly(rv);
  153. rv = mChannel->SetLoadFlags(aLoadFlags);
  154. if (NS_FAILED(rv))
  155. return SendCancelEarly(rv);
  156. if (!mReceivedAppData && !SetupAppData(loadContext, aParent)) {
  157. return false;
  158. }
  159. rv = mChannel->SetNotificationCallbacks(this);
  160. if (NS_FAILED(rv))
  161. return SendCancelEarly(rv);
  162. nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
  163. if (loadInfo && loadInfo->GetEnforceSecurity()) {
  164. rv = mChannel->AsyncOpen2(this);
  165. }
  166. else {
  167. rv = mChannel->AsyncOpen(this, nullptr);
  168. }
  169. if (NS_FAILED(rv))
  170. return SendCancelEarly(rv);
  171. return true;
  172. }
  173. bool
  174. WyciwygChannelParent::RecvWriteToCacheEntry(const nsString& data)
  175. {
  176. if (!mReceivedAppData) {
  177. printf_stderr("WyciwygChannelParent::RecvWriteToCacheEntry: FATAL ERROR: didn't receive app data\n");
  178. return false;
  179. }
  180. if (mChannel)
  181. mChannel->WriteToCacheEntry(data);
  182. return true;
  183. }
  184. bool
  185. WyciwygChannelParent::RecvCloseCacheEntry(const nsresult& reason)
  186. {
  187. if (mChannel) {
  188. mChannel->CloseCacheEntry(reason);
  189. }
  190. return true;
  191. }
  192. bool
  193. WyciwygChannelParent::RecvSetCharsetAndSource(const int32_t& aCharsetSource,
  194. const nsCString& aCharset)
  195. {
  196. if (mChannel)
  197. mChannel->SetCharsetAndSource(aCharsetSource, aCharset);
  198. return true;
  199. }
  200. bool
  201. WyciwygChannelParent::RecvSetSecurityInfo(const nsCString& aSecurityInfo)
  202. {
  203. if (mChannel) {
  204. nsCOMPtr<nsISupports> securityInfo;
  205. NS_DeserializeObject(aSecurityInfo, getter_AddRefs(securityInfo));
  206. mChannel->SetSecurityInfo(securityInfo);
  207. }
  208. return true;
  209. }
  210. bool
  211. WyciwygChannelParent::RecvCancel(const nsresult& aStatusCode)
  212. {
  213. if (mChannel)
  214. mChannel->Cancel(aStatusCode);
  215. return true;
  216. }
  217. //-----------------------------------------------------------------------------
  218. // WyciwygChannelParent::nsIRequestObserver
  219. //-----------------------------------------------------------------------------
  220. NS_IMETHODIMP
  221. WyciwygChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
  222. {
  223. LOG(("WyciwygChannelParent::OnStartRequest [this=%p]\n", this));
  224. nsresult rv;
  225. nsCOMPtr<nsIWyciwygChannel> chan = do_QueryInterface(aRequest, &rv);
  226. NS_ENSURE_SUCCESS(rv, rv);
  227. nsresult status;
  228. chan->GetStatus(&status);
  229. int64_t contentLength = -1;
  230. chan->GetContentLength(&contentLength);
  231. int32_t charsetSource = kCharsetUninitialized;
  232. nsAutoCString charset;
  233. chan->GetCharsetAndSource(&charsetSource, charset);
  234. nsCOMPtr<nsISupports> securityInfo;
  235. chan->GetSecurityInfo(getter_AddRefs(securityInfo));
  236. nsCString secInfoStr;
  237. if (securityInfo) {
  238. nsCOMPtr<nsISerializable> serializable = do_QueryInterface(securityInfo);
  239. if (serializable)
  240. NS_SerializeToString(serializable, secInfoStr);
  241. else {
  242. NS_ERROR("Can't serialize security info");
  243. return NS_ERROR_UNEXPECTED;
  244. }
  245. }
  246. if (mIPCClosed ||
  247. !SendOnStartRequest(status, contentLength, charsetSource, charset, secInfoStr)) {
  248. return NS_ERROR_UNEXPECTED;
  249. }
  250. return NS_OK;
  251. }
  252. NS_IMETHODIMP
  253. WyciwygChannelParent::OnStopRequest(nsIRequest *aRequest,
  254. nsISupports *aContext,
  255. nsresult aStatusCode)
  256. {
  257. LOG(("WyciwygChannelParent::OnStopRequest: [this=%p status=%ul]\n",
  258. this, aStatusCode));
  259. if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
  260. return NS_ERROR_UNEXPECTED;
  261. }
  262. return NS_OK;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // WyciwygChannelParent::nsIStreamListener
  266. //-----------------------------------------------------------------------------
  267. NS_IMETHODIMP
  268. WyciwygChannelParent::OnDataAvailable(nsIRequest *aRequest,
  269. nsISupports *aContext,
  270. nsIInputStream *aInputStream,
  271. uint64_t aOffset,
  272. uint32_t aCount)
  273. {
  274. LOG(("WyciwygChannelParent::OnDataAvailable [this=%p]\n", this));
  275. nsCString data;
  276. nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
  277. if (NS_FAILED(rv))
  278. return rv;
  279. if (mIPCClosed || !SendOnDataAvailable(data, aOffset)) {
  280. return NS_ERROR_UNEXPECTED;
  281. }
  282. return NS_OK;
  283. }
  284. //-----------------------------------------------------------------------------
  285. // WyciwygChannelParent::nsIInterfaceRequestor
  286. //-----------------------------------------------------------------------------
  287. NS_IMETHODIMP
  288. WyciwygChannelParent::GetInterface(const nsIID& uuid, void** result)
  289. {
  290. // Only support nsILoadContext if child channel's callbacks did too
  291. if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
  292. nsCOMPtr<nsILoadContext> copy = mLoadContext;
  293. copy.forget(result);
  294. return NS_OK;
  295. }
  296. return QueryInterface(uuid, result);
  297. }
  298. } // namespace net
  299. } // namespace mozilla