Bug 537787 - Remote websockets. r=jduell

This commit is contained in:
Josh Matthews
2011-05-04 15:36:23 +02:00
parent 1e75be97e6
commit b02c36b9bf
24 changed files with 1491 additions and 187 deletions

View File

@@ -1244,7 +1244,7 @@ nsWebSocket::Send(const nsAString& aData, PRBool *aRet)
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
// We need to check if there isn't unpaired surrogates.
// Check for unpaired surrogates.
PRUint32 i, length = aData.Length();
for (i = 0; i < length; ++i) {
if (NS_IS_LOW_SURROGATE(aData[i])) {

View File

@@ -67,6 +67,7 @@ IPDLDIRS = \
netwerk/protocol/ftp \
netwerk/protocol/http \
netwerk/protocol/wyciwyg \
netwerk/protocol/websocket \
netwerk/cookie \
uriloader/prefetch \
$(NULL)

View File

@@ -64,6 +64,7 @@
#include "nsNetStrings.h"
#include "nsDNSPrefetch.h"
#include "nsAboutProtocolHandler.h"
#include "nsXULAppAPI.h"
#include "nsNetCID.h"
@@ -283,10 +284,47 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
#ifdef NECKO_PROTOCOL_websocket
#include "nsWebSocketHandler.h"
#include "WebSocketChannelChild.h"
namespace mozilla {
namespace net {
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebSocketHandler)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebSocketSSLHandler)
static BaseWebSocketChannel*
WebSocketHandlerConstructor(bool aSecure)
{
if (IsNeckoChild()) {
return new WebSocketChannelChild(aSecure);
}
if (aSecure) {
return new nsWebSocketSSLHandler;
} else {
return new nsWebSocketHandler;
}
}
#define WEB_SOCKET_HANDLER_CONSTRUCTOR(type, secure) \
static nsresult \
type##Constructor(nsISupports *aOuter, REFNSIID aIID, \
void **aResult) \
{ \
nsresult rv; \
\
BaseWebSocketChannel * inst; \
\
*aResult = NULL; \
if (NULL != aOuter) { \
rv = NS_ERROR_NO_AGGREGATION; \
return rv; \
} \
inst = WebSocketHandlerConstructor(secure); \
NS_ADDREF(inst); \
rv = inst->QueryInterface(aIID, aResult); \
NS_RELEASE(inst); \
return rv; \
}
WEB_SOCKET_HANDLER_CONSTRUCTOR(nsWebSocketHandler, false)
WEB_SOCKET_HANDLER_CONSTRUCTOR(nsWebSocketSSLHandler, true)
#undef WEB_SOCKET_HANDLER_CONSTRUCTOR
} // namespace mozilla::net
} // namespace mozilla
#endif

View File

@@ -39,7 +39,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIChannel.h"
#include "nsISupports.h"
#include "mozilla/net/ChannelEventQueue.h"
namespace mozilla {
@@ -51,7 +51,7 @@ ChannelEventQueue::FlushQueue()
// Events flushed could include destruction of channel (and our own
// destructor) unless we make sure its refcount doesn't drop to 0 while this
// method is running.
nsCOMPtr<nsIChannel> kungFuDeathGrip(mOwner);
nsCOMPtr<nsISupports> kungFuDeathGrip(mOwner);
// Prevent flushed events from flushing the queue recursively
mFlushing = true;

View File

@@ -45,7 +45,7 @@
#include <nsTArray.h>
#include <nsAutoPtr.h>
class nsIChannel;
class nsISupports;
namespace mozilla {
namespace net {
@@ -70,7 +70,7 @@ class AutoEventEnqueuerBase;
class ChannelEventQueue
{
public:
ChannelEventQueue(nsIChannel *owner)
ChannelEventQueue(nsISupports *owner)
: mForced(false)
, mSuspended(false)
, mFlushing(false)
@@ -116,7 +116,7 @@ class ChannelEventQueue
bool mFlushing;
// Keep ptr to avoid refcount cycle: only grab ref during flushing.
nsIChannel *mOwner;
nsISupports *mOwner;
friend class AutoEventEnqueuer;
};

View File

@@ -46,6 +46,7 @@
#include "mozilla/net/CookieServiceChild.h"
#include "mozilla/net/WyciwygChannelChild.h"
#include "mozilla/net/FTPChannelChild.h"
#include "mozilla/net/WebSocketChannelChild.h"
namespace mozilla {
namespace net {
@@ -167,5 +168,20 @@ NeckoChild::DeallocPWyciwygChannel(PWyciwygChannelChild* channel)
return true;
}
PWebSocketChild*
NeckoChild::AllocPWebSocket(PBrowserChild* browser)
{
NS_NOTREACHED("AllocPWebSocket should not be called");
return nsnull;
}
bool
NeckoChild::DeallocPWebSocket(PWebSocketChild* child)
{
WebSocketChannelChild* p = static_cast<WebSocketChannelChild*>(child);
p->ReleaseIPDLReference();
return true;
}
}} // mozilla::net

View File

@@ -67,6 +67,8 @@ protected:
virtual bool DeallocPWyciwygChannel(PWyciwygChannelChild*);
virtual PFTPChannelChild* AllocPFTPChannel();
virtual bool DeallocPFTPChannel(PFTPChannelChild*);
virtual PWebSocketChild* AllocPWebSocket(PBrowserChild*);
virtual bool DeallocPWebSocket(PWebSocketChild*);
};
/**

View File

@@ -44,9 +44,13 @@
#include "mozilla/net/CookieServiceParent.h"
#include "mozilla/net/WyciwygChannelParent.h"
#include "mozilla/net/FTPChannelParent.h"
#include "mozilla/net/WebSocketChannelParent.h"
#include "mozilla/dom/TabParent.h"
#include "nsHTMLDNSPrefetch.h"
using mozilla::dom::TabParent;
namespace mozilla {
namespace net {
@@ -120,6 +124,23 @@ NeckoParent::DeallocPWyciwygChannel(PWyciwygChannelParent* channel)
return true;
}
PWebSocketParent*
NeckoParent::AllocPWebSocket(PBrowserParent* browser)
{
TabParent* tabParent = static_cast<TabParent*>(browser);
WebSocketChannelParent* p = new WebSocketChannelParent(tabParent);
p->AddRef();
return p;
}
bool
NeckoParent::DeallocPWebSocket(PWebSocketParent* actor)
{
WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
p->Release();
return true;
}
bool
NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
const PRUint16& flags)

View File

@@ -64,6 +64,8 @@ protected:
virtual bool DeallocPWyciwygChannel(PWyciwygChannelParent*);
virtual PFTPChannelParent* AllocPFTPChannel();
virtual bool DeallocPFTPChannel(PFTPChannelParent*);
virtual PWebSocketParent* AllocPWebSocket(PBrowserParent* browser);
virtual bool DeallocPWebSocket(PWebSocketParent*);
virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
const PRUint16& flags);
};

View File

@@ -44,6 +44,7 @@ include protocol PCookieService;
include protocol PBrowser;
include protocol PWyciwygChannel;
include protocol PFTPChannel;
include protocol PWebSocket;
namespace mozilla {
namespace net {
@@ -57,6 +58,7 @@ sync protocol PNecko
manages PCookieService;
manages PWyciwygChannel;
manages PFTPChannel;
manages PWebSocket;
parent:
__delete__();
@@ -64,6 +66,7 @@ parent:
PCookieService();
PWyciwygChannel();
PFTPChannel();
PWebSocket(PBrowser browser);
HTMLDNSPrefetch(nsString hostname, PRUint16 flags);

View File

@@ -57,7 +57,7 @@ namespace net {
FTPChannelChild::FTPChannelChild(nsIURI* uri)
: mIPCOpen(false)
, mEventQ(this)
, mEventQ(static_cast<nsIFTPChannel*>(this))
, mCanceled(false)
, mSuspendCount(0)
, mIsPending(PR_FALSE)

View File

@@ -66,7 +66,7 @@ HttpChannelChild::HttpChannelChild()
, mSendResumeAt(false)
, mIPCOpen(false)
, mKeptAlive(false)
, mEventQ(this)
, mEventQ(static_cast<nsIHttpChannel*>(this))
{
LOG(("Creating HttpChannelChild @%x\n", this));
}

View File

@@ -0,0 +1,222 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "WebSocketLog.h"
#include "BaseWebSocketChannel.h"
#include "nsWebSocketHandler.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
#include "nsAutoPtr.h"
#include "nsStandardURL.h"
#if defined(PR_LOGGING)
PRLogModuleInfo *webSocketLog = nsnull;
#endif
namespace mozilla {
namespace net {
BaseWebSocketChannel::BaseWebSocketChannel()
: mEncrypted(false)
{
#if defined(PR_LOGGING)
if (!webSocketLog)
webSocketLog = PR_NewLogModule("nsWebSocket");
#endif
}
//-----------------------------------------------------------------------------
// BaseWebSocketChannel::nsIWebSocketProtocol
//-----------------------------------------------------------------------------
NS_IMETHODIMP
BaseWebSocketChannel::GetOriginalURI(nsIURI **aOriginalURI)
{
LOG(("BaseWebSocketChannel::GetOriginalURI() %p\n", this));
if (!mOriginalURI)
return NS_ERROR_NOT_INITIALIZED;
NS_ADDREF(*aOriginalURI = mOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::GetURI(nsIURI **aURI)
{
LOG(("BaseWebSocketChannel::GetURI() %p\n", this));
if (!mOriginalURI)
return NS_ERROR_NOT_INITIALIZED;
if (mURI)
NS_ADDREF(*aURI = mURI);
else
NS_ADDREF(*aURI = mOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::
GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks)
{
LOG(("BaseWebSocketChannel::GetNotificationCallbacks() %p\n", this));
NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::
SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks)
{
LOG(("BaseWebSocketChannel::SetNotificationCallbacks() %p\n", this));
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
{
LOG(("BaseWebSocketChannel::GetLoadGroup() %p\n", this));
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
LOG(("BaseWebSocketChannel::SetLoadGroup() %p\n", this));
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::GetProtocol(nsACString &aProtocol)
{
LOG(("BaseWebSocketChannel::GetProtocol() %p\n", this));
aProtocol = mProtocol;
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::SetProtocol(const nsACString &aProtocol)
{
LOG(("BaseWebSocketChannel::SetProtocol() %p\n", this));
mProtocol = aProtocol; /* the sub protocol */
return NS_OK;
}
//-----------------------------------------------------------------------------
// BaseWebSocketChannel::nsIProtocolHandler
//-----------------------------------------------------------------------------
NS_IMETHODIMP
BaseWebSocketChannel::GetScheme(nsACString &aScheme)
{
LOG(("BaseWebSocketHandler::GetScheme() %p\n", this));
if (mEncrypted)
aScheme.AssignLiteral("wss");
else
aScheme.AssignLiteral("ws");
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::GetDefaultPort(PRInt32 *aDefaultPort)
{
LOG(("BaseWebSocketHandler::GetDefaultPort() %p\n", this));
if (mEncrypted)
*aDefaultPort = kDefaultWSSPort;
else
*aDefaultPort = kDefaultWSPort;
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::GetProtocolFlags(PRUint32 *aProtocolFlags)
{
LOG(("BaseWebSocketHandler::GetProtocolFlags() %p\n", this));
*aProtocolFlags = URI_NORELATIVE | URI_NON_PERSISTABLE | ALLOWS_PROXY |
ALLOWS_PROXY_HTTP | URI_DOES_NOT_RETURN_DATA | URI_DANGEROUS_TO_LOAD;
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::NewURI(const nsACString & aSpec, const char *aOriginCharset,
nsIURI *aBaseURI, nsIURI **_retval NS_OUTPARAM)
{
LOG(("BaseWebSocketHandler::NewURI() %p\n", this));
PRInt32 port;
nsresult rv = GetDefaultPort(&port);
if (NS_FAILED(rv))
return rv;
nsRefPtr<nsStandardURL> url = new nsStandardURL();
rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY, port, aSpec,
aOriginCharset, aBaseURI);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*_retval = url);
return NS_OK;
}
NS_IMETHODIMP
BaseWebSocketChannel::NewChannel(nsIURI *aURI, nsIChannel **_retval NS_OUTPARAM)
{
LOG(("BaseWebSocketHandler::NewChannel() %p\n", this));
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
BaseWebSocketChannel::AllowPort(PRInt32 port, const char *scheme,
PRBool *_retval NS_OUTPARAM)
{
LOG(("BaseWebSocketHandler::AllowPort() %p\n", this));
// do not override any blacklisted ports
*_retval = PR_FALSE;
return NS_OK;
}
} // namespace net
} // namespace mozilla

