Bug 504553 - Patch 1 - WebSockets in Workers: Dispatch WebSocketChannel::StartWebsocketConnect to target thread, r=jduell

This commit is contained in:
Steve Workman 2014-04-17 11:53:58 -07:00
Родитель c0a0bd1fad
Коммит dbb8893f00
8 изменённых файлов: 118 добавлений и 42 удалений

Просмотреть файл

@ -6,6 +6,7 @@
#include "WebSocket.h"
#include "mozilla/dom/WebSocketBinding.h"
#include "mozilla/net/WebSocketChannel.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -41,7 +42,8 @@
#include "nsContentPolicyUtils.h"
#include "nsWrapperCacheInlines.h"
#include "nsIObserverService.h"
#include "nsIWebSocketChannel.h"
using namespace mozilla::net;
namespace mozilla {
namespace dom {
@ -1124,19 +1126,12 @@ nsresult
WebSocket::UpdateURI()
{
// Check for Redirections
nsCOMPtr<nsIURI> uri;
nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<BaseWebSocketChannel> channel;
channel = static_cast<BaseWebSocketChannel*>(mChannel.get());
MOZ_ASSERT(channel);
nsAutoCString spec;
rv = uri->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
CopyUTF8toUTF16(spec, mEffectiveURL);
bool isWSS = false;
rv = uri->SchemeIs("wss", &isWSS);
NS_ENSURE_SUCCESS(rv, rv);
mSecure = isWSS ? true : false;
channel->GetEffectiveURL(mEffectiveURL);
mSecure = channel->IsEncrypted();
return NS_OK;
}

Просмотреть файл

@ -53,6 +53,10 @@ class BaseWebSocketChannel : public nsIWebSocketChannel,
NS_IMETHOD GetPingTimeout(uint32_t *aSeconds);
NS_IMETHOD SetPingTimeout(uint32_t aSeconds);
// Off main thread URI access.
virtual void GetEffectiveURL(nsAString& aEffectiveURL) const = 0;
virtual bool IsEncrypted() const = 0;
protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURI;

Просмотреть файл

@ -41,7 +41,8 @@ parent:
child:
// Forwarded notifications corresponding to the nsIWebSocketListener interface
OnStart(nsCString aProtocol, nsCString aExtensions);
OnStart(nsCString aProtocol, nsCString aExtensions,
nsString aEffectiveURL, bool aEncrypted);
OnStop(nsresult aStatusCode);
OnMessageAvailable(nsCString aMsg);
OnBinaryMessageAvailable(nsCString aMsg);

Просмотреть файл

@ -208,8 +208,6 @@ public:
void Add(nsCString &address, int32_t port)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
if (mDelaysDisabled)
return;
@ -222,8 +220,6 @@ public:
FailDelay* Lookup(nsCString &address, int32_t port,
uint32_t *outIndex = nullptr)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
if (mDelaysDisabled)
return nullptr;
@ -293,8 +289,6 @@ public:
// battery life than using a periodic timer.
void Remove(nsCString &address, int32_t port)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
TimeStamp rightNow = TimeStamp::Now();
// iterate from end, to make deletion indexing easier
@ -343,7 +337,6 @@ public:
// delay/queue the connection (returns false)
static void ConditionallyConnect(WebSocketChannel *ws)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
NS_ABORT_IF_FALSE(ws->mConnecting == NOT_CONNECTING, "opening state");
StaticMutexAutoLock lock(sLock);
@ -368,7 +361,6 @@ public:
static void OnConnected(WebSocketChannel *aChannel)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
NS_ABORT_IF_FALSE(aChannel->mConnecting == CONNECTING_IN_PROGRESS,
"Channel completed connect, but not connecting?");
@ -395,8 +387,6 @@ public:
// w/o ever successfully creating a connection)
static void OnStopSession(WebSocketChannel *aChannel, nsresult aReason)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
StaticMutexAutoLock lock(sLock);
if (!sManager) {
return;
@ -573,7 +563,7 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_GetCurrentThread() == mChannel->mTargetThread);
MOZ_ASSERT(mChannel->IsOnTargetThread());
if (mLen < 0)
mChannel->mListener->OnMessageAvailable(mChannel->mContext, mData);
@ -607,7 +597,7 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_GetCurrentThread() == mChannel->mTargetThread);
MOZ_ASSERT(mChannel->IsOnTargetThread());
nsWSAdmissionManager::OnStopSession(mChannel, mReason);
@ -645,7 +635,7 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_GetCurrentThread() == mChannel->mTargetThread);
MOZ_ASSERT(mChannel->IsOnTargetThread());
mChannel->mListener->OnServerClose(mChannel->mContext, mCode, mReason);
return NS_OK;
@ -676,7 +666,7 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_GetCurrentThread() == mChannel->mTargetThread);
MOZ_ASSERT(mChannel->IsOnTargetThread());
LOG(("WebSocketChannel::CallAcknowledge: Size %u\n", mSize));
mChannel->mListener->OnAcknowledge(mChannel->mContext, mSize);
@ -1178,6 +1168,28 @@ WebSocketChannel::Shutdown()
nsWSAdmissionManager::Shutdown();
}
bool
WebSocketChannel::IsOnTargetThread()
{
MOZ_ASSERT(mTargetThread);
bool isOnTargetThread = false;
nsresult rv = mTargetThread->IsOnCurrentThread(&isOnTargetThread);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return NS_FAILED(rv) ? false : isOnTargetThread;
}
void
WebSocketChannel::GetEffectiveURL(nsAString& aEffectiveURL) const
{
aEffectiveURL = mEffectiveURL;
}
bool
WebSocketChannel::IsEncrypted() const
{
return mEncrypted;
}
void
WebSocketChannel::BeginOpen()
{
@ -2372,6 +2384,12 @@ WebSocketChannel::ApplyForAdmission()
nsresult
WebSocketChannel::StartWebsocketData()
{
if (!IsOnTargetThread()) {
return mTargetThread->Dispatch(
NS_NewRunnableMethod(this, &WebSocketChannel::StartWebsocketData),
NS_DISPATCH_NORMAL);
}
LOG(("WebSocketChannel::StartWebsocketData() %p", this));
NS_ABORT_IF_FALSE(!mDataStarted, "StartWebsocketData twice");
mDataStarted = 1;
@ -2384,8 +2402,9 @@ WebSocketChannel::StartWebsocketData()
LOG(("WebSocketChannel::StartWebsocketData Notifying Listener %p\n",
mListener.get()));
if (mListener)
if (mListener) {
mListener->OnStart(mContext);
}
// Start keepalive ping timer, if we're using keepalive.
if (mPingInterval) {
@ -2974,7 +2993,7 @@ nsresult
WebSocketChannel::SendMsgCommon(const nsACString *aMsg, bool aIsBinary,
uint32_t aLength, nsIInputStream *aStream)
{
NS_ABORT_IF_FALSE(NS_GetCurrentThread() == mTargetThread, "not target thread");
NS_ABORT_IF_FALSE(IsOnTargetThread(), "not target thread");
if (mRequestedClose) {
LOG(("WebSocketChannel:: Error: send when closed\n"));
@ -3190,6 +3209,13 @@ WebSocketChannel::OnStartRequest(nsIRequest *aRequest,
if (NS_FAILED(rv))
return rv;
// Update mEffectiveURL for off main thread URI access.
nsCOMPtr<nsIURI> uri = mURI ? mURI : mOriginalURI;
nsAutoCString spec;
rv = uri->GetSpec(spec);
MOZ_ASSERT(NS_SUCCEEDED(rv));
CopyUTF8toUTF16(spec, mEffectiveURL);
mGotUpgradeOK = 1;
if (mRecvdHttpUpgradeTransport)
return StartWebsocketData();

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsIProtocolProxyCallback.h"
#include "nsIChannelEventSink.h"
#include "nsIHttpChannelInternal.h"
#include "nsIStringStream.h"
#include "BaseWebSocketChannel.h"
#ifdef MOZ_WIDGET_GONK
@ -96,6 +97,11 @@ public:
WebSocketChannel();
static void Shutdown();
bool IsOnTargetThread();
// Off main thread URI access.
void GetEffectiveURL(nsAString& aEffectiveURL) const MOZ_OVERRIDE;
bool IsEncrypted() const MOZ_OVERRIDE;
enum {
// Non Control Frames
@ -185,6 +191,7 @@ private:
// Used for off main thread access to the URI string.
nsCString mHost;
nsString mEffectiveURL;
nsCOMPtr<nsISocketTransport> mTransport;
nsCOMPtr<nsIAsyncInputStream> mSocketIn;

Просмотреть файл

@ -49,13 +49,13 @@ NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
NS_INTERFACE_MAP_END
WebSocketChannelChild::WebSocketChannelChild(bool aSecure)
WebSocketChannelChild::WebSocketChannelChild(bool aEncrypted)
: mIPCOpen(false)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n", this));
BaseWebSocketChannel::mEncrypted = aSecure;
mEncrypted = aEncrypted;
mEventQ = new ChannelEventQueue(static_cast<nsIWebSocketChannel*>(this));
}
@ -80,6 +80,18 @@ WebSocketChannelChild::ReleaseIPDLReference()
Release();
}
void
WebSocketChannelChild::GetEffectiveURL(nsAString& aEffectiveURL) const
{
aEffectiveURL = mEffectiveURL;
}
bool
WebSocketChannelChild::IsEncrypted() const
{
return mEncrypted;
}
class WrappedChannelEvent : public nsRunnable
{
public:
@ -113,43 +125,57 @@ class StartEvent : public ChannelEvent
public:
StartEvent(WebSocketChannelChild* aChild,
const nsCString& aProtocol,
const nsCString& aExtensions)
const nsCString& aExtensions,
const nsString& aEffectiveURL,
bool aEncrypted)
: mChild(aChild)
, mProtocol(aProtocol)
, mExtensions(aExtensions)
, mEffectiveURL(aEffectiveURL)
, mEncrypted(aEncrypted)
{}
void Run()
{
mChild->OnStart(mProtocol, mExtensions);
mChild->OnStart(mProtocol, mExtensions, mEffectiveURL, mEncrypted);
}
private:
WebSocketChannelChild* mChild;
nsCString mProtocol;
nsCString mExtensions;
nsString mEffectiveURL;
bool mEncrypted;
};
bool
WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol,
const nsCString& aExtensions)
const nsCString& aExtensions,
const nsString& aEffectiveURL,
const bool& aEncrypted)
{
if (mEventQ->ShouldEnqueue()) {
mEventQ->Enqueue(new StartEvent(this, aProtocol, aExtensions));
mEventQ->Enqueue(new StartEvent(this, aProtocol, aExtensions,
aEffectiveURL, aEncrypted));
} else if (mTargetThread) {
DispatchToTargetThread(new StartEvent(this, aProtocol, aExtensions));
DispatchToTargetThread(new StartEvent(this, aProtocol, aExtensions,
aEffectiveURL, aEncrypted));
} else {
OnStart(aProtocol, aExtensions);
OnStart(aProtocol, aExtensions, aEffectiveURL, aEncrypted);
}
return true;
}
void
WebSocketChannelChild::OnStart(const nsCString& aProtocol,
const nsCString& aExtensions)
const nsCString& aExtensions,
const nsString& aEffectiveURL,
const bool& aEncrypted)
{
LOG(("WebSocketChannelChild::RecvOnStart() %p\n", this));
SetProtocol(aProtocol);
mNegotiatedExtensions = aExtensions;
mEffectiveURL = aEffectiveURL;
mEncrypted = aEncrypted;
if (mListener) {
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;

Просмотреть файл

@ -40,17 +40,23 @@ class WebSocketChannelChild : public BaseWebSocketChannel,
void AddIPDLReference();
void ReleaseIPDLReference();
// Off main thread URI access.
void GetEffectiveURL(nsAString& aEffectiveURL) const MOZ_OVERRIDE;
bool IsEncrypted() const MOZ_OVERRIDE;
private:
~WebSocketChannelChild();
bool RecvOnStart(const nsCString& aProtocol, const nsCString& aExtensions) MOZ_OVERRIDE;
bool RecvOnStart(const nsCString& aProtocol, const nsCString& aExtensions,
const nsString& aEffectiveURL, const bool& aSecure) MOZ_OVERRIDE;
bool RecvOnStop(const nsresult& aStatusCode) MOZ_OVERRIDE;
bool RecvOnMessageAvailable(const nsCString& aMsg) MOZ_OVERRIDE;
bool RecvOnBinaryMessageAvailable(const nsCString& aMsg) MOZ_OVERRIDE;
bool RecvOnAcknowledge(const uint32_t& aSize) MOZ_OVERRIDE;
bool RecvOnServerClose(const uint16_t& aCode, const nsCString &aReason) MOZ_OVERRIDE;
void OnStart(const nsCString& aProtocol, const nsCString& aExtensions);
void OnStart(const nsCString& aProtocol, const nsCString& aExtensions,
const nsString& aEffectiveURL, const bool& aSecure);
void OnStop(const nsresult& aStatusCode);
void OnMessageAvailable(const nsCString& aMsg);
void OnBinaryMessageAvailable(const nsCString& aMsg);
@ -62,6 +68,7 @@ class WebSocketChannelChild : public BaseWebSocketChannel,
bool IsOnTargetThread();
nsRefPtr<ChannelEventQueue> mEventQ;
nsString mEffectiveURL;
bool mIPCOpen;
friend class StartEvent;

Просмотреть файл

@ -12,6 +12,7 @@
#include "SerializedLoadContext.h"
#include "nsIOService.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/WebSocketChannel.h"
using namespace mozilla::ipc;
@ -189,11 +190,20 @@ WebSocketChannelParent::OnStart(nsISupports *aContext)
{
LOG(("WebSocketChannelParent::OnStart() %p\n", this));
nsAutoCString protocol, extensions;
nsString effectiveURL;
bool encrypted = false;
if (mChannel) {
mChannel->GetProtocol(protocol);
mChannel->GetExtensions(extensions);
nsRefPtr<WebSocketChannel> channel;
channel = static_cast<WebSocketChannel*>(mChannel.get());
MOZ_ASSERT(channel);
channel->GetEffectiveURL(effectiveURL);
encrypted = channel->IsEncrypted();
}
if (!mIPCOpen || !SendOnStart(protocol, extensions)) {
if (!mIPCOpen || !SendOnStart(protocol, extensions, effectiveURL, encrypted)) {
return NS_ERROR_FAILURE;
}
return NS_OK;