WebSocketChannelParent.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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 "WebSocketLog.h"
  6. #include "WebSocketChannelParent.h"
  7. #include "nsIAuthPromptProvider.h"
  8. #include "mozilla/ipc/InputStreamUtils.h"
  9. #include "mozilla/ipc/URIUtils.h"
  10. #include "mozilla/ipc/BackgroundUtils.h"
  11. #include "SerializedLoadContext.h"
  12. #include "mozilla/net/NeckoCommon.h"
  13. #include "mozilla/net/WebSocketChannel.h"
  14. using namespace mozilla::ipc;
  15. namespace mozilla {
  16. namespace net {
  17. NS_IMPL_ISUPPORTS(WebSocketChannelParent,
  18. nsIWebSocketListener,
  19. nsIInterfaceRequestor)
  20. WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider,
  21. nsILoadContext* aLoadContext,
  22. PBOverrideStatus aOverrideStatus,
  23. uint32_t aSerial)
  24. : mAuthProvider(aAuthProvider)
  25. , mLoadContext(aLoadContext)
  26. , mIPCOpen(true)
  27. , mSerial(aSerial)
  28. {
  29. // Websocket channels can't have a private browsing override
  30. MOZ_ASSERT_IF(!aLoadContext, aOverrideStatus == kPBOverride_Unset);
  31. }
  32. WebSocketChannelParent::~WebSocketChannelParent()
  33. {
  34. }
  35. //-----------------------------------------------------------------------------
  36. // WebSocketChannelParent::PWebSocketChannelParent
  37. //-----------------------------------------------------------------------------
  38. bool
  39. WebSocketChannelParent::RecvDeleteSelf()
  40. {
  41. LOG(("WebSocketChannelParent::RecvDeleteSelf() %p\n", this));
  42. mChannel = nullptr;
  43. mAuthProvider = nullptr;
  44. return mIPCOpen ? Send__delete__(this) : true;
  45. }
  46. bool
  47. WebSocketChannelParent::RecvAsyncOpen(const OptionalURIParams& aURI,
  48. const nsCString& aOrigin,
  49. const uint64_t& aInnerWindowID,
  50. const nsCString& aProtocol,
  51. const bool& aSecure,
  52. const uint32_t& aPingInterval,
  53. const bool& aClientSetPingInterval,
  54. const uint32_t& aPingTimeout,
  55. const bool& aClientSetPingTimeout,
  56. const OptionalLoadInfoArgs& aLoadInfoArgs,
  57. const OptionalTransportProvider& aTransportProvider,
  58. const nsCString& aNegotiatedExtensions)
  59. {
  60. LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this));
  61. nsresult rv;
  62. nsCOMPtr<nsIURI> uri;
  63. nsCOMPtr<nsILoadInfo> loadInfo;
  64. rv = LoadInfoArgsToLoadInfo(aLoadInfoArgs, getter_AddRefs(loadInfo));
  65. if (NS_FAILED(rv)) {
  66. goto fail;
  67. }
  68. if (aSecure) {
  69. mChannel =
  70. do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
  71. } else {
  72. mChannel =
  73. do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
  74. }
  75. if (NS_FAILED(rv))
  76. goto fail;
  77. rv = mChannel->SetSerial(mSerial);
  78. if (NS_WARN_IF(NS_FAILED(rv))) {
  79. goto fail;
  80. }
  81. rv = mChannel->SetLoadInfo(loadInfo);
  82. if (NS_FAILED(rv)) {
  83. goto fail;
  84. }
  85. rv = mChannel->SetNotificationCallbacks(this);
  86. if (NS_FAILED(rv))
  87. goto fail;
  88. rv = mChannel->SetProtocol(aProtocol);
  89. if (NS_FAILED(rv))
  90. goto fail;
  91. if (aTransportProvider.type() != OptionalTransportProvider::Tvoid_t) {
  92. RefPtr<TransportProviderParent> provider =
  93. static_cast<TransportProviderParent*>(
  94. aTransportProvider.get_PTransportProviderParent());
  95. rv = mChannel->SetServerParameters(provider, aNegotiatedExtensions);
  96. if (NS_FAILED(rv)) {
  97. goto fail;
  98. }
  99. } else {
  100. uri = DeserializeURI(aURI);
  101. if (!uri) {
  102. rv = NS_ERROR_FAILURE;
  103. goto fail;
  104. }
  105. }
  106. // only use ping values from child if they were overridden by client code.
  107. if (aClientSetPingInterval) {
  108. // IDL allows setting in seconds, so must be multiple of 1000 ms
  109. MOZ_ASSERT(aPingInterval >= 1000 && !(aPingInterval % 1000));
  110. mChannel->SetPingInterval(aPingInterval / 1000);
  111. }
  112. if (aClientSetPingTimeout) {
  113. MOZ_ASSERT(aPingTimeout >= 1000 && !(aPingTimeout % 1000));
  114. mChannel->SetPingTimeout(aPingTimeout / 1000);
  115. }
  116. rv = mChannel->AsyncOpen(uri, aOrigin, aInnerWindowID, this, nullptr);
  117. if (NS_FAILED(rv))
  118. goto fail;
  119. return true;
  120. fail:
  121. mChannel = nullptr;
  122. return SendOnStop(rv);
  123. }
  124. bool
  125. WebSocketChannelParent::RecvClose(const uint16_t& code, const nsCString& reason)
  126. {
  127. LOG(("WebSocketChannelParent::RecvClose() %p\n", this));
  128. if (mChannel) {
  129. nsresult rv = mChannel->Close(code, reason);
  130. NS_ENSURE_SUCCESS(rv, true);
  131. }
  132. return true;
  133. }
  134. bool
  135. WebSocketChannelParent::RecvSendMsg(const nsCString& aMsg)
  136. {
  137. LOG(("WebSocketChannelParent::RecvSendMsg() %p\n", this));
  138. if (mChannel) {
  139. nsresult rv = mChannel->SendMsg(aMsg);
  140. NS_ENSURE_SUCCESS(rv, true);
  141. }
  142. return true;
  143. }
  144. bool
  145. WebSocketChannelParent::RecvSendBinaryMsg(const nsCString& aMsg)
  146. {
  147. LOG(("WebSocketChannelParent::RecvSendBinaryMsg() %p\n", this));
  148. if (mChannel) {
  149. nsresult rv = mChannel->SendBinaryMsg(aMsg);
  150. NS_ENSURE_SUCCESS(rv, true);
  151. }
  152. return true;
  153. }
  154. bool
  155. WebSocketChannelParent::RecvSendBinaryStream(const InputStreamParams& aStream,
  156. const uint32_t& aLength)
  157. {
  158. LOG(("WebSocketChannelParent::RecvSendBinaryStream() %p\n", this));
  159. if (mChannel) {
  160. nsTArray<mozilla::ipc::FileDescriptor> fds;
  161. nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aStream, fds);
  162. if (!stream) {
  163. return false;
  164. }
  165. nsresult rv = mChannel->SendBinaryStream(stream, aLength);
  166. NS_ENSURE_SUCCESS(rv, true);
  167. }
  168. return true;
  169. }
  170. //-----------------------------------------------------------------------------
  171. // WebSocketChannelParent::nsIRequestObserver
  172. //-----------------------------------------------------------------------------
  173. NS_IMETHODIMP
  174. WebSocketChannelParent::OnStart(nsISupports *aContext)
  175. {
  176. LOG(("WebSocketChannelParent::OnStart() %p\n", this));
  177. nsAutoCString protocol, extensions;
  178. nsString effectiveURL;
  179. bool encrypted = false;
  180. if (mChannel) {
  181. mChannel->GetProtocol(protocol);
  182. mChannel->GetExtensions(extensions);
  183. RefPtr<WebSocketChannel> channel;
  184. channel = static_cast<WebSocketChannel*>(mChannel.get());
  185. MOZ_ASSERT(channel);
  186. channel->GetEffectiveURL(effectiveURL);
  187. encrypted = channel->IsEncrypted();
  188. }
  189. if (!mIPCOpen || !SendOnStart(protocol, extensions, effectiveURL, encrypted)) {
  190. return NS_ERROR_FAILURE;
  191. }
  192. return NS_OK;
  193. }
  194. NS_IMETHODIMP
  195. WebSocketChannelParent::OnStop(nsISupports *aContext, nsresult aStatusCode)
  196. {
  197. LOG(("WebSocketChannelParent::OnStop() %p\n", this));
  198. if (!mIPCOpen || !SendOnStop(aStatusCode)) {
  199. return NS_ERROR_FAILURE;
  200. }
  201. return NS_OK;
  202. }
  203. NS_IMETHODIMP
  204. WebSocketChannelParent::OnMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
  205. {
  206. LOG(("WebSocketChannelParent::OnMessageAvailable() %p\n", this));
  207. if (!mIPCOpen || !SendOnMessageAvailable(nsCString(aMsg))) {
  208. return NS_ERROR_FAILURE;
  209. }
  210. return NS_OK;
  211. }
  212. NS_IMETHODIMP
  213. WebSocketChannelParent::OnBinaryMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
  214. {
  215. LOG(("WebSocketChannelParent::OnBinaryMessageAvailable() %p\n", this));
  216. if (!mIPCOpen || !SendOnBinaryMessageAvailable(nsCString(aMsg))) {
  217. return NS_ERROR_FAILURE;
  218. }
  219. return NS_OK;
  220. }
  221. NS_IMETHODIMP
  222. WebSocketChannelParent::OnAcknowledge(nsISupports *aContext, uint32_t aSize)
  223. {
  224. LOG(("WebSocketChannelParent::OnAcknowledge() %p\n", this));
  225. if (!mIPCOpen || !SendOnAcknowledge(aSize)) {
  226. return NS_ERROR_FAILURE;
  227. }
  228. return NS_OK;
  229. }
  230. NS_IMETHODIMP
  231. WebSocketChannelParent::OnServerClose(nsISupports *aContext,
  232. uint16_t code, const nsACString & reason)
  233. {
  234. LOG(("WebSocketChannelParent::OnServerClose() %p\n", this));
  235. if (!mIPCOpen || !SendOnServerClose(code, nsCString(reason))) {
  236. return NS_ERROR_FAILURE;
  237. }
  238. return NS_OK;
  239. }
  240. void
  241. WebSocketChannelParent::ActorDestroy(ActorDestroyReason why)
  242. {
  243. LOG(("WebSocketChannelParent::ActorDestroy() %p\n", this));
  244. mIPCOpen = false;
  245. }
  246. //-----------------------------------------------------------------------------
  247. // WebSocketChannelParent::nsIInterfaceRequestor
  248. //-----------------------------------------------------------------------------
  249. NS_IMETHODIMP
  250. WebSocketChannelParent::GetInterface(const nsIID & iid, void **result)
  251. {
  252. LOG(("WebSocketChannelParent::GetInterface() %p\n", this));
  253. if (mAuthProvider && iid.Equals(NS_GET_IID(nsIAuthPromptProvider)))
  254. return mAuthProvider->GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
  255. iid, result);
  256. // Only support nsILoadContext if child channel's callbacks did too
  257. if (iid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
  258. nsCOMPtr<nsILoadContext> copy = mLoadContext;
  259. copy.forget(result);
  260. return NS_OK;
  261. }
  262. return QueryInterface(iid, result);
  263. }
  264. } // namespace net
  265. } // namespace mozilla