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