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 #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 "nsCOMPtr.h" 16 #include "nsCycleCollectionParticipant.h" 17 #include "nsISupports.h" 18 #include "nsISupportsUtils.h" 19 #include "nsString.h" 20 #include "nsWrapperCache.h" 21 22 #define DEFAULT_WS_SCHEME_PORT 80 23 #define DEFAULT_WSS_SCHEME_PORT 443 24 25 class nsIInputStream; 26 class nsITransportProvider; 27 28 namespace mozilla { 29 namespace dom { 30 31 class Blob; 32 33 class WebSocketImpl; 34 35 class WebSocket final : public DOMEventTargetHelper 36 { 37 friend class WebSocketImpl; 38 39 public: 40 enum { 41 CONNECTING = 0, 42 OPEN = 1, 43 CLOSING = 2, 44 CLOSED = 3 45 }; 46 47 public: 48 NS_DECL_ISUPPORTS_INHERITED 49 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED( 50 WebSocket, DOMEventTargetHelper) 51 52 // EventTarget 53 virtual void EventListenerAdded(nsIAtom* aType) override; 54 virtual void EventListenerRemoved(nsIAtom* aType) override; 55 56 virtual void DisconnectFromOwner() override; 57 58 // nsWrapperCache GetParentObject()59 nsPIDOMWindowInner* GetParentObject() { return GetOwner(); } 60 61 virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override; 62 63 public: // static helpers: 64 65 // Determine if preferences allow WebSocket 66 static bool PrefEnabled(JSContext* aCx = nullptr, JSObject* aGlobal = nullptr); 67 68 public: // WebIDL interface: 69 70 // Constructor: 71 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, 72 const nsAString& aUrl, 73 ErrorResult& rv); 74 75 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, 76 const nsAString& aUrl, 77 const nsAString& aProtocol, 78 ErrorResult& rv); 79 80 static already_AddRefed<WebSocket> Constructor(const GlobalObject& aGlobal, 81 const nsAString& aUrl, 82 const Sequence<nsString>& aProtocols, 83 ErrorResult& rv); 84 85 static already_AddRefed<WebSocket> CreateServerWebSocket(const GlobalObject& aGlobal, 86 const nsAString& aUrl, 87 const Sequence<nsString>& aProtocols, 88 nsITransportProvider* aTransportProvider, 89 const nsAString& aNegotiatedExtensions, 90 ErrorResult& rv); 91 92 static already_AddRefed<WebSocket> ConstructorCommon(const GlobalObject& aGlobal, 93 const nsAString& aUrl, 94 const Sequence<nsString>& aProtocols, 95 nsITransportProvider* aTransportProvider, 96 const nsACString& aNegotiatedExtensions, 97 ErrorResult& rv); 98 99 // webIDL: readonly attribute DOMString url 100 void GetUrl(nsAString& aResult); 101 102 // webIDL: readonly attribute unsigned short readyState; 103 uint16_t ReadyState(); 104 105 // webIDL: readonly attribute unsigned long bufferedAmount; 106 uint32_t BufferedAmount() const; 107 108 // webIDL: attribute Function? onopen; 109 IMPL_EVENT_HANDLER(open) 110 111 // webIDL: attribute Function? onerror; 112 IMPL_EVENT_HANDLER(error) 113 114 // webIDL: attribute Function? onclose; 115 IMPL_EVENT_HANDLER(close) 116 117 // webIDL: readonly attribute DOMString extensions; 118 void GetExtensions(nsAString& aResult); 119 120 // webIDL: readonly attribute DOMString protocol; 121 void GetProtocol(nsAString& aResult); 122 123 // webIDL: void close(optional unsigned short code, optional DOMString reason): 124 void Close(const Optional<uint16_t>& aCode, 125 const Optional<nsAString>& aReason, 126 ErrorResult& aRv); 127 128 // webIDL: attribute Function? onmessage; 129 IMPL_EVENT_HANDLER(message) 130 131 // webIDL: attribute DOMString binaryType; 132 dom::BinaryType BinaryType() const; 133 void SetBinaryType(dom::BinaryType aData); 134 135 // webIDL: void send(DOMString|Blob|ArrayBufferView data); 136 void Send(const nsAString& aData, 137 ErrorResult& aRv); 138 void Send(Blob& aData, 139 ErrorResult& aRv); 140 void Send(const ArrayBuffer& aData, 141 ErrorResult& aRv); 142 void Send(const ArrayBufferView& aData, 143 ErrorResult& aRv); 144 145 private: // constructor && destructor 146 explicit WebSocket(nsPIDOMWindowInner* aOwnerWindow); 147 virtual ~WebSocket(); 148 149 void SetReadyState(uint16_t aReadyState); 150 151 // These methods actually do the dispatch for various events. 152 nsresult CreateAndDispatchSimpleEvent(const nsAString& aName); 153 nsresult CreateAndDispatchMessageEvent(const nsACString& aData, 154 bool aIsBinary); 155 nsresult CreateAndDispatchCloseEvent(bool aWasClean, 156 uint16_t aCode, 157 const nsAString& aReason); 158 159 // if there are "strong event listeners" (see comment in WebSocket.cpp) or 160 // outgoing not sent messages then this method keeps the object alive 161 // when js doesn't have strong references to it. 162 void UpdateMustKeepAlive(); 163 // ATTENTION, when calling this method the object can be released 164 // (and possibly collected). 165 void DontKeepAliveAnyMore(); 166 167 private: 168 WebSocket(const WebSocket& x) = delete; // prevent bad usage 169 WebSocket& operator=(const WebSocket& x) = delete; 170 171 void Send(nsIInputStream* aMsgStream, 172 const nsACString& aMsgString, 173 uint32_t aMsgLength, 174 bool aIsBinary, 175 ErrorResult& aRv); 176 177 void AssertIsOnTargetThread() const; 178 179 // Raw pointer because this WebSocketImpl is created, managed and destroyed by 180 // WebSocket. 181 WebSocketImpl* mImpl; 182 183 bool mIsMainThread; 184 185 bool mKeepingAlive; 186 bool mCheckMustKeepAlive; 187 188 uint32_t mOutgoingBufferedAmount; 189 190 // related to the WebSocket constructor steps 191 nsString mURI; 192 nsString mEffectiveURL; // after redirects 193 nsCString mEstablishedExtensions; 194 nsCString mEstablishedProtocol; 195 196 dom::BinaryType mBinaryType; 197 198 // This mutex protects mReadyState that is the only variable that is used in 199 // different threads. 200 mozilla::Mutex mMutex; 201 202 // This value should not be used directly but use ReadyState() instead. 203 uint16_t mReadyState; 204 }; 205 206 } //namespace dom 207 } //namespace mozilla 208 209 #endif 210