summaryrefslogtreecommitdiffstats
path: root/dom/websocket/WebSocket.h
blob: a290750cf0338a55fb385f0b9aa462c609587333 (plain)
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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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/CheckedInt.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/WebSocketBinding.h"  // for BinaryType
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Mutex.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;
class nsITransportProvider;

namespace mozilla {
class ErrorResult;

namespace dom {

class Blob;
class StringOrStringSequence;
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_CLASS_INHERITED(WebSocket, DOMEventTargetHelper)
  virtual bool IsCertainlyAliveForCC() const override;

  // EventTarget
  using EventTarget::EventListenerAdded;
  virtual void EventListenerAdded(nsAtom* aType) override;

  using EventTarget::EventListenerRemoved;
  virtual void EventListenerRemoved(nsAtom* aType) override;

  virtual void DisconnectFromOwner() override;

  mozilla::Maybe<EventCallbackDebuggerNotificationType>
  GetDebuggerNotificationType() const override;

  // nsWrapperCache
  virtual JSObject* WrapObject(JSContext* cx,
                               JS::Handle<JSObject*> aGivenProto) 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,
      const StringOrStringSequence& aProtocols, ErrorResult& rv);

  static already_AddRefed<WebSocket> CreateServerWebSocket(
      const GlobalObject& aGlobal, const nsAString& aUrl,
      const Sequence<nsString>& aProtocols,
      nsITransportProvider* aTransportProvider,
      const nsAString& aNegotiatedExtensions, ErrorResult& rv);

  static already_AddRefed<WebSocket> ConstructorCommon(
      const GlobalObject& aGlobal, const nsAString& aUrl,
      const Sequence<nsString>& aProtocols,
      nsITransportProvider* aTransportProvider,
      const nsACString& aNegotiatedExtensions, 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 long bufferedAmount;
  uint64_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(Blob& aData, ErrorResult& aRv);
  void Send(const ArrayBuffer& aData, ErrorResult& aRv);
  void Send(const ArrayBufferView& aData, ErrorResult& aRv);

 private:  // constructor && destructor
  explicit WebSocket(nsIGlobalObject* aGlobal);
  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 CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode,
                                       const nsAString& aReason);

  static bool IsValidProtocolString(const nsString& aValue);

  // 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;

  CheckedUint64 mOutgoingBufferedAmount;

  // related to the WebSocket constructor steps
  nsString mURI;
  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 MOZ_GUARDED_BY(mMutex);
};

}  // namespace dom
}  // namespace mozilla

#endif