diff --git a/docshell/shistory/SHistoryParent.h b/docshell/shistory/SHistoryParent.h index 56cc95016e12..230b38c68d0f 100644 --- a/docshell/shistory/SHistoryParent.h +++ b/docshell/shistory/SHistoryParent.h @@ -15,6 +15,7 @@ namespace mozilla { namespace dom { +class PSHEntryOrSharedID; class SHistoryParent; class SHEntryParent; diff --git a/netwerk/base/ThrottleQueue.cpp b/netwerk/base/ThrottleQueue.cpp index 88d4f017a2f2..62007a0c2f97 100644 --- a/netwerk/base/ThrottleQueue.cpp +++ b/netwerk/base/ThrottleQueue.cpp @@ -5,8 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ThrottleQueue.h" +#include "mozilla/net/InputChannelThrottleQueueParent.h" #include "nsISeekableStream.h" #include "nsIAsyncInputStream.h" +#include "nsIOService.h" #include "nsStreamUtils.h" #include "nsNetUtil.h" @@ -214,6 +216,20 @@ void ThrottleInputStream::AllowInput() { //----------------------------------------------------------------------------- +// static +already_AddRefed ThrottleQueue::Create() { + MOZ_ASSERT(XRE_IsParentProcess()); + + nsCOMPtr tq; + if (gIOService->UseSocketProcess()) { + tq = new InputChannelThrottleQueueParent(); + } else { + tq = new ThrottleQueue(); + } + + return tq.forget(); +} + NS_IMPL_ISUPPORTS(ThrottleQueue, nsIInputChannelThrottleQueue, nsITimerCallback, nsINamed) @@ -364,5 +380,21 @@ void ThrottleQueue::DequeueStream(ThrottleInputStream* aStream) { mAsyncEvents.RemoveElement(aStream); } +NS_IMETHODIMP +ThrottleQueue::GetMeanBytesPerSecond(uint32_t* aMeanBytesPerSecond) { + NS_ENSURE_ARG(aMeanBytesPerSecond); + + *aMeanBytesPerSecond = mMeanBytesPerSecond; + return NS_OK; +} + +NS_IMETHODIMP +ThrottleQueue::GetMaxBytesPerSecond(uint32_t* aMaxBytesPerSecond) { + NS_ENSURE_ARG(aMaxBytesPerSecond); + + *aMaxBytesPerSecond = mMaxBytesPerSecond; + return NS_OK; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/base/ThrottleQueue.h b/netwerk/base/ThrottleQueue.h index ef2bcc56474f..49885e888739 100644 --- a/netwerk/base/ThrottleQueue.h +++ b/netwerk/base/ThrottleQueue.h @@ -26,11 +26,11 @@ class ThrottleInputStream; * may be a bit choppy. */ -class ThrottleQueue final : public nsIInputChannelThrottleQueue, - public nsITimerCallback, - public nsINamed { +class ThrottleQueue : public nsIInputChannelThrottleQueue, + public nsITimerCallback, + public nsINamed { public: - ThrottleQueue(); + static already_AddRefed Create(); NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTCHANNELTHROTTLEQUEUE @@ -40,8 +40,9 @@ class ThrottleQueue final : public nsIInputChannelThrottleQueue, void QueueStream(ThrottleInputStream* aStream); void DequeueStream(ThrottleInputStream* aStream); - private: - ~ThrottleQueue(); + protected: + ThrottleQueue(); + virtual ~ThrottleQueue(); struct ThrottleEntry { TimeStamp mTime; diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index 4d553ffdbbbe..686499d91e26 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -179,6 +179,7 @@ EXPORTS.mozilla.net += [ 'SimpleChannelParent.h', 'SSLTokensCache.h', 'TCPFastOpen.h', + 'ThrottleQueue.h', ] UNIFIED_SOURCES += [ diff --git a/netwerk/base/nsIThrottledInputChannel.idl b/netwerk/base/nsIThrottledInputChannel.idl index 76b8cc2a5b50..ae8d7321db2b 100644 --- a/netwerk/base/nsIThrottledInputChannel.idl +++ b/netwerk/base/nsIThrottledInputChannel.idl @@ -27,6 +27,13 @@ interface nsIInputChannelThrottleQueue : nsISupports */ void init(in unsigned long aMeanBytesPerSecond, in unsigned long aMaxBytesPerSecond); + /** + * Internal use only. Get the values set by init method. + */ + [noscript] readonly attribute unsigned long meanBytesPerSecond; + [noscript] readonly attribute unsigned long maxBytesPerSecond; + + /** * Return the number of bytes that are available to the caller in * this time slice. diff --git a/netwerk/build/components.conf b/netwerk/build/components.conf index fae7bc5ac2e2..741b60023c19 100644 --- a/netwerk/build/components.conf +++ b/netwerk/build/components.conf @@ -415,7 +415,8 @@ Classes = [ { 'cid': '{4c39159c-cd90-4dd3-97a7-06af5e6d84c4}', 'contract_ids': ['@mozilla.org/network/throttlequeue;1'], - 'type': 'mozilla::net::ThrottleQueue', + 'type': 'nsIInputChannelThrottleQueue', + 'constructor': 'mozilla::net::ThrottleQueue::Create', 'headers': ['/netwerk/base/ThrottleQueue.h'], }, { diff --git a/netwerk/ipc/InputChannelThrottleQueueChild.cpp b/netwerk/ipc/InputChannelThrottleQueueChild.cpp new file mode 100644 index 000000000000..ef7a916b79f4 --- /dev/null +++ b/netwerk/ipc/InputChannelThrottleQueueChild.cpp @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 et cin: */ +/* 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/. */ + +#include "InputChannelThrottleQueueChild.h" +#include "nsThreadUtils.h" + +namespace mozilla { +namespace net { + +NS_IMPL_ISUPPORTS_INHERITED0(InputChannelThrottleQueueChild, ThrottleQueue) + +NS_IMETHODIMP +InputChannelThrottleQueueChild::RecordRead(uint32_t aBytesRead) { + ThrottleQueue::RecordRead(aBytesRead); + + RefPtr self = this; + NS_DispatchToMainThread(NS_NewRunnableFunction( + "InputChannelThrottleQueueChild::RecordRead", [self, aBytesRead]() { + if (self->CanSend()) { + Unused << self->SendRecordRead(aBytesRead); + } + })); + return NS_OK; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/InputChannelThrottleQueueChild.h b/netwerk/ipc/InputChannelThrottleQueueChild.h new file mode 100644 index 000000000000..a758dac417f4 --- /dev/null +++ b/netwerk/ipc/InputChannelThrottleQueueChild.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 InputChannelThrottleQueueChild_h__ +#define InputChannelThrottleQueueChild_h__ + +#include "mozilla/net/PInputChannelThrottleQueueChild.h" +#include "mozilla/net/ThrottleQueue.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace net { + +class InputChannelThrottleQueueChild final + : public PInputChannelThrottleQueueChild, + public ThrottleQueue { + public: + friend class PInputChannelThrottleQueueChild; + NS_DECL_ISUPPORTS_INHERITED + + explicit InputChannelThrottleQueueChild() = default; + NS_IMETHOD RecordRead(uint32_t aBytesRead) override; + + private: + virtual ~InputChannelThrottleQueueChild() = default; +}; + +} // namespace net +} // namespace mozilla + +#endif // InputChannelThrottleQueueChild_h__ diff --git a/netwerk/ipc/InputChannelThrottleQueueParent.cpp b/netwerk/ipc/InputChannelThrottleQueueParent.cpp new file mode 100644 index 000000000000..30a406facb18 --- /dev/null +++ b/netwerk/ipc/InputChannelThrottleQueueParent.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 et cin: */ +/* 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/. */ + +#include "InputChannelThrottleQueueParent.h" +#include "mozilla/net/SocketProcessParent.h" +#include "nsIOService.h" + +namespace mozilla { +namespace net { + +NS_IMPL_ADDREF(InputChannelThrottleQueueParent) +NS_INTERFACE_MAP_BEGIN(InputChannelThrottleQueueParent) + NS_INTERFACE_MAP_ENTRY(nsIInputChannelThrottleQueue) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY_CONCRETE(InputChannelThrottleQueueParent) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP_(MozExternalRefCountType) +InputChannelThrottleQueueParent::Release(void) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); + + if (!mRefCnt.isThreadSafe) { + NS_ASSERT_OWNINGTHREAD(InputChannelThrottleQueueParent); + } + + nsrefcnt count = --mRefCnt; + NS_LOG_RELEASE(this, count, "InputChannelThrottleQueueParent"); + + if (count == 0) { + if (!mRefCnt.isThreadSafe) { + NS_ASSERT_OWNINGTHREAD(InputChannelThrottleQueueParent); + } + + mRefCnt = 1; /* stabilize */ + delete (this); + return 0; + } + + // When ref count goes down to 1 (held internally by IPDL), it means that + // we are done with this ThrottleQueue. We should send a delete message + // to delete the InputChannelThrottleQueueChild in socket process. + if (count == 1 && CanSend()) { + mozilla::Unused << Send__delete__(this); + return 1; + } + return count; +} + +InputChannelThrottleQueueParent::InputChannelThrottleQueueParent() + : mBytesProcessed(0), mMeanBytesPerSecond(0), mMaxBytesPerSecond(0) {} + +mozilla::ipc::IPCResult InputChannelThrottleQueueParent::RecvRecordRead( + const uint32_t& aBytesRead) { + mBytesProcessed += aBytesRead; + return IPC_OK(); +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::RecordRead(uint32_t aBytesRead) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::Available(uint32_t aRemaining, + uint32_t* aAvailable) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::Init(uint32_t aMeanBytesPerSecond, + uint32_t aMaxBytesPerSecond) { + // Can be called on any thread. + if (aMeanBytesPerSecond == 0 || aMaxBytesPerSecond == 0 || + aMaxBytesPerSecond < aMeanBytesPerSecond) { + return NS_ERROR_ILLEGAL_VALUE; + } + + mMeanBytesPerSecond = aMeanBytesPerSecond; + mMaxBytesPerSecond = aMaxBytesPerSecond; + + RefPtr self = this; + gIOService->CallOrWaitForSocketProcess( + [self, meanBytesPerSecond(mMeanBytesPerSecond), + maxBytesPerSecond(mMaxBytesPerSecond)] { + Unused << SocketProcessParent::GetSingleton() + ->SendPInputChannelThrottleQueueConstructor( + self, meanBytesPerSecond, maxBytesPerSecond); + }); + + return NS_OK; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::BytesProcessed(uint64_t* aResult) { + *aResult = mBytesProcessed; + return NS_OK; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::WrapStream(nsIInputStream* aInputStream, + nsIAsyncInputStream** aResult) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::GetMeanBytesPerSecond( + uint32_t* aMeanBytesPerSecond) { + NS_ENSURE_ARG(aMeanBytesPerSecond); + + *aMeanBytesPerSecond = mMeanBytesPerSecond; + return NS_OK; +} + +NS_IMETHODIMP +InputChannelThrottleQueueParent::GetMaxBytesPerSecond( + uint32_t* aMaxBytesPerSecond) { + NS_ENSURE_ARG(aMaxBytesPerSecond); + + *aMaxBytesPerSecond = mMaxBytesPerSecond; + return NS_OK; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/InputChannelThrottleQueueParent.h b/netwerk/ipc/InputChannelThrottleQueueParent.h new file mode 100644 index 000000000000..a81424fd3031 --- /dev/null +++ b/netwerk/ipc/InputChannelThrottleQueueParent.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 InputChannelThrottleQueueParent_h__ +#define InputChannelThrottleQueueParent_h__ + +#include "nsISupportsImpl.h" +#include "nsIThrottledInputChannel.h" +#include "mozilla/net/PInputChannelThrottleQueueParent.h" + +namespace mozilla { +namespace net { + +#define INPUT_CHANNEL_THROTTLE_QUEUE_PARENT_IID \ + { \ + 0x4f151655, 0x70b3, 0x4350, { \ + 0x9b, 0xd9, 0xe3, 0x2b, 0xe5, 0xeb, 0xb2, 0x9e \ + } \ + } + +class InputChannelThrottleQueueParent final + : public PInputChannelThrottleQueueParent, + public nsIInputChannelThrottleQueue { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIINPUTCHANNELTHROTTLEQUEUE + NS_DECLARE_STATIC_IID_ACCESSOR(INPUT_CHANNEL_THROTTLE_QUEUE_PARENT_IID) + + friend class PInputChannelThrottleQueueParent; + + explicit InputChannelThrottleQueueParent(); + mozilla::ipc::IPCResult RecvRecordRead(const uint32_t& aBytesRead); + void ActorDestroy(ActorDestroyReason aWhy) override {} + + private: + virtual ~InputChannelThrottleQueueParent() = default; + + uint64_t mBytesProcessed; + uint32_t mMeanBytesPerSecond; + uint32_t mMaxBytesPerSecond; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(InputChannelThrottleQueueParent, + INPUT_CHANNEL_THROTTLE_QUEUE_PARENT_IID) + +} // namespace net +} // namespace mozilla + +#endif // InputChannelThrottleQueueParent_h__ diff --git a/netwerk/ipc/PInputChannelThrottleQueue.ipdl b/netwerk/ipc/PInputChannelThrottleQueue.ipdl new file mode 100644 index 000000000000..5668fed06a04 --- /dev/null +++ b/netwerk/ipc/PInputChannelThrottleQueue.ipdl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* 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/. */ + +include protocol PSocketProcess; + +namespace mozilla { +namespace net { + +refcounted protocol PInputChannelThrottleQueue +{ + manager PSocketProcess; + +parent: + async RecordRead(uint32_t aBytesRead); + +child: + async __delete__(); +}; + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/PSocketProcess.ipdl b/netwerk/ipc/PSocketProcess.ipdl index 65135810506d..06f5151687c8 100644 --- a/netwerk/ipc/PSocketProcess.ipdl +++ b/netwerk/ipc/PSocketProcess.ipdl @@ -12,6 +12,7 @@ include protocol PHttpConnectionMgr; include protocol PFileDescriptorSet; include protocol PChildToParentStream; include protocol PParentToChildStream; +include protocol PInputChannelThrottleQueue; include MemoryReportTypes; include NeckoChannelParams; @@ -41,6 +42,7 @@ protocol PSocketProcess manages PHttpConnectionMgr; manages PChildToParentStream; manages PParentToChildStream; + manages PInputChannelThrottleQueue; parent: async InitCrashReporter(Shmem shmem, NativeThreadId threadId); @@ -77,11 +79,14 @@ child: async InitProfiler(Endpoint aEndpoint); // test-only async SocketProcessTelemetryPing(); + async PHttpTransaction(); async PParentToChildStream(); async PHttpConnectionMgr(); async OnHttpActivityDistributorActivated(bool aIsActivated); + async PInputChannelThrottleQueue(uint32_t meanBytesPerSecond, + uint32_t maxBytesPerSecond); both: async PFileDescriptorSet(FileDescriptor fd); diff --git a/netwerk/ipc/SocketProcessChild.cpp b/netwerk/ipc/SocketProcessChild.cpp index 811c55baa673..13b4442fb2f5 100644 --- a/netwerk/ipc/SocketProcessChild.cpp +++ b/netwerk/ipc/SocketProcessChild.cpp @@ -7,6 +7,7 @@ #include "SocketProcessLogging.h" #include "base/task.h" +#include "InputChannelThrottleQueueChild.h" #include "HttpTransactionChild.h" #include "HttpConnectionMgrChild.h" #include "mozilla/Assertions.h" @@ -311,6 +312,14 @@ SocketProcessChild::RecvOnHttpActivityDistributorActivated( } return IPC_OK(); } +already_AddRefed +SocketProcessChild::AllocPInputChannelThrottleQueueChild( + const uint32_t& aMeanBytesPerSecond, const uint32_t& aMaxBytesPerSecond) { + RefPtr p = + new InputChannelThrottleQueueChild(); + p->Init(aMeanBytesPerSecond, aMaxBytesPerSecond); + return p.forget(); +} } // namespace net } // namespace mozilla diff --git a/netwerk/ipc/SocketProcessChild.h b/netwerk/ipc/SocketProcessChild.h index bc933935add2..73c834bd9776 100644 --- a/netwerk/ipc/SocketProcessChild.h +++ b/netwerk/ipc/SocketProcessChild.h @@ -74,6 +74,10 @@ class SocketProcessChild final mozilla::ipc::IPCResult RecvOnHttpActivityDistributorActivated( const bool& aIsActivated); + already_AddRefed + AllocPInputChannelThrottleQueueChild(const uint32_t& aMeanBytesPerSecond, + const uint32_t& aMaxBytesPerSecond); + private: // Mapping of content process id and the SocketProcessBridgeParent. // This table keeps SocketProcessBridgeParent alive in socket process. diff --git a/netwerk/ipc/moz.build b/netwerk/ipc/moz.build index 81b5077d51fc..bb79cdda2086 100644 --- a/netwerk/ipc/moz.build +++ b/netwerk/ipc/moz.build @@ -11,6 +11,8 @@ EXPORTS.mozilla.net += [ 'DocumentChannelChild.h', 'DocumentChannelParent.h', 'DocumentLoadListener.h', + 'InputChannelThrottleQueueChild.h', + 'InputChannelThrottleQueueParent.h', 'NeckoChild.h', 'NeckoCommon.h', 'NeckoMessageUtils.h', @@ -30,6 +32,8 @@ UNIFIED_SOURCES += [ 'DocumentChannelChild.cpp', 'DocumentChannelParent.cpp', 'DocumentLoadListener.cpp', + 'InputChannelThrottleQueueChild.cpp', + 'InputChannelThrottleQueueParent.cpp', 'NeckoChild.cpp', 'NeckoCommon.cpp', 'NeckoParent.cpp', @@ -48,6 +52,7 @@ IPDL_SOURCES = [ 'PDataChannel.ipdl', 'PDocumentChannel.ipdl', 'PFileChannel.ipdl', + 'PInputChannelThrottleQueue.ipdl', 'PNecko.ipdl', 'PSimpleChannel.ipdl', 'PSocketProcess.ipdl', diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 7cf45c19d3b8..1f948e75377d 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -4201,7 +4201,9 @@ HttpBaseChannel::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue) { NS_IMETHODIMP HttpBaseChannel::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue) { - *aQueue = mThrottleQueue; + NS_ENSURE_ARG_POINTER(aQueue); + nsCOMPtr queue = mThrottleQueue; + queue.forget(aQueue); return NS_OK; } diff --git a/netwerk/protocol/http/HttpTransactionChild.cpp b/netwerk/protocol/http/HttpTransactionChild.cpp index 4c98dbd7e069..c074bd86d324 100644 --- a/netwerk/protocol/http/HttpTransactionChild.cpp +++ b/netwerk/protocol/http/HttpTransactionChild.cpp @@ -10,6 +10,7 @@ #include "HttpTransactionChild.h" #include "mozilla/ipc/IPCStreamUtils.h" +#include "mozilla/net/InputChannelThrottleQueueChild.h" #include "mozilla/net/SocketProcessChild.h" #include "nsInputStreamPump.h" #include "nsHttpHandler.h" @@ -20,7 +21,7 @@ namespace mozilla { namespace net { NS_IMPL_ISUPPORTS(HttpTransactionChild, nsIRequestObserver, nsIStreamListener, - nsITransportEventSink); + nsITransportEventSink, nsIThrottledInputChannel); //----------------------------------------------------------------------------- // HttpTransactionChild @@ -206,7 +207,8 @@ mozilla::ipc::IPCResult HttpTransactionChild::RecvInit( const uint32_t& aClassOfService, const uint32_t& aInitialRwin, const bool& aResponseTimeoutEnabled, const uint64_t& aChannelId, const bool& aHasTransactionObserver, - const Maybe& aPushedStreamArg) { + const Maybe& aPushedStreamArg, + const mozilla::Maybe& aThrottleQueue) { mRequestHead = aReqHeaders; if (aRequestBody) { mUploadStream = mozilla::ipc::DeserializeIPCStream(aRequestBody); @@ -228,6 +230,11 @@ mozilla::ipc::IPCResult HttpTransactionChild::RecvInit( }; } + if (aThrottleQueue.isSome()) { + mThrottleQueue = + static_cast(aThrottleQueue.ref()); + } + nsresult rv = InitInternal( aCaps, aArgs, &mRequestHead, mUploadStream, aReqContentLength, aReqBodyIncludesHeaders, aTopLevelOuterContentWindowId, @@ -466,5 +473,22 @@ HttpTransactionChild::OnTransportStatus(nsITransport* aTransport, return NS_OK; } +//----------------------------------------------------------------------------- +// HttpBaseChannel::nsIThrottledInputChannel +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +HttpTransactionChild::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +HttpTransactionChild::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue) { + nsCOMPtr queue = + static_cast(mThrottleQueue.get()); + queue.forget(aQueue); + return NS_OK; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/http/HttpTransactionChild.h b/netwerk/protocol/http/HttpTransactionChild.h index 7cdfa0f22da2..f44e20c09492 100644 --- a/netwerk/protocol/http/HttpTransactionChild.h +++ b/netwerk/protocol/http/HttpTransactionChild.h @@ -11,6 +11,7 @@ #include "nsHttpRequestHead.h" #include "nsIRequest.h" #include "nsIStreamListener.h" +#include "nsIThrottledInputChannel.h" #include "nsITransport.h" class nsInputStreamPump; @@ -18,6 +19,7 @@ class nsInputStreamPump; namespace mozilla { namespace net { +class InputChannelThrottleQueueChild; class nsHttpConnectionInfo; class nsHttpTransaction; class nsProxyInfo; @@ -28,12 +30,14 @@ class nsProxyInfo; //----------------------------------------------------------------------------- class HttpTransactionChild final : public PHttpTransactionChild, public nsIStreamListener, - public nsITransportEventSink { + public nsITransportEventSink, + public nsIThrottledInputChannel { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSITRANSPORTEVENTSINK + NS_DECL_NSITHROTTLEDINPUTCHANNEL explicit HttpTransactionChild(); @@ -47,7 +51,8 @@ class HttpTransactionChild final : public PHttpTransactionChild, const uint32_t& aClassOfService, const uint32_t& aInitialRwin, const bool& aResponseTimeoutEnabled, const uint64_t& aChannelId, const bool& aHasTransactionObserver, - const Maybe& aPushedStreamArg); + const Maybe& aPushedStreamArg, + const mozilla::Maybe& aThrottleQueue); mozilla::ipc::IPCResult RecvUpdateClassOfService( const uint32_t& classOfService); mozilla::ipc::IPCResult RecvCancelPump(const nsresult& aStatus); @@ -89,6 +94,7 @@ class HttpTransactionChild final : public PHttpTransactionChild, nsCOMPtr mTransactionPump; std::function mTransactionObserver; Maybe mTransactionObserverResult; + RefPtr mThrottleQueue; }; } // namespace net diff --git a/netwerk/protocol/http/HttpTransactionParent.cpp b/netwerk/protocol/http/HttpTransactionParent.cpp index 2757af041bbe..6161f2429192 100644 --- a/netwerk/protocol/http/HttpTransactionParent.cpp +++ b/netwerk/protocol/http/HttpTransactionParent.cpp @@ -9,6 +9,7 @@ #include "HttpTransactionParent.h" #include "mozilla/ipc/IPCStreamUtils.h" +#include "mozilla/net/InputChannelThrottleQueueParent.h" #include "mozilla/net/ChannelEventQueue.h" #include "mozilla/net/SocketProcessParent.h" #include "nsHttpHandler.h" @@ -190,6 +191,21 @@ nsresult HttpTransactionParent::Init( pushedStreamArg.ref().pushedStreamId() = aPushedStreamId; } + nsCOMPtr throttled = do_QueryInterface(mEventsink); + Maybe throttleQueue; + if (throttled) { + nsCOMPtr queue; + nsresult rv = throttled->GetThrottleQueue(getter_AddRefs(queue)); + // In case of failure, just carry on without throttling. + if (NS_SUCCEEDED(rv) && queue) { + LOG1(("HttpTransactionParent::Init %p using throttle queue %p\n", this, + queue.get())); + RefPtr tqParent = do_QueryObject(queue); + MOZ_ASSERT(tqParent); + throttleQueue.emplace(tqParent.get()); + } + } + // TODO: Figure out if we have to implement nsIThreadRetargetableRequest in // bug 1544378. if (!SendInit(caps, infoArgs, *requestHead, @@ -198,7 +214,7 @@ nsresult HttpTransactionParent::Init( topLevelOuterContentWindowId, static_cast(trafficCategory), requestContextID, classOfService, initialRwin, responseTimeoutEnabled, mChannelId, - !!mTransactionObserver, pushedStreamArg)) { + !!mTransactionObserver, pushedStreamArg, throttleQueue)) { return NS_ERROR_FAILURE; } diff --git a/netwerk/protocol/http/PHttpTransaction.ipdl b/netwerk/protocol/http/PHttpTransaction.ipdl index 51434ab47617..e8dc395ce8b5 100644 --- a/netwerk/protocol/http/PHttpTransaction.ipdl +++ b/netwerk/protocol/http/PHttpTransaction.ipdl @@ -7,6 +7,7 @@ include protocol PSocketProcess; include protocol PFileDescriptorSet; // FIXME: bug #792908 +include protocol PInputChannelThrottleQueue; include IPCStream; include NeckoChannelParams; @@ -72,7 +73,8 @@ child: bool responseTimeoutEnabled, uint64_t channelId, bool hasTransactionObserver, - H2PushedStreamArg? pushedStreamArg); + H2PushedStreamArg? pushedStreamArg, + PInputChannelThrottleQueue? throttleQueue); async UpdateClassOfService(uint32_t classOfService); async CancelPump(nsresult status); diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index e0e487df94cd..4204d6a19eb4 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -407,9 +407,9 @@ nsresult nsHttpTransaction::Init( } nsCOMPtr throttled = do_QueryInterface(mChannel); - nsIInputChannelThrottleQueue* queue; if (throttled) { - rv = throttled->GetThrottleQueue(&queue); + nsCOMPtr queue; + rv = throttled->GetThrottleQueue(getter_AddRefs(queue)); // In case of failure, just carry on without throttling. if (NS_SUCCEEDED(rv) && queue) { nsCOMPtr wrappedStream; @@ -421,7 +421,7 @@ nsresult nsHttpTransaction::Init( LOG( ("nsHttpTransaction::Init %p wrapping input stream using throttle " "queue %p\n", - this, queue)); + this, queue.get())); mRequestStream = wrappedStream; } }