WebSocket.h (6197B)
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/CheckedInt.h" 11 #include "mozilla/DOMEventTargetHelper.h" 12 #include "mozilla/Mutex.h" 13 #include "mozilla/dom/TypedArray.h" 14 #include "mozilla/dom/WebSocketBinding.h" // for BinaryType 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 class ErrorResult; 30 31 namespace dom { 32 33 class Blob; 34 class StringOrStringSequence; 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 mozilla::Maybe<EventCallbackDebuggerNotificationType> 58 GetDebuggerNotificationType() const override; 59 60 // nsWrapperCache 61 virtual JSObject* WrapObject(JSContext* cx, 62 JS::Handle<JSObject*> aGivenProto) override; 63 64 public: // static helpers: 65 // Determine if preferences allow WebSocket 66 static bool PrefEnabled(JSContext* aCx = nullptr, 67 JSObject* aGlobal = nullptr); 68 69 public: // WebIDL interface: 70 // Constructor: 71 static already_AddRefed<WebSocket> Constructor( 72 const GlobalObject& aGlobal, const nsAString& aUrl, 73 const StringOrStringSequence& aProtocols, ErrorResult& rv); 74 75 static already_AddRefed<WebSocket> CreateServerWebSocket( 76 const GlobalObject& aGlobal, const nsAString& aUrl, 77 const Sequence<nsString>& aProtocols, 78 nsITransportProvider* aTransportProvider, 79 const nsAString& aNegotiatedExtensions, ErrorResult& rv); 80 81 static already_AddRefed<WebSocket> ConstructorCommon( 82 const GlobalObject& aGlobal, const nsAString& aUrl, 83 const Sequence<nsString>& aProtocols, 84 nsITransportProvider* aTransportProvider, 85 const nsACString& aNegotiatedExtensions, ErrorResult& rv); 86 87 // webIDL: readonly attribute DOMString url 88 void GetUrl(nsAString& aResult); 89 90 // webIDL: readonly attribute unsigned short readyState; 91 uint16_t ReadyState(); 92 93 // webIDL: readonly attribute unsigned long long bufferedAmount; 94 uint64_t BufferedAmount() const; 95 96 // webIDL: attribute Function? onopen; 97 IMPL_EVENT_HANDLER(open) 98 99 // webIDL: attribute Function? onerror; 100 IMPL_EVENT_HANDLER(error) 101 102 // webIDL: attribute Function? onclose; 103 IMPL_EVENT_HANDLER(close) 104 105 // webIDL: readonly attribute DOMString extensions; 106 void GetExtensions(nsAString& aResult); 107 108 // webIDL: readonly attribute DOMString protocol; 109 void GetProtocol(nsAString& aResult); 110 111 // webIDL: void close(optional unsigned short code, 112 // optional DOMString reason): 113 void Close(const Optional<uint16_t>& aCode, 114 const Optional<nsAString>& aReason, ErrorResult& aRv); 115 116 // webIDL: attribute Function? onmessage; 117 IMPL_EVENT_HANDLER(message) 118 119 // webIDL: attribute DOMString binaryType; 120 dom::BinaryType BinaryType() const; 121 void SetBinaryType(dom::BinaryType aData); 122 123 // webIDL: void send(DOMString|Blob|ArrayBufferView data); 124 void Send(const nsAString& aData, ErrorResult& aRv); 125 void Send(Blob& aData, ErrorResult& aRv); 126 void Send(const ArrayBuffer& aData, ErrorResult& aRv); 127 void Send(const ArrayBufferView& aData, ErrorResult& aRv); 128 129 private: // constructor && destructor 130 explicit WebSocket(nsIGlobalObject* aGlobal); 131 virtual ~WebSocket(); 132 133 void SetReadyState(uint16_t aReadyState); 134 135 // These methods actually do the dispatch for various events. 136 nsresult CreateAndDispatchSimpleEvent(const nsAString& aName); 137 nsresult CreateAndDispatchMessageEvent(const nsACString& aData, 138 bool aIsBinary); 139 nsresult CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode, 140 const nsAString& aReason); 141 142 static bool IsValidProtocolString(const nsString& aValue); 143 144 // if there are "strong event listeners" (see comment in WebSocket.cpp) or 145 // outgoing not sent messages then this method keeps the object alive 146 // when js doesn't have strong references to it. 147 void UpdateMustKeepAlive(); 148 // ATTENTION, when calling this method the object can be released 149 // (and possibly collected). 150 void DontKeepAliveAnyMore(); 151 152 private: 153 WebSocket(const WebSocket& x) = delete; // prevent bad usage 154 WebSocket& operator=(const WebSocket& x) = delete; 155 156 void Send(nsIInputStream* aMsgStream, const nsACString& aMsgString, 157 uint32_t aMsgLength, bool aIsBinary, ErrorResult& aRv); 158 159 void AssertIsOnTargetThread() const; 160 161 // Raw pointer because this WebSocketImpl is created, managed and destroyed by 162 // WebSocket. 163 WebSocketImpl* mImpl; 164 165 bool mIsMainThread; 166 167 bool mKeepingAlive; 168 bool mCheckMustKeepAlive; 169 170 CheckedUint64 mOutgoingBufferedAmount; 171 172 // related to the WebSocket constructor steps 173 nsString mURI; 174 nsString mEffectiveURL; // after redirects 175 nsCString mEstablishedExtensions; 176 nsCString mEstablishedProtocol; 177 178 dom::BinaryType mBinaryType; 179 180 // This mutex protects mReadyState that is the only variable that is used in 181 // different threads. 182 mozilla::Mutex mMutex; 183 184 // This value should not be used directly but use ReadyState() instead. 185 uint16_t mReadyState MOZ_GUARDED_BY(mMutex); 186 }; 187 188 } // namespace dom 189 } // namespace mozilla 190 191 #endif