diff options
Diffstat (limited to 'netwerk/protocol/http/Http2Push.cpp')
-rw-r--r-- | netwerk/protocol/http/Http2Push.cpp | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/netwerk/protocol/http/Http2Push.cpp b/netwerk/protocol/http/Http2Push.cpp index b6fc485e2..34fc425d2 100644 --- a/netwerk/protocol/http/Http2Push.cpp +++ b/netwerk/protocol/http/Http2Push.cpp @@ -30,8 +30,8 @@ class CallChannelOnPush final : public Runnable { Http2PushedStream *pushStream) : mAssociatedChannel(associatedChannel) , mPushedURI(pushedURI) - , mPushedStream(pushStream) { + mPushedStreamWrapper = new Http2PushedStreamWrapper(pushStream); } NS_IMETHOD Run() override @@ -40,21 +40,94 @@ class CallChannelOnPush final : public Runnable { RefPtr<nsHttpChannel> channel; CallQueryInterface(mAssociatedChannel, channel.StartAssignment()); MOZ_ASSERT(channel); - if (channel && NS_SUCCEEDED(channel->OnPush(mPushedURI, mPushedStream))) { + if (channel && NS_SUCCEEDED(channel->OnPush(mPushedURI, mPushedStreamWrapper))) { return NS_OK; } LOG3(("Http2PushedStream Orphan %p failed OnPush\n", this)); - mPushedStream->OnPushFailed(); + mPushedStreamWrapper->OnPushFailed(); return NS_OK; } private: nsCOMPtr<nsIHttpChannelInternal> mAssociatedChannel; const nsCString mPushedURI; - Http2PushedStream *mPushedStream; + RefPtr<Http2PushedStreamWrapper> mPushedStreamWrapper; }; +// Because WeakPtr isn't thread-safe we must ensure that the object is destroyed +// on the socket thread, so any Release() called on a different thread is +// dispatched to the socket thread. +bool Http2PushedStreamWrapper::DispatchRelease() { + if (PR_GetCurrentThread() == gSocketThread) { + return false; + } + + gSocketTransportService->Dispatch( + NewNonOwningRunnableMethod(this, &Http2PushedStreamWrapper::Release), + NS_DISPATCH_NORMAL); + + return true; +} + +NS_IMPL_ADDREF(Http2PushedStreamWrapper) +NS_IMETHODIMP_(MozExternalRefCountType) +Http2PushedStreamWrapper::Release() { + nsrefcnt count = mRefCnt - 1; + if (DispatchRelease()) { + // Redispatched to the socket thread. + return count; + } + + MOZ_ASSERT(0 != mRefCnt, "dup release"); + count = --mRefCnt; + NS_LOG_RELEASE(this, count, "Http2PushedStreamWrapper"); + + if (0 == count) { + mRefCnt = 1; + delete (this); + return 0; + } + + return count; +} + +NS_INTERFACE_MAP_BEGIN(Http2PushedStreamWrapper) +NS_INTERFACE_MAP_END + +Http2PushedStreamWrapper::Http2PushedStreamWrapper( + Http2PushedStream* aPushStream) { + MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread"); + mStream = aPushStream; + mRequestString = aPushStream->GetRequestString(); +} + +Http2PushedStreamWrapper::~Http2PushedStreamWrapper() { + MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread"); +} + +Http2PushedStream* Http2PushedStreamWrapper::GetStream() { + MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "not on socket thread"); + if (mStream) { + Http2Stream* stream = mStream; + return static_cast<Http2PushedStream*>(stream); + } + return nullptr; +} + +void Http2PushedStreamWrapper::OnPushFailed() { + if (PR_GetCurrentThread() == gSocketThread) { + if (mStream) { + Http2Stream* stream = mStream; + static_cast<Http2PushedStream*>(stream)->OnPushFailed(); + } + } else { + gSocketTransportService->Dispatch( + NewRunnableMethod(this, &Http2PushedStreamWrapper::OnPushFailed), + NS_DISPATCH_NORMAL); + } +} + ////////////////////////////////////////// // Http2PushedStream ////////////////////////////////////////// |