View File

@@ -0,0 +1,94 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_BaseWebSocketChannel_h
#define mozilla_net_BaseWebSocketChannel_h
#include "nsIWebSocketProtocol.h"
#include "nsIProtocolHandler.h"
#include "nsCOMPtr.h"
#include "nsString.h"
namespace mozilla {
namespace net {
const static PRInt32 kDefaultWSPort = 80;
const static PRInt32 kDefaultWSSPort = 443;
class BaseWebSocketChannel : public nsIWebSocketProtocol,
public nsIProtocolHandler
{
public:
BaseWebSocketChannel();
NS_DECL_NSIPROTOCOLHANDLER
NS_IMETHOD QueryInterface(const nsIID & uuid, void **result NS_OUTPARAM) = 0;
NS_IMETHOD_(nsrefcnt ) AddRef(void) = 0;
NS_IMETHOD_(nsrefcnt ) Release(void) = 0;
// Partial implementation of nsIWebSocketProtocol
//
NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI);
NS_IMETHOD GetURI(nsIURI **aURI);
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks);
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks);
NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
NS_IMETHOD GetProtocol(nsACString &aProtocol);
NS_IMETHOD SetProtocol(const nsACString &aProtocol);
protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIWebSocketListener> mListener;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCString mProtocol;
nsCString mOrigin;
PRBool mEncrypted;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_BaseWebSocketChannel_h

View File

@@ -49,16 +49,30 @@ XPIDL_MODULE = necko_websocket
GRE_MODULE = 1
FORCE_STATIC_LIB = 1
EXPORTS_NAMESPACES = mozilla/net
XPIDLSRCS = \
nsIWebSocketProtocol.idl \
$(NULL)
CPPSRCS = \
nsWebSocketHandler.cpp
nsWebSocketHandler.cpp \
WebSocketChannelParent.cpp \
WebSocketChannelChild.cpp \
BaseWebSocketChannel.cpp \
$(NULL)
EXPORTS_mozilla/net = \
nsWebSocketHandler.h \
WebSocketChannelParent.h \
WebSocketChannelChild.h \
BaseWebSocketChannel.h \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir)/../../base/src \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/xpcom/ds \
$(NULL)

View File

@@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
include protocol PNecko;
include protocol PBrowser;
include "mozilla/net/NeckoMessageUtils.h";
using IPC::URI;
namespace mozilla {
namespace net {
async protocol PWebSocket
{
manager PNecko;
parent:
// Forwarded methods corresponding to methods on nsIWebSocketProtocolHandler
AsyncOpen(URI aURI, nsCString aOrigin, nsCString aProtocol, bool aSecure);
Close();
SendMsg(nsCString aMsg);
SendBinaryMsg(nsCString aMsg);
DeleteSelf();
child:
// Forwarded notifications corresponding to the nsIWebSocketListener interface
OnStart(nsCString aProtocol);
OnStop(nsresult aStatusCode);
OnMessageAvailable(nsCString aMsg);
OnBinaryMessageAvailable(nsCString aMsg);
OnAcknowledge(PRUint32 aSize);
OnServerClose();
// Only sent in the event that AsyncOpen fails
AsyncOpenFailed();
__delete__();
};
} //namespace net
} //namespace mozilla

