LCOV - code coverage report
Current view: top level - dom/base - nsDOMDataChannel.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 278 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 55 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 ts=8 sts=2 et sw=2 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 "nsDOMDataChannel.h"
       8             : 
       9             : #include "base/basictypes.h"
      10             : #include "mozilla/Logging.h"
      11             : 
      12             : #include "nsDOMDataChannelDeclarations.h"
      13             : #include "nsDOMDataChannel.h"
      14             : #include "nsIDOMDataChannel.h"
      15             : #include "mozilla/DOMEventTargetHelper.h"
      16             : #include "mozilla/dom/File.h"
      17             : #include "mozilla/dom/MessageEvent.h"
      18             : #include "mozilla/dom/MessageEventBinding.h"
      19             : #include "mozilla/dom/ScriptSettings.h"
      20             : 
      21             : #include "nsError.h"
      22             : #include "nsContentUtils.h"
      23             : #include "nsCycleCollectionParticipant.h"
      24             : #include "nsIScriptObjectPrincipal.h"
      25             : #include "nsProxyRelease.h"
      26             : 
      27             : #include "DataChannel.h"
      28             : #include "DataChannelLog.h"
      29             : 
      30             : #undef LOG
      31             : #define LOG(args) MOZ_LOG(mozilla::gDataChannelLog, mozilla::LogLevel::Debug, args)
      32             : 
      33             : // Since we've moved the windows.h include down here, we have to explicitly
      34             : // undef GetBinaryType, otherwise we'll get really odd conflicts
      35             : #ifdef GetBinaryType
      36             : #undef GetBinaryType
      37             : #endif
      38             : 
      39             : using namespace mozilla;
      40             : using namespace mozilla::dom;
      41             : 
      42           0 : nsDOMDataChannel::~nsDOMDataChannel()
      43             : {
      44             :   // Don't call us anymore!  Likely isn't an issue (or maybe just less of
      45             :   // one) once we block GC until all the (appropriate) onXxxx handlers
      46             :   // are dropped. (See WebRTC spec)
      47           0 :   LOG(("%p: Close()ing %p", this, mDataChannel.get()));
      48           0 :   mDataChannel->SetListener(nullptr, nullptr);
      49           0 :   mDataChannel->Close();
      50           0 : }
      51             : 
      52             : /* virtual */ JSObject*
      53           0 : nsDOMDataChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      54             : {
      55           0 :   return DataChannelBinding::Wrap(aCx, this, aGivenProto);
      56             : }
      57             : 
      58             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataChannel)
      59             : 
      60           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
      61             :                                                   DOMEventTargetHelper)
      62           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      63             : 
      64           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
      65             :                                                 DOMEventTargetHelper)
      66           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      67             : 
      68           0 : NS_IMPL_ADDREF_INHERITED(nsDOMDataChannel, DOMEventTargetHelper)
      69           0 : NS_IMPL_RELEASE_INHERITED(nsDOMDataChannel, DOMEventTargetHelper)
      70             : 
      71           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDataChannel)
      72           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMDataChannel)
      73           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
      74             : 
      75           0 : nsDOMDataChannel::nsDOMDataChannel(already_AddRefed<mozilla::DataChannel>& aDataChannel,
      76           0 :                                    nsPIDOMWindowInner* aWindow)
      77             :   : DOMEventTargetHelper(aWindow)
      78             :   , mDataChannel(aDataChannel)
      79             :   , mBinaryType(DC_BINARY_TYPE_BLOB)
      80             :   , mCheckMustKeepAlive(true)
      81           0 :   , mSentClose(false)
      82             : {
      83           0 : }
      84             : 
      85             : nsresult
      86           0 : nsDOMDataChannel::Init(nsPIDOMWindowInner* aDOMWindow)
      87             : {
      88             :   nsresult rv;
      89           0 :   nsAutoString urlParam;
      90             : 
      91           0 :   MOZ_ASSERT(mDataChannel);
      92           0 :   mDataChannel->SetListener(this, nullptr);
      93             : 
      94             :   // Now grovel through the objects to get a usable origin for onMessage
      95           0 :   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aDOMWindow);
      96           0 :   NS_ENSURE_STATE(sgo);
      97           0 :   nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
      98           0 :   NS_ENSURE_STATE(scriptContext);
      99             : 
     100           0 :   nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal(do_QueryInterface(aDOMWindow));
     101           0 :   NS_ENSURE_STATE(scriptPrincipal);
     102           0 :   nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
     103           0 :   NS_ENSURE_STATE(principal);
     104             : 
     105             :   // Attempt to kill "ghost" DataChannel (if one can happen): but usually too early for check to fail
     106           0 :   rv = CheckInnerWindowCorrectness();
     107           0 :   NS_ENSURE_SUCCESS(rv,rv);
     108             : 
     109           0 :   rv = nsContentUtils::GetUTFOrigin(principal,mOrigin);
     110           0 :   LOG(("%s: origin = %s\n",__FUNCTION__,NS_LossyConvertUTF16toASCII(mOrigin).get()));
     111           0 :   return rv;
     112             : }
     113             : 
     114           0 : NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, open)
     115           0 : NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, error)
     116           0 : NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, close)
     117           0 : NS_IMPL_EVENT_HANDLER(nsDOMDataChannel, message)
     118             : 
     119             : // Most of the GetFoo()/SetFoo()s don't need to touch shared resources and
     120             : // are safe after Close()
     121             : NS_IMETHODIMP
     122           0 : nsDOMDataChannel::GetLabel(nsAString& aLabel)
     123             : {
     124           0 :   mDataChannel->GetLabel(aLabel);
     125           0 :   return NS_OK;
     126             : }
     127             : 
     128             : NS_IMETHODIMP
     129           0 : nsDOMDataChannel::GetProtocol(nsAString& aProtocol)
     130             : {
     131           0 :   mDataChannel->GetProtocol(aProtocol);
     132           0 :   return NS_OK;
     133             : }
     134             : 
     135             : uint16_t
     136           0 : nsDOMDataChannel::Id() const
     137             : {
     138           0 :   return mDataChannel->GetStream();
     139             : }
     140             : 
     141             : NS_IMETHODIMP
     142           0 : nsDOMDataChannel::GetId(uint16_t *aId)
     143             : {
     144           0 :   *aId = Id();
     145           0 :   return NS_OK;
     146             : }
     147             : 
     148             : // XXX should be GetType()?  Open question for the spec
     149             : bool
     150           0 : nsDOMDataChannel::Reliable() const
     151             : {
     152           0 :   return mDataChannel->GetType() == mozilla::DataChannelConnection::RELIABLE;
     153             : }
     154             : 
     155             : NS_IMETHODIMP
     156           0 : nsDOMDataChannel::GetReliable(bool* aReliable)
     157             : {
     158           0 :   *aReliable = Reliable();
     159           0 :   return NS_OK;
     160             : }
     161             : 
     162             : bool
     163           0 : nsDOMDataChannel::Ordered() const
     164             : {
     165           0 :   return mDataChannel->GetOrdered();
     166             : }
     167             : 
     168             : NS_IMETHODIMP
     169           0 : nsDOMDataChannel::GetOrdered(bool* aOrdered)
     170             : {
     171           0 :   *aOrdered = Ordered();
     172           0 :   return NS_OK;
     173             : }
     174             : 
     175             : RTCDataChannelState
     176           0 : nsDOMDataChannel::ReadyState() const
     177             : {
     178           0 :   return static_cast<RTCDataChannelState>(mDataChannel->GetReadyState());
     179             : }
     180             : 
     181             : 
     182             : NS_IMETHODIMP
     183           0 : nsDOMDataChannel::GetReadyState(nsAString& aReadyState)
     184             : {
     185             :   // mState is handled on multiple threads and needs locking
     186           0 :   uint16_t readyState = mozilla::DataChannel::CLOSED;
     187           0 :   if (!mSentClose) {
     188           0 :     readyState = mDataChannel->GetReadyState();
     189             :   }
     190             :   // From the WebRTC spec
     191             :   const char * stateName[] = {
     192             :     "connecting",
     193             :     "open",
     194             :     "closing",
     195             :     "closed"
     196           0 :   };
     197           0 :   MOZ_ASSERT(/*readyState >= mozilla::DataChannel::CONNECTING && */ // Always true due to datatypes
     198             :              readyState <= mozilla::DataChannel::CLOSED);
     199           0 :   aReadyState.AssignASCII(stateName[readyState]);
     200             : 
     201           0 :   return NS_OK;
     202             : }
     203             : 
     204             : uint32_t
     205           0 : nsDOMDataChannel::BufferedAmount() const
     206             : {
     207           0 :   if (!mSentClose) {
     208           0 :     return mDataChannel->GetBufferedAmount();
     209             :   }
     210           0 :   return 0;
     211             : }
     212             : 
     213             : uint32_t
     214           0 : nsDOMDataChannel::BufferedAmountLowThreshold() const
     215             : {
     216           0 :   return mDataChannel->GetBufferedAmountLowThreshold();
     217             : }
     218             : 
     219             : NS_IMETHODIMP
     220           0 : nsDOMDataChannel::GetBufferedAmount(uint32_t* aBufferedAmount)
     221             : {
     222           0 :   *aBufferedAmount = BufferedAmount();
     223           0 :   return NS_OK;
     224             : }
     225             : 
     226             : void
     227           0 : nsDOMDataChannel::SetBufferedAmountLowThreshold(uint32_t aThreshold)
     228             : {
     229           0 :   mDataChannel->SetBufferedAmountLowThreshold(aThreshold);
     230           0 : }
     231             : 
     232           0 : NS_IMETHODIMP nsDOMDataChannel::GetBinaryType(nsAString & aBinaryType)
     233             : {
     234           0 :   switch (mBinaryType) {
     235             :   case DC_BINARY_TYPE_ARRAYBUFFER:
     236           0 :     aBinaryType.AssignLiteral("arraybuffer");
     237           0 :     break;
     238             :   case DC_BINARY_TYPE_BLOB:
     239           0 :     aBinaryType.AssignLiteral("blob");
     240           0 :     break;
     241             :   default:
     242           0 :     NS_ERROR("Should not happen");
     243             :   }
     244           0 :   return NS_OK;
     245             : }
     246             : 
     247             : NS_IMETHODIMP
     248           0 : nsDOMDataChannel::SetBinaryType(const nsAString& aBinaryType)
     249             : {
     250           0 :   if (aBinaryType.EqualsLiteral("arraybuffer")) {
     251           0 :     mBinaryType = DC_BINARY_TYPE_ARRAYBUFFER;
     252           0 :   } else if (aBinaryType.EqualsLiteral("blob")) {
     253           0 :     mBinaryType = DC_BINARY_TYPE_BLOB;
     254             :   } else  {
     255           0 :     return NS_ERROR_INVALID_ARG;
     256             :   }
     257           0 :   return NS_OK;
     258             : }
     259             : 
     260             : NS_IMETHODIMP
     261           0 : nsDOMDataChannel::Close()
     262             : {
     263           0 :   mDataChannel->Close();
     264           0 :   UpdateMustKeepAlive();
     265           0 :   return NS_OK;
     266             : }
     267             : 
     268             : // All of the following is copy/pasted from WebSocket.cpp.
     269             : void
     270           0 : nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv)
     271             : {
     272           0 :   NS_ConvertUTF16toUTF8 msgString(aData);
     273           0 :   Send(nullptr, msgString, msgString.Length(), false, aRv);
     274           0 : }
     275             : 
     276             : void
     277           0 : nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv)
     278             : {
     279           0 :   MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
     280             : 
     281           0 :   nsCOMPtr<nsIInputStream> msgStream;
     282           0 :   aData.GetInternalStream(getter_AddRefs(msgStream), aRv);
     283           0 :   if (NS_WARN_IF(aRv.Failed())){
     284           0 :     return;
     285             :   }
     286             : 
     287           0 :   uint64_t msgLength = aData.GetSize(aRv);
     288           0 :   if (NS_WARN_IF(aRv.Failed())){
     289           0 :     return;
     290             :   }
     291             : 
     292           0 :   if (msgLength > UINT32_MAX) {
     293           0 :     aRv.Throw(NS_ERROR_FILE_TOO_BIG);
     294           0 :     return;
     295             :   }
     296             : 
     297           0 :   Send(msgStream, EmptyCString(), msgLength, true, aRv);
     298             : }
     299             : 
     300             : void
     301           0 : nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
     302             : {
     303           0 :   MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
     304             : 
     305           0 :   aData.ComputeLengthAndData();
     306             : 
     307             :   static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
     308             : 
     309           0 :   uint32_t len = aData.Length();
     310           0 :   char* data = reinterpret_cast<char*>(aData.Data());
     311             : 
     312           0 :   nsDependentCSubstring msgString(data, len);
     313           0 :   Send(nullptr, msgString, len, true, aRv);
     314           0 : }
     315             : 
     316             : void
     317           0 : nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv)
     318             : {
     319           0 :   MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
     320             : 
     321           0 :   aData.ComputeLengthAndData();
     322             : 
     323             :   static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
     324             : 
     325           0 :   uint32_t len = aData.Length();
     326           0 :   char* data = reinterpret_cast<char*>(aData.Data());
     327             : 
     328           0 :   nsDependentCSubstring msgString(data, len);
     329           0 :   Send(nullptr, msgString, len, true, aRv);
     330           0 : }
     331             : 
     332             : void
     333           0 : nsDOMDataChannel::Send(nsIInputStream* aMsgStream,
     334             :                        const nsACString& aMsgString,
     335             :                        uint32_t aMsgLength,
     336             :                        bool aIsBinary,
     337             :                        ErrorResult& aRv)
     338             : {
     339           0 :   MOZ_ASSERT(NS_IsMainThread());
     340           0 :   uint16_t state = mozilla::DataChannel::CLOSED;
     341           0 :   if (!mSentClose) {
     342           0 :     state = mDataChannel->GetReadyState();
     343             :   }
     344             : 
     345             :   // In reality, the DataChannel protocol allows this, but we want it to
     346             :   // look like WebSockets
     347           0 :   if (state == mozilla::DataChannel::CONNECTING) {
     348           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     349           0 :     return;
     350             :   }
     351             : 
     352           0 :   if (state == mozilla::DataChannel::CLOSING ||
     353             :       state == mozilla::DataChannel::CLOSED) {
     354           0 :     return;
     355             :   }
     356             : 
     357           0 :   MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
     358             :              "Unknown state in nsDOMDataChannel::Send");
     359             : 
     360             :   bool sent;
     361           0 :   if (aMsgStream) {
     362           0 :     sent = mDataChannel->SendBinaryStream(aMsgStream, aMsgLength);
     363             :   } else {
     364           0 :     if (aIsBinary) {
     365           0 :       sent = mDataChannel->SendBinaryMsg(aMsgString);
     366             :     } else {
     367           0 :       sent = mDataChannel->SendMsg(aMsgString);
     368             :     }
     369             :   }
     370           0 :   if (!sent) {
     371           0 :     aRv.Throw(NS_ERROR_FAILURE);
     372             :   }
     373             : }
     374             : 
     375             : nsresult
     376           0 : nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
     377             :                                        bool aBinary)
     378             : {
     379           0 :   MOZ_ASSERT(NS_IsMainThread());
     380             : 
     381           0 :   LOG(("DoOnMessageAvailable%s\n",aBinary ? ((mBinaryType == DC_BINARY_TYPE_BLOB) ? " (blob)" : " (binary)") : ""));
     382             : 
     383           0 :   nsresult rv = CheckInnerWindowCorrectness();
     384           0 :   if (NS_FAILED(rv)) {
     385           0 :     return NS_OK;
     386             :   }
     387             : 
     388           0 :   AutoJSAPI jsapi;
     389           0 :   if (NS_WARN_IF(!jsapi.Init(GetOwner()))) {
     390           0 :     return NS_ERROR_FAILURE;
     391             :   }
     392           0 :   JSContext* cx = jsapi.cx();
     393             : 
     394           0 :   JS::Rooted<JS::Value> jsData(cx);
     395             : 
     396           0 :   if (aBinary) {
     397           0 :     if (mBinaryType == DC_BINARY_TYPE_BLOB) {
     398             :       RefPtr<Blob> blob =
     399           0 :         Blob::CreateStringBlob(GetOwner(), aData, EmptyString());
     400           0 :       MOZ_ASSERT(blob);
     401             : 
     402           0 :       if (!ToJSValue(cx, blob, &jsData)) {
     403           0 :         return NS_ERROR_FAILURE;
     404             :       }
     405           0 :     } else if (mBinaryType == DC_BINARY_TYPE_ARRAYBUFFER) {
     406           0 :       JS::Rooted<JSObject*> arrayBuf(cx);
     407           0 :       rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
     408           0 :       NS_ENSURE_SUCCESS(rv, rv);
     409           0 :       jsData.setObject(*arrayBuf);
     410             :     } else {
     411           0 :       MOZ_CRASH("Unknown binary type!");
     412             :       return NS_ERROR_UNEXPECTED;
     413             :     }
     414             :   } else {
     415           0 :     NS_ConvertUTF8toUTF16 utf16data(aData);
     416           0 :     JSString* jsString = JS_NewUCStringCopyN(cx, utf16data.get(), utf16data.Length());
     417           0 :     NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE);
     418             : 
     419           0 :     jsData.setString(jsString);
     420             :   }
     421             : 
     422           0 :   RefPtr<MessageEvent> event = new MessageEvent(this, nullptr, nullptr);
     423             : 
     424           0 :   event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false, false,
     425           0 :                           jsData, mOrigin, EmptyString(), nullptr,
     426           0 :                           Sequence<OwningNonNull<MessagePort>>());
     427           0 :   event->SetTrusted(true);
     428             : 
     429           0 :   LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
     430           0 :   rv = DispatchDOMEvent(nullptr, static_cast<Event*>(event), nullptr, nullptr);
     431           0 :   if (NS_FAILED(rv)) {
     432           0 :     NS_WARNING("Failed to dispatch the message event!!!");
     433             :   }
     434           0 :   return rv;
     435             : }
     436             : 
     437             : nsresult
     438           0 : nsDOMDataChannel::OnMessageAvailable(nsISupports* aContext,
     439             :                                      const nsACString& aMessage)
     440             : {
     441           0 :   MOZ_ASSERT(NS_IsMainThread());
     442           0 :   return DoOnMessageAvailable(aMessage, false);
     443             : }
     444             : 
     445             : nsresult
     446           0 : nsDOMDataChannel::OnBinaryMessageAvailable(nsISupports* aContext,
     447             :                                            const nsACString& aMessage)
     448             : {
     449           0 :   MOZ_ASSERT(NS_IsMainThread());
     450           0 :   return DoOnMessageAvailable(aMessage, true);
     451             : }
     452             : 
     453             : nsresult
     454           0 : nsDOMDataChannel::OnSimpleEvent(nsISupports* aContext, const nsAString& aName)
     455             : {
     456           0 :   MOZ_ASSERT(NS_IsMainThread());
     457             : 
     458           0 :   nsresult rv = CheckInnerWindowCorrectness();
     459           0 :   if (NS_FAILED(rv)) {
     460           0 :     return NS_OK;
     461             :   }
     462             : 
     463           0 :   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
     464             : 
     465           0 :   event->InitEvent(aName, false, false);
     466           0 :   event->SetTrusted(true);
     467             : 
     468           0 :   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     469             : }
     470             : 
     471             : nsresult
     472           0 : nsDOMDataChannel::OnChannelConnected(nsISupports* aContext)
     473             : {
     474           0 :   LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
     475             : 
     476           0 :   return OnSimpleEvent(aContext, NS_LITERAL_STRING("open"));
     477             : }
     478             : 
     479             : nsresult
     480           0 : nsDOMDataChannel::OnChannelClosed(nsISupports* aContext)
     481             : {
     482             :   nsresult rv;
     483             :   // so we don't have to worry if we're notified from different paths in
     484             :   // the underlying code
     485           0 :   if (!mSentClose) {
     486             :     // Ok, we're done with it.
     487           0 :     mDataChannel->ReleaseConnection();
     488           0 :     LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
     489             : 
     490           0 :     rv = OnSimpleEvent(aContext, NS_LITERAL_STRING("close"));
     491             :     // no more events can happen
     492           0 :     mSentClose = true;
     493             :   } else {
     494           0 :     rv = NS_OK;
     495             :   }
     496           0 :   DontKeepAliveAnyMore();
     497           0 :   return rv;
     498             : }
     499             : 
     500             : nsresult
     501           0 : nsDOMDataChannel::OnBufferLow(nsISupports* aContext)
     502             : {
     503           0 :   LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
     504             : 
     505           0 :   return OnSimpleEvent(aContext, NS_LITERAL_STRING("bufferedamountlow"));
     506             : }
     507             : 
     508             : nsresult
     509           0 : nsDOMDataChannel::NotBuffered(nsISupports* aContext)
     510             : {
     511             :   // In the rare case that we held off GC to let the buffer drain
     512           0 :   UpdateMustKeepAlive();
     513           0 :   return NS_OK;
     514             : }
     515             : 
     516             : void
     517           0 : nsDOMDataChannel::AppReady()
     518             : {
     519           0 :   if (!mSentClose) { // may not be possible, simpler to just test anyways
     520           0 :     mDataChannel->AppReady();
     521             :   }
     522           0 : }
     523             : 
     524             : //-----------------------------------------------------------------------------
     525             : // Methods that keep alive the DataChannel object when:
     526             : //   1. the object has registered event listeners that can be triggered
     527             : //      ("strong event listeners");
     528             : //   2. there are outgoing not sent messages.
     529             : //-----------------------------------------------------------------------------
     530             : 
     531             : void
     532           0 : nsDOMDataChannel::UpdateMustKeepAlive()
     533             : {
     534           0 :   MOZ_ASSERT(NS_IsMainThread());
     535             : 
     536           0 :   if (!mCheckMustKeepAlive) {
     537           0 :     return;
     538             :   }
     539             : 
     540           0 :   bool shouldKeepAlive = false;
     541           0 :   uint16_t readyState = mDataChannel->GetReadyState();
     542             : 
     543           0 :   switch (readyState)
     544             :   {
     545             :     case DataChannel::CONNECTING:
     546             :     case DataChannel::WAITING_TO_OPEN:
     547             :     {
     548           0 :       if (mListenerManager &&
     549           0 :           (mListenerManager->HasListenersFor(nsGkAtoms::onopen) ||
     550           0 :            mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
     551           0 :            mListenerManager->HasListenersFor(nsGkAtoms::onerror) ||
     552           0 :            mListenerManager->HasListenersFor(nsGkAtoms::onbufferedamountlow) ||
     553           0 :            mListenerManager->HasListenersFor(nsGkAtoms::onclose))) {
     554           0 :         shouldKeepAlive = true;
     555             :       }
     556             :     }
     557           0 :     break;
     558             : 
     559             :     case DataChannel::OPEN:
     560             :     case DataChannel::CLOSING:
     561             :     {
     562           0 :       if (mDataChannel->GetBufferedAmount() != 0 ||
     563           0 :           (mListenerManager &&
     564           0 :            (mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
     565           0 :             mListenerManager->HasListenersFor(nsGkAtoms::onerror) ||
     566           0 :             mListenerManager->HasListenersFor(nsGkAtoms::onbufferedamountlow) ||
     567           0 :             mListenerManager->HasListenersFor(nsGkAtoms::onclose)))) {
     568           0 :         shouldKeepAlive = true;
     569             :       }
     570             :     }
     571           0 :     break;
     572             : 
     573             :     case DataChannel::CLOSED:
     574             :     {
     575           0 :       shouldKeepAlive = false;
     576             :     }
     577             :   }
     578             : 
     579           0 :   if (mSelfRef && !shouldKeepAlive) {
     580             :     // release our self-reference (safely) by putting it in an event (always)
     581           0 :     NS_ReleaseOnMainThread("nsDOMDataChannel::mSelfRef", mSelfRef.forget(), true);
     582           0 :   } else if (!mSelfRef && shouldKeepAlive) {
     583           0 :     mSelfRef = this;
     584             :   }
     585             : }
     586             : 
     587             : void
     588           0 : nsDOMDataChannel::DontKeepAliveAnyMore()
     589             : {
     590           0 :   MOZ_ASSERT(NS_IsMainThread());
     591             : 
     592           0 :   if (mSelfRef) {
     593             :     // Since we're on MainThread, force an eventloop trip to avoid deleting ourselves.
     594           0 :     NS_ReleaseOnMainThread("nsDOMDataChannel::mSelfRef", mSelfRef.forget(), true);
     595             :   }
     596             : 
     597           0 :   mCheckMustKeepAlive = false;
     598           0 : }
     599             : 
     600             : void
     601           0 : nsDOMDataChannel::EventListenerAdded(nsIAtom* aType)
     602             : {
     603           0 :   MOZ_ASSERT(NS_IsMainThread());
     604           0 :   UpdateMustKeepAlive();
     605           0 : }
     606             : 
     607             : void
     608           0 : nsDOMDataChannel::EventListenerRemoved(nsIAtom* aType)
     609             : {
     610           0 :   MOZ_ASSERT(NS_IsMainThread());
     611           0 :   UpdateMustKeepAlive();
     612           0 : }
     613             : 
     614             : 
     615             : /* static */
     616             : nsresult
     617           0 : NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel>&& aDataChannel,
     618             :                      nsPIDOMWindowInner* aWindow,
     619             :                      nsIDOMDataChannel** aDomDataChannel)
     620             : {
     621             :   RefPtr<nsDOMDataChannel> domdc =
     622           0 :     new nsDOMDataChannel(aDataChannel, aWindow);
     623             : 
     624           0 :   nsresult rv = domdc->Init(aWindow);
     625           0 :   NS_ENSURE_SUCCESS(rv,rv);
     626             : 
     627           0 :   return CallQueryInterface(domdc, aDomDataChannel);
     628             : }
     629             : 
     630             : /* static */
     631             : void
     632           0 : NS_DataChannelAppReady(nsIDOMDataChannel* aDomDataChannel)
     633             : {
     634           0 :   ((nsDOMDataChannel *)aDomDataChannel)->AppReady();
     635           0 : }

Generated by: LCOV version 1.13