WebSocketChannelChild.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  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 "base/compiler_specific.h"
  7. #include "mozilla/dom/TabChild.h"
  8. #include "mozilla/net/NeckoChild.h"
  9. #include "WebSocketChannelChild.h"
  10. #include "nsITabChild.h"
  11. #include "nsNetUtil.h"
  12. #include "mozilla/ipc/InputStreamUtils.h"
  13. #include "mozilla/ipc/URIUtils.h"
  14. #include "mozilla/ipc/BackgroundUtils.h"
  15. #include "mozilla/net/ChannelEventQueue.h"
  16. #include "SerializedLoadContext.h"
  17. using namespace mozilla::ipc;
  18. namespace mozilla {
  19. namespace net {
  20. NS_IMPL_ADDREF(WebSocketChannelChild)
  21. NS_IMETHODIMP_(MozExternalRefCountType) WebSocketChannelChild::Release()
  22. {
  23. NS_PRECONDITION(0 != mRefCnt, "dup release");
  24. --mRefCnt;
  25. NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");
  26. if (mRefCnt == 1) {
  27. MaybeReleaseIPCObject();
  28. return mRefCnt;
  29. }
  30. if (mRefCnt == 0) {
  31. mRefCnt = 1; /* stabilize */
  32. delete this;
  33. return 0;
  34. }
  35. return mRefCnt;
  36. }
  37. NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
  38. NS_INTERFACE_MAP_ENTRY(nsIWebSocketChannel)
  39. NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
  40. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketChannel)
  41. NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
  42. NS_INTERFACE_MAP_END
  43. WebSocketChannelChild::WebSocketChannelChild(bool aEncrypted)
  44. : mIPCState(Closed)
  45. , mMutex("WebSocketChannelChild::mMutex")
  46. {
  47. MOZ_ASSERT(NS_IsMainThread(), "not main thread");
  48. LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n", this));
  49. mEncrypted = aEncrypted;
  50. mEventQ = new ChannelEventQueue(static_cast<nsIWebSocketChannel*>(this));
  51. }
  52. WebSocketChannelChild::~WebSocketChannelChild()
  53. {
  54. LOG(("WebSocketChannelChild::~WebSocketChannelChild() %p\n", this));
  55. }
  56. void
  57. WebSocketChannelChild::AddIPDLReference()
  58. {
  59. MOZ_ASSERT(NS_IsMainThread());
  60. {
  61. MutexAutoLock lock(mMutex);
  62. MOZ_ASSERT(mIPCState == Closed, "Attempt to retain more than one IPDL reference");
  63. mIPCState = Opened;
  64. }
  65. AddRef();
  66. }
  67. void
  68. WebSocketChannelChild::ReleaseIPDLReference()
  69. {
  70. MOZ_ASSERT(NS_IsMainThread());
  71. {
  72. MutexAutoLock lock(mMutex);
  73. MOZ_ASSERT(mIPCState != Closed, "Attempt to release nonexistent IPDL reference");
  74. mIPCState = Closed;
  75. }
  76. Release();
  77. }
  78. void
  79. WebSocketChannelChild::MaybeReleaseIPCObject()
  80. {
  81. {
  82. MutexAutoLock lock(mMutex);
  83. if (mIPCState != Opened) {
  84. return;
  85. }
  86. mIPCState = Closing;
  87. }
  88. if (!NS_IsMainThread()) {
  89. MOZ_ALWAYS_SUCCEEDS(
  90. NS_DispatchToMainThread(NewRunnableMethod(this,
  91. &WebSocketChannelChild::MaybeReleaseIPCObject)));
  92. return;
  93. }
  94. SendDeleteSelf();
  95. }
  96. void
  97. WebSocketChannelChild::GetEffectiveURL(nsAString& aEffectiveURL) const
  98. {
  99. aEffectiveURL = mEffectiveURL;
  100. }
  101. bool
  102. WebSocketChannelChild::IsEncrypted() const
  103. {
  104. return mEncrypted;
  105. }
  106. class WrappedChannelEvent : public Runnable
  107. {
  108. public:
  109. explicit WrappedChannelEvent(ChannelEvent *aChannelEvent)
  110. : mChannelEvent(aChannelEvent)
  111. {
  112. MOZ_RELEASE_ASSERT(aChannelEvent);
  113. }
  114. NS_IMETHOD Run() override
  115. {
  116. mChannelEvent->Run();
  117. return NS_OK;
  118. }
  119. private:
  120. nsAutoPtr<ChannelEvent> mChannelEvent;
  121. };
  122. void
  123. WebSocketChannelChild::DispatchToTargetThread(ChannelEvent *aChannelEvent)
  124. {
  125. MOZ_RELEASE_ASSERT(NS_IsMainThread());
  126. MOZ_RELEASE_ASSERT(mTargetThread);
  127. MOZ_RELEASE_ASSERT(aChannelEvent);
  128. mTargetThread->Dispatch(new WrappedChannelEvent(aChannelEvent),
  129. NS_DISPATCH_NORMAL);
  130. }
  131. class EventTargetDispatcher : public ChannelEvent
  132. {
  133. public:
  134. EventTargetDispatcher(ChannelEvent* aChannelEvent,
  135. nsIEventTarget* aEventTarget)
  136. : mChannelEvent(aChannelEvent)
  137. , mEventTarget(aEventTarget)
  138. {}
  139. void Run()
  140. {
  141. if (mEventTarget) {
  142. mEventTarget->Dispatch(new WrappedChannelEvent(mChannelEvent.forget()),
  143. NS_DISPATCH_NORMAL);
  144. return;
  145. }
  146. mChannelEvent->Run();
  147. }
  148. private:
  149. nsAutoPtr<ChannelEvent> mChannelEvent;
  150. nsCOMPtr<nsIEventTarget> mEventTarget;
  151. };
  152. class StartEvent : public ChannelEvent
  153. {
  154. public:
  155. StartEvent(WebSocketChannelChild* aChild,
  156. const nsCString& aProtocol,
  157. const nsCString& aExtensions,
  158. const nsString& aEffectiveURL,
  159. bool aEncrypted)
  160. : mChild(aChild)
  161. , mProtocol(aProtocol)
  162. , mExtensions(aExtensions)
  163. , mEffectiveURL(aEffectiveURL)
  164. , mEncrypted(aEncrypted)
  165. {}
  166. void Run()
  167. {
  168. mChild->OnStart(mProtocol, mExtensions, mEffectiveURL, mEncrypted);
  169. }
  170. private:
  171. RefPtr<WebSocketChannelChild> mChild;
  172. nsCString mProtocol;
  173. nsCString mExtensions;
  174. nsString mEffectiveURL;
  175. bool mEncrypted;
  176. };
  177. bool
  178. WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol,
  179. const nsCString& aExtensions,
  180. const nsString& aEffectiveURL,
  181. const bool& aEncrypted)
  182. {
  183. mEventQ->RunOrEnqueue(
  184. new EventTargetDispatcher(new StartEvent(this, aProtocol, aExtensions,
  185. aEffectiveURL, aEncrypted),
  186. mTargetThread));
  187. return true;
  188. }
  189. void
  190. WebSocketChannelChild::OnStart(const nsCString& aProtocol,
  191. const nsCString& aExtensions,
  192. const nsString& aEffectiveURL,
  193. const bool& aEncrypted)
  194. {
  195. LOG(("WebSocketChannelChild::RecvOnStart() %p\n", this));
  196. SetProtocol(aProtocol);
  197. mNegotiatedExtensions = aExtensions;
  198. mEffectiveURL = aEffectiveURL;
  199. mEncrypted = aEncrypted;
  200. if (mListenerMT) {
  201. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  202. mListenerMT->mListener->OnStart(mListenerMT->mContext);
  203. }
  204. }
  205. class StopEvent : public ChannelEvent
  206. {
  207. public:
  208. StopEvent(WebSocketChannelChild* aChild,
  209. const nsresult& aStatusCode)
  210. : mChild(aChild)
  211. , mStatusCode(aStatusCode)
  212. {}
  213. void Run()
  214. {
  215. mChild->OnStop(mStatusCode);
  216. }
  217. private:
  218. RefPtr<WebSocketChannelChild> mChild;
  219. nsresult mStatusCode;
  220. };
  221. bool
  222. WebSocketChannelChild::RecvOnStop(const nsresult& aStatusCode)
  223. {
  224. mEventQ->RunOrEnqueue(
  225. new EventTargetDispatcher(new StopEvent(this, aStatusCode),
  226. mTargetThread));
  227. return true;
  228. }
  229. void
  230. WebSocketChannelChild::OnStop(const nsresult& aStatusCode)
  231. {
  232. LOG(("WebSocketChannelChild::RecvOnStop() %p\n", this));
  233. if (mListenerMT) {
  234. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  235. mListenerMT->mListener->OnStop(mListenerMT->mContext, aStatusCode);
  236. }
  237. }
  238. class MessageEvent : public ChannelEvent
  239. {
  240. public:
  241. MessageEvent(WebSocketChannelChild* aChild,
  242. const nsCString& aMessage,
  243. bool aBinary)
  244. : mChild(aChild)
  245. , mMessage(aMessage)
  246. , mBinary(aBinary)
  247. {}
  248. void Run()
  249. {
  250. if (!mBinary) {
  251. mChild->OnMessageAvailable(mMessage);
  252. } else {
  253. mChild->OnBinaryMessageAvailable(mMessage);
  254. }
  255. }
  256. private:
  257. RefPtr<WebSocketChannelChild> mChild;
  258. nsCString mMessage;
  259. bool mBinary;
  260. };
  261. bool
  262. WebSocketChannelChild::RecvOnMessageAvailable(const nsCString& aMsg)
  263. {
  264. mEventQ->RunOrEnqueue(
  265. new EventTargetDispatcher(new MessageEvent(this, aMsg, false),
  266. mTargetThread));
  267. return true;
  268. }
  269. void
  270. WebSocketChannelChild::OnMessageAvailable(const nsCString& aMsg)
  271. {
  272. LOG(("WebSocketChannelChild::RecvOnMessageAvailable() %p\n", this));
  273. if (mListenerMT) {
  274. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  275. mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext, aMsg);
  276. }
  277. }
  278. bool
  279. WebSocketChannelChild::RecvOnBinaryMessageAvailable(const nsCString& aMsg)
  280. {
  281. mEventQ->RunOrEnqueue(
  282. new EventTargetDispatcher(new MessageEvent(this, aMsg, true),
  283. mTargetThread));
  284. return true;
  285. }
  286. void
  287. WebSocketChannelChild::OnBinaryMessageAvailable(const nsCString& aMsg)
  288. {
  289. LOG(("WebSocketChannelChild::RecvOnBinaryMessageAvailable() %p\n", this));
  290. if (mListenerMT) {
  291. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  292. mListenerMT->mListener->OnBinaryMessageAvailable(mListenerMT->mContext,
  293. aMsg);
  294. }
  295. }
  296. class AcknowledgeEvent : public ChannelEvent
  297. {
  298. public:
  299. AcknowledgeEvent(WebSocketChannelChild* aChild,
  300. const uint32_t& aSize)
  301. : mChild(aChild)
  302. , mSize(aSize)
  303. {}
  304. void Run()
  305. {
  306. mChild->OnAcknowledge(mSize);
  307. }
  308. private:
  309. RefPtr<WebSocketChannelChild> mChild;
  310. uint32_t mSize;
  311. };
  312. bool
  313. WebSocketChannelChild::RecvOnAcknowledge(const uint32_t& aSize)
  314. {
  315. mEventQ->RunOrEnqueue(
  316. new EventTargetDispatcher(new AcknowledgeEvent(this, aSize),
  317. mTargetThread));
  318. return true;
  319. }
  320. void
  321. WebSocketChannelChild::OnAcknowledge(const uint32_t& aSize)
  322. {
  323. LOG(("WebSocketChannelChild::RecvOnAcknowledge() %p\n", this));
  324. if (mListenerMT) {
  325. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  326. mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, aSize);
  327. }
  328. }
  329. class ServerCloseEvent : public ChannelEvent
  330. {
  331. public:
  332. ServerCloseEvent(WebSocketChannelChild* aChild,
  333. const uint16_t aCode,
  334. const nsCString &aReason)
  335. : mChild(aChild)
  336. , mCode(aCode)
  337. , mReason(aReason)
  338. {}
  339. void Run()
  340. {
  341. mChild->OnServerClose(mCode, mReason);
  342. }
  343. private:
  344. RefPtr<WebSocketChannelChild> mChild;
  345. uint16_t mCode;
  346. nsCString mReason;
  347. };
  348. bool
  349. WebSocketChannelChild::RecvOnServerClose(const uint16_t& aCode,
  350. const nsCString& aReason)
  351. {
  352. mEventQ->RunOrEnqueue(
  353. new EventTargetDispatcher(new ServerCloseEvent(this, aCode, aReason),
  354. mTargetThread));
  355. return true;
  356. }
  357. void
  358. WebSocketChannelChild::OnServerClose(const uint16_t& aCode,
  359. const nsCString& aReason)
  360. {
  361. LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n", this));
  362. if (mListenerMT) {
  363. AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  364. mListenerMT->mListener->OnServerClose(mListenerMT->mContext, aCode,
  365. aReason);
  366. }
  367. }
  368. NS_IMETHODIMP
  369. WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
  370. const nsACString &aOrigin,
  371. uint64_t aInnerWindowID,
  372. nsIWebSocketListener *aListener,
  373. nsISupports *aContext)
  374. {
  375. LOG(("WebSocketChannelChild::AsyncOpen() %p\n", this));
  376. MOZ_ASSERT(NS_IsMainThread(), "not main thread");
  377. MOZ_ASSERT((aURI && !mIsServerSide) || (!aURI && mIsServerSide),
  378. "Invalid aURI for WebSocketChannelChild::AsyncOpen");
  379. MOZ_ASSERT(aListener && !mListenerMT,
  380. "Invalid state for WebSocketChannelChild::AsyncOpen");
  381. mozilla::dom::TabChild* tabChild = nullptr;
  382. nsCOMPtr<nsITabChild> iTabChild;
  383. NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
  384. NS_GET_IID(nsITabChild),
  385. getter_AddRefs(iTabChild));
  386. if (iTabChild) {
  387. tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
  388. }
  389. if (MissingRequiredTabChild(tabChild, "websocket")) {
  390. return NS_ERROR_ILLEGAL_VALUE;
  391. }
  392. // Corresponding release in DeallocPWebSocket
  393. AddIPDLReference();
  394. OptionalURIParams uri;
  395. OptionalLoadInfoArgs loadInfoArgs;
  396. OptionalTransportProvider transportProvider;
  397. if (!mIsServerSide) {
  398. uri = URIParams();
  399. SerializeURI(aURI, uri.get_URIParams());
  400. nsresult rv = LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
  401. NS_ENSURE_SUCCESS(rv, rv);
  402. transportProvider = void_t();
  403. } else {
  404. uri = void_t();
  405. loadInfoArgs = void_t();
  406. MOZ_ASSERT(mServerTransportProvider);
  407. PTransportProviderChild *ipcChild;
  408. nsresult rv = mServerTransportProvider->GetIPCChild(&ipcChild);
  409. NS_ENSURE_SUCCESS(rv, rv);
  410. transportProvider = ipcChild;
  411. }
  412. gNeckoChild->SendPWebSocketConstructor(this, tabChild,
  413. IPC::SerializedLoadContext(this),
  414. mSerial);
  415. if (!SendAsyncOpen(uri, nsCString(aOrigin), aInnerWindowID, mProtocol,
  416. mEncrypted, mPingInterval, mClientSetPingInterval,
  417. mPingResponseTimeout, mClientSetPingTimeout, loadInfoArgs,
  418. transportProvider, mNegotiatedExtensions)) {
  419. return NS_ERROR_UNEXPECTED;
  420. }
  421. if (mIsServerSide) {
  422. mServerTransportProvider = nullptr;
  423. }
  424. mOriginalURI = aURI;
  425. mURI = mOriginalURI;
  426. mListenerMT = new ListenerAndContextContainer(aListener, aContext);
  427. mOrigin = aOrigin;
  428. mWasOpened = 1;
  429. return NS_OK;
  430. }
  431. class CloseEvent : public Runnable
  432. {
  433. public:
  434. CloseEvent(WebSocketChannelChild *aChild,
  435. uint16_t aCode,
  436. const nsACString& aReason)
  437. : mChild(aChild)
  438. , mCode(aCode)
  439. , mReason(aReason)
  440. {
  441. MOZ_RELEASE_ASSERT(!NS_IsMainThread());
  442. MOZ_ASSERT(aChild);
  443. }
  444. NS_IMETHOD Run() override
  445. {
  446. MOZ_RELEASE_ASSERT(NS_IsMainThread());
  447. mChild->Close(mCode, mReason);
  448. return NS_OK;
  449. }
  450. private:
  451. RefPtr<WebSocketChannelChild> mChild;
  452. uint16_t mCode;
  453. nsCString mReason;
  454. };
  455. NS_IMETHODIMP
  456. WebSocketChannelChild::Close(uint16_t code, const nsACString & reason)
  457. {
  458. if (!NS_IsMainThread()) {
  459. MOZ_RELEASE_ASSERT(NS_GetCurrentThread() == mTargetThread);
  460. return NS_DispatchToMainThread(new CloseEvent(this, code, reason));
  461. }
  462. LOG(("WebSocketChannelChild::Close() %p\n", this));
  463. {
  464. MutexAutoLock lock(mMutex);
  465. if (mIPCState != Opened) {
  466. return NS_ERROR_UNEXPECTED;
  467. }
  468. }
  469. if (!SendClose(code, nsCString(reason))) {
  470. return NS_ERROR_UNEXPECTED;
  471. }
  472. return NS_OK;
  473. }
  474. class MsgEvent : public Runnable
  475. {
  476. public:
  477. MsgEvent(WebSocketChannelChild *aChild,
  478. const nsACString &aMsg,
  479. bool aBinaryMsg)
  480. : mChild(aChild)
  481. , mMsg(aMsg)
  482. , mBinaryMsg(aBinaryMsg)
  483. {
  484. MOZ_RELEASE_ASSERT(!NS_IsMainThread());
  485. MOZ_ASSERT(aChild);
  486. }
  487. NS_IMETHOD Run() override
  488. {
  489. MOZ_RELEASE_ASSERT(NS_IsMainThread());
  490. if (mBinaryMsg) {
  491. mChild->SendBinaryMsg(mMsg);
  492. } else {
  493. mChild->SendMsg(mMsg);
  494. }
  495. return NS_OK;
  496. }
  497. private:
  498. RefPtr<WebSocketChannelChild> mChild;
  499. nsCString mMsg;
  500. bool mBinaryMsg;
  501. };
  502. NS_IMETHODIMP
  503. WebSocketChannelChild::SendMsg(const nsACString &aMsg)
  504. {
  505. if (!NS_IsMainThread()) {
  506. MOZ_RELEASE_ASSERT(IsOnTargetThread());
  507. return NS_DispatchToMainThread(new MsgEvent(this, aMsg, false));
  508. }
  509. LOG(("WebSocketChannelChild::SendMsg() %p\n", this));
  510. {
  511. MutexAutoLock lock(mMutex);
  512. if (mIPCState != Opened) {
  513. return NS_ERROR_UNEXPECTED;
  514. }
  515. }
  516. if (!SendSendMsg(nsCString(aMsg))) {
  517. return NS_ERROR_UNEXPECTED;
  518. }
  519. return NS_OK;
  520. }
  521. NS_IMETHODIMP
  522. WebSocketChannelChild::SendBinaryMsg(const nsACString &aMsg)
  523. {
  524. if (!NS_IsMainThread()) {
  525. MOZ_RELEASE_ASSERT(IsOnTargetThread());
  526. return NS_DispatchToMainThread(new MsgEvent(this, aMsg, true));
  527. }
  528. LOG(("WebSocketChannelChild::SendBinaryMsg() %p\n", this));
  529. {
  530. MutexAutoLock lock(mMutex);
  531. if (mIPCState != Opened) {
  532. return NS_ERROR_UNEXPECTED;
  533. }
  534. }
  535. if (!SendSendBinaryMsg(nsCString(aMsg))) {
  536. return NS_ERROR_UNEXPECTED;
  537. }
  538. return NS_OK;
  539. }
  540. class BinaryStreamEvent : public Runnable
  541. {
  542. public:
  543. BinaryStreamEvent(WebSocketChannelChild *aChild,
  544. OptionalInputStreamParams *aStream,
  545. uint32_t aLength)
  546. : mChild(aChild)
  547. , mStream(aStream)
  548. , mLength(aLength)
  549. {
  550. MOZ_RELEASE_ASSERT(!NS_IsMainThread());
  551. MOZ_ASSERT(aChild);
  552. }
  553. NS_IMETHOD Run() override
  554. {
  555. MOZ_ASSERT(NS_IsMainThread());
  556. mChild->SendBinaryStream(mStream, mLength);
  557. return NS_OK;
  558. }
  559. private:
  560. RefPtr<WebSocketChannelChild> mChild;
  561. nsAutoPtr<OptionalInputStreamParams> mStream;
  562. uint32_t mLength;
  563. };
  564. NS_IMETHODIMP
  565. WebSocketChannelChild::SendBinaryStream(nsIInputStream *aStream,
  566. uint32_t aLength)
  567. {
  568. OptionalInputStreamParams *stream = new OptionalInputStreamParams();
  569. nsTArray<mozilla::ipc::FileDescriptor> fds;
  570. SerializeInputStream(aStream, *stream, fds);
  571. MOZ_ASSERT(fds.IsEmpty());
  572. if (!NS_IsMainThread()) {
  573. MOZ_RELEASE_ASSERT(NS_GetCurrentThread() == mTargetThread);
  574. return NS_DispatchToMainThread(new BinaryStreamEvent(this, stream, aLength));
  575. }
  576. return SendBinaryStream(stream, aLength);
  577. }
  578. nsresult
  579. WebSocketChannelChild::SendBinaryStream(OptionalInputStreamParams *aStream,
  580. uint32_t aLength)
  581. {
  582. LOG(("WebSocketChannelChild::SendBinaryStream() %p\n", this));
  583. nsAutoPtr<OptionalInputStreamParams> stream(aStream);
  584. {
  585. MutexAutoLock lock(mMutex);
  586. if (mIPCState != Opened) {
  587. return NS_ERROR_UNEXPECTED;
  588. }
  589. }
  590. if (!SendSendBinaryStream(*stream, aLength)) {
  591. return NS_ERROR_UNEXPECTED;
  592. }
  593. return NS_OK;
  594. }
  595. NS_IMETHODIMP
  596. WebSocketChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
  597. {
  598. LOG(("WebSocketChannelChild::GetSecurityInfo() %p\n", this));
  599. return NS_ERROR_NOT_AVAILABLE;
  600. }
  601. //-----------------------------------------------------------------------------
  602. // WebSocketChannelChild::nsIThreadRetargetableRequest
  603. //-----------------------------------------------------------------------------
  604. NS_IMETHODIMP
  605. WebSocketChannelChild::RetargetDeliveryTo(nsIEventTarget* aTargetThread)
  606. {
  607. nsresult rv = BaseWebSocketChannel::RetargetDeliveryTo(aTargetThread);
  608. MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
  609. return mEventQ->RetargetDeliveryTo(aTargetThread);
  610. }
  611. bool
  612. WebSocketChannelChild::IsOnTargetThread()
  613. {
  614. MOZ_ASSERT(mTargetThread);
  615. bool isOnTargetThread = false;
  616. nsresult rv = mTargetThread->IsOnCurrentThread(&isOnTargetThread);
  617. MOZ_ASSERT(NS_SUCCEEDED(rv));
  618. return NS_FAILED(rv) ? false : isOnTargetThread;
  619. }
  620. } // namespace net
  621. } // namespace mozilla