LCOV - code coverage report
Current view: top level - netwerk/protocol/websocket - WebSocketChannelChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 379 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 78 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 ts=8 et tw=80 : */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "WebSocketLog.h"
       8             : #include "base/compiler_specific.h"
       9             : #include "mozilla/dom/TabChild.h"
      10             : #include "mozilla/net/NeckoChild.h"
      11             : #include "WebSocketChannelChild.h"
      12             : #include "nsContentUtils.h"
      13             : #include "nsITabChild.h"
      14             : #include "nsNetUtil.h"
      15             : #include "mozilla/ipc/IPCStreamUtils.h"
      16             : #include "mozilla/ipc/URIUtils.h"
      17             : #include "mozilla/ipc/BackgroundUtils.h"
      18             : #include "mozilla/net/ChannelEventQueue.h"
      19             : #include "SerializedLoadContext.h"
      20             : 
      21             : using namespace mozilla::ipc;
      22             : 
      23             : namespace mozilla {
      24             : namespace net {
      25             : 
      26           0 : NS_IMPL_ADDREF(WebSocketChannelChild)
      27             : 
      28           0 : NS_IMETHODIMP_(MozExternalRefCountType) WebSocketChannelChild::Release()
      29             : {
      30           0 :   NS_PRECONDITION(0 != mRefCnt, "dup release");
      31           0 :   --mRefCnt;
      32           0 :   NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");
      33             : 
      34           0 :   if (mRefCnt == 1) {
      35           0 :     MaybeReleaseIPCObject();
      36           0 :     return mRefCnt;
      37             :   }
      38             : 
      39           0 :   if (mRefCnt == 0) {
      40           0 :     mRefCnt = 1; /* stabilize */
      41           0 :     delete this;
      42           0 :     return 0;
      43             :   }
      44           0 :   return mRefCnt;
      45             : }
      46             : 
      47           0 : NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
      48           0 :   NS_INTERFACE_MAP_ENTRY(nsIWebSocketChannel)
      49           0 :   NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
      50           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketChannel)
      51           0 :   NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
      52           0 : NS_INTERFACE_MAP_END
      53             : 
      54           0 : WebSocketChannelChild::WebSocketChannelChild(bool aEncrypted)
      55             :  : NeckoTargetHolder(nullptr)
      56             :  , mIPCState(Closed)
      57           0 :  , mMutex("WebSocketChannelChild::mMutex")
      58             : {
      59           0 :   MOZ_ASSERT(NS_IsMainThread(), "not main thread");
      60             : 
      61           0 :   LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n", this));
      62           0 :   mEncrypted = aEncrypted;
      63           0 :   mEventQ = new ChannelEventQueue(static_cast<nsIWebSocketChannel*>(this));
      64           0 : }
      65             : 
      66           0 : WebSocketChannelChild::~WebSocketChannelChild()
      67             : {
      68           0 :   LOG(("WebSocketChannelChild::~WebSocketChannelChild() %p\n", this));
      69           0 : }
      70             : 
      71             : void
      72           0 : WebSocketChannelChild::AddIPDLReference()
      73             : {
      74           0 :   MOZ_ASSERT(NS_IsMainThread());
      75             : 
      76             :   {
      77           0 :     MutexAutoLock lock(mMutex);
      78           0 :     MOZ_ASSERT(mIPCState == Closed, "Attempt to retain more than one IPDL reference");
      79           0 :     mIPCState = Opened;
      80             :   }
      81             : 
      82           0 :   AddRef();
      83           0 : }
      84             : 
      85             : void
      86           0 : WebSocketChannelChild::ReleaseIPDLReference()
      87             : {
      88           0 :   MOZ_ASSERT(NS_IsMainThread());
      89             : 
      90             :   {
      91           0 :     MutexAutoLock lock(mMutex);
      92           0 :     MOZ_ASSERT(mIPCState != Closed, "Attempt to release nonexistent IPDL reference");
      93           0 :     mIPCState = Closed;
      94             :   }
      95             : 
      96           0 :   Release();
      97           0 : }
      98             : 
      99             : void
     100           0 : WebSocketChannelChild::MaybeReleaseIPCObject()
     101             : {
     102             :   {
     103           0 :     MutexAutoLock lock(mMutex);
     104           0 :     if (mIPCState != Opened) {
     105           0 :       return;
     106             :     }
     107             : 
     108           0 :     mIPCState = Closing;
     109             :   }
     110             : 
     111           0 :   if (!NS_IsMainThread()) {
     112           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     113           0 :     MOZ_ALWAYS_SUCCEEDS(
     114             :       target->Dispatch(NewRunnableMethod("WebSocketChannelChild::MaybeReleaseIPCObject",
     115             :                                          this,
     116             :                                          &WebSocketChannelChild::MaybeReleaseIPCObject),
     117             :                        NS_DISPATCH_NORMAL));
     118           0 :     return;
     119             :   }
     120             : 
     121           0 :   SendDeleteSelf();
     122             : }
     123             : 
     124             : void
     125           0 : WebSocketChannelChild::GetEffectiveURL(nsAString& aEffectiveURL) const
     126             : {
     127           0 :   aEffectiveURL = mEffectiveURL;
     128           0 : }
     129             : 
     130             : bool
     131           0 : WebSocketChannelChild::IsEncrypted() const
     132             : {
     133           0 :   return mEncrypted;
     134             : }
     135             : 
     136           0 : class WrappedChannelEvent : public Runnable
     137             : {
     138             : public:
     139           0 :   explicit WrappedChannelEvent(ChannelEvent* aChannelEvent)
     140           0 :     : Runnable("net::WrappedChannelEvent")
     141           0 :     , mChannelEvent(aChannelEvent)
     142             :   {
     143           0 :     MOZ_RELEASE_ASSERT(aChannelEvent);
     144           0 :   }
     145           0 :   NS_IMETHOD Run() override
     146             :   {
     147           0 :     mChannelEvent->Run();
     148           0 :     return NS_OK;
     149             :   }
     150             : private:
     151             :   nsAutoPtr<ChannelEvent> mChannelEvent;
     152             : };
     153             : 
     154             : void
     155           0 : WebSocketChannelChild::DispatchToTargetThread(ChannelEvent *aChannelEvent)
     156             : {
     157           0 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
     158           0 :   MOZ_RELEASE_ASSERT(mTargetThread);
     159           0 :   MOZ_RELEASE_ASSERT(aChannelEvent);
     160             : 
     161           0 :   mTargetThread->Dispatch(new WrappedChannelEvent(aChannelEvent),
     162           0 :                           NS_DISPATCH_NORMAL);
     163           0 : }
     164             : 
     165           0 : class EventTargetDispatcher : public ChannelEvent
     166             : {
     167             : public:
     168           0 :   EventTargetDispatcher(ChannelEvent* aChannelEvent,
     169             :                         nsIEventTarget* aEventTarget)
     170           0 :     : mChannelEvent(aChannelEvent)
     171           0 :     , mEventTarget(aEventTarget)
     172           0 :   {}
     173             : 
     174           0 :   void Run()
     175             :   {
     176           0 :     if (mEventTarget) {
     177           0 :       mEventTarget->Dispatch(new WrappedChannelEvent(mChannelEvent.forget()),
     178           0 :                              NS_DISPATCH_NORMAL);
     179           0 :       return;
     180             :     }
     181             : 
     182           0 :     mChannelEvent->Run();
     183             :   }
     184             : 
     185           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     186             :   {
     187           0 :     nsCOMPtr<nsIEventTarget> target = mEventTarget;
     188           0 :     if (!target) {
     189           0 :       target = GetMainThreadEventTarget();
     190             :     }
     191           0 :     return target.forget();
     192             :   }
     193             : 
     194             : private:
     195             :   nsAutoPtr<ChannelEvent> mChannelEvent;
     196             :   nsCOMPtr<nsIEventTarget> mEventTarget;
     197             : };
     198             : 
     199           0 : class StartEvent : public ChannelEvent
     200             : {
     201             :  public:
     202           0 :   StartEvent(WebSocketChannelChild* aChild,
     203             :              const nsCString& aProtocol,
     204             :              const nsCString& aExtensions,
     205             :              const nsString& aEffectiveURL,
     206             :              bool aEncrypted)
     207           0 :   : mChild(aChild)
     208             :   , mProtocol(aProtocol)
     209             :   , mExtensions(aExtensions)
     210             :   , mEffectiveURL(aEffectiveURL)
     211           0 :   , mEncrypted(aEncrypted)
     212           0 :   {}
     213             : 
     214           0 :   void Run()
     215             :   {
     216           0 :     mChild->OnStart(mProtocol, mExtensions, mEffectiveURL, mEncrypted);
     217           0 :   }
     218             : 
     219           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     220             :   {
     221           0 :     return do_AddRef(GetCurrentThreadEventTarget());
     222             :   }
     223             : 
     224             :  private:
     225             :   RefPtr<WebSocketChannelChild> mChild;
     226             :   nsCString mProtocol;
     227             :   nsCString mExtensions;
     228             :   nsString mEffectiveURL;
     229             :   bool mEncrypted;
     230             : };
     231             : 
     232             : mozilla::ipc::IPCResult
     233           0 : WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol,
     234             :                                    const nsCString& aExtensions,
     235             :                                    const nsString& aEffectiveURL,
     236             :                                    const bool& aEncrypted)
     237             : {
     238           0 :   mEventQ->RunOrEnqueue(
     239           0 :     new EventTargetDispatcher(new StartEvent(this, aProtocol, aExtensions,
     240           0 :                                              aEffectiveURL, aEncrypted),
     241           0 :                               mTargetThread));
     242             : 
     243           0 :   return IPC_OK();
     244             : }
     245             : 
     246             : void
     247           0 : WebSocketChannelChild::OnStart(const nsCString& aProtocol,
     248             :                                const nsCString& aExtensions,
     249             :                                const nsString& aEffectiveURL,
     250             :                                const bool& aEncrypted)
     251             : {
     252           0 :   LOG(("WebSocketChannelChild::RecvOnStart() %p\n", this));
     253           0 :   SetProtocol(aProtocol);
     254           0 :   mNegotiatedExtensions = aExtensions;
     255           0 :   mEffectiveURL = aEffectiveURL;
     256           0 :   mEncrypted = aEncrypted;
     257             : 
     258           0 :   if (mListenerMT) {
     259           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     260           0 :     nsresult rv = mListenerMT->mListener->OnStart(mListenerMT->mContext);
     261           0 :     if (NS_FAILED(rv)) {
     262           0 :       LOG(("WebSocketChannelChild::OnStart "
     263             :            "mListenerMT->mListener->OnStart() failed with error 0x%08" PRIx32,
     264             :            static_cast<uint32_t>(rv)));
     265             :     }
     266             :   }
     267           0 : }
     268             : 
     269           0 : class StopEvent : public ChannelEvent
     270             : {
     271             :  public:
     272           0 :   StopEvent(WebSocketChannelChild* aChild,
     273             :             const nsresult& aStatusCode)
     274           0 :   : mChild(aChild)
     275           0 :   , mStatusCode(aStatusCode)
     276           0 :   {}
     277             : 
     278           0 :   void Run()
     279             :   {
     280           0 :     mChild->OnStop(mStatusCode);
     281           0 :   }
     282             : 
     283           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     284             :   {
     285           0 :     return do_AddRef(GetCurrentThreadEventTarget());
     286             :   }
     287             : 
     288             :  private:
     289             :   RefPtr<WebSocketChannelChild> mChild;
     290             :   nsresult mStatusCode;
     291             : };
     292             : 
     293             : mozilla::ipc::IPCResult
     294           0 : WebSocketChannelChild::RecvOnStop(const nsresult& aStatusCode)
     295             : {
     296           0 :   mEventQ->RunOrEnqueue(
     297           0 :     new EventTargetDispatcher(new StopEvent(this, aStatusCode),
     298           0 :                               mTargetThread));
     299             : 
     300           0 :   return IPC_OK();
     301             : }
     302             : 
     303             : void
     304           0 : WebSocketChannelChild::OnStop(const nsresult& aStatusCode)
     305             : {
     306           0 :   LOG(("WebSocketChannelChild::RecvOnStop() %p\n", this));
     307           0 :   if (mListenerMT) {
     308           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     309             :     nsresult rv =
     310           0 :       mListenerMT->mListener->OnStop(mListenerMT->mContext, aStatusCode);
     311           0 :     if (NS_FAILED(rv)) {
     312           0 :       LOG(("WebSocketChannel::OnStop "
     313             :            "mListenerMT->mListener->OnStop() failed with error 0x%08" PRIx32,
     314             :            static_cast<uint32_t>(rv)));
     315             :     }
     316             :   }
     317           0 : }
     318             : 
     319           0 : class MessageEvent : public ChannelEvent
     320             : {
     321             :  public:
     322           0 :   MessageEvent(WebSocketChannelChild* aChild,
     323             :                const nsCString& aMessage,
     324             :                bool aBinary)
     325           0 :   : mChild(aChild)
     326             :   , mMessage(aMessage)
     327           0 :   , mBinary(aBinary)
     328           0 :   {}
     329             : 
     330           0 :   void Run()
     331             :   {
     332           0 :     if (!mBinary) {
     333           0 :       mChild->OnMessageAvailable(mMessage);
     334             :     } else {
     335           0 :       mChild->OnBinaryMessageAvailable(mMessage);
     336             :     }
     337           0 :   }
     338             : 
     339           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     340             :   {
     341           0 :     return do_AddRef(GetCurrentThreadEventTarget());
     342             :   }
     343             : 
     344             :  private:
     345             :   RefPtr<WebSocketChannelChild> mChild;
     346             :   nsCString mMessage;
     347             :   bool mBinary;
     348             : };
     349             : 
     350             : mozilla::ipc::IPCResult
     351           0 : WebSocketChannelChild::RecvOnMessageAvailable(const nsCString& aMsg)
     352             : {
     353           0 :   mEventQ->RunOrEnqueue(
     354           0 :     new EventTargetDispatcher(new MessageEvent(this, aMsg, false),
     355           0 :                               mTargetThread));
     356             : 
     357           0 :   return IPC_OK();
     358             : }
     359             : 
     360             : void
     361           0 : WebSocketChannelChild::OnMessageAvailable(const nsCString& aMsg)
     362             : {
     363           0 :   LOG(("WebSocketChannelChild::RecvOnMessageAvailable() %p\n", this));
     364           0 :   if (mListenerMT) {
     365           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     366             :     nsresult rv =
     367           0 :       mListenerMT->mListener->OnMessageAvailable(mListenerMT->mContext, aMsg);
     368           0 :     if (NS_FAILED(rv)) {
     369           0 :       LOG(("WebSocketChannelChild::OnMessageAvailable "
     370             :            "mListenerMT->mListener->OnMessageAvailable() "
     371             :            "failed with error 0x%08" PRIx32, static_cast<uint32_t>(rv)));
     372             :     }
     373             :   }
     374           0 : }
     375             : 
     376             : mozilla::ipc::IPCResult
     377           0 : WebSocketChannelChild::RecvOnBinaryMessageAvailable(const nsCString& aMsg)
     378             : {
     379           0 :   mEventQ->RunOrEnqueue(
     380           0 :     new EventTargetDispatcher(new MessageEvent(this, aMsg, true),
     381           0 :                               mTargetThread));
     382             : 
     383           0 :   return IPC_OK();
     384             : }
     385             : 
     386             : void
     387           0 : WebSocketChannelChild::OnBinaryMessageAvailable(const nsCString& aMsg)
     388             : {
     389           0 :   LOG(("WebSocketChannelChild::RecvOnBinaryMessageAvailable() %p\n", this));
     390           0 :   if (mListenerMT) {
     391           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     392             :     nsresult rv =
     393           0 :       mListenerMT->mListener->OnBinaryMessageAvailable(mListenerMT->mContext,
     394           0 :                                                        aMsg);
     395           0 :     if (NS_FAILED(rv)) {
     396           0 :       LOG(("WebSocketChannelChild::OnBinaryMessageAvailable "
     397             :            "mListenerMT->mListener->OnBinaryMessageAvailable() "
     398             :            "failed with error 0x%08" PRIx32, static_cast<uint32_t>(rv)));
     399             :     }
     400             :   }
     401           0 : }
     402             : 
     403           0 : class AcknowledgeEvent : public ChannelEvent
     404             : {
     405             :  public:
     406           0 :   AcknowledgeEvent(WebSocketChannelChild* aChild,
     407             :                    const uint32_t& aSize)
     408           0 :   : mChild(aChild)
     409           0 :   , mSize(aSize)
     410           0 :   {}
     411             : 
     412           0 :   void Run()
     413             :   {
     414           0 :     mChild->OnAcknowledge(mSize);
     415           0 :   }
     416             : 
     417           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     418             :   {
     419           0 :     return do_AddRef(GetCurrentThreadEventTarget());
     420             :   }
     421             : 
     422             :  private:
     423             :   RefPtr<WebSocketChannelChild> mChild;
     424             :   uint32_t mSize;
     425             : };
     426             : 
     427             : mozilla::ipc::IPCResult
     428           0 : WebSocketChannelChild::RecvOnAcknowledge(const uint32_t& aSize)
     429             : {
     430           0 :   mEventQ->RunOrEnqueue(
     431           0 :     new EventTargetDispatcher(new AcknowledgeEvent(this, aSize),
     432           0 :                               mTargetThread));
     433             : 
     434           0 :   return IPC_OK();
     435             : }
     436             : 
     437             : void
     438           0 : WebSocketChannelChild::OnAcknowledge(const uint32_t& aSize)
     439             : {
     440           0 :   LOG(("WebSocketChannelChild::RecvOnAcknowledge() %p\n", this));
     441           0 :   if (mListenerMT) {
     442           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     443             :     nsresult rv =
     444           0 :       mListenerMT->mListener->OnAcknowledge(mListenerMT->mContext, aSize);
     445           0 :     if (NS_FAILED(rv)) {
     446           0 :       LOG(("WebSocketChannel::OnAcknowledge "
     447             :            "mListenerMT->mListener->OnAcknowledge() "
     448             :            "failed with error 0x%08" PRIx32, static_cast<uint32_t>(rv)));
     449             :     }
     450             :   }
     451           0 : }
     452             : 
     453           0 : class ServerCloseEvent : public ChannelEvent
     454             : {
     455             :  public:
     456           0 :   ServerCloseEvent(WebSocketChannelChild* aChild,
     457             :                    const uint16_t aCode,
     458             :                    const nsCString &aReason)
     459           0 :   : mChild(aChild)
     460             :   , mCode(aCode)
     461           0 :   , mReason(aReason)
     462           0 :   {}
     463             : 
     464           0 :   void Run()
     465             :   {
     466           0 :     mChild->OnServerClose(mCode, mReason);
     467           0 :   }
     468             : 
     469           0 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     470             :   {
     471           0 :     return do_AddRef(GetCurrentThreadEventTarget());
     472             :   }
     473             : 
     474             :  private:
     475             :   RefPtr<WebSocketChannelChild> mChild;
     476             :   uint16_t mCode;
     477             :   nsCString mReason;
     478             : };
     479             : 
     480             : mozilla::ipc::IPCResult
     481           0 : WebSocketChannelChild::RecvOnServerClose(const uint16_t& aCode,
     482             :                                          const nsCString& aReason)
     483             : {
     484           0 :   mEventQ->RunOrEnqueue(
     485           0 :     new EventTargetDispatcher(new ServerCloseEvent(this, aCode, aReason),
     486           0 :                               mTargetThread));
     487             : 
     488           0 :   return IPC_OK();
     489             : }
     490             : 
     491             : void
     492           0 : WebSocketChannelChild::OnServerClose(const uint16_t& aCode,
     493             :                                      const nsCString& aReason)
     494             : {
     495           0 :   LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n", this));
     496           0 :   if (mListenerMT) {
     497           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     498             :     DebugOnly<nsresult> rv =
     499           0 :       mListenerMT->mListener->OnServerClose(mListenerMT->mContext, aCode,
     500           0 :                                             aReason);
     501           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     502             :   }
     503           0 : }
     504             : 
     505             : void
     506           0 : WebSocketChannelChild::SetupNeckoTarget()
     507             : {
     508           0 :   mNeckoTarget = nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, TaskCategory::Network);
     509           0 :   if (!mNeckoTarget) {
     510           0 :     return;
     511             :   }
     512             : 
     513           0 :   gNeckoChild->SetEventTargetForActor(this, mNeckoTarget);
     514             : }
     515             : 
     516             : NS_IMETHODIMP
     517           0 : WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
     518             :                                  const nsACString &aOrigin,
     519             :                                  uint64_t aInnerWindowID,
     520             :                                  nsIWebSocketListener *aListener,
     521             :                                  nsISupports *aContext)
     522             : {
     523           0 :   LOG(("WebSocketChannelChild::AsyncOpen() %p\n", this));
     524             : 
     525           0 :   MOZ_ASSERT(NS_IsMainThread(), "not main thread");
     526           0 :   MOZ_ASSERT((aURI && !mIsServerSide) || (!aURI && mIsServerSide),
     527             :              "Invalid aURI for WebSocketChannelChild::AsyncOpen");
     528           0 :   MOZ_ASSERT(aListener && !mListenerMT,
     529             :              "Invalid state for WebSocketChannelChild::AsyncOpen");
     530             : 
     531           0 :   mozilla::dom::TabChild* tabChild = nullptr;
     532           0 :   nsCOMPtr<nsITabChild> iTabChild;
     533           0 :   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
     534             :                                 NS_GET_IID(nsITabChild),
     535           0 :                                 getter_AddRefs(iTabChild));
     536           0 :   if (iTabChild) {
     537           0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
     538             :   }
     539           0 :   if (MissingRequiredTabChild(tabChild, "websocket")) {
     540           0 :     return NS_ERROR_ILLEGAL_VALUE;
     541             :   }
     542             : 
     543           0 :   ContentChild* cc = static_cast<ContentChild*>(gNeckoChild->Manager());
     544           0 :   if (cc->IsShuttingDown()) {
     545           0 :     return NS_ERROR_FAILURE;
     546             :   }
     547             : 
     548             :   // Corresponding release in DeallocPWebSocket
     549           0 :   AddIPDLReference();
     550             : 
     551           0 :   OptionalURIParams uri;
     552           0 :   OptionalLoadInfoArgs loadInfoArgs;
     553           0 :   OptionalTransportProvider transportProvider;
     554             : 
     555           0 :   if (!mIsServerSide) {
     556           0 :     uri = URIParams();
     557           0 :     SerializeURI(aURI, uri.get_URIParams());
     558           0 :     nsresult rv = LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
     559           0 :     NS_ENSURE_SUCCESS(rv, rv);
     560             : 
     561           0 :     transportProvider = void_t();
     562             :   } else {
     563           0 :     uri = void_t();
     564           0 :     loadInfoArgs = void_t();
     565             : 
     566           0 :     MOZ_ASSERT(mServerTransportProvider);
     567             :     PTransportProviderChild *ipcChild;
     568           0 :     nsresult rv = mServerTransportProvider->GetIPCChild(&ipcChild);
     569           0 :     NS_ENSURE_SUCCESS(rv, rv);
     570             : 
     571           0 :     transportProvider = ipcChild;
     572             :   }
     573             : 
     574             :   // This must be called before sending constructor message.
     575           0 :   SetupNeckoTarget();
     576             : 
     577           0 :   gNeckoChild->SendPWebSocketConstructor(this, tabChild,
     578           0 :                                          IPC::SerializedLoadContext(this),
     579           0 :                                          mSerial);
     580           0 :   if (!SendAsyncOpen(uri, nsCString(aOrigin), aInnerWindowID, mProtocol,
     581             :                      mEncrypted, mPingInterval, mClientSetPingInterval,
     582             :                      mPingResponseTimeout, mClientSetPingTimeout, loadInfoArgs,
     583           0 :                      transportProvider, mNegotiatedExtensions)) {
     584           0 :     return NS_ERROR_UNEXPECTED;
     585             :   }
     586             : 
     587           0 :   if (mIsServerSide) {
     588           0 :     mServerTransportProvider = nullptr;
     589             :   }
     590             : 
     591           0 :   mOriginalURI = aURI;
     592           0 :   mURI = mOriginalURI;
     593           0 :   mListenerMT = new ListenerAndContextContainer(aListener, aContext);
     594           0 :   mOrigin = aOrigin;
     595           0 :   mWasOpened = 1;
     596             : 
     597           0 :   return NS_OK;
     598             : }
     599             : 
     600           0 : class CloseEvent : public Runnable
     601             : {
     602             : public:
     603           0 :   CloseEvent(WebSocketChannelChild* aChild,
     604             :              uint16_t aCode,
     605             :              const nsACString& aReason)
     606           0 :     : Runnable("net::CloseEvent")
     607             :     , mChild(aChild)
     608             :     , mCode(aCode)
     609           0 :     , mReason(aReason)
     610             :   {
     611           0 :     MOZ_RELEASE_ASSERT(!NS_IsMainThread());
     612           0 :     MOZ_ASSERT(aChild);
     613           0 :   }
     614           0 :   NS_IMETHOD Run() override
     615             :   {
     616           0 :     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     617           0 :     mChild->Close(mCode, mReason);
     618           0 :     return NS_OK;
     619             :   }
     620             : private:
     621             :   RefPtr<WebSocketChannelChild> mChild;
     622             :   uint16_t                        mCode;
     623             :   nsCString                       mReason;
     624             : };
     625             : 
     626             : NS_IMETHODIMP
     627           0 : WebSocketChannelChild::Close(uint16_t code, const nsACString & reason)
     628             : {
     629           0 :   if (!NS_IsMainThread()) {
     630           0 :     MOZ_RELEASE_ASSERT(mTargetThread->IsOnCurrentThread());
     631           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     632           0 :     return target->Dispatch(new CloseEvent(this, code, reason),
     633           0 :                             NS_DISPATCH_NORMAL);
     634             :   }
     635           0 :   LOG(("WebSocketChannelChild::Close() %p\n", this));
     636             : 
     637             :   {
     638           0 :     MutexAutoLock lock(mMutex);
     639           0 :     if (mIPCState != Opened) {
     640           0 :       return NS_ERROR_UNEXPECTED;
     641             :     }
     642             :   }
     643             : 
     644           0 :   if (!SendClose(code, nsCString(reason))) {
     645           0 :     return NS_ERROR_UNEXPECTED;
     646             :   }
     647             : 
     648           0 :   return NS_OK;
     649             : }
     650             : 
     651           0 : class MsgEvent : public Runnable
     652             : {
     653             : public:
     654           0 :   MsgEvent(WebSocketChannelChild* aChild,
     655             :            const nsACString& aMsg,
     656             :            bool aBinaryMsg)
     657           0 :     : Runnable("net::MsgEvent")
     658             :     , mChild(aChild)
     659             :     , mMsg(aMsg)
     660           0 :     , mBinaryMsg(aBinaryMsg)
     661             :   {
     662           0 :     MOZ_RELEASE_ASSERT(!NS_IsMainThread());
     663           0 :     MOZ_ASSERT(aChild);
     664           0 :   }
     665           0 :   NS_IMETHOD Run() override
     666             :   {
     667           0 :     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     668           0 :     if (mBinaryMsg) {
     669           0 :       mChild->SendBinaryMsg(mMsg);
     670             :     } else {
     671           0 :       mChild->SendMsg(mMsg);
     672             :     }
     673           0 :     return NS_OK;
     674             :   }
     675             : private:
     676             :   RefPtr<WebSocketChannelChild> mChild;
     677             :   nsCString                       mMsg;
     678             :   bool                            mBinaryMsg;
     679             : };
     680             : 
     681             : NS_IMETHODIMP
     682           0 : WebSocketChannelChild::SendMsg(const nsACString &aMsg)
     683             : {
     684           0 :   if (!NS_IsMainThread()) {
     685           0 :     MOZ_RELEASE_ASSERT(IsOnTargetThread());
     686           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     687           0 :     return target->Dispatch(new MsgEvent(this, aMsg, false),
     688           0 :                             NS_DISPATCH_NORMAL);
     689             :   }
     690           0 :   LOG(("WebSocketChannelChild::SendMsg() %p\n", this));
     691             : 
     692             :   {
     693           0 :     MutexAutoLock lock(mMutex);
     694           0 :     if (mIPCState != Opened) {
     695           0 :       return NS_ERROR_UNEXPECTED;
     696             :     }
     697             :   }
     698             : 
     699           0 :   if (!SendSendMsg(nsCString(aMsg))) {
     700           0 :     return NS_ERROR_UNEXPECTED;
     701             :   }
     702             : 
     703           0 :   return NS_OK;
     704             : }
     705             : 
     706             : NS_IMETHODIMP
     707           0 : WebSocketChannelChild::SendBinaryMsg(const nsACString &aMsg)
     708             : {
     709           0 :   if (!NS_IsMainThread()) {
     710           0 :     MOZ_RELEASE_ASSERT(IsOnTargetThread());
     711           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     712           0 :     return target->Dispatch(new MsgEvent(this, aMsg, true),
     713           0 :                             NS_DISPATCH_NORMAL);
     714             :   }
     715           0 :   LOG(("WebSocketChannelChild::SendBinaryMsg() %p\n", this));
     716             : 
     717             :   {
     718           0 :     MutexAutoLock lock(mMutex);
     719           0 :     if (mIPCState != Opened) {
     720           0 :       return NS_ERROR_UNEXPECTED;
     721             :     }
     722             :   }
     723             : 
     724           0 :   if (!SendSendBinaryMsg(nsCString(aMsg))) {
     725           0 :     return NS_ERROR_UNEXPECTED;
     726             :   }
     727             : 
     728           0 :   return NS_OK;
     729             : }
     730             : 
     731           0 : class BinaryStreamEvent : public Runnable
     732             : {
     733             : public:
     734           0 :   BinaryStreamEvent(WebSocketChannelChild* aChild,
     735             :                     nsIInputStream* aStream,
     736             :                     uint32_t aLength)
     737           0 :     : Runnable("net::BinaryStreamEvent")
     738             :     , mChild(aChild)
     739             :     , mStream(aStream)
     740           0 :     , mLength(aLength)
     741             :   {
     742           0 :     MOZ_RELEASE_ASSERT(!NS_IsMainThread());
     743           0 :     MOZ_ASSERT(aChild);
     744           0 :   }
     745           0 :   NS_IMETHOD Run() override
     746             :   {
     747           0 :     MOZ_ASSERT(NS_IsMainThread());
     748           0 :     nsresult rv = mChild->SendBinaryStream(mStream, mLength);
     749           0 :     if (NS_FAILED(rv)) {
     750           0 :       LOG(("WebSocketChannelChild::BinaryStreamEvent %p "
     751             :            "SendBinaryStream failed (%08" PRIx32 ")\n", this, static_cast<uint32_t>(rv)));
     752             :     }
     753           0 :     return NS_OK;
     754             :   }
     755             : private:
     756             :   RefPtr<WebSocketChannelChild> mChild;
     757             :   nsCOMPtr<nsIInputStream> mStream;
     758             :   uint32_t mLength;
     759             : };
     760             : 
     761             : NS_IMETHODIMP
     762           0 : WebSocketChannelChild::SendBinaryStream(nsIInputStream *aStream,
     763             :                                         uint32_t aLength)
     764             : {
     765           0 :   if (!NS_IsMainThread()) {
     766           0 :     MOZ_RELEASE_ASSERT(mTargetThread->IsOnCurrentThread());
     767           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     768           0 :     return target->Dispatch(new BinaryStreamEvent(this, aStream, aLength),
     769           0 :                             NS_DISPATCH_NORMAL);
     770             :   }
     771             : 
     772           0 :   LOG(("WebSocketChannelChild::SendBinaryStream() %p\n", this));
     773             : 
     774           0 :   AutoIPCStream autoStream;
     775           0 :   autoStream.Serialize(aStream,
     776           0 :                        static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager()));
     777             : 
     778             :   {
     779           0 :     MutexAutoLock lock(mMutex);
     780           0 :     if (mIPCState != Opened) {
     781           0 :       return NS_ERROR_UNEXPECTED;
     782             :     }
     783             :   }
     784             : 
     785           0 :   if (!SendSendBinaryStream(autoStream.TakeValue(), aLength)) {
     786           0 :     return NS_ERROR_UNEXPECTED;
     787             :   }
     788             : 
     789           0 :   return NS_OK;
     790             : }
     791             : 
     792             : NS_IMETHODIMP
     793           0 : WebSocketChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
     794             : {
     795           0 :   LOG(("WebSocketChannelChild::GetSecurityInfo() %p\n", this));
     796           0 :   return NS_ERROR_NOT_AVAILABLE;
     797             : }
     798             : 
     799             : bool
     800           0 : WebSocketChannelChild::IsOnTargetThread()
     801             : {
     802           0 :   MOZ_ASSERT(mTargetThread);
     803           0 :   bool isOnTargetThread = false;
     804           0 :   nsresult rv = mTargetThread->IsOnCurrentThread(&isOnTargetThread);
     805           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
     806           0 :   return NS_FAILED(rv) ? false : isOnTargetThread;
     807             : }
     808             : 
     809             : } // namespace net
     810             : } // namespace mozilla

Generated by: LCOV version 1.13