зеркало из https://github.com/mozilla/gecko-dev.git
Bug 504553 - Patch 1 - WebSockets in Workers: Dispatch WebSocketChannel::StartWebsocketConnect to target thread, r=jduell
This commit is contained in:
Родитель
c0a0bd1fad
Коммит
dbb8893f00
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче