diff -r 000000000000 -r 6474c204b198 content/base/src/WebSocket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/base/src/WebSocket.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,261 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef WebSocket_h__ +#define WebSocket_h__ + +#include "mozilla/Attributes.h" +#include "mozilla/dom/TypedArray.h" +#include "mozilla/dom/WebSocketBinding.h" // for BinaryType +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/ErrorResult.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIInterfaceRequestor.h" +#include "nsIObserver.h" +#include "nsIRequest.h" +#include "nsISupports.h" +#include "nsISupportsUtils.h" +#include "nsIWebSocketChannel.h" +#include "nsIWebSocketListener.h" +#include "nsString.h" +#include "nsWeakReference.h" +#include "nsWrapperCache.h" + +#define DEFAULT_WS_SCHEME_PORT 80 +#define DEFAULT_WSS_SCHEME_PORT 443 + +namespace mozilla { +namespace dom { + +class WebSocket : public DOMEventTargetHelper, + public nsIInterfaceRequestor, + public nsIWebSocketListener, + public nsIObserver, + public nsSupportsWeakReference, + public nsIRequest +{ +friend class CallDispatchConnectionCloseEvents; +friend class nsAutoCloseWS; + +public: + enum { + CONNECTING = 0, + OPEN = 1, + CLOSING = 2, + CLOSED = 3 + }; + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED( + WebSocket, DOMEventTargetHelper) + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIWEBSOCKETLISTENER + NS_DECL_NSIOBSERVER + NS_DECL_NSIREQUEST + + // EventTarget + virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE; + virtual void EventListenerRemoved(nsIAtom* aType) MOZ_OVERRIDE; + + virtual void DisconnectFromOwner() MOZ_OVERRIDE; + + // nsWrapperCache + nsPIDOMWindow* GetParentObject() { return GetOwner(); } + + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; + +public: // static helpers: + + // Determine if preferences allow WebSocket + static bool PrefEnabled(JSContext* aCx = nullptr, JSObject* aGlobal = nullptr); + +public: // WebIDL interface: + + // Constructor: + static already_AddRefed Constructor(const GlobalObject& aGlobal, + const nsAString& aUrl, + ErrorResult& rv); + + static already_AddRefed Constructor(const GlobalObject& aGlobal, + const nsAString& aUrl, + const nsAString& aProtocol, + ErrorResult& rv); + + static already_AddRefed Constructor(const GlobalObject& aGlobal, + const nsAString& aUrl, + const Sequence& aProtocols, + ErrorResult& rv); + + // webIDL: readonly attribute DOMString url + void GetUrl(nsAString& aResult); + + // webIDL: readonly attribute unsigned short readyState; + uint16_t ReadyState() const { return mReadyState; } + + // webIDL: readonly attribute unsigned long bufferedAmount; + uint32_t BufferedAmount() const { return mOutgoingBufferedAmount; } + + // webIDL: attribute Function? onopen; + IMPL_EVENT_HANDLER(open) + + // webIDL: attribute Function? onerror; + IMPL_EVENT_HANDLER(error) + + // webIDL: attribute Function? onclose; + IMPL_EVENT_HANDLER(close) + + // webIDL: readonly attribute DOMString extensions; + void GetExtensions(nsAString& aResult); + + // webIDL: readonly attribute DOMString protocol; + void GetProtocol(nsAString& aResult); + + // webIDL: void close(optional unsigned short code, optional DOMString reason): + void Close(const Optional& aCode, + const Optional& aReason, + ErrorResult& aRv); + + // webIDL: attribute Function? onmessage; + IMPL_EVENT_HANDLER(message) + + // webIDL: attribute DOMString binaryType; + dom::BinaryType BinaryType() const { return mBinaryType; } + void SetBinaryType(dom::BinaryType aData) { mBinaryType = aData; } + + // webIDL: void send(DOMString|Blob|ArrayBufferView data); + void Send(const nsAString& aData, + ErrorResult& aRv); + void Send(nsIDOMBlob* aData, + ErrorResult& aRv); + void Send(const ArrayBuffer& aData, + ErrorResult& aRv); + void Send(const ArrayBufferView& aData, + ErrorResult& aRv); + +private: // constructor && distructor + WebSocket(nsPIDOMWindow* aOwnerWindow); + virtual ~WebSocket(); + +protected: + nsresult Init(JSContext* aCx, + nsIPrincipal* aPrincipal, + const nsAString& aURL, + nsTArray& aProtocolArray); + + void Send(nsIInputStream* aMsgStream, + const nsACString& aMsgString, + uint32_t aMsgLength, + bool aIsBinary, + ErrorResult& aRv); + + nsresult ParseURL(const nsString& aURL); + nsresult EstablishConnection(); + + // These methods when called can release the WebSocket object + void FailConnection(uint16_t reasonCode, + const nsACString& aReasonString = EmptyCString()); + nsresult CloseConnection(uint16_t reasonCode, + const nsACString& aReasonString = EmptyCString()); + nsresult Disconnect(); + + nsresult ConsoleError(); + nsresult PrintErrorOnConsole(const char* aBundleURI, + const char16_t* aError, + const char16_t** aFormatStrings, + uint32_t aFormatStringsLen); + + nsresult DoOnMessageAvailable(const nsACString& aMsg, + bool isBinary); + + // ConnectionCloseEvents: 'error' event if needed, then 'close' event. + // - These must not be dispatched while we are still within an incoming call + // from JS (ex: close()). Set 'sync' to false in that case to dispatch in a + // separate new event. + nsresult ScheduleConnectionCloseEvents(nsISupports* aContext, + nsresult aStatusCode, + bool sync); + // 2nd half of ScheduleConnectionCloseEvents, sometimes run in its own event. + void DispatchConnectionCloseEvents(); + + // These methods actually do the dispatch for various events. + nsresult CreateAndDispatchSimpleEvent(const nsString& aName); + nsresult CreateAndDispatchMessageEvent(const nsACString& aData, + bool isBinary); + nsresult CreateAndDispatchCloseEvent(bool aWasClean, + uint16_t aCode, + const nsString& aReason); + + // if there are "strong event listeners" (see comment in WebSocket.cpp) or + // outgoing not sent messages then this method keeps the object alive + // when js doesn't have strong references to it. + void UpdateMustKeepAlive(); + // ATTENTION, when calling this method the object can be released + // (and possibly collected). + void DontKeepAliveAnyMore(); + + nsresult UpdateURI(); + +protected: //data + + nsCOMPtr mChannel; + + // related to the WebSocket constructor steps + nsString mOriginalURL; + nsString mEffectiveURL; // after redirects + bool mSecure; // if true it is using SSL and the wss scheme, + // otherwise it is using the ws scheme with no SSL + + bool mKeepingAlive; + bool mCheckMustKeepAlive; + bool mOnCloseScheduled; + bool mFailed; + bool mDisconnected; + + // Set attributes of DOM 'onclose' message + bool mCloseEventWasClean; + nsString mCloseEventReason; + uint16_t mCloseEventCode; + + nsCString mAsciiHost; // hostname + uint32_t mPort; + nsCString mResource; // [filepath[?query]] + nsString mUTF16Origin; + + nsCOMPtr mURI; + nsCString mRequestedProtocolList; + nsCString mEstablishedProtocol; + nsCString mEstablishedExtensions; + + uint16_t mReadyState; + + nsCOMPtr mPrincipal; + + uint32_t mOutgoingBufferedAmount; + + dom::BinaryType mBinaryType; + + // Web Socket owner information: + // - the script file name, UTF8 encoded. + // - source code line number where the Web Socket object was constructed. + // - the ID of the inner window where the script lives. Note that this may not + // be the same as the Web Socket owner window. + // These attributes are used for error reporting. + nsCString mScriptFile; + uint32_t mScriptLine; + uint64_t mInnerWindowID; + +private: + WebSocket(const WebSocket& x) MOZ_DELETE; // prevent bad usage + WebSocket& operator=(const WebSocket& x) MOZ_DELETE; +}; + +} //namespace dom +} //namespace mozilla + +#endif