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/. */
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"
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"
26 #include "nsWeakReference.h"
27 #include "nsWrapperCache.h"
29 #define DEFAULT_WS_SCHEME_PORT 80
30 #define DEFAULT_WSS_SCHEME_PORT 443
35 class WebSocket MOZ_FINAL
: public DOMEventTargetHelper
,
36 public nsIInterfaceRequestor
,
37 public nsIWebSocketListener
,
39 public nsSupportsWeakReference
,
42 friend class CallDispatchConnectionCloseEvents
;
43 friend class nsAutoCloseWS
;
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
63 virtual void EventListenerAdded(nsIAtom
* aType
) MOZ_OVERRIDE
;
64 virtual void EventListenerRemoved(nsIAtom
* aType
) MOZ_OVERRIDE
;
66 virtual void DisconnectFromOwner() MOZ_OVERRIDE
;
69 nsPIDOMWindow
* GetParentObject() { return GetOwner(); }
71 virtual JSObject
* WrapObject(JSContext
*cx
) MOZ_OVERRIDE
;
73 public: // static helpers:
75 // Determine if preferences allow WebSocket
76 static bool PrefEnabled(JSContext
* aCx
= nullptr, JSObject
* aGlobal
= nullptr);
78 public: // WebIDL interface:
81 static already_AddRefed
<WebSocket
> Constructor(const GlobalObject
& aGlobal
,
82 const nsAString
& aUrl
,
85 static already_AddRefed
<WebSocket
> Constructor(const GlobalObject
& aGlobal
,
86 const nsAString
& aUrl
,
87 const nsAString
& aProtocol
,
90 static already_AddRefed
<WebSocket
> Constructor(const GlobalObject
& aGlobal
,
91 const nsAString
& aUrl
,
92 const Sequence
<nsString
>& aProtocols
,
95 // webIDL: readonly attribute DOMString url
96 void GetUrl(nsAString
& aResult
);
98 // webIDL: readonly attribute unsigned short readyState;
99 uint16_t ReadyState() const { return mReadyState
; }
101 // webIDL: readonly attribute unsigned long bufferedAmount;
102 uint32_t BufferedAmount() const { return mOutgoingBufferedAmount
; }
104 // webIDL: attribute Function? onopen;
105 IMPL_EVENT_HANDLER(open
)
107 // webIDL: attribute Function? onerror;
108 IMPL_EVENT_HANDLER(error
)
110 // webIDL: attribute Function? onclose;
111 IMPL_EVENT_HANDLER(close
)
113 // webIDL: readonly attribute DOMString extensions;
114 void GetExtensions(nsAString
& aResult
);
116 // webIDL: readonly attribute DOMString protocol;
117 void GetProtocol(nsAString
& aResult
);
119 // webIDL: void close(optional unsigned short code, optional DOMString reason):
120 void Close(const Optional
<uint16_t>& aCode
,
121 const Optional
<nsAString
>& aReason
,
124 // webIDL: attribute Function? onmessage;
125 IMPL_EVENT_HANDLER(message
)
127 // webIDL: attribute DOMString binaryType;
128 dom::BinaryType
BinaryType() const { return mBinaryType
; }
129 void SetBinaryType(dom::BinaryType aData
) { mBinaryType
= aData
; }
131 // webIDL: void send(DOMString|Blob|ArrayBufferView data);
132 void Send(const nsAString
& aData
,
134 void Send(nsIDOMBlob
* aData
,
136 void Send(const ArrayBuffer
& aData
,
138 void Send(const ArrayBufferView
& aData
,
141 private: // constructor && distructor
142 explicit WebSocket(nsPIDOMWindow
* aOwnerWindow
);
143 virtual ~WebSocket();
146 nsresult
Init(JSContext
* aCx
,
147 nsIPrincipal
* aPrincipal
,
148 const nsAString
& aURL
,
149 nsTArray
<nsString
>& aProtocolArray
);
151 void Send(nsIInputStream
* aMsgStream
,
152 const nsACString
& aMsgString
,
157 nsresult
ParseURL(const nsString
& aURL
);
158 nsresult
EstablishConnection();
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();
167 nsresult
ConsoleError();
168 nsresult
PrintErrorOnConsole(const char* aBundleURI
,
169 const char16_t
* aError
,
170 const char16_t
** aFormatStrings
,
171 uint32_t aFormatStringsLen
);
173 nsresult
DoOnMessageAvailable(const nsACString
& aMsg
,
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
,
183 // 2nd half of ScheduleConnectionCloseEvents, sometimes run in its own event.
184 void DispatchConnectionCloseEvents();
186 // These methods actually do the dispatch for various events.
187 nsresult
CreateAndDispatchSimpleEvent(const nsString
& aName
);
188 nsresult
CreateAndDispatchMessageEvent(const nsACString
& aData
,
190 nsresult
CreateAndDispatchCloseEvent(bool aWasClean
,
192 const nsString
& aReason
);
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();
202 nsresult
UpdateURI();
206 nsCOMPtr
<nsIWebSocketChannel
> mChannel
;
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
215 bool mCheckMustKeepAlive
;
216 bool mOnCloseScheduled
;
220 // Set attributes of DOM 'onclose' message
221 bool mCloseEventWasClean
;
222 nsString mCloseEventReason
;
223 uint16_t mCloseEventCode
;
225 nsCString mAsciiHost
; // hostname
227 nsCString mResource
; // [filepath[?query]]
228 nsString mUTF16Origin
;
230 nsCOMPtr
<nsIURI
> mURI
;
231 nsCString mRequestedProtocolList
;
232 nsCString mEstablishedProtocol
;
233 nsCString mEstablishedExtensions
;
235 uint16_t mReadyState
;
237 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
239 uint32_t mOutgoingBufferedAmount
;
241 dom::BinaryType mBinaryType
;
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
;
254 WebSocket(const WebSocket
& x
) MOZ_DELETE
; // prevent bad usage
255 WebSocket
& operator=(const WebSocket
& x
) MOZ_DELETE
;
259 } //namespace mozilla