|
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 #ifndef WebSocket_h__ |
|
8 #define WebSocket_h__ |
|
9 |
|
10 #include "mozilla/Attributes.h" |
|
11 #include "mozilla/dom/TypedArray.h" |
|
12 #include "mozilla/dom/WebSocketBinding.h" // for BinaryType |
|
13 #include "mozilla/DOMEventTargetHelper.h" |
|
14 #include "mozilla/ErrorResult.h" |
|
15 #include "nsAutoPtr.h" |
|
16 #include "nsCOMPtr.h" |
|
17 #include "nsCycleCollectionParticipant.h" |
|
18 #include "nsIInterfaceRequestor.h" |
|
19 #include "nsIObserver.h" |
|
20 #include "nsIRequest.h" |
|
21 #include "nsISupports.h" |
|
22 #include "nsISupportsUtils.h" |
|
23 #include "nsIWebSocketChannel.h" |
|
24 #include "nsIWebSocketListener.h" |
|
25 #include "nsString.h" |
|
26 #include "nsWeakReference.h" |
|
27 #include "nsWrapperCache.h" |
|
28 |
|
29 #define DEFAULT_WS_SCHEME_PORT 80 |
|
30 #define DEFAULT_WSS_SCHEME_PORT 443 |
|
31 |
|
32 namespace mozilla { |
|
33 namespace dom { |
|
34 |
|
35 class WebSocket : public DOMEventTargetHelper, |
|
36 public nsIInterfaceRequestor, |
|
37 public nsIWebSocketListener, |
|
38 public nsIObserver, |
|
39 public nsSupportsWeakReference, |
|
40 public nsIRequest |
|
41 { |
|
42 friend class CallDispatchConnectionCloseEvents; |
|
43 friend class nsAutoCloseWS; |
|
44 |
|
45 public: |
|
46 enum { |
|
47 CONNECTING = 0, |
|
48 OPEN = 1, |
|
49 CLOSING = 2, |
|
50 CLOSED = 3 |
|
51 }; |
|
52 |
|
53 public: |
|
54 NS_DECL_ISUPPORTS_INHERITED |
|
55 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED( |
|
56 WebSocket, DOMEventTargetHelper) |
|
57 NS_DECL_NSIINTERFACEREQUESTOR |
|
58 NS_DECL_NSIWEBSOCKETLISTENER |
|
59 NS_DECL_NSIOBSERVER |
|
60 NS_DECL_NSIREQUEST |
|
61 |
|
62 // EventTarget |
|
63 virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE; |
|
64 virtual void EventListenerRemoved(nsIAtom* aType) MOZ_OVERRIDE; |
|
65 |
|
66 virtual void DisconnectFromOwner() MOZ_OVERRIDE; |
|
67 |
|
68 // nsWrapperCache |
|
69 nsPIDOMWindow* GetParentObject() { return GetOwner(); } |
|
70 |
|
71 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; |
|
72 |
|
73 public: // static helpers: |
|
74 |
|
75 // Determine if preferences allow WebSocket |
|
76 static bool PrefEnabled(JSContext* aCx = nullptr, JSObject* aGlobal = nullptr); |
|
77 |
|
78 public: // WebIDL interface: |
|
79 |
|
80 // Constructor: |
|
81 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, |
|
82 const nsAString& aUrl, |
|
83 ErrorResult& rv); |
|
84 |
|
85 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, |
|
86 const nsAString& aUrl, |
|
87 const nsAString& aProtocol, |
|
88 ErrorResult& rv); |
|
89 |
|
90 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, |
|
91 const nsAString& aUrl, |
|
92 const Sequence<nsString>& aProtocols, |
|
93 ErrorResult& rv); |
|
94 |
|
95 // webIDL: readonly attribute DOMString url |
|
96 void GetUrl(nsAString& aResult); |
|
97 |
|
98 // webIDL: readonly attribute unsigned short readyState; |
|
99 uint16_t ReadyState() const { return mReadyState; } |
|
100 |
|
101 // webIDL: readonly attribute unsigned long bufferedAmount; |
|
102 uint32_t BufferedAmount() const { return mOutgoingBufferedAmount; } |
|
103 |
|
104 // webIDL: attribute Function? onopen; |
|
105 IMPL_EVENT_HANDLER(open) |
|
106 |
|
107 // webIDL: attribute Function? onerror; |
|
108 IMPL_EVENT_HANDLER(error) |
|
109 |
|
110 // webIDL: attribute Function? onclose; |
|
111 IMPL_EVENT_HANDLER(close) |
|
112 |
|
113 // webIDL: readonly attribute DOMString extensions; |
|
114 void GetExtensions(nsAString& aResult); |
|
115 |
|
116 // webIDL: readonly attribute DOMString protocol; |
|
117 void GetProtocol(nsAString& aResult); |
|
118 |
|
119 // webIDL: void close(optional unsigned short code, optional DOMString reason): |
|
120 void Close(const Optional<uint16_t>& aCode, |
|
121 const Optional<nsAString>& aReason, |
|
122 ErrorResult& aRv); |
|
123 |
|
124 // webIDL: attribute Function? onmessage; |
|
125 IMPL_EVENT_HANDLER(message) |
|
126 |
|
127 // webIDL: attribute DOMString binaryType; |
|
128 dom::BinaryType BinaryType() const { return mBinaryType; } |
|
129 void SetBinaryType(dom::BinaryType aData) { mBinaryType = aData; } |
|
130 |
|
131 // webIDL: void send(DOMString|Blob|ArrayBufferView data); |
|
132 void Send(const nsAString& aData, |
|
133 ErrorResult& aRv); |
|
134 void Send(nsIDOMBlob* aData, |
|
135 ErrorResult& aRv); |
|
136 void Send(const ArrayBuffer& aData, |
|
137 ErrorResult& aRv); |
|
138 void Send(const ArrayBufferView& aData, |
|
139 ErrorResult& aRv); |
|
140 |
|
141 private: // constructor && distructor |
|
142 WebSocket(nsPIDOMWindow* aOwnerWindow); |
|
143 virtual ~WebSocket(); |
|
144 |
|
145 protected: |
|
146 nsresult Init(JSContext* aCx, |
|
147 nsIPrincipal* aPrincipal, |
|
148 const nsAString& aURL, |
|
149 nsTArray<nsString>& aProtocolArray); |
|
150 |
|
151 void Send(nsIInputStream* aMsgStream, |
|
152 const nsACString& aMsgString, |
|
153 uint32_t aMsgLength, |
|
154 bool aIsBinary, |
|
155 ErrorResult& aRv); |
|
156 |
|
157 nsresult ParseURL(const nsString& aURL); |
|
158 nsresult EstablishConnection(); |
|
159 |
|
160 // These methods when called can release the WebSocket object |
|
161 void FailConnection(uint16_t reasonCode, |
|
162 const nsACString& aReasonString = EmptyCString()); |
|
163 nsresult CloseConnection(uint16_t reasonCode, |
|
164 const nsACString& aReasonString = EmptyCString()); |
|
165 nsresult Disconnect(); |
|
166 |
|
167 nsresult ConsoleError(); |
|
168 nsresult PrintErrorOnConsole(const char* aBundleURI, |
|
169 const char16_t* aError, |
|
170 const char16_t** aFormatStrings, |
|
171 uint32_t aFormatStringsLen); |
|
172 |
|
173 nsresult DoOnMessageAvailable(const nsACString& aMsg, |
|
174 bool isBinary); |
|
175 |
|
176 // ConnectionCloseEvents: 'error' event if needed, then 'close' event. |
|
177 // - These must not be dispatched while we are still within an incoming call |
|
178 // from JS (ex: close()). Set 'sync' to false in that case to dispatch in a |
|
179 // separate new event. |
|
180 nsresult ScheduleConnectionCloseEvents(nsISupports* aContext, |
|
181 nsresult aStatusCode, |
|
182 bool sync); |
|
183 // 2nd half of ScheduleConnectionCloseEvents, sometimes run in its own event. |
|
184 void DispatchConnectionCloseEvents(); |
|
185 |
|
186 // These methods actually do the dispatch for various events. |
|
187 nsresult CreateAndDispatchSimpleEvent(const nsString& aName); |
|
188 nsresult CreateAndDispatchMessageEvent(const nsACString& aData, |
|
189 bool isBinary); |
|
190 nsresult CreateAndDispatchCloseEvent(bool aWasClean, |
|
191 uint16_t aCode, |
|
192 const nsString& aReason); |
|
193 |
|
194 // if there are "strong event listeners" (see comment in WebSocket.cpp) or |
|
195 // outgoing not sent messages then this method keeps the object alive |
|
196 // when js doesn't have strong references to it. |
|
197 void UpdateMustKeepAlive(); |
|
198 // ATTENTION, when calling this method the object can be released |
|
199 // (and possibly collected). |
|
200 void DontKeepAliveAnyMore(); |
|
201 |
|
202 nsresult UpdateURI(); |
|
203 |
|
204 protected: //data |
|
205 |
|
206 nsCOMPtr<nsIWebSocketChannel> mChannel; |
|
207 |
|
208 // related to the WebSocket constructor steps |
|
209 nsString mOriginalURL; |
|
210 nsString mEffectiveURL; // after redirects |
|
211 bool mSecure; // if true it is using SSL and the wss scheme, |
|
212 // otherwise it is using the ws scheme with no SSL |
|
213 |
|
214 bool mKeepingAlive; |
|
215 bool mCheckMustKeepAlive; |
|
216 bool mOnCloseScheduled; |
|
217 bool mFailed; |
|
218 bool mDisconnected; |
|
219 |
|
220 // Set attributes of DOM 'onclose' message |
|
221 bool mCloseEventWasClean; |
|
222 nsString mCloseEventReason; |
|
223 uint16_t mCloseEventCode; |
|
224 |
|
225 nsCString mAsciiHost; // hostname |
|
226 uint32_t mPort; |
|
227 nsCString mResource; // [filepath[?query]] |
|
228 nsString mUTF16Origin; |
|
229 |
|
230 nsCOMPtr<nsIURI> mURI; |
|
231 nsCString mRequestedProtocolList; |
|
232 nsCString mEstablishedProtocol; |
|
233 nsCString mEstablishedExtensions; |
|
234 |
|
235 uint16_t mReadyState; |
|
236 |
|
237 nsCOMPtr<nsIPrincipal> mPrincipal; |
|
238 |
|
239 uint32_t mOutgoingBufferedAmount; |
|
240 |
|
241 dom::BinaryType mBinaryType; |
|
242 |
|
243 // Web Socket owner information: |
|
244 // - the script file name, UTF8 encoded. |
|
245 // - source code line number where the Web Socket object was constructed. |
|
246 // - the ID of the inner window where the script lives. Note that this may not |
|
247 // be the same as the Web Socket owner window. |
|
248 // These attributes are used for error reporting. |
|
249 nsCString mScriptFile; |
|
250 uint32_t mScriptLine; |
|
251 uint64_t mInnerWindowID; |
|
252 |
|
253 private: |
|
254 WebSocket(const WebSocket& x) MOZ_DELETE; // prevent bad usage |
|
255 WebSocket& operator=(const WebSocket& x) MOZ_DELETE; |
|
256 }; |
|
257 |
|
258 } //namespace dom |
|
259 } //namespace mozilla |
|
260 |
|
261 #endif |