tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebSocketEventService.cpp (18738B)


      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 "WebSocketEventListenerChild.h"
      8 #include "WebSocketEventService.h"
      9 #include "WebSocketFrame.h"
     10 
     11 #include "mozilla/net/NeckoChild.h"
     12 #include "mozilla/StaticPtr.h"
     13 #include "nsISupportsPrimitives.h"
     14 #include "nsIObserverService.h"
     15 #include "nsXULAppAPI.h"
     16 #include "nsSocketTransportService2.h"
     17 #include "nsThreadUtils.h"
     18 #include "mozilla/Services.h"
     19 #include "nsIWebSocketImpl.h"
     20 
     21 namespace mozilla {
     22 namespace net {
     23 
     24 namespace {
     25 
     26 StaticRefPtr<WebSocketEventService> gWebSocketEventService;
     27 
     28 bool IsChildProcess() {
     29  return XRE_GetProcessType() != GeckoProcessType_Default;
     30 }
     31 
     32 }  // anonymous namespace
     33 
     34 class WebSocketBaseRunnable : public Runnable {
     35 public:
     36  WebSocketBaseRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID)
     37      : Runnable("net::WebSocketBaseRunnable"),
     38        mWebSocketSerialID(aWebSocketSerialID),
     39        mInnerWindowID(aInnerWindowID) {}
     40 
     41  NS_IMETHOD Run() override {
     42    MOZ_ASSERT(NS_IsMainThread());
     43 
     44    RefPtr<WebSocketEventService> service =
     45        WebSocketEventService::GetOrCreate();
     46    MOZ_ASSERT(service);
     47 
     48    WebSocketEventService::WindowListeners listeners;
     49    service->GetListeners(mInnerWindowID, listeners);
     50 
     51    for (uint32_t i = 0; i < listeners.Length(); ++i) {
     52      DoWork(listeners[i]);
     53    }
     54 
     55    return NS_OK;
     56  }
     57 
     58 protected:
     59  ~WebSocketBaseRunnable() = default;
     60 
     61  virtual void DoWork(nsIWebSocketEventListener* aListener) = 0;
     62 
     63  uint32_t mWebSocketSerialID;
     64  uint64_t mInnerWindowID;
     65 };
     66 
     67 class WebSocketFrameRunnable final : public WebSocketBaseRunnable {
     68 public:
     69  WebSocketFrameRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
     70                         already_AddRefed<WebSocketFrame> aFrame,
     71                         bool aFrameSent)
     72      : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID),
     73        mFrame(std::move(aFrame)),
     74        mFrameSent(aFrameSent) {}
     75 
     76 private:
     77  virtual void DoWork(nsIWebSocketEventListener* aListener) override {
     78    DebugOnly<nsresult> rv{};
     79    if (mFrameSent) {
     80      rv = aListener->FrameSent(mWebSocketSerialID, mFrame);
     81    } else {
     82      rv = aListener->FrameReceived(mWebSocketSerialID, mFrame);
     83    }
     84 
     85    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Frame op failed");
     86  }
     87 
     88  RefPtr<WebSocketFrame> mFrame;
     89  bool mFrameSent;
     90 };
     91 
     92 class WebSocketCreatedRunnable final : public WebSocketBaseRunnable {
     93 public:
     94  WebSocketCreatedRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
     95                           const nsAString& aURI, const nsACString& aProtocols)
     96      : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID),
     97        mURI(aURI),
     98        mProtocols(aProtocols) {}
     99 
    100 private:
    101  virtual void DoWork(nsIWebSocketEventListener* aListener) override {
    102    DebugOnly<nsresult> rv =
    103        aListener->WebSocketCreated(mWebSocketSerialID, mURI, mProtocols);
    104    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketCreated failed");
    105  }
    106 
    107  const nsString mURI;
    108  const nsCString mProtocols;
    109 };
    110 
    111 class WebSocketOpenedRunnable final : public WebSocketBaseRunnable {
    112 public:
    113  WebSocketOpenedRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
    114                          const nsAString& aEffectiveURI,
    115                          const nsACString& aProtocols,
    116                          const nsACString& aExtensions,
    117                          uint64_t aHttpChannelId)
    118      : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID),
    119        mEffectiveURI(aEffectiveURI),
    120        mProtocols(aProtocols),
    121        mExtensions(aExtensions),
    122        mHttpChannelId(aHttpChannelId) {}
    123 
    124 private:
    125  virtual void DoWork(nsIWebSocketEventListener* aListener) override {
    126    DebugOnly<nsresult> rv =
    127        aListener->WebSocketOpened(mWebSocketSerialID, mEffectiveURI,
    128                                   mProtocols, mExtensions, mHttpChannelId);
    129    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketOpened failed");
    130  }
    131 
    132  const nsString mEffectiveURI;
    133  const nsCString mProtocols;
    134  const nsCString mExtensions;
    135  uint64_t mHttpChannelId;
    136 };
    137 
    138 class WebSocketMessageAvailableRunnable final : public WebSocketBaseRunnable {
    139 public:
    140  WebSocketMessageAvailableRunnable(uint32_t aWebSocketSerialID,
    141                                    uint64_t aInnerWindowID,
    142                                    const nsACString& aData,
    143                                    uint16_t aMessageType)
    144      : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID),
    145        mData(aData),
    146        mMessageType(aMessageType) {}
    147 
    148 private:
    149  virtual void DoWork(nsIWebSocketEventListener* aListener) override {
    150    DebugOnly<nsresult> rv = aListener->WebSocketMessageAvailable(
    151        mWebSocketSerialID, mData, mMessageType);
    152    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketMessageAvailable failed");
    153  }
    154 
    155  const nsCString mData;
    156  uint16_t mMessageType;
    157 };
    158 
    159 class WebSocketClosedRunnable final : public WebSocketBaseRunnable {
    160 public:
    161  WebSocketClosedRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
    162                          bool aWasClean, uint16_t aCode,
    163                          const nsAString& aReason)
    164      : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID),
    165        mWasClean(aWasClean),
    166        mCode(aCode),
    167        mReason(aReason) {}
    168 
    169 private:
    170  virtual void DoWork(nsIWebSocketEventListener* aListener) override {
    171    DebugOnly<nsresult> rv = aListener->WebSocketClosed(
    172        mWebSocketSerialID, mWasClean, mCode, mReason);
    173    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketClosed failed");
    174  }
    175 
    176  bool mWasClean;
    177  uint16_t mCode;
    178  const nsString mReason;
    179 };
    180 
    181 /* static */
    182 already_AddRefed<WebSocketEventService> WebSocketEventService::Get() {
    183  MOZ_ASSERT(NS_IsMainThread());
    184  RefPtr<WebSocketEventService> service = gWebSocketEventService.get();
    185  return service.forget();
    186 }
    187 
    188 /* static */
    189 already_AddRefed<WebSocketEventService> WebSocketEventService::GetOrCreate() {
    190  MOZ_ASSERT(NS_IsMainThread());
    191 
    192  if (!gWebSocketEventService) {
    193    gWebSocketEventService = new WebSocketEventService();
    194  }
    195 
    196  RefPtr<WebSocketEventService> service = gWebSocketEventService.get();
    197  return service.forget();
    198 }
    199 
    200 NS_INTERFACE_MAP_BEGIN(WebSocketEventService)
    201  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketEventService)
    202  NS_INTERFACE_MAP_ENTRY(nsIObserver)
    203  NS_INTERFACE_MAP_ENTRY(nsIWebSocketEventService)
    204 NS_INTERFACE_MAP_END
    205 
    206 NS_IMPL_ADDREF(WebSocketEventService)
    207 NS_IMPL_RELEASE(WebSocketEventService)
    208 
    209 WebSocketEventService::WebSocketEventService() : mCountListeners(0) {
    210  MOZ_ASSERT(NS_IsMainThread());
    211 
    212  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    213  if (obs) {
    214    obs->AddObserver(this, "xpcom-shutdown", false);
    215    obs->AddObserver(this, "inner-window-destroyed", false);
    216  }
    217 }
    218 
    219 WebSocketEventService::~WebSocketEventService() {
    220  MOZ_ASSERT(NS_IsMainThread());
    221 }
    222 
    223 void WebSocketEventService::WebSocketCreated(uint32_t aWebSocketSerialID,
    224                                             uint64_t aInnerWindowID,
    225                                             const nsAString& aURI,
    226                                             const nsACString& aProtocols,
    227                                             nsIEventTarget* aTarget) {
    228  // Let's continue only if we have some listeners.
    229  if (!HasListeners()) {
    230    return;
    231  }
    232 
    233  RefPtr<WebSocketCreatedRunnable> runnable = new WebSocketCreatedRunnable(
    234      aWebSocketSerialID, aInnerWindowID, aURI, aProtocols);
    235  DebugOnly<nsresult> rv = aTarget
    236                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    237                               : NS_DispatchToMainThread(runnable);
    238  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    239 }
    240 
    241 void WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID,
    242                                            uint64_t aInnerWindowID,
    243                                            const nsAString& aEffectiveURI,
    244                                            const nsACString& aProtocols,
    245                                            const nsACString& aExtensions,
    246                                            uint64_t aHttpChannelId,
    247                                            nsIEventTarget* aTarget) {
    248  // Let's continue only if we have some listeners.
    249  if (!HasListeners()) {
    250    return;
    251  }
    252 
    253  RefPtr<WebSocketOpenedRunnable> runnable = new WebSocketOpenedRunnable(
    254      aWebSocketSerialID, aInnerWindowID, aEffectiveURI, aProtocols,
    255      aExtensions, aHttpChannelId);
    256  DebugOnly<nsresult> rv = aTarget
    257                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    258                               : NS_DispatchToMainThread(runnable);
    259  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    260 }
    261 
    262 void WebSocketEventService::WebSocketMessageAvailable(
    263    uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
    264    const nsACString& aData, uint16_t aMessageType, nsIEventTarget* aTarget) {
    265  // Let's continue only if we have some listeners.
    266  if (!HasListeners()) {
    267    return;
    268  }
    269 
    270  RefPtr<WebSocketMessageAvailableRunnable> runnable =
    271      new WebSocketMessageAvailableRunnable(aWebSocketSerialID, aInnerWindowID,
    272                                            aData, aMessageType);
    273  DebugOnly<nsresult> rv = aTarget
    274                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    275                               : NS_DispatchToMainThread(runnable);
    276  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    277 }
    278 
    279 void WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID,
    280                                            uint64_t aInnerWindowID,
    281                                            bool aWasClean, uint16_t aCode,
    282                                            const nsAString& aReason,
    283                                            nsIEventTarget* aTarget) {
    284  // Let's continue only if we have some listeners.
    285  if (!HasListeners()) {
    286    return;
    287  }
    288 
    289  RefPtr<WebSocketClosedRunnable> runnable = new WebSocketClosedRunnable(
    290      aWebSocketSerialID, aInnerWindowID, aWasClean, aCode, aReason);
    291  DebugOnly<nsresult> rv = aTarget
    292                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    293                               : NS_DispatchToMainThread(runnable);
    294  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    295 }
    296 
    297 void WebSocketEventService::FrameReceived(
    298    uint32_t aWebSocketSerialID, uint64_t aInnerWindowID,
    299    already_AddRefed<WebSocketFrame> aFrame, nsIEventTarget* aTarget) {
    300  RefPtr<WebSocketFrame> frame(std::move(aFrame));
    301  MOZ_ASSERT(frame);
    302 
    303  // Let's continue only if we have some listeners.
    304  if (!HasListeners()) {
    305    return;
    306  }
    307 
    308  RefPtr<WebSocketFrameRunnable> runnable =
    309      new WebSocketFrameRunnable(aWebSocketSerialID, aInnerWindowID,
    310                                 frame.forget(), false /* frameSent */);
    311  DebugOnly<nsresult> rv = aTarget
    312                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    313                               : NS_DispatchToMainThread(runnable);
    314  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    315 }
    316 
    317 void WebSocketEventService::FrameSent(uint32_t aWebSocketSerialID,
    318                                      uint64_t aInnerWindowID,
    319                                      already_AddRefed<WebSocketFrame> aFrame,
    320                                      nsIEventTarget* aTarget) {
    321  RefPtr<WebSocketFrame> frame(std::move(aFrame));
    322  MOZ_ASSERT(frame);
    323 
    324  // Let's continue only if we have some listeners.
    325  if (!HasListeners()) {
    326    return;
    327  }
    328 
    329  RefPtr<WebSocketFrameRunnable> runnable = new WebSocketFrameRunnable(
    330      aWebSocketSerialID, aInnerWindowID, frame.forget(), true /* frameSent */);
    331 
    332  DebugOnly<nsresult> rv = aTarget
    333                               ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
    334                               : NS_DispatchToMainThread(runnable);
    335  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
    336 }
    337 
    338 void WebSocketEventService::AssociateWebSocketImplWithSerialID(
    339    nsIWebSocketImpl* aWebSocketImpl, uint32_t aWebSocketSerialID) {
    340  MOZ_ASSERT(NS_IsMainThread());
    341 
    342  mWebSocketImplMap.InsertOrUpdate(aWebSocketSerialID,
    343                                   do_GetWeakReference(aWebSocketImpl));
    344 }
    345 
    346 NS_IMETHODIMP
    347 WebSocketEventService::SendMessage(uint32_t aWebSocketSerialID,
    348                                   const nsAString& aMessage) {
    349  MOZ_ASSERT(NS_IsMainThread());
    350 
    351  nsWeakPtr weakPtr = mWebSocketImplMap.Get(aWebSocketSerialID);
    352  nsCOMPtr<nsIWebSocketImpl> webSocketImpl = do_QueryReferent(weakPtr);
    353 
    354  if (!webSocketImpl) {
    355    return NS_ERROR_NOT_AVAILABLE;
    356  }
    357 
    358  return webSocketImpl->SendMessage(aMessage);
    359 }
    360 
    361 NS_IMETHODIMP
    362 WebSocketEventService::AddListener(uint64_t aInnerWindowID,
    363                                   nsIWebSocketEventListener* aListener) {
    364  MOZ_ASSERT(NS_IsMainThread());
    365 
    366  if (!aListener) {
    367    return NS_ERROR_FAILURE;
    368  }
    369 
    370  ++mCountListeners;
    371 
    372  mWindows
    373      .LookupOrInsertWith(
    374          aInnerWindowID,
    375          [&] {
    376            auto listener = MakeUnique<WindowListener>();
    377 
    378            if (IsChildProcess()) {
    379              PWebSocketEventListenerChild* actor =
    380                  gNeckoChild->SendPWebSocketEventListenerConstructor(
    381                      aInnerWindowID);
    382 
    383              listener->mActor =
    384                  static_cast<WebSocketEventListenerChild*>(actor);
    385              MOZ_ASSERT(listener->mActor);
    386            }
    387 
    388            return listener;
    389          })
    390      ->mListeners.AppendElement(aListener);
    391 
    392  return NS_OK;
    393 }
    394 
    395 NS_IMETHODIMP
    396 WebSocketEventService::RemoveListener(uint64_t aInnerWindowID,
    397                                      nsIWebSocketEventListener* aListener) {
    398  MOZ_ASSERT(NS_IsMainThread());
    399 
    400  if (!aListener) {
    401    return NS_ERROR_FAILURE;
    402  }
    403 
    404  WindowListener* listener = mWindows.Get(aInnerWindowID);
    405  if (!listener) {
    406    return NS_ERROR_FAILURE;
    407  }
    408 
    409  if (!listener->mListeners.RemoveElement(aListener)) {
    410    return NS_ERROR_FAILURE;
    411  }
    412 
    413  // The last listener for this window.
    414  if (listener->mListeners.IsEmpty()) {
    415    if (IsChildProcess()) {
    416      ShutdownActorListener(listener);
    417    }
    418 
    419    mWindows.Remove(aInnerWindowID);
    420  }
    421 
    422  MOZ_ASSERT(mCountListeners);
    423  --mCountListeners;
    424 
    425  return NS_OK;
    426 }
    427 
    428 NS_IMETHODIMP
    429 WebSocketEventService::HasListenerFor(uint64_t aInnerWindowID, bool* aResult) {
    430  MOZ_ASSERT(NS_IsMainThread());
    431 
    432  *aResult = mWindows.Get(aInnerWindowID);
    433 
    434  return NS_OK;
    435 }
    436 
    437 NS_IMETHODIMP
    438 WebSocketEventService::Observe(nsISupports* aSubject, const char* aTopic,
    439                               const char16_t* aData) {
    440  MOZ_ASSERT(NS_IsMainThread());
    441 
    442  if (!strcmp(aTopic, "xpcom-shutdown")) {
    443    Shutdown();
    444    return NS_OK;
    445  }
    446 
    447  if (!strcmp(aTopic, "inner-window-destroyed") && HasListeners()) {
    448    nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
    449    NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
    450 
    451    uint64_t innerID;
    452    nsresult rv = wrapper->GetData(&innerID);
    453    NS_ENSURE_SUCCESS(rv, rv);
    454 
    455    WindowListener* listener = mWindows.Get(innerID);
    456    if (!listener) {
    457      return NS_OK;
    458    }
    459 
    460    MOZ_ASSERT(mCountListeners >= listener->mListeners.Length());
    461    mCountListeners -= listener->mListeners.Length();
    462 
    463    if (IsChildProcess()) {
    464      ShutdownActorListener(listener);
    465    }
    466 
    467    mWindows.Remove(innerID);
    468  }
    469 
    470  // This should not happen.
    471  return NS_ERROR_FAILURE;
    472 }
    473 
    474 void WebSocketEventService::Shutdown() {
    475  MOZ_ASSERT(NS_IsMainThread());
    476 
    477  if (gWebSocketEventService) {
    478    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    479    if (obs) {
    480      obs->RemoveObserver(gWebSocketEventService, "xpcom-shutdown");
    481      obs->RemoveObserver(gWebSocketEventService, "inner-window-destroyed");
    482    }
    483 
    484    mWindows.Clear();
    485    gWebSocketEventService = nullptr;
    486  }
    487 }
    488 
    489 bool WebSocketEventService::HasListeners() const { return !!mCountListeners; }
    490 
    491 void WebSocketEventService::GetListeners(
    492    uint64_t aInnerWindowID,
    493    WebSocketEventService::WindowListeners& aListeners) const {
    494  aListeners.Clear();
    495 
    496  WindowListener* listener = mWindows.Get(aInnerWindowID);
    497  if (!listener) {
    498    return;
    499  }
    500 
    501  aListeners.AppendElements(listener->mListeners);
    502 }
    503 
    504 void WebSocketEventService::ShutdownActorListener(WindowListener* aListener) {
    505  MOZ_ASSERT(aListener);
    506  MOZ_ASSERT(aListener->mActor);
    507  aListener->mActor->Close();
    508  aListener->mActor = nullptr;
    509 }
    510 
    511 already_AddRefed<WebSocketFrame> WebSocketEventService::CreateFrameIfNeeded(
    512    bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode,
    513    bool aMaskBit, uint32_t aMask, const nsCString& aPayload) {
    514  if (!HasListeners()) {
    515    return nullptr;
    516  }
    517 
    518  return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
    519                                       aOpCode, aMaskBit, aMask, aPayload);
    520 }
    521 
    522 already_AddRefed<WebSocketFrame> WebSocketEventService::CreateFrameIfNeeded(
    523    bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode,
    524    bool aMaskBit, uint32_t aMask, uint8_t* aPayload, uint32_t aPayloadLength) {
    525  if (!HasListeners()) {
    526    return nullptr;
    527  }
    528 
    529  nsAutoCString payloadStr;
    530  if (NS_WARN_IF(!(payloadStr.Assign((const char*)aPayload, aPayloadLength,
    531                                     mozilla::fallible)))) {
    532    return nullptr;
    533  }
    534 
    535  return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
    536                                       aOpCode, aMaskBit, aMask, payloadStr);
    537 }
    538 
    539 already_AddRefed<WebSocketFrame> WebSocketEventService::CreateFrameIfNeeded(
    540    bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode,
    541    bool aMaskBit, uint32_t aMask, uint8_t* aPayloadInHdr,
    542    uint32_t aPayloadInHdrLength, uint8_t* aPayload, uint32_t aPayloadLength) {
    543  if (!HasListeners()) {
    544    return nullptr;
    545  }
    546 
    547  uint32_t payloadLength = aPayloadLength + aPayloadInHdrLength;
    548 
    549  nsAutoCString payload;
    550  if (NS_WARN_IF(!payload.SetLength(payloadLength, fallible))) {
    551    return nullptr;
    552  }
    553 
    554  char* payloadPtr = payload.BeginWriting();
    555  if (aPayloadInHdrLength) {
    556    memcpy(payloadPtr, aPayloadInHdr, aPayloadInHdrLength);
    557  }
    558 
    559  memcpy(payloadPtr + aPayloadInHdrLength, aPayload, aPayloadLength);
    560 
    561  return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
    562                                       aOpCode, aMaskBit, aMask, payload);
    563 }
    564 
    565 }  // namespace net
    566 }  // namespace mozilla