View File

@@ -0,0 +1,446 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "WebSocketLog.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/net/NeckoChild.h"
#include "WebSocketChannelChild.h"
#include "nsITabChild.h"
namespace mozilla {
namespace net {
NS_IMPL_ADDREF(WebSocketChannelChild)
NS_IMETHODIMP_(nsrefcnt) WebSocketChannelChild::Release()
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
NS_ASSERT_OWNINGTHREAD(WebSocketChannelChild);
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");
if (mRefCnt == 1 && mIPCOpen) {
SendDeleteSelf();
return mRefCnt;
}
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
}
return mRefCnt;
}
NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
NS_INTERFACE_MAP_ENTRY(nsIWebSocketProtocol)
NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketProtocol)
NS_INTERFACE_MAP_END
WebSocketChannelChild::WebSocketChannelChild(bool aSecure)
: mEventQ(static_cast<nsIWebSocketProtocol*>(this))
, mIPCOpen(false)
, mCancelled(false)
{
LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n", this));
BaseWebSocketChannel::mEncrypted = aSecure;
}
WebSocketChannelChild::~WebSocketChannelChild()
{
LOG(("WebSocketChannelChild::~WebSocketChannelChild() %p\n", this));
}
void
WebSocketChannelChild::AddIPDLReference()
{
NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference");
mIPCOpen = true;
AddRef();
}
void
WebSocketChannelChild::ReleaseIPDLReference()
{
NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
mIPCOpen = false;
Release();
}
class StartEvent : public ChannelEvent
{
public:
StartEvent(WebSocketChannelChild* aChild,
const nsCString& aProtocol)
: mChild(aChild)
, mProtocol(aProtocol)
{}
void Run()
{
mChild->OnStart(mProtocol);
}
private:
WebSocketChannelChild* mChild;
nsCString mProtocol;
};
bool
WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol)
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new StartEvent(this, aProtocol));
} else {
OnStart(aProtocol);
}
return true;
}
void
WebSocketChannelChild::OnStart(const nsCString& aProtocol)
{
LOG(("WebSocketChannelChild::RecvOnStart() %p\n", this));
SetProtocol(aProtocol);
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnStart(mContext);
}
}
class StopEvent : public ChannelEvent
{
public:
StopEvent(WebSocketChannelChild* aChild,
const nsresult& aStatusCode)
: mChild(aChild)
, mStatusCode(aStatusCode)
{}
void Run()
{
mChild->OnStop(mStatusCode);
}
private:
WebSocketChannelChild* mChild;
nsresult mStatusCode;
};
bool
WebSocketChannelChild::RecvOnStop(const nsresult& aStatusCode)
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new StopEvent(this, aStatusCode));
} else {
OnStop(aStatusCode);
}
return true;
}
void
WebSocketChannelChild::OnStop(const nsresult& aStatusCode)
{
LOG(("WebSocketChannelChild::RecvOnStop() %p\n", this));
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnStop(mContext, aStatusCode);
}
}
class MessageEvent : public ChannelEvent
{
public:
MessageEvent(WebSocketChannelChild* aChild,
const nsCString& aMessage,
bool aBinary)
: mChild(aChild)
, mMessage(aMessage)
, mBinary(aBinary)
{}
void Run()
{
if (!mBinary) {
mChild->OnMessageAvailable(mMessage);
} else {
mChild->OnBinaryMessageAvailable(mMessage);
}
}
private:
WebSocketChannelChild* mChild;
nsCString mMessage;
bool mBinary;
};
bool
WebSocketChannelChild::RecvOnMessageAvailable(const nsCString& aMsg)
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new MessageEvent(this, aMsg, false));
} else {
OnMessageAvailable(aMsg);
}
return true;
}
void
WebSocketChannelChild::OnMessageAvailable(const nsCString& aMsg)
{
LOG(("WebSocketChannelChild::RecvOnMessageAvailable() %p\n", this));
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnMessageAvailable(mContext, aMsg);
}
}
bool
WebSocketChannelChild::RecvOnBinaryMessageAvailable(const nsCString& aMsg)
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new MessageEvent(this, aMsg, true));
} else {
OnBinaryMessageAvailable(aMsg);
}
return true;
}
void
WebSocketChannelChild::OnBinaryMessageAvailable(const nsCString& aMsg)
{
LOG(("WebSocketChannelChild::RecvOnBinaryMessageAvailable() %p\n", this));
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnBinaryMessageAvailable(mContext, aMsg);
}
}
class AcknowledgeEvent : public ChannelEvent
{
public:
AcknowledgeEvent(WebSocketChannelChild* aChild,
const PRUint32& aSize)
: mChild(aChild)
, mSize(aSize)
{}
void Run()
{
mChild->OnAcknowledge(mSize);
}
private:
WebSocketChannelChild* mChild;
PRUint32 mSize;
};
bool
WebSocketChannelChild::RecvOnAcknowledge(const PRUint32& aSize)
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new AcknowledgeEvent(this, aSize));
} else {
OnAcknowledge(aSize);
}
return true;
}
void
WebSocketChannelChild::OnAcknowledge(const PRUint32& aSize)
{
LOG(("WebSocketChannelChild::RecvOnAcknowledge() %p\n", this));
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnAcknowledge(mContext, aSize);
}
}
class ServerCloseEvent : public ChannelEvent
{
public:
ServerCloseEvent(WebSocketChannelChild* aChild)
: mChild(aChild)
{}
void Run()
{
mChild->OnServerClose();
}
private:
WebSocketChannelChild* mChild;
};
bool
WebSocketChannelChild::RecvOnServerClose()
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new ServerCloseEvent(this));
} else {
OnServerClose();
}
return true;
}
void
WebSocketChannelChild::OnServerClose()
{
LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n", this));
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
mListener->OnServerClose(mContext);
}
}
class AsyncOpenFailedEvent : public ChannelEvent
{
public:
AsyncOpenFailedEvent(WebSocketChannelChild* aChild)
: mChild(aChild)
{}
void Run()
{
mChild->AsyncOpenFailed();
}
private:
WebSocketChannelChild* mChild;
};
bool
WebSocketChannelChild::RecvAsyncOpenFailed()
{
if (mEventQ.ShouldEnqueue()) {
mEventQ.Enqueue(new AsyncOpenFailedEvent(this));
} else {
AsyncOpenFailed();
}
return true;
}
void
WebSocketChannelChild::AsyncOpenFailed()
{
LOG(("WebSocketChannelChild::RecvAsyncOpenFailed() %p\n", this));
mCancelled = true;
if (mIPCOpen)
SendDeleteSelf();
}
NS_IMETHODIMP
WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
const nsACString &aOrigin,
nsIWebSocketListener *aListener,
nsISupports *aContext)
{
LOG(("WebSocketChannelChild::AsyncOpen() %p\n", this));
NS_ABORT_IF_FALSE(aURI && aListener && !mListener,
"Invalid state for WebSocketChannelChild::AsyncOpen");
mozilla::dom::TabChild* tabChild = nsnull;
nsCOMPtr<nsITabChild> iTabChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsITabChild),
getter_AddRefs(iTabChild));
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
// Corresponding release in DeallocPWebSocket
AddIPDLReference();
gNeckoChild->SendPWebSocketConstructor(this, tabChild);
if (!SendAsyncOpen(aURI, nsCString(aOrigin), mProtocol, mEncrypted))
return NS_ERROR_UNEXPECTED;
mOriginalURI = aURI;
mURI = mOriginalURI;
mListener = aListener;
mContext = aContext;
mOrigin = aOrigin;
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelChild::Close()
{
LOG(("WebSocketChannelChild::Close() %p\n", this));
if (mCancelled)
return NS_ERROR_UNEXPECTED;
if (!mIPCOpen || !SendClose())
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelChild::SendMsg(const nsACString &aMsg)
{
LOG(("WebSocketChannelChild::SendMsg() %p\n", this));
if (mCancelled)
return NS_ERROR_UNEXPECTED;
if (!mIPCOpen || !SendSendMsg(nsCString(aMsg)))
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelChild::SendBinaryMsg(const nsACString &aMsg)
{
LOG(("WebSocketChannelChild::SendBinaryMsg() %p\n", this));
if (mCancelled)
return NS_ERROR_UNEXPECTED;
if (!mIPCOpen || !SendSendBinaryMsg(nsCString(aMsg)))
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
{
LOG(("WebSocketChannelChild::GetSecurityInfo() %p\n", this));
return NS_ERROR_NOT_AVAILABLE;
}
} // namespace net
} // namespace mozilla

View File

@@ -0,0 +1,107 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_WebSocketChannelChild_h
#define mozilla_net_WebSocketChannelChild_h
#include "mozilla/net/PWebSocketChild.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "mozilla/net/BaseWebSocketChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
namespace mozilla {
namespace net {
class WebSocketChannelChild : public BaseWebSocketChannel,
public PWebSocketChild
{
public:
WebSocketChannelChild(bool aSecure);
~WebSocketChannelChild();
NS_DECL_ISUPPORTS
// nsIWebSocketProtocol methods BaseWebSocketChannel didn't implement for us
//
NS_SCRIPTABLE NS_IMETHOD AsyncOpen(nsIURI *aURI,
const nsACString &aOrigin,
nsIWebSocketListener *aListener,
nsISupports *aContext);
NS_SCRIPTABLE NS_IMETHOD Close();
NS_SCRIPTABLE NS_IMETHOD SendMsg(const nsACString &aMsg);
NS_SCRIPTABLE NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
NS_SCRIPTABLE NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
void AddIPDLReference();
void ReleaseIPDLReference();
private:
bool RecvOnStart(const nsCString& aProtocol);
bool RecvOnStop(const nsresult& aStatusCode);
bool RecvOnMessageAvailable(const nsCString& aMsg);
bool RecvOnBinaryMessageAvailable(const nsCString& aMsg);
bool RecvOnAcknowledge(const PRUint32& aSize);
bool RecvOnServerClose();
bool RecvAsyncOpenFailed();
void OnStart(const nsCString& aProtocol);
void OnStop(const nsresult& aStatusCode);
void OnMessageAvailable(const nsCString& aMsg);
void OnBinaryMessageAvailable(const nsCString& aMsg);
void OnAcknowledge(const PRUint32& aSize);
void OnServerClose();
void AsyncOpenFailed();
ChannelEventQueue mEventQ;
bool mIPCOpen;
bool mCancelled;
friend class StartEvent;
friend class StopEvent;
friend class MessageEvent;
friend class AcknowledgeEvent;
friend class ServerCloseEvent;
friend class AsyncOpenFailedEvent;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_WebSocketChannelChild_h

View File

@@ -0,0 +1,226 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "WebSocketLog.h"
#include "WebSocketChannelParent.h"
#include "nsIAuthPromptProvider.h"
namespace mozilla {
namespace net {
NS_IMPL_THREADSAFE_ISUPPORTS2(WebSocketChannelParent,
nsIWebSocketListener,
nsIInterfaceRequestor)
WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider)
: mAuthProvider(aAuthProvider)
, mIPCOpen(true)
{
#if defined(PR_LOGGING)
if (!webSocketLog)
webSocketLog = PR_NewLogModule("nsWebSocket");
#endif
}
bool
WebSocketChannelParent::RecvDeleteSelf()
{
LOG(("WebSocketChannelParent::RecvDeleteSelf() %p\n", this));
mChannel = nsnull;
mAuthProvider = nsnull;
return mIPCOpen ? Send__delete__(this) : true;
}
bool
WebSocketChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
const nsCString& aOrigin,
const nsCString& aProtocol,
const bool& aSecure)
{
LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this));
nsresult rv;
if (aSecure) {
mChannel =
do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
} else {
mChannel =
do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
}
if (NS_FAILED(rv))
return CancelEarly();
rv = mChannel->SetNotificationCallbacks(this);
if (NS_FAILED(rv))
return CancelEarly();
rv = mChannel->SetProtocol(aProtocol);
if (NS_FAILED(rv))
return CancelEarly();
rv = mChannel->AsyncOpen(aURI, aOrigin, this, nsnull);
if (NS_FAILED(rv))
return CancelEarly();
return true;
}
bool
WebSocketChannelParent::RecvClose()
{
LOG(("WebSocketChannelParent::RecvClose() %p\n", this));
if (mChannel) {
nsresult rv = mChannel->Close();
NS_ENSURE_SUCCESS(rv, true);
}
return true;
}
bool
WebSocketChannelParent::RecvSendMsg(const nsCString& aMsg)
{
LOG(("WebSocketChannelParent::RecvSendMsg() %p\n", this));
if (mChannel) {
nsresult rv = mChannel->SendMsg(aMsg);
NS_ENSURE_SUCCESS(rv, true);
}
return true;
}
bool
WebSocketChannelParent::RecvSendBinaryMsg(const nsCString& aMsg)
{
LOG(("WebSocketChannelParent::RecvSendBinaryMsg() %p\n", this));
if (mChannel) {
nsresult rv = mChannel->SendBinaryMsg(aMsg);
NS_ENSURE_SUCCESS(rv, true);
}
return true;
}
bool
WebSocketChannelParent::CancelEarly()
{
LOG(("WebSocketChannelParent::CancelEarly() %p\n", this));
return mIPCOpen ? SendAsyncOpenFailed() : true;
}
NS_IMETHODIMP
WebSocketChannelParent::GetInterface(const nsIID & iid, void **result NS_OUTPARAM)
{
LOG(("WebSocketChannelParent::GetInterface() %p\n", this));
if (mAuthProvider && iid.Equals(NS_GET_IID(nsIAuthPromptProvider)))
return mAuthProvider->GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
iid, result);
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
WebSocketChannelParent::OnStart(nsISupports *aContext)
{
LOG(("WebSocketChannelParent::OnStart() %p\n", this));
nsCAutoString protocol;
if (mChannel) {
mChannel->GetProtocol(protocol);
}
if (!mIPCOpen || !SendOnStart(protocol)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelParent::OnStop(nsISupports *aContext, nsresult aStatusCode)
{
LOG(("WebSocketChannelParent::OnStop() %p\n", this));
if (!mIPCOpen || !SendOnStop(aStatusCode)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelParent::OnMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
{
LOG(("WebSocketChannelParent::OnMessageAvailable() %p\n", this));
if (!mIPCOpen || !SendOnMessageAvailable(nsCString(aMsg))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelParent::OnBinaryMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
{
LOG(("WebSocketChannelParent::OnBinaryMessageAvailable() %p\n", this));
if (!mIPCOpen || !SendOnBinaryMessageAvailable(nsCString(aMsg))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelParent::OnAcknowledge(nsISupports *aContext, PRUint32 aSize)
{
LOG(("WebSocketChannelParent::OnAcknowledge() %p\n", this));
if (!mIPCOpen || !SendOnAcknowledge(aSize)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
WebSocketChannelParent::OnServerClose(nsISupports *aContext)
{
LOG(("WebSocketChannelParent::OnServerClose() %p\n", this));
if (!mIPCOpen || !SendOnServerClose()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
void
WebSocketChannelParent::ActorDestroy(ActorDestroyReason why)
{
LOG(("WebSocketChannelParent::ActorDestroy() %p\n", this));
mIPCOpen = false;
}
} // namespace net
} // namespace mozilla

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_WebSocketChannelParent_h
#define mozilla_net_WebSocketChannelParent_h
#include "mozilla/net/PWebSocketParent.h"
#include "mozilla/net/nsWebSocketHandler.h"
#include "nsCOMPtr.h"
#include "nsString.h"
class nsIAuthPromptProvider;
namespace mozilla {
namespace net {
class WebSocketChannelParent : public PWebSocketParent,
public nsIWebSocketListener,
public nsIInterfaceRequestor
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBSOCKETLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider);
private:
bool RecvAsyncOpen(const IPC::URI& aURI,
const nsCString& aOrigin,
const nsCString& aProtocol,
const bool& aSecure);
bool RecvClose();
bool RecvSendMsg(const nsCString& aMsg);
bool RecvSendBinaryMsg(const nsCString& aMsg);
bool RecvDeleteSelf();
bool CancelEarly();
void ActorDestroy(ActorDestroyReason why);
nsCOMPtr<nsIAuthPromptProvider> mAuthProvider;
nsCOMPtr<nsIWebSocketProtocol> mChannel;
bool mIPCOpen;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_WebSocketChannelParent_h

View File

@@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef WebSocketLog_h
#define WebSocketLog_h
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG
#endif
#if defined(PR_LOG)
#error "This file must be #included before any IPDL-generated files or other files that #include prlog.h"
#endif
#include "base/basictypes.h"
#include "prlog.h"
#include "mozilla/net/NeckoChild.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* webSocketLog;
#endif
#undef LOG
#define LOG(args) PR_LOG(webSocketLog, PR_LOG_DEBUG, args)
#endif

View File

@@ -0,0 +1,40 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla Firefox.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation <http://www.mozilla.org/>.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Josh Matthews <josh@joshmatthews.net>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
IPDLSRCS = \
PWebSocket.ipdl \
$(NULL)

View File

@@ -37,6 +37,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "WebSocketLog.h"
#include "nsWebSocketHandler.h"
#include "nsISocketTransportService.h"
@@ -69,7 +70,6 @@
#include "prmem.h"
#include "prnetdb.h"
#include "prbit.h"
#include "prlog.h"
#include "zlib.h"
extern PRThread *gSocketThread;
@@ -90,11 +90,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS11(nsWebSocketHandler,
nsIInterfaceRequestor,
nsIChannelEventSink)
#if defined(PR_LOGGING)
static PRLogModuleInfo *webSocketLog = nsnull;
#endif
#define LOG(args) PR_LOG(webSocketLog, PR_LOG_DEBUG, args)
// Use this fake ptr so the Fin message stays in sequence in the
// main transmit queue
#define kFinMessage (reinterpret_cast<nsCString *>(0x01))
@@ -490,7 +485,6 @@ static nsWSAdmissionManager *sWebSocketAdmissions = nsnull;
// nsWebSocketHandler
nsWebSocketHandler::nsWebSocketHandler() :
mEncrypted(PR_FALSE),
mCloseTimeout(20000),
mOpenTimeout(20000),
mPingTimeout(0),
@@ -522,10 +516,6 @@ nsWebSocketHandler::nsWebSocketHandler() :
mDynamicOutput(nsnull)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
#if defined(PR_LOGGING)
if (!webSocketLog)
webSocketLog = PR_NewLogModule("nsWebSocket");
#endif
LOG(("WebSocketHandler::nsWebSocketHandler() %p\n", this));
@@ -1894,50 +1884,6 @@ nsWebSocketHandler::Notify(nsITimer *timer)
return NS_OK;
}
// nsIWebSocketProtocol
NS_IMETHODIMP
nsWebSocketHandler::GetOriginalURI(nsIURI **aOriginalURI)
{
LOG(("WebSocketHandler::GetOriginalURI() %p\n", this));
if (!mOriginalURI)
return NS_ERROR_NOT_INITIALIZED;
NS_ADDREF(*aOriginalURI = mOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetURI(nsIURI **aURI)
{
LOG(("WebSocketHandler::GetURI() %p\n", this));
if (!mOriginalURI)
return NS_ERROR_NOT_INITIALIZED;
if (mURI)
NS_ADDREF(*aURI = mURI);
else
NS_ADDREF(*aURI = mOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::
GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks)
{
LOG(("WebSocketHandler::GetNotificationCallbacks() %p\n", this));
NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::
SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks)
{
LOG(("WebSocketHandler::SetNotificationCallbacks() %p\n", this));
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetSecurityInfo(nsISupports **aSecurityInfo)
@@ -1952,37 +1898,6 @@ nsWebSocketHandler::GetSecurityInfo(nsISupports **aSecurityInfo)
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetLoadGroup(nsILoadGroup **aLoadGroup)
{
LOG(("WebSocketHandler::GetLoadGroup() %p\n", this));
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
LOG(("WebSocketHandler::SetLoadGroup() %p\n", this));
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetProtocol(nsACString &aProtocol)
{
LOG(("WebSocketHandler::GetProtocol() %p\n", this));
aProtocol = mProtocol;
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::SetProtocol(const nsACString &aProtocol)
{
LOG(("WebSocketHandler::SetProtocol() %p\n", this));
mProtocol = aProtocol; /* the sub protocol */
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::AsyncOpen(nsIURI *aURI,
@@ -2664,79 +2579,5 @@ nsWebSocketHandler::OnDataAvailable(nsIRequest *aRequest,
return NS_OK;
}
// nsIProtocolHandler
NS_IMETHODIMP
nsWebSocketHandler::GetScheme(nsACString &aScheme)
{
LOG(("WebSocketHandler::GetScheme() %p\n", this));
if (mEncrypted)
aScheme.AssignLiteral("wss");
else
aScheme.AssignLiteral("ws");
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetDefaultPort(PRInt32 *aDefaultPort)
{
LOG(("WebSocketHandler::GetDefaultPort() %p\n", this));
if (mEncrypted)
*aDefaultPort = kDefaultWSSPort;
else
*aDefaultPort = kDefaultWSPort;
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
{
LOG(("WebSocketHandler::GetProtocolFlags() %p\n", this));
*aProtocolFlags = URI_NORELATIVE | URI_NON_PERSISTABLE | ALLOWS_PROXY |
ALLOWS_PROXY_HTTP | URI_DOES_NOT_RETURN_DATA | URI_DANGEROUS_TO_LOAD;
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::NewURI(const nsACString & aSpec, const char *aOriginCharset,
nsIURI *aBaseURI, nsIURI **_retval NS_OUTPARAM)
{
LOG(("WebSocketHandler::NewURI() %p\n", this));
PRInt32 port;
nsresult rv = GetDefaultPort(&port);
if (NS_FAILED(rv))
return rv;
nsRefPtr<nsStandardURL> url = new nsStandardURL();
rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY, port, aSpec,
aOriginCharset, aBaseURI);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*_retval = url);
return NS_OK;
}
NS_IMETHODIMP
nsWebSocketHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval NS_OUTPARAM)
{
LOG(("WebSocketHandler::NewChannel() %p\n", this));
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsWebSocketHandler::AllowPort(PRInt32 port, const char *scheme,
PRBool *_retval NS_OUTPARAM)
{
LOG(("WebSocketHandler::AllowPort() %p\n", this));
// do not override any blacklisted ports
*_retval = PR_FALSE;
return NS_OK;
}
} // namespace mozilla::net
} // namespace mozilla

View File

@@ -37,6 +37,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_nsWebSocketHandler_h
#define mozilla_net_nsWebSocketHandler_h
#include "nsIWebSocketProtocol.h"
#include "nsIURI.h"
@@ -57,6 +59,7 @@
#include "nsIStringStream.h"
#include "nsIHttpChannelInternal.h"
#include "nsIRandomGenerator.h"
#include "BaseWebSocketChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
@@ -68,10 +71,9 @@ class nsPostMessage;
class nsWSAdmissionManager;
class nsWSCompression;
class nsWebSocketHandler : public nsIWebSocketProtocol,
class nsWebSocketHandler : public BaseWebSocketChannel,
public nsIHttpUpgradeListener,
public nsIStreamListener,
public nsIProtocolHandler,
public nsIInputStreamCallback,
public nsIOutputStreamCallback,
public nsITimerCallback,
@@ -81,11 +83,9 @@ class nsWebSocketHandler : public nsIWebSocketProtocol,
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBSOCKETPROTOCOL
NS_DECL_NSIHTTPUPGRADELISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIOUTPUTSTREAMCALLBACK
NS_DECL_NSITIMERCALLBACK
@@ -93,6 +93,17 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
// nsIWebSocketProtocol methods BaseWebSocketChannel didn't implement for us
//
NS_IMETHOD AsyncOpen(nsIURI *aURI,
const nsACString &aOrigin,
nsIWebSocketListener *aListener,
nsISupports *aContext);
NS_IMETHOD Close();
NS_IMETHOD SendMsg(const nsACString &aMsg);
NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
nsWebSocketHandler();
static void Shutdown();
@@ -109,8 +120,6 @@ public:
};
const static PRUint32 kControlFrameMask = 0x8;
const static PRInt32 kDefaultWSPort = 80;
const static PRInt32 kDefaultWSSPort = 443;
const static PRUint8 kMaskBit = 0x80;
const static PRUint8 kFinalFragBit = 0x80;
@@ -125,8 +134,7 @@ public:
protected:
virtual ~nsWebSocketHandler();
PRBool mEncrypted;
private:
friend class nsPostMessage;
friend class nsWSAdmissionManager;
@@ -196,11 +204,6 @@ private:
PRInt32 mBinaryLen;
};
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIWebSocketListener> mListener;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIEventTarget> mSocketThread;
nsCOMPtr<nsIHttpChannelInternal> mChannel;
nsCOMPtr<nsIHttpChannel> mHttpChannel;
@@ -209,8 +212,6 @@ private:
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIRandomGenerator> mRandomGenerator;
nsCString mProtocol;
nsCString mOrigin;
nsCString mHashedSecret;
nsCString mAddress;
@@ -280,9 +281,11 @@ private:
class nsWebSocketSSLHandler : public nsWebSocketHandler
{
public:
nsWebSocketSSLHandler() {nsWebSocketHandler::mEncrypted = PR_TRUE;}
nsWebSocketSSLHandler() { BaseWebSocketChannel::mEncrypted = PR_TRUE; }
protected:
virtual ~nsWebSocketSSLHandler() {}
};
}} // namespace mozilla::net
#endif // mozilla_net_nsWebSocketHandler_h