DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef WebSocket_h__
#define WebSocket_h__

#include "mozilla/Attributes.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/WebSocketBinding.h" // for BinaryType
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/ErrorResult.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
#include "nsISupportsUtils.h"
#include "nsString.h"
#include "nsWrapperCache.h"

#define DEFAULT_WS_SCHEME_PORT  80
#define DEFAULT_WSS_SCHEME_PORT 443

class nsIInputStream;

namespace mozilla {
namespace dom {

namespace workers {
class WorkerPrivate;
}

class File;

class WebSocketImpl;

class WebSocket final : public DOMEventTargetHelper
{
  friend class WebSocketImpl;

public:
  enum {
    CONNECTING = 0,
    OPEN       = 1,
    CLOSING    = 2,
    CLOSED     = 3
  };

public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(
    WebSocket, DOMEventTargetHelper)

  // EventTarget
  virtual void EventListenerAdded(nsIAtom* aType) override;
  virtual void EventListenerRemoved(nsIAtom* aType) override;

  virtual void DisconnectFromOwner() override;

  // nsWrapperCache
  nsPIDOMWindow* GetParentObject() { return GetOwner(); }

  virtual JSObject* WrapObject(JSContext* cx) override;

public: // static helpers:

  // Determine if preferences allow WebSocket
  static bool PrefEnabled(JSContext* aCx = nullptr, JSObject* aGlobal = nullptr);

public: // WebIDL interface:

  // Constructor:
  static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal,
                                                 const nsAString& aUrl,
                                                 ErrorResult& rv);

  static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal,
                                                 const nsAString& aUrl,
                                                 const nsAString& aProtocol,
                                                 ErrorResult& rv);

  static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal,
                                                 const nsAString& aUrl,
                                                 const Sequence<nsString>& aProtocols,
                                                 ErrorResult& rv);

  // webIDL: readonly attribute DOMString url
  void GetUrl(nsAString& aResult);

  // webIDL: readonly attribute unsigned short readyState;
  uint16_t ReadyState();

  // webIDL: readonly attribute unsigned long bufferedAmount;
  uint32_t BufferedAmount() const;

  // webIDL: attribute Function? onopen;
  IMPL_EVENT_HANDLER(open)

  // webIDL: attribute Function? onerror;
  IMPL_EVENT_HANDLER(error)

  // webIDL: attribute Function? onclose;
  IMPL_EVENT_HANDLER(close)

  // webIDL: readonly attribute DOMString extensions;
  void GetExtensions(nsAString& aResult);

  // webIDL: readonly attribute DOMString protocol;
  void GetProtocol(nsAString& aResult);

  // webIDL: void close(optional unsigned short code, optional DOMString reason):
  void Close(const Optional<uint16_t>& aCode,
             const Optional<nsAString>& aReason,
             ErrorResult& aRv);

  // webIDL: attribute Function? onmessage;
  IMPL_EVENT_HANDLER(message)

  // webIDL: attribute DOMString binaryType;
  dom::BinaryType BinaryType() const;
  void SetBinaryType(dom::BinaryType aData);

  // webIDL: void send(DOMString|Blob|ArrayBufferView data);
  void Send(const nsAString& aData,
            ErrorResult& aRv);
  void Send(File& aData,
            ErrorResult& aRv);
  void Send(const ArrayBuffer& aData,
            ErrorResult& aRv);
  void Send(const ArrayBufferView& aData,
            ErrorResult& aRv);

private: // constructor && distructor
  explicit WebSocket(nsPIDOMWindow* aOwnerWindow);
  virtual ~WebSocket();

  void SetReadyState(uint16_t aReadyState);

  // These methods actually do the dispatch for various events.
  nsresult CreateAndDispatchSimpleEvent(const nsAString& aName);
  nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
                                         bool aIsBinary);
  nsresult CreateAndDispatchMessageEvent(JSContext* aCx,
                                         const nsACString& aData,
                                         bool aIsBinary);
  nsresult CreateAndDispatchCloseEvent(bool aWasClean,
                                       uint16_t aCode,
                                       const nsAString& aReason);

  // if there are "strong event listeners" (see comment in WebSocket.cpp) or
  // outgoing not sent messages then this method keeps the object alive
  // when js doesn't have strong references to it.
  void UpdateMustKeepAlive();
  // ATTENTION, when calling this method the object can be released
  // (and possibly collected).
  void DontKeepAliveAnyMore();

private:
  WebSocket(const WebSocket& x) = delete;   // prevent bad usage
  WebSocket& operator=(const WebSocket& x) = delete;

  void Send(nsIInputStream* aMsgStream,
            const nsACString& aMsgString,
            uint32_t aMsgLength,
            bool aIsBinary,
            ErrorResult& aRv);

  void AssertIsOnTargetThread() const;

  // Raw pointer because this WebSocketImpl is created, managed and destroyed by
  // WebSocket.
  WebSocketImpl* mImpl;

  bool mIsMainThread;

  bool mKeepingAlive;
  bool mCheckMustKeepAlive;

  uint32_t mOutgoingBufferedAmount;

  // related to the WebSocket constructor steps
  nsString mOriginalURL;
  nsString mEffectiveURL;   // after redirects
  nsCString mEstablishedExtensions;
  nsCString mEstablishedProtocol;

  dom::BinaryType mBinaryType;

  // This mutex protects mReadyState that is the only variable that is used in
  // different threads.
  mozilla::Mutex mMutex;

  // This value should not be used directly but use ReadyState() instead.
  uint16_t mReadyState;
};

} //namespace dom
} //namespace mozilla

#endif