author | Narcis Beleuzu <nbeleuzu@mozilla.com> |
Wed, 13 Nov 2019 09:24:22 +0200 | |
changeset 501704 | 2f19e7b646e0a52fa855b75c868f0a3f3a990ad3 |
parent 501703 | c9769928194867af402830fae75ce4290289f9c1 |
child 501705 | 10992479f249f70907e688b5c5622deb042d9ba7 |
push id | 36797 |
push user | opoprus@mozilla.com |
push date | Wed, 13 Nov 2019 09:55:25 +0000 |
treeherder | mozilla-central@2f19e7b646e0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1588241 |
milestone | 72.0a1 |
backs out | 6a4727c44078f7eca99f39b72a6f8eab2752c3f0 125430c4316a188db6ce5b50da3ffdd99c4fc5aa 449606f22baf89dbd2ddd4fc537219c13907bd11 c9a6203582acc7285034ab684d1f844e2ddda108 48362412c9d583393fc81a551543499b4bf31039 a21cd1c41c6cbea911d0039764bdab6bc523cbf5 8d2cf0fc6b9bd03e2a34b6cefc0bd3be36bd06c0 17e7f137067f89c0d82cada3af77b1bc5161c547 |
first release with | nightly linux32
2f19e7b646e0
/
72.0a1
/
20191113095525
/
files
nightly linux64
2f19e7b646e0
/
72.0a1
/
20191113095525
/
files
nightly mac
2f19e7b646e0
/
72.0a1
/
20191113095525
/
files
nightly win32
2f19e7b646e0
/
72.0a1
/
20191113095525
/
files
nightly win64
2f19e7b646e0
/
72.0a1
/
20191113095525
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
72.0a1
/
20191113095525
/
pushlog to previous
nightly linux64
72.0a1
/
20191113095525
/
pushlog to previous
nightly mac
72.0a1
/
20191113095525
/
pushlog to previous
nightly win32
72.0a1
/
20191113095525
/
pushlog to previous
nightly win64
72.0a1
/
20191113095525
/
pushlog to previous
|
--- a/browser/base/content/test/trackingUI/browser.ini +++ b/browser/base/content/test/trackingUI/browser.ini @@ -8,53 +8,52 @@ support-files = cookieSetterPage.html cookieServer.sjs embeddedPage.html trackingAPI.js trackingPage.html [browser_trackingUI_3.js] [browser_trackingUI_animation.js] -skip-if = fission # See bug 1580752. +skip-if = fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_animation_2.js] -skip-if = fission # See bug 1580752. +skip-if = fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_appMenu.js] [browser_trackingUI_background_tabs.js] -skip-if = fission # See bug 1580752. +skip-if = fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_categories.js] [browser_trackingUI_cookies_subview.js] -skip-if = fission # See bug 1580752. [browser_trackingUI_cryptominers.js] skip-if = fission && debug || # Causing crashes [@ mozilla::net::HttpChannelChild::DoOnStartRequest(nsIRequest*, nsISupports*)] - fission # See bug 1580752. + fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_fetch.js] support-files = file_trackingUI_fetch.html file_trackingUI_fetch.js file_trackingUI_fetch.js^headers^ [browser_trackingUI_fingerprinters.js] -skip-if = fission # See bug 1580752. +skip-if = fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_open_preferences.js] -skip-if = fission # See bug 1580752. +skip-if = fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_pbmode_exceptions.js] skip-if = fission # Crashes: @ mozilla::dom::BrowserBridgeParent::RecvShow(mozilla::gfx::IntSizeTyped<mozilla::ScreenPixel> const&, bool const&, nsSizeMode const&) [browser_trackingUI_report_breakage.js] skip-if = fission || debug || asan # Bug 1546797 [browser_trackingUI_socialtracking.js] skip-if = fission && debug || # Crashes: @ mozilla::net::HttpChannelChild::DoOnStartRequest(nsIRequest*, nsISupports*) - fission # See bug 1580752. + fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_shield_visibility.js] [browser_trackingUI_state.js] skip-if = serviceworker_e10s || fission # see https://bugzilla.mozilla.org/show_bug.cgi?id=1511303#c1 #Bug 1574939 [browser_trackingUI_state_reset.js] skip-if = fission && debug || #Bug 1574939 - fission # See bug 1580752. + fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_telemetry.js] skip-if = fission && debug || #Bug 1574939 - fission # See bug 1580752. + fission # Times out under Fission with DocumentChannel enabled. [browser_trackingUI_trackers_subview.js] skip-if = fission && debug || #Bug 1574939 - fission # See bug 1580752. + fission # Times out under Fission with DocumentChannel enabled.
--- a/netwerk/ipc/ChannelEventQueue.cpp +++ b/netwerk/ipc/ChannelEventQueue.cpp @@ -70,17 +70,17 @@ void ChannelEventQueue::FlushQueue() { MOZ_DIAGNOSTIC_ASSERT(false); isCurrentThread = true; } if (!isCurrentThread) { // Next event needs to run on another thread. Put it back to // the front of the queue can try resume on that thread. Suspend(); - PrependEvent(std::move(event)); + PrependEvent(event); needResumeOnOtherThread = true; { MutexAutoLock lock(mMutex); MOZ_ASSERT(mFlushing); mFlushing = false; MOZ_ASSERT(!mEventQueue.IsEmpty()); }
--- a/netwerk/ipc/ChannelEventQueue.h +++ b/netwerk/ipc/ChannelEventQueue.h @@ -65,46 +65,16 @@ class NeckoTargetChannelEvent : public C return mChild->GetNeckoTarget(); } protected: T* mChild; }; -class ChannelFunctionEvent : public ChannelEvent { - public: - ChannelFunctionEvent( - std::function<already_AddRefed<nsIEventTarget>()>&& aGetEventTarget, - std::function<void()>&& aCallback) - : mGetEventTarget(std::move(aGetEventTarget)), - mCallback(std::move(aCallback)) {} - - void Run() override { mCallback(); } - already_AddRefed<nsIEventTarget> GetEventTarget() override { - return mGetEventTarget(); - } - - private: - const std::function<already_AddRefed<nsIEventTarget>()> mGetEventTarget; - const std::function<void()> mCallback; -}; - -class NeckoTargetChannelFunctionEvent : public ChannelFunctionEvent { - public: - template <typename T> - NeckoTargetChannelFunctionEvent(T* aChild, std::function<void()>&& aCallback) - : ChannelFunctionEvent( - [child = RefPtr<T>(aChild)]() { - MOZ_ASSERT(child); - return child->GetNeckoTarget(); - }, - std::move(aCallback)) {} -}; - // Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a // queue if still dispatching previous one(s) to listeners/observers. // Otherwise synchronous XMLHttpRequests and/or other code that spins the // event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for // instance) to be dispatched and called before mListener->OnStartRequest has // completed. class ChannelEventQueue final { @@ -127,17 +97,17 @@ class ChannelEventQueue final { // // @param aCallback - the ChannelEvent // @param aAssertionWhenNotQueued - this optional param will be used in an // assertion when the event is executed directly. inline void RunOrEnqueue(ChannelEvent* aCallback, bool aAssertionWhenNotQueued = false); // Append ChannelEvent in front of the event queue. - inline nsresult PrependEvent(UniquePtr<ChannelEvent>&& aEvent); + inline nsresult PrependEvent(UniquePtr<ChannelEvent>& aEvent); inline nsresult PrependEvents(nsTArray<UniquePtr<ChannelEvent>>& aEvents); // After StartForcedQueueing is called, RunOrEnqueue() will start enqueuing // events that will be run/flushed when EndForcedQueueing is called. // - Note: queueing may still be required after EndForcedQueueing() (if the // queue is suspended, etc): always call RunOrEnqueue() to avoid race // conditions. inline void StartForcedQueueing(); @@ -256,17 +226,17 @@ inline void ChannelEventQueue::EndForced } if (tryFlush) { MaybeFlushQueue(); } } inline nsresult ChannelEventQueue::PrependEvent( - UniquePtr<ChannelEvent>&& aEvent) { + UniquePtr<ChannelEvent>& aEvent) { MutexAutoLock lock(mMutex); // Prepending event while no queue flush foreseen might cause the following // channel events not run. This assertion here guarantee there must be a // queue flush, either triggered by Resume or EndForcedQueueing, to execute // the added event. MOZ_ASSERT(mSuspended || !!mForcedCount);
--- a/netwerk/ipc/DocumentChannelChild.cpp +++ b/netwerk/ipc/DocumentChannelChild.cpp @@ -38,16 +38,17 @@ NS_INTERFACE_MAP_BEGIN(DocumentChannelCh // internally, but doesn't implement the interface. Everything // before AsyncOpen should be duplicated in the parent process // on the real http channel, but anything trying to QI to nsIHttpChannel // after that will be failing and get confused. NS_WARNING( "Trying to request nsIHttpChannel from DocumentChannelChild, this is " "likely broken"); } + NS_INTERFACE_MAP_ENTRY(nsIClassifiedChannel) NS_INTERFACE_MAP_ENTRY(nsITraceableChannel) NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentChannelChild) NS_INTERFACE_MAP_END_INHERITING(nsBaseChannel) NS_IMPL_ADDREF_INHERITED(DocumentChannelChild, nsBaseChannel) NS_IMPL_RELEASE_INHERITED(DocumentChannelChild, nsBaseChannel) DocumentChannelChild::DocumentChannelChild( @@ -185,24 +186,41 @@ DocumentChannelChild::AsyncOpen(nsIStrea mIsPending = true; mWasOpened = true; mListener = listener; return NS_OK; } +class DocumentFailedAsyncOpenEvent + : public NeckoTargetChannelEvent<DocumentChannelChild> { + public: + DocumentFailedAsyncOpenEvent(DocumentChannelChild* aChild, + nsresult aStatusCode) + : NeckoTargetChannelEvent<DocumentChannelChild>(aChild), + mStatus(aStatusCode) {} + + void Run() override { mChild->DoFailedAsyncOpen(mStatus); } + + private: + nsresult mStatus; +}; + IPCResult DocumentChannelChild::RecvFailedAsyncOpen( const nsresult& aStatusCode) { - RefPtr<DocumentChannelChild> self = this; - mEventQueue->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [self, aStatusCode]() { self->ShutdownListeners(aStatusCode); })); + mEventQueue->RunOrEnqueue( + new DocumentFailedAsyncOpenEvent(this, aStatusCode)); return IPC_OK(); } +void DocumentChannelChild::DoFailedAsyncOpen(const nsresult& aStatusCode) { + ShutdownListeners(aStatusCode); +} + void DocumentChannelChild::ShutdownListeners(nsresult aStatusCode) { mStatus = aStatusCode; nsCOMPtr<nsIStreamListener> l = mListener; if (l) { l->OnStartRequest(this); } @@ -447,16 +465,67 @@ IPCResult DocumentChannelChild::RecvConf Maybe<nsresult> cancelCode; rv = CSPService::ConsultCSPForRedirect(originalUri, aNewUri, mLoadInfo, cancelCode); aResolve(Tuple<const nsresult&, const Maybe<nsresult>&>(rv, cancelCode)); return IPC_OK(); } +IPCResult DocumentChannelChild::RecvNotifyClassificationFlags( + const uint32_t& aClassificationFlags, const bool& aIsThirdParty) { + if (aIsThirdParty) { + mThirdPartyClassificationFlags |= aClassificationFlags; + } else { + mFirstPartyClassificationFlags |= aClassificationFlags; + } + return IPC_OK(); +} + +IPCResult DocumentChannelChild::RecvNotifyChannelClassifierProtectionDisabled( + const uint32_t& aAcceptedReason) { + UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( + this, aAcceptedReason); + return IPC_OK(); +} + +IPCResult DocumentChannelChild::RecvNotifyCookieAllowed() { + AntiTrackingCommon::NotifyBlockingDecision( + this, AntiTrackingCommon::BlockingDecision::eAllow, 0); + return IPC_OK(); +} + +IPCResult DocumentChannelChild::RecvNotifyCookieBlocked( + const uint32_t& aRejectedReason) { + AntiTrackingCommon::NotifyBlockingDecision( + this, AntiTrackingCommon::BlockingDecision::eBlock, aRejectedReason); + return IPC_OK(); +} + +IPCResult DocumentChannelChild::RecvSetClassifierMatchedInfo( + const nsCString& aList, const nsCString& aProvider, + const nsCString& aFullHash) { + SetMatchedInfo(aList, aProvider, aFullHash); + return IPC_OK(); +} + +IPCResult DocumentChannelChild::RecvSetClassifierMatchedTrackingInfo( + const nsCString& aLists, const nsCString& aFullHash) { + nsTArray<nsCString> lists, fullhashes; + for (const nsACString& token : aLists.Split(',')) { + lists.AppendElement(token); + } + for (const nsACString& token : aFullHash.Split(',')) { + fullhashes.AppendElement(token); + } + + SetMatchedTrackingInfo(lists, fullhashes); + return IPC_OK(); +} + mozilla::ipc::IPCResult DocumentChannelChild::RecvAttachStreamFilter( Endpoint<extensions::PStreamFilterParent>&& aEndpoint) { extensions::StreamFilterParent::Attach(this, std::move(aEndpoint)); return IPC_OK(); } //----------------------------------------------------------------------------- // DocumentChannelChild::nsITraceableChannel @@ -469,16 +538,74 @@ DocumentChannelChild::SetNewListener(nsI nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener); wrapper.forget(_retval); mListener = aListener; return NS_OK; } +//----------------------------------------------------------------------------- +// DocumentChannelChild::nsIClassifiedChannel + +NS_IMETHODIMP +DocumentChannelChild::GetMatchedList(nsACString& aList) { + aList = mMatchedList; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetMatchedProvider(nsACString& aProvider) { + aProvider = mMatchedProvider; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetMatchedFullHash(nsACString& aFullHash) { + aFullHash = mMatchedFullHash; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::SetMatchedInfo(const nsACString& aList, + const nsACString& aProvider, + const nsACString& aFullHash) { + NS_ENSURE_ARG(!aList.IsEmpty()); + + mMatchedList = aList; + mMatchedProvider = aProvider; + mMatchedFullHash = aFullHash; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetMatchedTrackingLists(nsTArray<nsCString>& aLists) { + aLists = mMatchedTrackingLists; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetMatchedTrackingFullHashes( + nsTArray<nsCString>& aFullHashes) { + aFullHashes = mMatchedTrackingFullHashes; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::SetMatchedTrackingInfo( + const nsTArray<nsCString>& aLists, const nsTArray<nsCString>& aFullHashes) { + NS_ENSURE_ARG(!aLists.IsEmpty()); + // aFullHashes can be empty for non hash-matching algorithm, for example, + // host based test entries in preference. + + mMatchedTrackingLists = aLists; + mMatchedTrackingFullHashes = aFullHashes; + return NS_OK; +} + NS_IMETHODIMP DocumentChannelChild::Cancel(nsresult aStatusCode) { if (mCanceled) { return NS_OK; } mCanceled = true; if (CanSend()) { @@ -510,10 +637,70 @@ DocumentChannelChild::Resume() { if (!--mSuspendCount) { SendResume(); } mEventQueue->Resume(); return NS_OK; } +NS_IMETHODIMP +DocumentChannelChild::IsTrackingResource(bool* aIsTrackingResource) { + MOZ_ASSERT(!mFirstPartyClassificationFlags || + !mThirdPartyClassificationFlags); + *aIsTrackingResource = UrlClassifierCommon::IsTrackingClassificationFlag( + mThirdPartyClassificationFlags) || + UrlClassifierCommon::IsTrackingClassificationFlag( + mFirstPartyClassificationFlags); + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::IsThirdPartyTrackingResource(bool* aIsTrackingResource) { + MOZ_ASSERT( + !(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)); + *aIsTrackingResource = UrlClassifierCommon::IsTrackingClassificationFlag( + mThirdPartyClassificationFlags); + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::IsSocialTrackingResource( + bool* aIsSocialTrackingResource) { + MOZ_ASSERT(!mFirstPartyClassificationFlags || + !mThirdPartyClassificationFlags); + *aIsSocialTrackingResource = + UrlClassifierCommon::IsSocialTrackingClassificationFlag( + mThirdPartyClassificationFlags) || + UrlClassifierCommon::IsSocialTrackingClassificationFlag( + mFirstPartyClassificationFlags); + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetClassificationFlags(uint32_t* aClassificationFlags) { + MOZ_ASSERT(aClassificationFlags); + if (mThirdPartyClassificationFlags) { + *aClassificationFlags = mThirdPartyClassificationFlags; + } else { + *aClassificationFlags = mFirstPartyClassificationFlags; + } + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetFirstPartyClassificationFlags( + uint32_t* aClassificationFlags) { + MOZ_ASSERT(aClassificationFlags); + *aClassificationFlags = mFirstPartyClassificationFlags; + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelChild::GetThirdPartyClassificationFlags( + uint32_t* aClassificationFlags) { + MOZ_ASSERT(aClassificationFlags); + *aClassificationFlags = mThirdPartyClassificationFlags; + return NS_OK; +} + } // namespace net } // namespace mozilla
--- a/netwerk/ipc/DocumentChannelChild.h +++ b/netwerk/ipc/DocumentChannelChild.h @@ -7,40 +7,43 @@ #ifndef mozilla_net_DocumentChannelChild_h #define mozilla_net_DocumentChannelChild_h #include "mozilla/net/ChannelEventQueue.h" #include "mozilla/net/PDocumentChannelChild.h" #include "nsBaseChannel.h" #include "nsIChildChannel.h" +#include "nsIClassifiedChannel.h" #include "nsITraceableChannel.h" #define DOCUMENT_CHANNEL_CHILD_IID \ { \ 0x6977bc44, 0xb1db, 0x41b7, { \ 0xb5, 0xc5, 0xe2, 0x13, 0x68, 0x22, 0xc9, 0x8f \ } \ } namespace mozilla { namespace net { class DocumentChannelChild final : public PDocumentChannelChild, public nsBaseChannel, + public nsIClassifiedChannel, public nsITraceableChannel { public: DocumentChannelChild(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo, const nsString* aInitiatorType, nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey, bool aIsActive, bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags); NS_DECL_ISUPPORTS_INHERITED; NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK + NS_DECL_NSICLASSIFIEDCHANNEL NS_DECL_NSITRACEABLECHANNEL NS_DECLARE_STATIC_IID_ACCESSOR(DOCUMENT_CHANNEL_CHILD_IID) // nsIRequest NS_IMETHOD Cancel(nsresult status) override; NS_IMETHOD Suspend() override; NS_IMETHOD Resume() override; @@ -67,34 +70,60 @@ class DocumentChannelChild final : publi const uint32_t& aRedirectMode, const uint32_t& aRedirectFlags, const Maybe<uint32_t>& aContentDisposition, const Maybe<nsString>& aContentDispositionFilename, RedirectToRealChannelResolver&& aResolve); mozilla::ipc::IPCResult RecvAttachStreamFilter( Endpoint<extensions::PStreamFilterParent>&& aEndpoint); + mozilla::ipc::IPCResult RecvNotifyClassificationFlags( + const uint32_t& aClassificationFlags, const bool& aIsThirdParty); + mozilla::ipc::IPCResult RecvNotifyChannelClassifierProtectionDisabled( + const uint32_t& aAcceptedReason); + mozilla::ipc::IPCResult RecvNotifyCookieAllowed(); + mozilla::ipc::IPCResult RecvNotifyCookieBlocked( + const uint32_t& aRejectedReason); + + mozilla::ipc::IPCResult RecvSetClassifierMatchedInfo( + const nsCString& aList, const nsCString& aProvider, + const nsCString& aFullHash); + mozilla::ipc::IPCResult RecvSetClassifierMatchedTrackingInfo( + const nsCString& aLists, const nsCString& aFullHash); + mozilla::ipc::IPCResult RecvConfirmRedirect( const LoadInfoArgs& aLoadInfo, nsIURI* aNewUri, ConfirmRedirectResolver&& aResolve); + void DoFailedAsyncOpen(const nsresult& aStatusCode); + const nsTArray<DocumentChannelRedirect>& GetRedirectChain() const { return mRedirects; } + friend class NeckoTargetChannelEvent<DocumentChannelChild>; + private: - friend class NeckoTargetChannelFunctionEvent; void ShutdownListeners(nsresult aStatusCode); ~DocumentChannelChild() = default; RefPtr<ChannelEventQueue> mEventQueue; nsCOMPtr<nsIChannel> mRedirectChannel; nsTArray<DocumentChannelRedirect> mRedirects; + // Classified channel's matched information + uint32_t mFirstPartyClassificationFlags = 0; + uint32_t mThirdPartyClassificationFlags = 0; + nsCString mMatchedList; + nsCString mMatchedProvider; + nsCString mMatchedFullHash; + nsTArray<nsCString> mMatchedTrackingLists; + nsTArray<nsCString> mMatchedTrackingFullHashes; + RedirectToRealChannelResolver mRedirectResolver; TimeStamp mAsyncOpenTime; const RefPtr<nsDocShellLoadState> mLoadState; const Maybe<nsString> mInitiatorType; const uint32_t mLoadType; const uint32_t mCacheKey; const bool mIsActive;
--- a/netwerk/ipc/DocumentChannelParent.cpp +++ b/netwerk/ipc/DocumentChannelParent.cpp @@ -284,27 +284,16 @@ void DocumentChannelParent::FinishReplac }, [redirectChannel](const ClassifierMatchedTrackingInfoParams& aParams) { redirectChannel->SetClassifierMatchedTrackingInfo( aParams.mLists, aParams.mFullHashes); }, [redirectChannel](const ClassificationFlagsParams& aParams) { redirectChannel->NotifyClassificationFlags( aParams.mClassificationFlags, aParams.mIsThirdParty); - }, - [redirectChannel]( - const NotifyChannelClassifierProtectionDisabledParams& aParams) { - redirectChannel->NotifyChannelClassifierProtectionDisabled( - aParams.mAcceptedReason); - }, - [redirectChannel](const NotifyCookieAllowedParams&) { - redirectChannel->NotifyCookieAllowed(); - }, - [redirectChannel](const NotifyCookieBlockedParams& aParams) { - redirectChannel->NotifyCookieBlocked(aParams.mRejectedReason); }); } RefPtr<HttpChannelParent> httpParent = do_QueryObject(redirectChannel); if (httpParent) { RefPtr<HttpChannelSecurityWarningReporter> reporter = httpParent; for (auto& variant : mSecurityWarningFunctions) { variant.match( @@ -698,82 +687,99 @@ DocumentChannelParent::GetInterface(cons return QueryInterface(aIID, result); } // Rather than forwarding all these nsIParentChannel functions to the child, we // cache a list of them, and then ask the 'real' channel to forward them for us // after it's created. NS_IMETHODIMP +DocumentChannelParent::NotifyChannelClassifierProtectionDisabled( + uint32_t aAcceptedReason) { + if (CanSend()) { + Unused << SendNotifyChannelClassifierProtectionDisabled(aAcceptedReason); + } + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelParent::NotifyCookieAllowed() { + if (CanSend()) { + Unused << SendNotifyCookieAllowed(); + } + return NS_OK; +} + +NS_IMETHODIMP +DocumentChannelParent::NotifyCookieBlocked(uint32_t aRejectedReason) { + if (CanSend()) { + Unused << SendNotifyCookieBlocked(aRejectedReason); + } + return NS_OK; +} + +NS_IMETHODIMP DocumentChannelParent::NotifyFlashPluginStateChanged( nsIHttpChannel::FlashPluginState aState) { mIParentChannelFunctions.AppendElement( IParentChannelFunction{VariantIndex<0>{}, aState}); return NS_OK; } NS_IMETHODIMP DocumentChannelParent::SetClassifierMatchedInfo(const nsACString& aList, const nsACString& aProvider, const nsACString& aFullHash) { ClassifierMatchedInfoParams params; params.mList = aList; params.mProvider = aProvider; params.mFullHash = aFullHash; + if (CanSend()) { + Unused << SendSetClassifierMatchedInfo(params.mList, params.mProvider, + params.mFullHash); + } + mIParentChannelFunctions.AppendElement( IParentChannelFunction{VariantIndex<1>{}, std::move(params)}); return NS_OK; } NS_IMETHODIMP DocumentChannelParent::SetClassifierMatchedTrackingInfo( const nsACString& aLists, const nsACString& aFullHash) { ClassifierMatchedTrackingInfoParams params; params.mLists = aLists; params.mFullHashes = aFullHash; + if (CanSend()) { + Unused << SendSetClassifierMatchedTrackingInfo(params.mLists, + params.mFullHashes); + } + mIParentChannelFunctions.AppendElement( IParentChannelFunction{VariantIndex<2>{}, std::move(params)}); return NS_OK; } NS_IMETHODIMP DocumentChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags, bool aIsThirdParty) { + if (CanSend()) { + Unused << SendNotifyClassificationFlags(aClassificationFlags, + aIsThirdParty); + } + mIParentChannelFunctions.AppendElement(IParentChannelFunction{ VariantIndex<3>{}, ClassificationFlagsParams{aClassificationFlags, aIsThirdParty}}); return NS_OK; } NS_IMETHODIMP -DocumentChannelParent::NotifyChannelClassifierProtectionDisabled( - uint32_t aAcceptedReason) { - mIParentChannelFunctions.AppendElement(IParentChannelFunction{ - VariantIndex<4>{}, - NotifyChannelClassifierProtectionDisabledParams{aAcceptedReason}}); - return NS_OK; -} - -NS_IMETHODIMP -DocumentChannelParent::NotifyCookieAllowed() { - mIParentChannelFunctions.AppendElement( - IParentChannelFunction{VariantIndex<5>{}, NotifyCookieAllowedParams()}); - return NS_OK; -} - -NS_IMETHODIMP -DocumentChannelParent::NotifyCookieBlocked(uint32_t aRejectedReason) { - mIParentChannelFunctions.AppendElement(IParentChannelFunction{ - VariantIndex<6>{}, NotifyCookieBlockedParams{aRejectedReason}}); - return NS_OK; -} - -NS_IMETHODIMP DocumentChannelParent::Delete() { // TODO - not sure we need it, but should delete the child or call on the // child to release the parent. if (!CanSend()) { return NS_ERROR_UNEXPECTED; } Unused << SendDeleteSelf(); return NS_OK;
--- a/netwerk/ipc/DocumentChannelParent.h +++ b/netwerk/ipc/DocumentChannelParent.h @@ -125,32 +125,19 @@ class DocumentChannelParent : public nsI struct ClassifierMatchedTrackingInfoParams { nsCString mLists; nsCString mFullHashes; }; struct ClassificationFlagsParams { uint32_t mClassificationFlags; bool mIsThirdParty; }; - - struct NotifyChannelClassifierProtectionDisabledParams { - uint32_t mAcceptedReason; - }; - - struct NotifyCookieAllowedParams {}; - - struct NotifyCookieBlockedParams { - uint32_t mRejectedReason; - }; - typedef mozilla::Variant< nsIHttpChannel::FlashPluginState, ClassifierMatchedInfoParams, - ClassifierMatchedTrackingInfoParams, ClassificationFlagsParams, - NotifyChannelClassifierProtectionDisabledParams, - NotifyCookieAllowedParams, NotifyCookieBlockedParams> + ClassifierMatchedTrackingInfoParams, ClassificationFlagsParams> IParentChannelFunction; // Store a list of all the attribute setters that have been called on this // channel, so that we can repeat them on the real channel that we redirect // to. nsTArray<IParentChannelFunction> mIParentChannelFunctions; // This defines a variant this describes all the functions
--- a/netwerk/ipc/PDocumentChannel.ipdl +++ b/netwerk/ipc/PDocumentChannel.ipdl @@ -45,16 +45,25 @@ parent: async __delete__(); child: // Used to cancel child channel if we hit errors during creating and // AsyncOpen of nsHttpChannel on the parent. async FailedAsyncOpen(nsresult status); + async NotifyClassificationFlags(uint32_t classificationFlags, bool +isThirdParty); + async NotifyChannelClassifierProtectionDisabled(uint32_t acceptedReason); + async NotifyCookieAllowed(); + async NotifyCookieBlocked(uint32_t rejectedReason); + + async SetClassifierMatchedInfo(nsCString list, nsCString provider, nsCString fullHash); + async SetClassifierMatchedTrackingInfo(nsCString lists, nsCString fullHash); + async AttachStreamFilter(Endpoint<PStreamFilterParent> aEndpoint); // This message is sent to a child that has been redirected to another process. // As a consequence, it should cleanup the channel listeners and remove the // request from the loadGroup. // aStatus must be an error result. async DisconnectChildListeners(nsresult aStatus);
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp +++ b/netwerk/protocol/ftp/FTPChannelChild.cpp @@ -28,32 +28,32 @@ using mozilla::dom::ContentChild; using namespace mozilla::ipc; #undef LOG #define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args) namespace mozilla { namespace net { -FTPChannelChild::FTPChannelChild(nsIURI* aUri) +FTPChannelChild::FTPChannelChild(nsIURI* uri) : mIPCOpen(false), - mEventQ(new ChannelEventQueue(static_cast<nsIFTPChannel*>(this))), mUnknownDecoderInvolved(false), mCanceled(false), mSuspendCount(0), mIsPending(false), mLastModifiedTime(0), mStartPos(0), mDivertingToParent(false), mFlushedForDiversion(false), mSuspendSent(false) { LOG(("Creating FTPChannelChild @%p\n", this)); // grab a reference to the handler to ensure that it doesn't go away. NS_ADDREF(gFtpHandler); - SetURI(aUri); + SetURI(uri); + mEventQ = new ChannelEventQueue(static_cast<nsIFTPChannel*>(this)); // We could support thread retargeting, but as long as we're being driven by // IPDL on the main thread it doesn't buy us anything. DisallowThreadRetargeting(); } FTPChannelChild::~FTPChannelChild() { LOG(("Destroying FTPChannelChild @%p\n", this)); @@ -79,58 +79,58 @@ void FTPChannelChild::ReleaseIPDLReferen NS_IMPL_ISUPPORTS_INHERITED(FTPChannelChild, nsBaseChannel, nsIFTPChannel, nsIUploadChannel, nsIResumableChannel, nsIProxiedChannel, nsIChildChannel, nsIDivertableChannel) //----------------------------------------------------------------------------- NS_IMETHODIMP -FTPChannelChild::GetLastModifiedTime(PRTime* aLastModifiedTime) { - *aLastModifiedTime = mLastModifiedTime; +FTPChannelChild::GetLastModifiedTime(PRTime* lastModifiedTime) { + *lastModifiedTime = mLastModifiedTime; return NS_OK; } NS_IMETHODIMP -FTPChannelChild::SetLastModifiedTime(PRTime aLastModifiedTime) { +FTPChannelChild::SetLastModifiedTime(PRTime lastModifiedTime) { return NS_ERROR_NOT_AVAILABLE; } NS_IMETHODIMP FTPChannelChild::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) { NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); mStartPos = aStartPos; mEntityID = aEntityID; return NS_OK; } NS_IMETHODIMP -FTPChannelChild::GetEntityID(nsACString& aEntityID) { - aEntityID = mEntityID; +FTPChannelChild::GetEntityID(nsACString& entityID) { + entityID = mEntityID; return NS_OK; } NS_IMETHODIMP FTPChannelChild::GetProxyInfo(nsIProxyInfo** aProxyInfo) { DROP_DEAD(); } NS_IMETHODIMP -FTPChannelChild::SetUploadStream(nsIInputStream* aStream, - const nsACString& aContentType, - int64_t aContentLength) { +FTPChannelChild::SetUploadStream(nsIInputStream* stream, + const nsACString& contentType, + int64_t contentLength) { NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); - mUploadStream = aStream; + mUploadStream = stream; // NOTE: contentLength is intentionally ignored here. return NS_OK; } NS_IMETHODIMP -FTPChannelChild::GetUploadStream(nsIInputStream** aStream) { - NS_ENSURE_ARG_POINTER(aStream); - *aStream = mUploadStream; - NS_IF_ADDREF(*aStream); +FTPChannelChild::GetUploadStream(nsIInputStream** stream) { + NS_ENSURE_ARG_POINTER(stream); + *stream = mUploadStream; + NS_IF_ADDREF(*stream); return NS_OK; } NS_IMETHODIMP FTPChannelChild::AsyncOpen(nsIStreamListener* aListener) { nsCOMPtr<nsIStreamListener> listener = aListener; nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); @@ -202,52 +202,78 @@ FTPChannelChild::AsyncOpen(nsIStreamList mIsPending = true; mWasOpened = true; return rv; } NS_IMETHODIMP -FTPChannelChild::IsPending(bool* aResult) { - *aResult = mIsPending; +FTPChannelChild::IsPending(bool* result) { + *result = mIsPending; return NS_OK; } -nsresult FTPChannelChild::OpenContentStream(bool aAsync, - nsIInputStream** aStream, - nsIChannel** aChannel) { +nsresult FTPChannelChild::OpenContentStream(bool async, nsIInputStream** stream, + nsIChannel** channel) { MOZ_CRASH("FTPChannel*Child* should never have OpenContentStream called!"); return NS_OK; } //----------------------------------------------------------------------------- // FTPChannelChild::PFTPChannelChild //----------------------------------------------------------------------------- +class FTPStartRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + FTPStartRequestEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus, + const int64_t& aContentLength, + const nsCString& aContentType, + const PRTime& aLastModified, const nsCString& aEntityID, + const URIParams& aURI) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild), + mChannelStatus(aChannelStatus), + mContentLength(aContentLength), + mContentType(aContentType), + mLastModified(aLastModified), + mEntityID(aEntityID), + mURI(aURI) {} + + void Run() override { + mChild->DoOnStartRequest(mChannelStatus, mContentLength, mContentType, + mLastModified, mEntityID, mURI); + } + + private: + nsresult mChannelStatus; + int64_t mContentLength; + nsCString mContentType; + PRTime mLastModified; + nsCString mEntityID; + URIParams mURI; +}; + mozilla::ipc::IPCResult FTPChannelChild::RecvOnStartRequest( const nsresult& aChannelStatus, const int64_t& aContentLength, const nsCString& aContentType, const PRTime& aLastModified, const nsCString& aEntityID, const URIParams& aURI) { // mFlushedForDiversion and mDivertingToParent should NEVER be set at this // stage, as they are set in the listener's OnStartRequest. MOZ_RELEASE_ASSERT( !mFlushedForDiversion, "mFlushedForDiversion should be unset before OnStartRequest!"); MOZ_RELEASE_ASSERT( !mDivertingToParent, "mDivertingToParent should be unset before OnStartRequest!"); LOG(("FTPChannelChild::RecvOnStartRequest [this=%p]\n", this)); - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - self->DoOnStartRequest(aChannelStatus, aContentLength, aContentType, - aLastModified, aEntityID, aURI); - })); + mEventQ->RunOrEnqueue( + new FTPStartRequestEvent(this, aChannelStatus, aContentLength, + aContentType, aLastModified, aEntityID, aURI)); return IPC_OK(); } void FTPChannelChild::DoOnStartRequest(const nsresult& aChannelStatus, const int64_t& aContentLength, const nsCString& aContentType, const PRTime& aLastModified, const nsCString& aEntityID, @@ -297,107 +323,178 @@ void FTPChannelChild::DoOnStartRequest(c if (mDivertingToParent) { mListener = nullptr; if (mLoadGroup) { mLoadGroup->RemoveRequest(this, nullptr, mStatus); } } } +class FTPDataAvailableEvent : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + FTPDataAvailableEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus, + const nsCString& aData, const uint64_t& aOffset, + const uint32_t& aCount) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild), + mChannelStatus(aChannelStatus), + mData(aData), + mOffset(aOffset), + mCount(aCount) {} + + void Run() override { + mChild->DoOnDataAvailable(mChannelStatus, mData, mOffset, mCount); + } + + private: + nsresult mChannelStatus; + nsCString mData; + uint64_t mOffset; + uint32_t mCount; +}; + mozilla::ipc::IPCResult FTPChannelChild::RecvOnDataAvailable( - const nsresult& aChannelStatus, const nsCString& aData, - const uint64_t& aOffset, const uint32_t& aCount) { + const nsresult& channelStatus, const nsCString& data, + const uint64_t& offset, const uint32_t& count) { MOZ_RELEASE_ASSERT(!mFlushedForDiversion, "Should not be receiving any more callbacks from parent!"); LOG(("FTPChannelChild::RecvOnDataAvailable [this=%p]\n", this)); - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, - [=]() { - self->DoOnDataAvailable(aChannelStatus, aData, - aOffset, aCount); - }), - mDivertingToParent); + mEventQ->RunOrEnqueue( + new FTPDataAvailableEvent(this, channelStatus, data, offset, count), + mDivertingToParent); return IPC_OK(); } -void FTPChannelChild::DoOnDataAvailable(const nsresult& aChannelStatus, - const nsCString& aData, - const uint64_t& aOffset, - const uint32_t& aCount) { +class MaybeDivertOnDataFTPEvent + : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + MaybeDivertOnDataFTPEvent(FTPChannelChild* child, const nsCString& data, + const uint64_t& offset, const uint32_t& count) + : NeckoTargetChannelEvent<FTPChannelChild>(child), + mData(data), + mOffset(offset), + mCount(count) {} + + void Run() override { mChild->MaybeDivertOnData(mData, mOffset, mCount); } + + private: + nsCString mData; + uint64_t mOffset; + uint32_t mCount; +}; + +void FTPChannelChild::MaybeDivertOnData(const nsCString& data, + const uint64_t& offset, + const uint32_t& count) { + if (mDivertingToParent) { + SendDivertOnDataAvailable(data, offset, count); + } +} + +void FTPChannelChild::DoOnDataAvailable(const nsresult& channelStatus, + const nsCString& data, + const uint64_t& offset, + const uint32_t& count) { LOG(("FTPChannelChild::DoOnDataAvailable [this=%p]\n", this)); if (!mCanceled && NS_SUCCEEDED(mStatus)) { - mStatus = aChannelStatus; + mStatus = channelStatus; } if (mDivertingToParent) { MOZ_RELEASE_ASSERT( !mFlushedForDiversion, "Should not be processing any more callbacks from parent!"); - SendDivertOnDataAvailable(aData, aOffset, aCount); - return; - } - - if (mCanceled) { + SendDivertOnDataAvailable(data, offset, count); return; } + if (mCanceled) return; + if (mUnknownDecoderInvolved) { - RefPtr<FTPChannelChild> self = this; mUnknownDecoderEventQ.AppendElement( - MakeUnique<NeckoTargetChannelFunctionEvent>(this, [=]() { - if (self->mDivertingToParent) { - self->SendDivertOnDataAvailable(aData, aOffset, aCount); - } - })); + MakeUnique<MaybeDivertOnDataFTPEvent>(this, data, offset, count)); } // NOTE: the OnDataAvailable contract requires the client to read all the data // in the inputstream. This code relies on that ('data' will go away after // this function). Apparently the previous, non-e10s behavior was to actually // support only reading part of the data, allowing later calls to read the // rest. nsCOMPtr<nsIInputStream> stringStream; nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), - MakeSpan(aData).To(aCount), NS_ASSIGNMENT_DEPEND); + MakeSpan(data).To(count), NS_ASSIGNMENT_DEPEND); if (NS_FAILED(rv)) { Cancel(rv); return; } AutoEventEnqueuer ensureSerialDispatch(mEventQ); - rv = mListener->OnDataAvailable(this, stringStream, aOffset, aCount); - if (NS_FAILED(rv)) { - Cancel(rv); - } + rv = mListener->OnDataAvailable(this, stringStream, offset, count); + if (NS_FAILED(rv)) Cancel(rv); stringStream->Close(); } +class FTPStopRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + FTPStopRequestEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus, + const nsCString& aErrorMsg, bool aUseUTF8) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild), + mChannelStatus(aChannelStatus), + mErrorMsg(aErrorMsg), + mUseUTF8(aUseUTF8) {} + + void Run() override { + mChild->DoOnStopRequest(mChannelStatus, mErrorMsg, mUseUTF8); + } + + private: + nsresult mChannelStatus; + nsCString mErrorMsg; + bool mUseUTF8; +}; + mozilla::ipc::IPCResult FTPChannelChild::RecvOnStopRequest( const nsresult& aChannelStatus, const nsCString& aErrorMsg, const bool& aUseUTF8) { MOZ_RELEASE_ASSERT(!mFlushedForDiversion, "Should not be receiving any more callbacks from parent!"); LOG(("FTPChannelChild::RecvOnStopRequest [this=%p status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus))); - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - self->DoOnStopRequest(aChannelStatus, aErrorMsg, aUseUTF8); - })); + mEventQ->RunOrEnqueue( + new FTPStopRequestEvent(this, aChannelStatus, aErrorMsg, aUseUTF8)); return IPC_OK(); } +class MaybeDivertOnStopFTPEvent + : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + MaybeDivertOnStopFTPEvent(FTPChannelChild* child, + const nsresult& aChannelStatus) + : NeckoTargetChannelEvent<FTPChannelChild>(child), + mChannelStatus(aChannelStatus) {} + + void Run() override { mChild->MaybeDivertOnStop(mChannelStatus); } + + private: + nsresult mChannelStatus; +}; + +void FTPChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus) { + if (mDivertingToParent) { + SendDivertOnStopRequest(aChannelStatus); + } +} + void FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus, const nsCString& aErrorMsg, bool aUseUTF8) { LOG(("FTPChannelChild::DoOnStopRequest [this=%p status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus))); if (mDivertingToParent) { MOZ_RELEASE_ASSERT( @@ -406,84 +503,92 @@ void FTPChannelChild::DoOnStopRequest(co SendDivertOnStopRequest(aChannelStatus); return; } if (!mCanceled) mStatus = aChannelStatus; if (mUnknownDecoderInvolved) { - RefPtr<FTPChannelChild> self = this; mUnknownDecoderEventQ.AppendElement( - MakeUnique<NeckoTargetChannelFunctionEvent>(this, [=]() { - if (self->mDivertingToParent) { - self->SendDivertOnStopRequest(aChannelStatus); - } - })); + MakeUnique<MaybeDivertOnStopFTPEvent>(this, aChannelStatus)); } { // Ensure that all queued ipdl events are dispatched before // we initiate protocol deletion below. mIsPending = false; AutoEventEnqueuer ensureSerialDispatch(mEventQ); (void)mListener->OnStopRequest(this, aChannelStatus); mListener = nullptr; - if (mLoadGroup) { - mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus); - } + if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus); } // This calls NeckoChild::DeallocPFTPChannelChild(), which deletes |this| if // IPDL holds the last reference. Don't rely on |this| existing after here! Send__delete__(this); } +class FTPFailedAsyncOpenEvent + : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + FTPFailedAsyncOpenEvent(FTPChannelChild* aChild, nsresult aStatus) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild), mStatus(aStatus) {} + + void Run() override { mChild->DoFailedAsyncOpen(mStatus); } + + private: + nsresult mStatus; +}; + mozilla::ipc::IPCResult FTPChannelChild::RecvFailedAsyncOpen( - const nsresult& aStatusCode) { + const nsresult& statusCode) { LOG(("FTPChannelChild::RecvFailedAsyncOpen [this=%p status=%" PRIx32 "]\n", - this, static_cast<uint32_t>(aStatusCode))); - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->DoFailedAsyncOpen(aStatusCode); })); + this, static_cast<uint32_t>(statusCode))); + mEventQ->RunOrEnqueue(new FTPFailedAsyncOpenEvent(this, statusCode)); return IPC_OK(); } -void FTPChannelChild::DoFailedAsyncOpen(const nsresult& aStatusCode) { +void FTPChannelChild::DoFailedAsyncOpen(const nsresult& statusCode) { LOG(("FTPChannelChild::DoFailedAsyncOpen [this=%p status=%" PRIx32 "]\n", - this, static_cast<uint32_t>(aStatusCode))); - mStatus = aStatusCode; + this, static_cast<uint32_t>(statusCode))); + mStatus = statusCode; - if (mLoadGroup) { - mLoadGroup->RemoveRequest(this, nullptr, aStatusCode); - } + if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, statusCode); if (mListener) { mListener->OnStartRequest(this); mIsPending = false; - mListener->OnStopRequest(this, aStatusCode); + mListener->OnStopRequest(this, statusCode); } else { mIsPending = false; } mListener = nullptr; - if (mIPCOpen) { - Send__delete__(this); + if (mIPCOpen) Send__delete__(this); +} + +class FTPFlushedForDiversionEvent + : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + explicit FTPFlushedForDiversionEvent(FTPChannelChild* aChild) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild) { + MOZ_RELEASE_ASSERT(aChild); } -} + + void Run() override { mChild->FlushedForDiversion(); } +}; mozilla::ipc::IPCResult FTPChannelChild::RecvFlushedForDiversion() { LOG(("FTPChannelChild::RecvFlushedForDiversion [this=%p]\n", this)); MOZ_ASSERT(mDivertingToParent); - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->FlushedForDiversion(); })); + mEventQ->RunOrEnqueue(new FTPFlushedForDiversionEvent(this), true); return IPC_OK(); } void FTPChannelChild::FlushedForDiversion() { LOG(("FTPChannelChild::FlushedForDiversion [this=%p]\n", this)); MOZ_RELEASE_ASSERT(mDivertingToParent); // Once this is set, it should not be unset before FTPChannelChild is taken @@ -502,41 +607,40 @@ mozilla::ipc::IPCResult FTPChannelChild: // DivertTo() has been called on parent, so we can now start sending queued // IPDL messages back to parent listener. if (NS_WARN_IF(NS_FAILED(Resume()))) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } +class FTPDeleteSelfEvent : public NeckoTargetChannelEvent<FTPChannelChild> { + public: + explicit FTPDeleteSelfEvent(FTPChannelChild* aChild) + : NeckoTargetChannelEvent<FTPChannelChild>(aChild) {} + void Run() override { mChild->DoDeleteSelf(); } +}; + mozilla::ipc::IPCResult FTPChannelChild::RecvDeleteSelf() { - RefPtr<FTPChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->DoDeleteSelf(); })); + mEventQ->RunOrEnqueue(new FTPDeleteSelfEvent(this)); return IPC_OK(); } void FTPChannelChild::DoDeleteSelf() { - if (mIPCOpen) { - Send__delete__(this); - } + if (mIPCOpen) Send__delete__(this); } NS_IMETHODIMP -FTPChannelChild::Cancel(nsresult aStatus) { +FTPChannelChild::Cancel(nsresult status) { LOG(("FTPChannelChild::Cancel [this=%p]\n", this)); - if (mCanceled) { - return NS_OK; - } + if (mCanceled) return NS_OK; mCanceled = true; - mStatus = aStatus; - if (mIPCOpen) { - SendCancel(aStatus); - } + mStatus = status; + if (mIPCOpen) SendCancel(status); return NS_OK; } NS_IMETHODIMP FTPChannelChild::Suspend() { NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE); LOG(("FTPChannelChild::Suspend [this=%p]\n", this)); @@ -571,17 +675,17 @@ FTPChannelChild::Resume() { return NS_OK; } //----------------------------------------------------------------------------- // FTPChannelChild::nsIChildChannel //----------------------------------------------------------------------------- NS_IMETHODIMP -FTPChannelChild::ConnectParent(uint32_t aId) { +FTPChannelChild::ConnectParent(uint32_t id) { NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE); NS_ENSURE_TRUE( !static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(), NS_ERROR_FAILURE); LOG(("FTPChannelChild::ConnectParent [this=%p]\n", this)); mozilla::dom::BrowserChild* browserChild = nullptr; @@ -597,42 +701,40 @@ FTPChannelChild::ConnectParent(uint32_t // This must happen before the constructor message is sent. SetupNeckoTarget(); // The socket transport in the chrome process now holds a logical ref to us // until OnStopRequest, or we do a redirect, or we hit an IPDL error. AddIPDLReference(); - FTPChannelConnectArgs connectArgs(aId); + FTPChannelConnectArgs connectArgs(id); if (!gNeckoChild->SendPFTPChannelConstructor( this, browserChild, IPC::SerializedLoadContext(this), connectArgs)) { return NS_ERROR_FAILURE; } return NS_OK; } NS_IMETHODIMP -FTPChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener, +FTPChannelChild::CompleteRedirectSetup(nsIStreamListener* listener, nsISupports* aContext) { LOG(("FTPChannelChild::CompleteRedirectSetup [this=%p]\n", this)); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); mIsPending = true; mWasOpened = true; - mListener = aListener; + mListener = listener; // add ourselves to the load group. - if (mLoadGroup) { - mLoadGroup->AddRequest(this, nullptr); - } + if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); // We already have an open IPDL connection to the parent. If on-modify-request // listeners or load group observers canceled us, let the parent handle it // and send it back to us naturally. return NS_OK; } //-----------------------------------------------------------------------------
--- a/netwerk/protocol/ftp/FTPChannelChild.h +++ b/netwerk/protocol/ftp/FTPChannelChild.h @@ -48,81 +48,92 @@ class FTPChannelChild final : public PFT NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIFTPCHANNEL NS_DECL_NSIUPLOADCHANNEL NS_DECL_NSIRESUMABLECHANNEL NS_DECL_NSIPROXIEDCHANNEL NS_DECL_NSICHILDCHANNEL NS_DECL_NSIDIVERTABLECHANNEL - NS_IMETHOD Cancel(nsresult aStatus) override; + NS_IMETHOD Cancel(nsresult status) override; NS_IMETHOD Suspend() override; NS_IMETHOD Resume() override; - explicit FTPChannelChild(nsIURI* aUri); + explicit FTPChannelChild(nsIURI* uri); void AddIPDLReference(); void ReleaseIPDLReference(); - NS_IMETHOD AsyncOpen(nsIStreamListener* aListener) override; + NS_IMETHOD AsyncOpen(nsIStreamListener* listener) override; // Note that we handle this ourselves, overriding the nsBaseChannel // default behavior, in order to be e10s-friendly. - NS_IMETHOD IsPending(bool* aResult) override; + NS_IMETHOD IsPending(bool* result) override; - nsresult OpenContentStream(bool aAsync, nsIInputStream** aStream, - nsIChannel** aChannel) override; + nsresult OpenContentStream(bool async, nsIInputStream** stream, + nsIChannel** channel) override; - bool IsSuspended() const; + bool IsSuspended(); void FlushedForDiversion(); protected: virtual ~FTPChannelChild(); mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& aChannelStatus, const int64_t& aContentLength, const nsCString& aContentType, const PRTime& aLastModified, const nsCString& aEntityID, const URIParams& aURI) override; - mozilla::ipc::IPCResult RecvOnDataAvailable(const nsresult& aChannelStatus, - const nsCString& aData, - const uint64_t& aOffset, - const uint32_t& aCount) override; - mozilla::ipc::IPCResult RecvOnStopRequest(const nsresult& aChannelStatus, + mozilla::ipc::IPCResult RecvOnDataAvailable(const nsresult& channelStatus, + const nsCString& data, + const uint64_t& offset, + const uint32_t& count) override; + mozilla::ipc::IPCResult RecvOnStopRequest(const nsresult& channelStatus, const nsCString& aErrorMsg, const bool& aUseUTF8) override; mozilla::ipc::IPCResult RecvFailedAsyncOpen( - const nsresult& aStatusCode) override; + const nsresult& statusCode) override; mozilla::ipc::IPCResult RecvFlushedForDiversion() override; mozilla::ipc::IPCResult RecvDivertMessages() override; mozilla::ipc::IPCResult RecvDeleteSelf() override; void DoOnStartRequest(const nsresult& aChannelStatus, const int64_t& aContentLength, const nsCString& aContentType, const PRTime& aLastModified, const nsCString& aEntityID, const URIParams& aURI); - void DoOnDataAvailable(const nsresult& aChannelStatus, const nsCString& aData, - const uint64_t& aOffset, const uint32_t& aCount); - void DoOnStopRequest(const nsresult& StatusCode, const nsCString& aErrorMsg, + void DoOnDataAvailable(const nsresult& channelStatus, const nsCString& data, + const uint64_t& offset, const uint32_t& count); + void MaybeDivertOnData(const nsCString& data, const uint64_t& offset, + const uint32_t& count); + void MaybeDivertOnStop(const nsresult& statusCode); + void DoOnStopRequest(const nsresult& statusCode, const nsCString& aErrorMsg, bool aUseUTF8); - void DoFailedAsyncOpen(const nsresult& aStatusCode); + void DoFailedAsyncOpen(const nsresult& statusCode); void DoDeleteSelf(); void SetupNeckoTarget() override; - friend class NeckoTargetChannelFunctionEvent; + friend class FTPStartRequestEvent; + friend class FTPDataAvailableEvent; + friend class MaybeDivertOnDataFTPEvent; + friend class FTPStopRequestEvent; + friend class MaybeDivertOnStopFTPEvent; + friend class FTPFailedAsyncOpenEvent; + friend class FTPFlushedForDiversionEvent; + friend class FTPDeleteSelfEvent; + friend class NeckoTargetChannelEvent<FTPChannelChild>; private: nsCOMPtr<nsIInputStream> mUploadStream; bool mIPCOpen; - const RefPtr<ChannelEventQueue> mEventQ; + RefPtr<ChannelEventQueue> mEventQ; // If nsUnknownDecoder is involved we queue onDataAvailable (and possibly // OnStopRequest) so that we can divert them if needed when the listener's // OnStartRequest is finally called nsTArray<UniquePtr<ChannelEvent>> mUnknownDecoderEventQ; bool mUnknownDecoderInvolved; bool mCanceled; @@ -142,14 +153,14 @@ class FTPChannelChild final : public PFT // Once set, no OnStart/OnData/OnStop callbacks should be received from the // parent channel, nor dequeued from the ChannelEventQueue. bool mFlushedForDiversion; // Set if SendSuspend is called. Determines if SendResume is needed when // diverting callbacks to parent. bool mSuspendSent; }; -inline bool FTPChannelChild::IsSuspended() const { return mSuspendCount != 0; } +inline bool FTPChannelChild::IsSuspended() { return mSuspendCount != 0; } } // namespace net } // namespace mozilla #endif // mozilla_net_FTPChannelChild_h
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp +++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp @@ -226,16 +226,145 @@ IPCResult HttpBackgroundChannelChild::Re return IPC_OK(); } mChannelChild->ProcessDivertMessages(); return IPC_OK(); } +IPCResult +HttpBackgroundChannelChild::RecvNotifyChannelClassifierProtectionDisabled( + const uint32_t& aAcceptedReason) { + LOG( + ("HttpBackgroundChannelChild::" + "RecvNotifyChannelClassifierProtectionDisabled [this=%p " + "aAcceptedReason=%" PRIu32 "]\n", + this, aAcceptedReason)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + // NotifyChannelClassifierProtectionDisabled has no order dependency to + // OnStartRequest. It this be handled as soon as possible + mChannelChild->ProcessNotifyChannelClassifierProtectionDisabled( + aAcceptedReason); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvNotifyCookieAllowed() { + LOG(("HttpBackgroundChannelChild::RecvNotifyCookieAllowed [this=%p]\n", + this)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + mChannelChild->ProcessNotifyCookieAllowed(); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvNotifyCookieBlocked( + const uint32_t& aRejectedReason) { + LOG( + ("HttpBackgroundChannelChild::RecvNotifyCookieBlocked [this=%p " + "aRejectedReason=%" PRIu32 "]\n", + this, aRejectedReason)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + mChannelChild->ProcessNotifyCookieBlocked(aRejectedReason); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvNotifyClassificationFlags( + const uint32_t& aClassificationFlags, const bool& aIsThirdParty) { + LOG( + ("HttpBackgroundChannelChild::RecvNotifyClassificationFlags " + "classificationFlags=%" PRIu32 ", thirdparty=%d [this=%p]\n", + aClassificationFlags, static_cast<int>(aIsThirdParty), this)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + // NotifyClassificationFlags has no order dependency to OnStartRequest. + // It this be handled as soon as possible + mChannelChild->ProcessNotifyClassificationFlags(aClassificationFlags, + aIsThirdParty); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvNotifyFlashPluginStateChanged( + const nsIHttpChannel::FlashPluginState& aState) { + LOG( + ("HttpBackgroundChannelChild::RecvNotifyFlashPluginStateChanged " + "[this=%p]\n", + this)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + // NotifyFlashPluginStateChanged has no order dependency to OnStartRequest. + // It this be handled as soon as possible + mChannelChild->ProcessNotifyFlashPluginStateChanged(aState); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo( + const ClassifierInfo& info) { + LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", + this)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + // SetClassifierMatchedInfo has no order dependency to OnStartRequest. + // It this be handled as soon as possible + mChannelChild->ProcessSetClassifierMatchedInfo(info.list(), info.provider(), + info.fullhash()); + + return IPC_OK(); +} + +IPCResult HttpBackgroundChannelChild::RecvSetClassifierMatchedTrackingInfo( + const ClassifierInfo& info) { + LOG( + ("HttpBackgroundChannelChild::RecvSetClassifierMatchedTrackingInfo " + "[this=%p]\n", + this)); + MOZ_ASSERT(OnSocketThread()); + + if (NS_WARN_IF(!mChannelChild)) { + return IPC_OK(); + } + + // SetClassifierMatchedTrackingInfo has no order dependency to OnStartRequest. + // It this be handled as soon as possible + mChannelChild->ProcessSetClassifierMatchedTrackingInfo(info.list(), + info.fullhash()); + + return IPC_OK(); +} void HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy) { LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this)); // This function might be called during shutdown phase, so OnSocketThread() // might return false even on STS thread. Use IsOnCurrentThreadInfallible() // to get correct information. MOZ_ASSERT(gSocketTransportService); MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.h +++ b/netwerk/protocol/http/HttpBackgroundChannelChild.h @@ -7,16 +7,17 @@ #ifndef mozilla_net_HttpBackgroundChannelChild_h #define mozilla_net_HttpBackgroundChannelChild_h #include "mozilla/net/PHttpBackgroundChannelChild.h" #include "nsIRunnable.h" #include "nsTArray.h" +using mozilla::dom::ClassifierInfo; using mozilla::ipc::IPCResult; namespace mozilla { namespace net { class HttpChannelChild; class HttpBackgroundChannelChild final : public PHttpBackgroundChannelChild { @@ -53,16 +54,33 @@ class HttpBackgroundChannelChild final : const nsHttpHeaderArray& aResponseTrailers); IPCResult RecvFlushedForDiversion(); IPCResult RecvDivertMessages(); IPCResult RecvOnStartRequestSent(); + IPCResult RecvNotifyChannelClassifierProtectionDisabled( + const uint32_t& aAcceptedReason); + + IPCResult RecvNotifyCookieAllowed(); + + IPCResult RecvNotifyCookieBlocked(const uint32_t& aRejectedReason); + + IPCResult RecvNotifyClassificationFlags(const uint32_t& aClassificationFlags, + const bool& aIsThirdParty); + + IPCResult RecvNotifyFlashPluginStateChanged( + const nsIHttpChannel::FlashPluginState& aState); + + IPCResult RecvSetClassifierMatchedInfo(const ClassifierInfo& info); + + IPCResult RecvSetClassifierMatchedTrackingInfo(const ClassifierInfo& info); + void ActorDestroy(ActorDestroyReason aWhy) override; private: virtual ~HttpBackgroundChannelChild(); // Initiate the creation of the PBckground IPC channel. // Return false if failed. bool CreateBackgroundChannel();
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.cpp +++ b/netwerk/protocol/http/HttpBackgroundChannelParent.cpp @@ -258,16 +258,233 @@ bool HttpBackgroundChannelParent::OnDive // the OnDataAvailables and OnStopRequest to associated HttpChannelParent. if (!SendDivertMessages()) { return false; } return true; } +bool HttpBackgroundChannelParent::OnNotifyChannelClassifierProtectionDisabled( + uint32_t aAcceptedReason) { + LOG( + ("HttpBackgroundChannelParent::" + "OnNotifyChannelClassifierProtectionDisabled [this=%p - " + "aAcceptedReason=%" PRIu32 "]\n", + this, aAcceptedReason)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + RefPtr<HttpBackgroundChannelParent> self = this; + nsresult rv = mBackgroundThread->Dispatch( + NS_NewRunnableFunction( + "net::HttpBackgroundChannelParent::" + "OnNotifyChannelClassifierProtectionDisabled", + [self, aAcceptedReason]() { + self->OnNotifyChannelClassifierProtectionDisabled( + aAcceptedReason); + }), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + return SendNotifyChannelClassifierProtectionDisabled(aAcceptedReason); +} + +bool HttpBackgroundChannelParent::OnNotifyCookieAllowed() { + LOG(("HttpBackgroundChannelParent::OnNotifyCookieAllowed [this=%p]\n", this)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + RefPtr<HttpBackgroundChannelParent> self = this; + nsresult rv = mBackgroundThread->Dispatch( + NS_NewRunnableFunction( + "net::HttpBackgroundChannelParent::OnNotifyCookieAllowed", + [self]() { self->OnNotifyCookieAllowed(); }), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + return SendNotifyCookieAllowed(); +} + +bool HttpBackgroundChannelParent::OnNotifyCookieBlocked( + uint32_t aRejectedReason) { + LOG( + ("HttpBackgroundChannelParent::OnNotifyCookieBlocked [this=%p " + "aRejectedReason=%" PRIu32 "]\n", + this, aRejectedReason)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + RefPtr<HttpBackgroundChannelParent> self = this; + nsresult rv = mBackgroundThread->Dispatch( + NS_NewRunnableFunction( + "net::HttpBackgroundChannelParent::OnNotifyCookieBlocked", + [self, aRejectedReason]() { + self->OnNotifyCookieBlocked(aRejectedReason); + }), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + return SendNotifyCookieBlocked(aRejectedReason); +} + +bool HttpBackgroundChannelParent::OnNotifyClassificationFlags( + uint32_t aClassificationFlags, bool aIsThirdParty) { + LOG( + ("HttpBackgroundChannelParent::OnNotifyClassificationFlags " + "classificationFlags=%" PRIu32 ", thirdparty=%d [this=%p]\n", + aClassificationFlags, static_cast<int>(aIsThirdParty), this)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + nsresult rv = mBackgroundThread->Dispatch( + NewRunnableMethod<uint32_t, bool>( + "net::HttpBackgroundChannelParent::OnNotifyClassificationFlags", + this, &HttpBackgroundChannelParent::OnNotifyClassificationFlags, + aClassificationFlags, aIsThirdParty), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + return SendNotifyClassificationFlags(aClassificationFlags, aIsThirdParty); +} + +bool HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged( + nsIHttpChannel::FlashPluginState aState) { + LOG( + ("HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged " + "[this=%p]\n", + this)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + RefPtr<HttpBackgroundChannelParent> self = this; + nsresult rv = mBackgroundThread->Dispatch( + NS_NewRunnableFunction( + "net::HttpBackgroundChannelParent::OnNotifyFlashPluginStateChanged", + [self, aState]() { + self->OnNotifyFlashPluginStateChanged(aState); + }), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + return SendNotifyFlashPluginStateChanged(aState); +} + +bool HttpBackgroundChannelParent::OnSetClassifierMatchedInfo( + const nsACString& aList, const nsACString& aProvider, + const nsACString& aFullHash) { + LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n", + this)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + nsresult rv = mBackgroundThread->Dispatch( + NewRunnableMethod<const nsCString, const nsCString, const nsCString>( + "net::HttpBackgroundChannelParent::OnSetClassifierMatchedInfo", + this, &HttpBackgroundChannelParent::OnSetClassifierMatchedInfo, + aList, aProvider, aFullHash), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + ClassifierInfo info; + info.list() = aList; + info.fullhash() = aFullHash; + info.provider() = aProvider; + + return SendSetClassifierMatchedInfo(info); +} + +bool HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo( + const nsACString& aLists, const nsACString& aFullHashes) { + LOG( + ("HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo " + "[this=%p]\n", + this)); + AssertIsInMainProcess(); + + if (NS_WARN_IF(!mIPCOpened)) { + return false; + } + + if (!IsOnBackgroundThread()) { + MutexAutoLock lock(mBgThreadMutex); + nsresult rv = mBackgroundThread->Dispatch( + NewRunnableMethod<const nsCString, const nsCString>( + "net::HttpBackgroundChannelParent::" + "OnSetClassifierMatchedTrackingInfo", + this, + &HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo, + aLists, aFullHashes), + NS_DISPATCH_NORMAL); + + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + + return NS_SUCCEEDED(rv); + } + + ClassifierInfo info; + info.list() = aLists; + info.fullhash() = aFullHashes; + + return SendSetClassifierMatchedTrackingInfo(info); +} void HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy) { LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this)); AssertIsInMainProcess(); AssertIsOnBackgroundThread(); mIPCOpened = false; RefPtr<HttpBackgroundChannelParent> self = this;
--- a/netwerk/protocol/http/HttpBackgroundChannelParent.h +++ b/netwerk/protocol/http/HttpBackgroundChannelParent.h @@ -52,16 +52,42 @@ class HttpBackgroundChannelParent final bool OnStopRequest(const nsresult& aChannelStatus, const ResourceTimingStruct& aTiming, const nsHttpHeaderArray& aResponseTrailers); // To send FlushedForDiversion and DivertMessages messages // over background channel. bool OnDiversion(); + // To send NotifyChannelClassifierProtectionDisabled message over background + // channel. + bool OnNotifyChannelClassifierProtectionDisabled(uint32_t aAcceptedReason); + + // To send NotifyCookieAllowed message over background channel. + bool OnNotifyCookieAllowed(); + + // To send NotifyCookieBlocked message over background channel. + bool OnNotifyCookieBlocked(uint32_t aRejectedReason); + + // To send NotifyClassificationFlags message over background channel. + bool OnNotifyClassificationFlags(uint32_t aClassificationFlags, + bool aIsThirdParty); + + // To send NotifyFlashPluginStateChanged message over background channel. + bool OnNotifyFlashPluginStateChanged(nsIHttpChannel::FlashPluginState aState); + + // To send SetClassifierMatchedInfo message over background channel. + bool OnSetClassifierMatchedInfo(const nsACString& aList, + const nsACString& aProvider, + const nsACString& aFullHash); + + // To send SetClassifierMatchedTrackingInfo message over background channel. + bool OnSetClassifierMatchedTrackingInfo(const nsACString& aLists, + const nsACString& aFullHashes); + protected: void ActorDestroy(ActorDestroyReason aWhy) override; private: virtual ~HttpBackgroundChannelParent(); Atomic<bool> mIPCOpened;
--- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -340,71 +340,163 @@ void HttpChannelChild::OnBackgroundChild } if (callback) { nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); neckoTarget->Dispatch(callback, NS_DISPATCH_NORMAL); } } +class AssociateApplicationCacheEvent + : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + AssociateApplicationCacheEvent(HttpChannelChild* aChild, + const nsCString& aGroupID, + const nsCString& aClientID) + : NeckoTargetChannelEvent<HttpChannelChild>(aChild), + groupID(aGroupID), + clientID(aClientID) {} + + void Run() override { mChild->AssociateApplicationCache(groupID, clientID); } + + private: + nsCString groupID; + nsCString clientID; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvAssociateApplicationCache( - const nsCString& aGroupID, const nsCString& aClientID) { + const nsCString& groupID, const nsCString& clientID) { LOG(("HttpChannelChild::RecvAssociateApplicationCache [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->AssociateApplicationCache(aGroupID, aClientID); })); + mEventQ->RunOrEnqueue( + new AssociateApplicationCacheEvent(this, groupID, clientID)); return IPC_OK(); } -void HttpChannelChild::AssociateApplicationCache(const nsCString& aGroupID, - const nsCString& aClientID) { +void HttpChannelChild::AssociateApplicationCache(const nsCString& groupID, + const nsCString& clientID) { LOG(("HttpChannelChild::AssociateApplicationCache [this=%p]\n", this)); mApplicationCache = new nsApplicationCache(); mLoadedFromApplicationCache = true; - mApplicationCache->InitAsHandle(aGroupID, aClientID); + mApplicationCache->InitAsHandle(groupID, clientID); } +class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + StartRequestEvent( + HttpChannelChild* aChild, const nsresult& aChannelStatus, + const nsHttpResponseHead& aResponseHead, const bool& aUseResponseHead, + const nsHttpHeaderArray& aRequestHeaders, + const ParentLoadInfoForwarderArgs& loadInfoForwarder, + const bool& aIsFromCache, const bool& aIsRacing, + const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId, + const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime, + const nsCString& aCachedCharset, + const nsCString& aSecurityInfoSerialization, const NetAddr& aSelfAddr, + const NetAddr& aPeerAddr, const uint32_t& aCacheKey, + const nsCString& altDataType, const int64_t& altDataLen, + const bool& deliveringAltData, const bool& aApplyConversion, + const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming, + const bool& aAllRedirectsSameOrigin) + : NeckoTargetChannelEvent<HttpChannelChild>(aChild), + mChannelStatus(aChannelStatus), + mResponseHead(aResponseHead), + mRequestHeaders(aRequestHeaders), + mUseResponseHead(aUseResponseHead), + mApplyConversion(aApplyConversion), + mIsFromCache(aIsFromCache), + mIsRacing(aIsRacing), + mCacheEntryAvailable(aCacheEntryAvailable), + mCacheEntryId(aCacheEntryId), + mCacheFetchCount(aCacheFetchCount), + mCacheExpirationTime(aCacheExpirationTime), + mCachedCharset(aCachedCharset), + mSecurityInfoSerialization(aSecurityInfoSerialization), + mSelfAddr(aSelfAddr), + mPeerAddr(aPeerAddr), + mCacheKey(aCacheKey), + mAltDataType(altDataType), + mAltDataLen(altDataLen), + mDeliveringAltData(deliveringAltData), + mLoadInfoForwarder(loadInfoForwarder), + mIsResolvedByTRR(aIsResolvedByTRR), + mTiming(aTiming), + mAllRedirectsSameOrigin(aAllRedirectsSameOrigin) {} + + void Run() override { + LOG(("StartRequestEvent [this=%p]\n", mChild)); + mChild->OnStartRequest( + mChannelStatus, mResponseHead, mUseResponseHead, mRequestHeaders, + mLoadInfoForwarder, mIsFromCache, mIsRacing, mCacheEntryAvailable, + mCacheEntryId, mCacheFetchCount, mCacheExpirationTime, mCachedCharset, + mSecurityInfoSerialization, mSelfAddr, mPeerAddr, mCacheKey, + mAltDataType, mAltDataLen, mDeliveringAltData, mApplyConversion, + mIsResolvedByTRR, mTiming, mAllRedirectsSameOrigin); + } + + private: + nsresult mChannelStatus; + nsHttpResponseHead mResponseHead; + nsHttpHeaderArray mRequestHeaders; + bool mUseResponseHead; + bool mApplyConversion; + bool mIsFromCache; + bool mIsRacing; + bool mCacheEntryAvailable; + uint64_t mCacheEntryId; + int32_t mCacheFetchCount; + uint32_t mCacheExpirationTime; + nsCString mCachedCharset; + nsCString mSecurityInfoSerialization; + NetAddr mSelfAddr; + NetAddr mPeerAddr; + uint32_t mCacheKey; + nsCString mAltDataType; + int64_t mAltDataLen; + bool mDeliveringAltData; + ParentLoadInfoForwarderArgs mLoadInfoForwarder; + bool mIsResolvedByTRR; + ResourceTimingStruct mTiming; + bool mAllRedirectsSameOrigin; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvOnStartRequest( - const nsresult& aChannelStatus, const nsHttpResponseHead& aResponseHead, - const bool& aUseResponseHead, const nsHttpHeaderArray& aRequestHeaders, - const ParentLoadInfoForwarderArgs& aLoadInfoForwarder, - const bool& aIsFromCache, const bool& aIsRacing, - const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId, - const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime, - const nsCString& aCachedCharset, const nsCString& aSecurityInfoSerialization, - const NetAddr& aSelfAddr, const NetAddr& aPeerAddr, - const int16_t& aRedirectCount, const uint32_t& aCacheKey, - const nsCString& aAltDataType, const int64_t& aAltDataLen, - const bool& aDeliveringAltData, const bool& aApplyConversion, + const nsresult& channelStatus, const nsHttpResponseHead& responseHead, + const bool& useResponseHead, const nsHttpHeaderArray& requestHeaders, + const ParentLoadInfoForwarderArgs& loadInfoForwarder, + const bool& isFromCache, const bool& isRacing, + const bool& cacheEntryAvailable, const uint64_t& cacheEntryId, + const int32_t& cacheFetchCount, const uint32_t& cacheExpirationTime, + const nsCString& cachedCharset, const nsCString& securityInfoSerialization, + const NetAddr& selfAddr, const NetAddr& peerAddr, + const int16_t& redirectCount, const uint32_t& cacheKey, + const nsCString& altDataType, const int64_t& altDataLen, + const bool& deliveringAltData, const bool& aApplyConversion, const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming, const bool& aAllRedirectsSameOrigin) { AUTO_PROFILER_LABEL("HttpChannelChild::RecvOnStartRequest", NETWORK); LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this)); // mFlushedForDiversion and mDivertingToParent should NEVER be set at this // stage, as they are set in the listener's OnStartRequest. MOZ_RELEASE_ASSERT( !mFlushedForDiversion, "mFlushedForDiversion should be unset before OnStartRequest!"); MOZ_RELEASE_ASSERT( !mDivertingToParent, "mDivertingToParent should be unset before OnStartRequest!"); - mRedirectCount = aRedirectCount; - - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - self->OnStartRequest( - aChannelStatus, aResponseHead, aUseResponseHead, aRequestHeaders, - aLoadInfoForwarder, aIsFromCache, aIsRacing, aCacheEntryAvailable, - aCacheEntryId, aCacheFetchCount, aCacheExpirationTime, aCachedCharset, - aSecurityInfoSerialization, aSelfAddr, aPeerAddr, aCacheKey, aAltDataType, - aAltDataLen, aDeliveringAltData, aApplyConversion, aIsResolvedByTRR, - aTiming, aAllRedirectsSameOrigin); - })); + mRedirectCount = redirectCount; + + mEventQ->RunOrEnqueue(new StartRequestEvent( + this, channelStatus, responseHead, useResponseHead, requestHeaders, + loadInfoForwarder, isFromCache, isRacing, cacheEntryAvailable, + cacheEntryId, cacheFetchCount, cacheExpirationTime, cachedCharset, + securityInfoSerialization, selfAddr, peerAddr, cacheKey, altDataType, + altDataLen, deliveringAltData, aApplyConversion, aIsResolvedByTRR, + aTiming, aAllRedirectsSameOrigin)); { // Child's mEventQ is to control the execution order of the IPC messages // from both main thread IPDL and PBackground IPDL. // To guarantee the ordering, PBackground IPC messages that are sent after // OnStartRequest will be throttled until OnStartRequest hits the Child's // mEventQ. MutexAutoLock lock(mBgChildMutex); @@ -418,26 +510,26 @@ mozilla::ipc::IPCResult HttpChannelChild NS_DISPATCH_NORMAL); } } return IPC_OK(); } void HttpChannelChild::OnStartRequest( - const nsresult& aChannelStatus, const nsHttpResponseHead& aResponseHead, - const bool& aUseResponseHead, const nsHttpHeaderArray& aRequestHeaders, - const ParentLoadInfoForwarderArgs& aLoadInfoForwarder, - const bool& aIsFromCache, const bool& aIsRacing, - const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId, - const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime, - const nsCString& aCachedCharset, const nsCString& aSecurityInfoSerialization, - const NetAddr& aSelfAddr, const NetAddr& aPeerAddr, const uint32_t& aCacheKey, - const nsCString& aAltDataType, const int64_t& aAltDataLen, - const bool& aDeliveringAltData, const bool& aApplyConversion, + const nsresult& channelStatus, const nsHttpResponseHead& responseHead, + const bool& useResponseHead, const nsHttpHeaderArray& requestHeaders, + const ParentLoadInfoForwarderArgs& loadInfoForwarder, + const bool& isFromCache, const bool& isRacing, + const bool& cacheEntryAvailable, const uint64_t& cacheEntryId, + const int32_t& cacheFetchCount, const uint32_t& cacheExpirationTime, + const nsCString& cachedCharset, const nsCString& securityInfoSerialization, + const NetAddr& selfAddr, const NetAddr& peerAddr, const uint32_t& cacheKey, + const nsCString& altDataType, const int64_t& altDataLen, + const bool& deliveringAltData, const bool& aApplyConversion, const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming, const bool& aAllRedirectsSameOrigin) { LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this)); // mFlushedForDiversion and mDivertingToParent should NEVER be set at this // stage, as they are set in the listener's OnStartRequest. MOZ_RELEASE_ASSERT( !mFlushedForDiversion, @@ -450,61 +542,61 @@ void HttpChannelChild::OnStartRequest( // OnStartRequest/OnStopRequest/OnDataAvailable IPC messages that need to // be handled. In that case we just ignore them to avoid calling the listener // twice. if (mOnStartRequestCalled && mIPCActorDeleted) { return; } if (!mCanceled && NS_SUCCEEDED(mStatus)) { - mStatus = aChannelStatus; + mStatus = channelStatus; } // Cookies headers should not be visible to the child process - MOZ_ASSERT(!aRequestHeaders.HasHeader(nsHttp::Cookie)); - MOZ_ASSERT(!nsHttpResponseHead(aResponseHead).HasHeader(nsHttp::Set_Cookie)); - - if (aUseResponseHead && !mCanceled) - mResponseHead = new nsHttpResponseHead(aResponseHead); - - if (!aSecurityInfoSerialization.IsEmpty()) { - nsresult rv = NS_DeserializeObject(aSecurityInfoSerialization, + MOZ_ASSERT(!requestHeaders.HasHeader(nsHttp::Cookie)); + MOZ_ASSERT(!nsHttpResponseHead(responseHead).HasHeader(nsHttp::Set_Cookie)); + + if (useResponseHead && !mCanceled) + mResponseHead = new nsHttpResponseHead(responseHead); + + if (!securityInfoSerialization.IsEmpty()) { + nsresult rv = NS_DeserializeObject(securityInfoSerialization, getter_AddRefs(mSecurityInfo)); MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserializing security info should not fail"); Unused << rv; // So we don't get an unused error in release builds. } - ipc::MergeParentLoadInfoForwarder(aLoadInfoForwarder, mLoadInfo); - - mIsFromCache = aIsFromCache; - mIsRacing = aIsRacing; - mCacheEntryAvailable = aCacheEntryAvailable; - mCacheEntryId = aCacheEntryId; - mCacheFetchCount = aCacheFetchCount; - mCacheExpirationTime = aCacheExpirationTime; - mCachedCharset = aCachedCharset; - mSelfAddr = aSelfAddr; - mPeerAddr = aPeerAddr; - - mAvailableCachedAltDataType = aAltDataType; - mDeliveringAltData = aDeliveringAltData; - mAltDataLength = aAltDataLen; + ipc::MergeParentLoadInfoForwarder(loadInfoForwarder, mLoadInfo); + + mIsFromCache = isFromCache; + mIsRacing = isRacing; + mCacheEntryAvailable = cacheEntryAvailable; + mCacheEntryId = cacheEntryId; + mCacheFetchCount = cacheFetchCount; + mCacheExpirationTime = cacheExpirationTime; + mCachedCharset = cachedCharset; + mSelfAddr = selfAddr; + mPeerAddr = peerAddr; + + mAvailableCachedAltDataType = altDataType; + mDeliveringAltData = deliveringAltData; + mAltDataLength = altDataLen; mResolvedByTRR = aIsResolvedByTRR; SetApplyConversion(aApplyConversion); mAfterOnStartRequestBegun = true; AutoEventEnqueuer ensureSerialDispatch(mEventQ); - mCacheKey = aCacheKey; + mCacheKey = cacheKey; // replace our request headers with what actually got sent in the parent - mRequestHead.SetHeaders(aRequestHeaders); + mRequestHead.SetHeaders(requestHeaders); // Note: this is where we would notify "http-on-examine-response" observers. // We have deliberately disabled this for child processes (see bug 806753) // // gHttpHandler->OnExamineResponse(this); mTracingEnabled = false; @@ -621,135 +713,176 @@ void HttpChannelChild::DoOnStartRequest( if (NS_FAILED(rv)) { Cancel(rv); } else if (listener) { mListener = listener; mCompressListener = listener; } } +class TransportAndDataEvent : public ChannelEvent { + public: + TransportAndDataEvent(HttpChannelChild* child, const nsresult& channelStatus, + const nsresult& transportStatus, const nsCString& data, + const uint64_t& offset, const uint32_t& count) + : mChild(child), + mChannelStatus(channelStatus), + mTransportStatus(transportStatus), + mData(data), + mOffset(offset), + mCount(count) {} + + void Run() override { + mChild->OnTransportAndData(mChannelStatus, mTransportStatus, mOffset, + mCount, mData); + } + + already_AddRefed<nsIEventTarget> GetEventTarget() override { + MOZ_ASSERT(mChild); + nsCOMPtr<nsIEventTarget> target = mChild->GetODATarget(); + return target.forget(); + } + + private: + HttpChannelChild* mChild; + nsresult mChannelStatus; + nsresult mTransportStatus; + nsCString mData; + uint64_t mOffset; + uint32_t mCount; +}; + void HttpChannelChild::ProcessOnTransportAndData( const nsresult& aChannelStatus, const nsresult& aTransportStatus, const uint64_t& aOffset, const uint32_t& aCount, const nsCString& aData) { LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this)); MOZ_ASSERT(OnSocketThread()); MOZ_RELEASE_ASSERT(!mFlushedForDiversion, "Should not be receiving any more callbacks from parent!"); - RefPtr<HttpChannelChild> self = this; mEventQ->RunOrEnqueue( - new ChannelFunctionEvent([self]() { return self->GetODATarget(); }, - [=]() { - self->OnTransportAndData( - aChannelStatus, aTransportStatus, aOffset, - aCount, aData); - }), + new TransportAndDataEvent(this, aChannelStatus, aTransportStatus, aData, + aOffset, aCount), mDivertingToParent); } -void HttpChannelChild::MaybeDivertOnData(const nsCString& aData, - const uint64_t& aOffset, - const uint32_t& aCount) { +class MaybeDivertOnDataHttpEvent + : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + MaybeDivertOnDataHttpEvent(HttpChannelChild* child, const nsCString& data, + const uint64_t& offset, const uint32_t& count) + : NeckoTargetChannelEvent<HttpChannelChild>(child), + mData(data), + mOffset(offset), + mCount(count) {} + + void Run() override { mChild->MaybeDivertOnData(mData, mOffset, mCount); } + + private: + nsCString mData; + uint64_t mOffset; + uint32_t mCount; +}; + +void HttpChannelChild::MaybeDivertOnData(const nsCString& data, + const uint64_t& offset, + const uint32_t& count) { LOG(("HttpChannelChild::MaybeDivertOnData [this=%p]", this)); if (mDivertingToParent) { - SendDivertOnDataAvailable(aData, aOffset, aCount); + SendDivertOnDataAvailable(data, offset, count); } } -void HttpChannelChild::OnTransportAndData(const nsresult& aChannelStatus, - const nsresult& aTransportStatus, - const uint64_t& aOffset, - const uint32_t& aCount, - const nsCString& aData) { +void HttpChannelChild::OnTransportAndData(const nsresult& channelStatus, + const nsresult& transportStatus, + const uint64_t& offset, + const uint32_t& count, + const nsCString& data) { LOG(("HttpChannelChild::OnTransportAndData [this=%p]\n", this)); if (!mCanceled && NS_SUCCEEDED(mStatus)) { - mStatus = aChannelStatus; + mStatus = channelStatus; } // For diversion to parent, just SendDivertOnDataAvailable. if (mDivertingToParent) { MOZ_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT( !mFlushedForDiversion, "Should not be processing any more callbacks from parent!"); - SendDivertOnDataAvailable(aData, aOffset, aCount); + SendDivertOnDataAvailable(data, offset, count); return; } - if (mCanceled) { - return; - } + if (mCanceled) return; if (mUnknownDecoderInvolved) { LOG(("UnknownDecoder is involved queue OnDataAvailable call. [this=%p]", this)); MOZ_ASSERT(NS_IsMainThread()); - RefPtr<HttpChannelChild> self = this; mUnknownDecoderEventQ.AppendElement( - MakeUnique<NeckoTargetChannelFunctionEvent>( - this, [=]() { self->MaybeDivertOnData(aData, aOffset, aCount); })); + MakeUnique<MaybeDivertOnDataHttpEvent>(this, data, offset, count)); } // Hold queue lock throughout all three calls, else we might process a later // necko msg in between them. AutoEventEnqueuer ensureSerialDispatch(mEventQ); int64_t progressMax; if (NS_FAILED(GetContentLength(&progressMax))) { progressMax = -1; } - const int64_t progress = aOffset + aCount; + const int64_t progress = offset + count; // OnTransportAndData will be run on retargeted thread if applicable, however // OnStatus/OnProgress event can only be fired on main thread. We need to // dispatch the status/progress event handling back to main thread with the // appropriate event target for networking. if (NS_IsMainThread()) { - DoOnStatus(this, aTransportStatus); + DoOnStatus(this, transportStatus); DoOnProgress(this, progress, progressMax); } else { RefPtr<HttpChannelChild> self = this; nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); MOZ_ASSERT(neckoTarget); DebugOnly<nsresult> rv = neckoTarget->Dispatch( NS_NewRunnableFunction( "net::HttpChannelChild::OnTransportAndData", - [self, aTransportStatus, progress, progressMax]() { - self->DoOnStatus(self, aTransportStatus); + [self, transportStatus, progress, progressMax]() { + self->DoOnStatus(self, transportStatus); self->DoOnProgress(self, progress, progressMax); }), NS_DISPATCH_NORMAL); MOZ_ASSERT(NS_SUCCEEDED(rv)); } // OnDataAvailable // // NOTE: the OnDataAvailable contract requires the client to read all the data // in the inputstream. This code relies on that ('data' will go away after // this function). Apparently the previous, non-e10s behavior was to actually // support only reading part of the data, allowing later calls to read the // rest. nsCOMPtr<nsIInputStream> stringStream; nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), - MakeSpan(aData).To(aCount), NS_ASSIGNMENT_DEPEND); + MakeSpan(data).To(count), NS_ASSIGNMENT_DEPEND); if (NS_FAILED(rv)) { Cancel(rv); return; } - DoOnDataAvailable(this, nullptr, stringStream, aOffset, aCount); + DoOnDataAvailable(this, nullptr, stringStream, offset, count); stringStream->Close(); if (NeedToReportBytesRead()) { - mUnreportBytesRead += aCount; + mUnreportBytesRead += count; if (mUnreportBytesRead >= gHttpHandler->SendWindowSize() >> 2) { if (NS_IsMainThread()) { Unused << SendBytesRead(mUnreportBytesRead); } else { // PHttpChannel connects to the main thread RefPtr<HttpChannelChild> self = this; int32_t bytesRead = mUnreportBytesRead; nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); @@ -829,145 +962,172 @@ void HttpChannelChild::DoOnProgress(nsIR mProgressSink->OnProgress(aRequest, nullptr, progress, progressMax); } } } void HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream, - uint64_t aOffset, uint32_t aCount) { + uint64_t offset, uint32_t count) { AUTO_PROFILER_LABEL("HttpChannelChild::DoOnDataAvailable", NETWORK); LOG(("HttpChannelChild::DoOnDataAvailable [this=%p]\n", this)); if (mCanceled) return; if (mListener) { nsCOMPtr<nsIStreamListener> listener(mListener); - nsresult rv = listener->OnDataAvailable(aRequest, aStream, aOffset, aCount); + nsresult rv = listener->OnDataAvailable(aRequest, aStream, offset, count); if (NS_FAILED(rv)) { CancelOnMainThread(rv); } } } +class StopRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + StopRequestEvent(HttpChannelChild* child, const nsresult& channelStatus, + const ResourceTimingStruct& timing, + const nsHttpHeaderArray& aResponseTrailers) + : NeckoTargetChannelEvent<HttpChannelChild>(child), + mChannelStatus(channelStatus), + mTiming(timing), + mResponseTrailers(aResponseTrailers) {} + + void Run() override { + mChild->OnStopRequest(mChannelStatus, mTiming, mResponseTrailers); + } + + private: + nsresult mChannelStatus; + ResourceTimingStruct mTiming; + nsHttpHeaderArray mResponseTrailers; +}; + void HttpChannelChild::ProcessOnStopRequest( const nsresult& aChannelStatus, const ResourceTimingStruct& aTiming, const nsHttpHeaderArray& aResponseTrailers) { LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this)); MOZ_ASSERT(OnSocketThread()); MOZ_RELEASE_ASSERT(!mFlushedForDiversion, "Should not be receiving any more callbacks from parent!"); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, - [=]() { - self->OnStopRequest(aChannelStatus, aTiming, - aResponseTrailers); - }), - mDivertingToParent); + mEventQ->RunOrEnqueue( + new StopRequestEvent(this, aChannelStatus, aTiming, aResponseTrailers), + mDivertingToParent); } +class MaybeDivertOnStopHttpEvent + : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + MaybeDivertOnStopHttpEvent(HttpChannelChild* child, + const nsresult& channelStatus) + : NeckoTargetChannelEvent<HttpChannelChild>(child), + mChannelStatus(channelStatus) {} + + void Run() override { mChild->MaybeDivertOnStop(mChannelStatus); } + + private: + nsresult mChannelStatus; +}; + void HttpChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus) { LOG( ("HttpChannelChild::MaybeDivertOnStop [this=%p, " "mDivertingToParent=%d status=%" PRIx32 "]", this, static_cast<bool>(mDivertingToParent), static_cast<uint32_t>(aChannelStatus))); if (mDivertingToParent) { SendDivertOnStopRequest(aChannelStatus); } } void HttpChannelChild::OnStopRequest( - const nsresult& aChannelStatus, const ResourceTimingStruct& aTiming, + const nsresult& channelStatus, const ResourceTimingStruct& timing, const nsHttpHeaderArray& aResponseTrailers) { LOG(("HttpChannelChild::OnStopRequest [this=%p status=%" PRIx32 "]\n", this, - static_cast<uint32_t>(aChannelStatus))); + static_cast<uint32_t>(channelStatus))); MOZ_ASSERT(NS_IsMainThread()); // If this channel was aborted by ActorDestroy, then there may be other // OnStartRequest/OnStopRequest/OnDataAvailable IPC messages that need to // be handled. In that case we just ignore them to avoid calling the listener // twice. if (mOnStopRequestCalled && mIPCActorDeleted) { return; } if (mDivertingToParent) { MOZ_RELEASE_ASSERT( !mFlushedForDiversion, "Should not be processing any more callbacks from parent!"); - SendDivertOnStopRequest(aChannelStatus); + SendDivertOnStopRequest(channelStatus); return; } if (mUnknownDecoderInvolved) { LOG(("UnknownDecoder is involved queue OnStopRequest call. [this=%p]", this)); MOZ_ASSERT(NS_IsMainThread()); - RefPtr<HttpChannelChild> self = this; mUnknownDecoderEventQ.AppendElement( - MakeUnique<NeckoTargetChannelFunctionEvent>( - this, [=]() { self->MaybeDivertOnStop(aChannelStatus); })); + MakeUnique<MaybeDivertOnStopHttpEvent>(this, channelStatus)); } nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener); if (conv) { conv->GetDecodedDataLength(&mDecodedBodySize); } - mTransactionTimings.domainLookupStart = aTiming.domainLookupStart; - mTransactionTimings.domainLookupEnd = aTiming.domainLookupEnd; - mTransactionTimings.connectStart = aTiming.connectStart; - mTransactionTimings.tcpConnectEnd = aTiming.tcpConnectEnd; - mTransactionTimings.secureConnectionStart = aTiming.secureConnectionStart; - mTransactionTimings.connectEnd = aTiming.connectEnd; - mTransactionTimings.requestStart = aTiming.requestStart; - mTransactionTimings.responseStart = aTiming.responseStart; - mTransactionTimings.responseEnd = aTiming.responseEnd; + mTransactionTimings.domainLookupStart = timing.domainLookupStart; + mTransactionTimings.domainLookupEnd = timing.domainLookupEnd; + mTransactionTimings.connectStart = timing.connectStart; + mTransactionTimings.tcpConnectEnd = timing.tcpConnectEnd; + mTransactionTimings.secureConnectionStart = timing.secureConnectionStart; + mTransactionTimings.connectEnd = timing.connectEnd; + mTransactionTimings.requestStart = timing.requestStart; + mTransactionTimings.responseStart = timing.responseStart; + mTransactionTimings.responseEnd = timing.responseEnd; // Do not overwrite or adjust the original mAsyncOpenTime by timing.fetchStart // We must use the original child process time in order to account for child // side work and IPC transit overhead. // XXX: This depends on TimeStamp being equivalent across processes. // This is true for modern hardware but for older platforms it is not always // true. - mRedirectStartTimeStamp = aTiming.redirectStart; - mRedirectEndTimeStamp = aTiming.redirectEnd; - mTransferSize = aTiming.transferSize; - mEncodedBodySize = aTiming.encodedBodySize; - mProtocolVersion = aTiming.protocolVersion; - - mCacheReadStart = aTiming.cacheReadStart; - mCacheReadEnd = aTiming.cacheReadEnd; + mRedirectStartTimeStamp = timing.redirectStart; + mRedirectEndTimeStamp = timing.redirectEnd; + mTransferSize = timing.transferSize; + mEncodedBodySize = timing.encodedBodySize; + mProtocolVersion = timing.protocolVersion; + + mCacheReadStart = timing.cacheReadStart; + mCacheReadEnd = timing.cacheReadEnd; #ifdef MOZ_GECKO_PROFILER if (profiler_can_accept_markers()) { int32_t priority = PRIORITY_NORMAL; GetPriority(&priority); profiler_add_network_marker( mURI, priority, mChannelId, NetworkLoadType::LOAD_STOP, mLastStatusReported, TimeStamp::Now(), mTransferSize, kCacheUnknown, &mTransactionTimings, nullptr, std::move(mSource)); } #endif mResponseTrailers = new nsHttpHeaderArray(aResponseTrailers); - DoPreOnStopRequest(aChannelStatus); + DoPreOnStopRequest(channelStatus); { // We must flush the queue before we Send__delete__ // (although we really shouldn't receive any msgs after OnStop), // so make sure this goes out of scope before then. AutoEventEnqueuer ensureSerialDispatch(mEventQ); - DoOnStopRequest(this, aChannelStatus, nullptr); + DoOnStopRequest(this, channelStatus, nullptr); // DoOnStopRequest() calls ReleaseListeners() } // If unknownDecoder is involved and the received content is short we will // know whether we need to divert to parent only after OnStopRequest of the // listeners chain is called in DoOnStopRequest. At that moment // unknownDecoder will call OnStartRequest of the real listeners of the // channel including the OnStopRequest of UrlLoader which decides whether we @@ -982,17 +1142,17 @@ void HttpChannelChild::OnStopRequest( CleanupBackgroundChannel(); // If there is a possibility we might want to write alt data to the cache // entry, we keep the channel alive. We still send the DocumentChannelCleanup // message but request the cache entry to be kept by the parent. // If the channel has failed, the cache entry is in a non-writtable state and // we want to release it to not block following consumers. - if (NS_SUCCEEDED(aChannelStatus) && !mPreferredCachedAltDataTypes.IsEmpty()) { + if (NS_SUCCEEDED(channelStatus) && !mPreferredCachedAltDataTypes.IsEmpty()) { mKeptAlive = true; SendDocumentChannelCleanup(false); // don't clear cache entry return; } if (mLoadFlags & LOAD_DOCUMENT_URI) { // Keep IPDL channel open, but only for updating security info. // If IPDL is already closed, then do nothing. @@ -1100,44 +1260,76 @@ void HttpChannelChild::DoOnStopRequest(n if (!mPreferredCachedAltDataTypes.IsEmpty()) { mAltDataCacheEntryAvailable = mCacheEntryAvailable; } mCacheEntryAvailable = false; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); } +class ProgressEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + ProgressEvent(HttpChannelChild* child, const int64_t& progress, + const int64_t& progressMax) + : NeckoTargetChannelEvent<HttpChannelChild>(child), + mProgress(progress), + mProgressMax(progressMax) {} + + void Run() override { + AutoEventEnqueuer ensureSerialDispatch(mChild->mEventQ); + mChild->DoOnProgress(mChild, mProgress, mProgressMax); + } + + private: + int64_t mProgress, mProgressMax; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvOnProgress( const int64_t& aProgress, const int64_t& aProgressMax) { LOG(("HttpChannelChild::RecvOnProgress [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - AutoEventEnqueuer ensureSerialDispatch(mEventQ); - self->DoOnProgress(self, aProgress, aProgressMax); - })); + mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax)); return IPC_OK(); } +class StatusEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + StatusEvent(HttpChannelChild* child, const nsresult& status) + : NeckoTargetChannelEvent<HttpChannelChild>(child), mStatus(status) {} + + void Run() override { + AutoEventEnqueuer ensureSerialDispatch(mChild->mEventQ); + mChild->DoOnStatus(mChild, mStatus); + } + + private: + nsresult mStatus; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvOnStatus( const nsresult& aStatus) { LOG(("HttpChannelChild::RecvOnStatus [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - AutoEventEnqueuer ensureSerialDispatch(self->mEventQ); - self->DoOnStatus(self, aStatus); - })); + mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus)); return IPC_OK(); } +class FailedAsyncOpenEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + FailedAsyncOpenEvent(HttpChannelChild* child, const nsresult& status) + : NeckoTargetChannelEvent<HttpChannelChild>(child), mStatus(status) {} + + void Run() override { mChild->FailedAsyncOpen(mStatus); } + + private: + nsresult mStatus; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvFailedAsyncOpen( - const nsresult& aStatus) { + const nsresult& status) { LOG(("HttpChannelChild::RecvFailedAsyncOpen [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->FailedAsyncOpen(aStatus); })); + mEventQ->RunOrEnqueue(new FailedAsyncOpenEvent(this, status)); return IPC_OK(); } // We need to have an implementation of this function just so that we can keep // all references to mCallOnResume of type HttpChannelChild: it's not OK in C++ // to set a member function ptr to a base class function. void HttpChannelChild::HandleAsyncAbort() { HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort(); @@ -1207,21 +1399,26 @@ void HttpChannelChild::DoNotifyListenerC MaybeCallSynthesizedCallback(); } void HttpChannelChild::DoAsyncAbort(nsresult aStatus) { Unused << AsyncAbort(aStatus); } +class DeleteSelfEvent : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + explicit DeleteSelfEvent(HttpChannelChild* child) + : NeckoTargetChannelEvent<HttpChannelChild>(child) {} + void Run() override { mChild->DeleteSelf(); } +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvDeleteSelf() { LOG(("HttpChannelChild::RecvDeleteSelf [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue( - new NeckoTargetChannelFunctionEvent(this, [=]() { self->DeleteSelf(); })); + mEventQ->RunOrEnqueue(new DeleteSelfEvent(this)); return IPC_OK(); } HttpChannelChild::OverrideRunnable::OverrideRunnable( HttpChannelChild* aChannel, HttpChannelChild* aNewChannel, InterceptStreamListener* aListener, nsIInputStream* aInput, nsIInterceptedBodyCallback* aCallback, nsAutoPtr<nsHttpResponseHead>& aHead, nsICacheInfoChannel* aCacheInfo) @@ -1295,16 +1492,24 @@ mozilla::ipc::IPCResult HttpChannelChild this, &HttpChannelChild::FinishInterceptedRedirect), NS_DISPATCH_NORMAL); return IPC_OK(); } void HttpChannelChild::DeleteSelf() { Send__delete__(this); } +class ContinueDoNotifyListenerEvent + : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + explicit ContinueDoNotifyListenerEvent(HttpChannelChild* child) + : NeckoTargetChannelEvent<HttpChannelChild>(child) {} + void Run() override { mChild->ContinueDoNotifyListener(); } +}; + void HttpChannelChild::DoNotifyListener() { LOG(("HttpChannelChild::DoNotifyListener this=%p", this)); MOZ_ASSERT(NS_IsMainThread()); // In case nsHttpChannel::OnStartRequest wasn't called (e.g. due to flag // LOAD_ONLY_IF_MODIFIED) we want to set mAfterOnStartRequestBegun to true // before notifying listener. if (!mAfterOnStartRequestBegun) { @@ -1313,19 +1518,17 @@ void HttpChannelChild::DoNotifyListener( if (mListener && !mOnStartRequestCalled) { nsCOMPtr<nsIStreamListener> listener = mListener; mOnStartRequestCalled = true; // avoid reentrancy bugs by setting this now listener->OnStartRequest(this); } mOnStartRequestCalled = true; - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=] { self->ContinueDoNotifyListener(); })); + mEventQ->RunOrEnqueue(new ContinueDoNotifyListenerEvent(this)); } void HttpChannelChild::ContinueDoNotifyListener() { LOG(("HttpChannelChild::ContinueDoNotifyListener this=%p", this)); MOZ_ASSERT(NS_IsMainThread()); // Make sure mIsPending is set to false. At this moment we are done from // the point of view of our consumer and we have to report our self @@ -1389,38 +1592,73 @@ void HttpChannelChild::FinishIntercepted mozilla::ipc::IPCResult HttpChannelChild::RecvReportSecurityMessage( const nsString& messageTag, const nsString& messageCategory) { DebugOnly<nsresult> rv = AddSecurityMessage(messageTag, messageCategory); MOZ_ASSERT(NS_SUCCEEDED(rv)); return IPC_OK(); } +class Redirect1Event : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + Redirect1Event(HttpChannelChild* child, const uint32_t& registrarId, + const URIParams& newURI, const uint32_t& newLoadFlags, + const uint32_t& redirectFlags, + const ParentLoadInfoForwarderArgs& loadInfoForwarder, + const nsHttpResponseHead& responseHead, + const nsACString& securityInfoSerialization, + const uint64_t& channelId, const ResourceTimingStruct& timing) + : NeckoTargetChannelEvent<HttpChannelChild>(child), + mRegistrarId(registrarId), + mNewURI(newURI), + mNewLoadFlags(newLoadFlags), + mRedirectFlags(redirectFlags), + mResponseHead(responseHead), + mSecurityInfoSerialization(securityInfoSerialization), + mChannelId(channelId), + mLoadInfoForwarder(loadInfoForwarder), + mTiming(timing) {} + + void Run() override { + mChild->Redirect1Begin(mRegistrarId, mNewURI, mNewLoadFlags, mRedirectFlags, + mLoadInfoForwarder, mResponseHead, + mSecurityInfoSerialization, mChannelId, mTiming); + } + + private: + uint32_t mRegistrarId; + URIParams mNewURI; + uint32_t mNewLoadFlags; + uint32_t mRedirectFlags; + nsHttpResponseHead mResponseHead; + nsCString mSecurityInfoSerialization; + uint64_t mChannelId; + ParentLoadInfoForwarderArgs mLoadInfoForwarder; + ResourceTimingStruct mTiming; +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvRedirect1Begin( - const uint32_t& aRegistrarId, const URIParams& aNewUri, - const uint32_t& aNewLoadFlags, const uint32_t& aRedirectFlags, - const ParentLoadInfoForwarderArgs& aLoadInfoForwarder, - const nsHttpResponseHead& aResponseHead, - const nsCString& aSecurityInfoSerialization, const uint64_t& aChannelId, - const NetAddr& aOldPeerAddr, const ResourceTimingStruct& aTiming) { + const uint32_t& registrarId, const URIParams& newUri, + const uint32_t& newLoadFlags, const uint32_t& redirectFlags, + const ParentLoadInfoForwarderArgs& loadInfoForwarder, + const nsHttpResponseHead& responseHead, + const nsCString& securityInfoSerialization, const uint64_t& channelId, + const NetAddr& oldPeerAddr, const ResourceTimingStruct& timing) { // TODO: handle security info LOG(("HttpChannelChild::RecvRedirect1Begin [this=%p]\n", this)); // We set peer address of child to the old peer, // Then it will be updated to new peer in OnStartRequest - mPeerAddr = aOldPeerAddr; + mPeerAddr = oldPeerAddr; // Cookies headers should not be visible to the child process - MOZ_ASSERT(!nsHttpResponseHead(aResponseHead).HasHeader(nsHttp::Set_Cookie)); - - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - self->Redirect1Begin(aRegistrarId, aNewUri, aNewLoadFlags, aRedirectFlags, - aLoadInfoForwarder, aResponseHead, - aSecurityInfoSerialization, aChannelId, aTiming); - })); + MOZ_ASSERT(!nsHttpResponseHead(responseHead).HasHeader(nsHttp::Set_Cookie)); + + mEventQ->RunOrEnqueue(new Redirect1Event( + this, registrarId, newUri, newLoadFlags, redirectFlags, loadInfoForwarder, + responseHead, securityInfoSerialization, channelId, timing)); return IPC_OK(); } nsresult HttpChannelChild::SetupRedirect(nsIURI* uri, const nsHttpResponseHead* responseHead, const uint32_t& redirectFlags, nsIChannel** outChannel) { LOG(("HttpChannelChild::SetupRedirect [this=%p]\n", this)); @@ -1595,107 +1833,119 @@ void HttpChannelChild::BeginNonIPCRedire void HttpChannelChild::OverrideSecurityInfoForNonIPCRedirect( nsISupports* securityInfo) { mResponseCouldBeSynthesized = true; DebugOnly<nsresult> rv = OverrideSecurityInfo(securityInfo); MOZ_ASSERT(NS_SUCCEEDED(rv)); } +class Redirect3Event : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + explicit Redirect3Event(HttpChannelChild* child) + : NeckoTargetChannelEvent<HttpChannelChild>(child) {} + void Run() override { mChild->Redirect3Complete(nullptr); } +}; + mozilla::ipc::IPCResult HttpChannelChild::RecvRedirect3Complete() { LOG(("HttpChannelChild::RecvRedirect3Complete [this=%p]\n", this)); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [self]() { self->Redirect3Complete(nullptr); })); + mEventQ->RunOrEnqueue(new Redirect3Event(this)); return IPC_OK(); } +class HttpFlushedForDiversionEvent + : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + explicit HttpFlushedForDiversionEvent(HttpChannelChild* aChild) + : NeckoTargetChannelEvent<HttpChannelChild>(aChild) { + MOZ_RELEASE_ASSERT(aChild); + } + + void Run() override { mChild->FlushedForDiversion(); } +}; + void HttpChannelChild::ProcessFlushedForDiversion() { LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this)); MOZ_ASSERT(OnSocketThread()); MOZ_RELEASE_ASSERT(mDivertingToParent); - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [self]() { self->FlushedForDiversion(); }), - true); + mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true); } -mozilla::ipc::IPCResult -HttpChannelChild::RecvNotifyChannelClassifierProtectionDisabled( - const uint32_t& aAcceptedReason) { +void HttpChannelChild::ProcessNotifyChannelClassifierProtectionDisabled( + uint32_t aAcceptedReason) { LOG( - ("HttpChannelChild::RecvNotifyChannelClassifierProtectionDisabled " + ("HttpChannelChild::ProcessNotifyChannelClassifierProtectionDisabled " "[this=%p aAcceptedReason=%" PRIu32 "]\n", this, aAcceptedReason)); - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(OnSocketThread()); RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=] { - UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( - self, aAcceptedReason); - })); - - return IPC_OK(); + nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); + neckoTarget->Dispatch( + NS_NewRunnableFunction( + "AntiTrackingCommon::NotifyChannelClassifierProtectionDisabled", + [self, aAcceptedReason]() { + UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( + self, aAcceptedReason); + }), + NS_DISPATCH_NORMAL); } -mozilla::ipc::IPCResult HttpChannelChild::RecvNotifyCookieAllowed() { - LOG(("HttpChannelChild::RecvNotifyCookieAllowed [this=%p]\n", this)); - MOZ_ASSERT(NS_IsMainThread()); +void HttpChannelChild::ProcessNotifyCookieAllowed() { + LOG(("HttpChannelChild::ProcessNotifyCookieAllowed [this=%p]\n", this)); + MOZ_ASSERT(OnSocketThread()); RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=] { - AntiTrackingCommon::NotifyBlockingDecision( - self, AntiTrackingCommon::BlockingDecision::eAllow, 0); - })); - - return IPC_OK(); + nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); + neckoTarget->Dispatch( + NS_NewRunnableFunction( + "UrlClassifierCommon::NotifyBlockingDecision", + [self]() { + AntiTrackingCommon::NotifyBlockingDecision( + self, AntiTrackingCommon::BlockingDecision::eAllow, 0); + }), + NS_DISPATCH_NORMAL); } -mozilla::ipc::IPCResult HttpChannelChild::RecvNotifyCookieBlocked( - const uint32_t& aRejectedReason) { - LOG(("HttpChannelChild::RecvNotifyCookieBlocked [this=%p]\n", this)); - MOZ_ASSERT(NS_IsMainThread()); +void HttpChannelChild::ProcessNotifyCookieBlocked(uint32_t aRejectedReason) { + LOG(("HttpChannelChild::ProcessNotifyCookieBlocked [this=%p]\n", this)); + MOZ_ASSERT(OnSocketThread()); RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=] { - AntiTrackingCommon::NotifyBlockingDecision( - self, AntiTrackingCommon::BlockingDecision::eBlock, aRejectedReason); - })); - - return IPC_OK(); + nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); + neckoTarget->Dispatch( + NS_NewRunnableFunction("AntiTrackingCommon::NotifyBlockingDecision", + [self, aRejectedReason]() { + AntiTrackingCommon::NotifyBlockingDecision( + self, + AntiTrackingCommon::BlockingDecision::eBlock, + aRejectedReason); + }), + NS_DISPATCH_NORMAL); } -mozilla::ipc::IPCResult HttpChannelChild::RecvNotifyClassificationFlags( - const uint32_t& aClassificationFlags, const bool& aIsThirdParty) { +void HttpChannelChild::ProcessNotifyClassificationFlags( + uint32_t aClassificationFlags, bool aIsThirdParty) { LOG( - ("HttpChannelChild::RecvNotifyClassificationFlags thirdparty=%d " + ("HttpChannelChild::ProcessNotifyClassificationFlags thirdparty=%d " "flags=%" PRIu32 " [this=%p]\n", static_cast<int>(aIsThirdParty), aClassificationFlags, this)); - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=] { - self->AddClassificationFlags(aClassificationFlags, aIsThirdParty); - })); - - return IPC_OK(); + MOZ_ASSERT(OnSocketThread()); + + AddClassificationFlags(aClassificationFlags, aIsThirdParty); } -mozilla::ipc::IPCResult HttpChannelChild::RecvNotifyFlashPluginStateChanged( - const nsIHttpChannel::FlashPluginState& aState) { - LOG(("HttpChannelChild::RecvNotifyFlashPluginStateChanged [this=%p]\n", +void HttpChannelChild::ProcessNotifyFlashPluginStateChanged( + nsIHttpChannel::FlashPluginState aState) { + LOG(("HttpChannelChild::ProcessNotifyFlashPluginStateChanged [this=%p]\n", this)); - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=] { self->SetFlashPluginState(aState); })); - - return IPC_OK(); + MOZ_ASSERT(OnSocketThread()); + + SetFlashPluginState(aState); } void HttpChannelChild::FlushedForDiversion() { LOG(("HttpChannelChild::FlushedForDiversion [this=%p]\n", this)); MOZ_RELEASE_ASSERT(mDivertingToParent); // Once this is set, it should not be unset before HttpChannelChild is taken // down. After it is set, no OnStart/OnData/OnStop callbacks should be @@ -1704,48 +1954,50 @@ void HttpChannelChild::FlushedForDiversi // If we're synthesized, it's up to the SyntheticDiversionListener to invoke // SendDivertComplete after it has sent the DivertOnStopRequestMessage. if (!mSynthesizedResponse) { SendDivertComplete(); } } -mozilla::ipc::IPCResult HttpChannelChild::RecvSetClassifierMatchedInfo( - const ClassifierInfo& aInfo) { - LOG(("HttpChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", this)); - MOZ_ASSERT(NS_IsMainThread()); - - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(this, [=]() { - self->SetMatchedInfo(aInfo.list(), aInfo.provider(), aInfo.fullhash()); - })); - - return IPC_OK(); +void HttpChannelChild::ProcessSetClassifierMatchedInfo( + const nsCString& aList, const nsCString& aProvider, + const nsCString& aFullHash) { + LOG(("HttpChannelChild::ProcessSetClassifierMatchedInfo [this=%p]\n", this)); + MOZ_ASSERT(OnSocketThread()); + + nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); + neckoTarget->Dispatch( + NewRunnableMethod<const nsCString, const nsCString, const nsCString>( + "HttpChannelChild::SetMatchedInfo", this, + &HttpChannelChild::SetMatchedInfo, aList, aProvider, aFullHash), + NS_DISPATCH_NORMAL); } -mozilla::ipc::IPCResult HttpChannelChild::RecvSetClassifierMatchedTrackingInfo( - const ClassifierInfo& aInfo) { - LOG(("HttpChannelChild::RecvSetClassifierMatchedTrackingInfo [this=%p]\n", +void HttpChannelChild::ProcessSetClassifierMatchedTrackingInfo( + const nsCString& aLists, const nsCString& aFullHashes) { + LOG(("HttpChannelChild::ProcessSetClassifierMatchedTrackingInfo [this=%p]\n", this)); - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(OnSocketThread()); nsTArray<nsCString> lists, fullhashes; - for (const nsACString& token : aInfo.list().Split(',')) { + for (const nsACString& token : aLists.Split(',')) { lists.AppendElement(token); } - for (const nsACString& token : aInfo.fullhash().Split(',')) { + for (const nsACString& token : aFullHashes.Split(',')) { fullhashes.AppendElement(token); } - RefPtr<HttpChannelChild> self = this; - mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent( - this, [=]() { self->SetMatchedTrackingInfo(lists, fullhashes); })); - - return IPC_OK(); + nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget(); + neckoTarget->Dispatch( + NewRunnableMethod<const nsTArray<nsCString>, const nsTArray<nsCString>>( + "HttpChannelChild::SetMatchedTrackingInfo", this, + &HttpChannelChild::SetMatchedTrackingInfo, lists, fullhashes), + NS_DISPATCH_NORMAL); } void HttpChannelChild::ProcessDivertMessages() { LOG(("HttpChannelChild::ProcessDivertMessages [this=%p]\n", this)); MOZ_ASSERT(OnSocketThread()); MOZ_RELEASE_ASSERT(mDivertingToParent); // DivertTo() has been called on parent, so we can now start sending queued @@ -1904,17 +2156,17 @@ HttpChannelChild::ConnectParent(uint32_t mBgChild = bgChild.forget(); } return NS_OK; } NS_IMETHODIMP -HttpChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener, +HttpChannelChild::CompleteRedirectSetup(nsIStreamListener* listener, nsISupports* aContext) { LOG(("HttpChannelChild::FinishRedirectSetup [this=%p]\n", this)); MOZ_ASSERT(NS_IsMainThread()); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); if (mShouldParentIntercept) { @@ -1926,17 +2178,17 @@ HttpChannelChild::CompleteRedirectSetup( // Since this method is called from RecvRedirect3Complete which itself is // called from either OnRedirectVerifyCallback via OverrideRunnable, or from // RecvRedirect3Complete. The order of events must always be: // 1. Teardown the IPDL connection // 2. AsyncOpen the connection again // 3. Cleanup the redirecting channel (the one calling Redirect3Complete) // 4. [optional] Call OverrideWithSynthesizedResponse on the redirected // channel if the call came from OverrideRunnable. - mInterceptedRedirectListener = aListener; + mInterceptedRedirectListener = listener; mInterceptedRedirectContext = aContext; // This will send a message to the parent notifying it that we are closing // down. After closing the IPC channel, we will proceed to execute // FinishInterceptedRedirect() which AsyncOpen's the channel again. SendFinishInterceptedRedirect(); // XXX valentin: The interception logic should be rewritten to avoid @@ -1953,50 +2205,50 @@ HttpChannelChild::CompleteRedirectSetup( mLastStatusReported = TimeStamp::Now(); PROFILER_ADD_NETWORK_MARKER(mURI, mPriority, mChannelId, NetworkLoadType::LOAD_START, mChannelCreationTimestamp, mLastStatusReported, 0, kCacheUnknown, nullptr, nullptr); mIsPending = true; mWasOpened = true; - mListener = aListener; + mListener = listener; // add ourselves to the load group. if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); // We already have an open IPDL connection to the parent. If on-modify-request // listeners or load group observers canceled us, let the parent handle it // and send it back to us naturally. return NS_OK; } //----------------------------------------------------------------------------- // HttpChannelChild::nsIAsyncVerifyRedirectCallback //----------------------------------------------------------------------------- NS_IMETHODIMP -HttpChannelChild::OnRedirectVerifyCallback(nsresult aResult) { +HttpChannelChild::OnRedirectVerifyCallback(nsresult result) { LOG(("HttpChannelChild::OnRedirectVerifyCallback [this=%p]\n", this)); MOZ_ASSERT(NS_IsMainThread()); Maybe<URIParams> redirectURI; nsresult rv; nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(mRedirectChannelChild); - if (NS_SUCCEEDED(aResult) && !mRedirectChannelChild) { + if (NS_SUCCEEDED(result) && !mRedirectChannelChild) { // mRedirectChannelChild doesn't exist means we're redirecting to a protocol // that doesn't implement nsIChildChannel. The redirect result should be set // as failed by veto listeners and shouldn't enter this condition. As the // last resort, we synthesize the error result as NS_ERROR_DOM_BAD_URI here // to let nsHttpChannel::ContinueProcessResponse2 know it's redirecting to // another protocol and throw an error. LOG((" redirecting to a protocol that doesn't implement nsIChildChannel")); - aResult = NS_ERROR_DOM_BAD_URI; + result = NS_ERROR_DOM_BAD_URI; } nsCOMPtr<nsIReferrerInfo> referrerInfo; if (newHttpChannel) { // Must not be called until after redirect observers called. newHttpChannel->SetOriginalURI(mOriginalURI); referrerInfo = newHttpChannel->GetReferrerInfo(); } @@ -2029,29 +2281,29 @@ HttpChannelChild::OnRedirectVerifyCallba RequestHeaderTuples emptyHeaders; RequestHeaderTuples* headerTuples = &emptyHeaders; nsLoadFlags loadFlags = 0; Maybe<CorsPreflightArgs> corsPreflightArgs; nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild = do_QueryInterface(mRedirectChannelChild); - if (newHttpChannelChild && NS_SUCCEEDED(aResult)) { + if (newHttpChannelChild && NS_SUCCEEDED(result)) { rv = newHttpChannelChild->AddCookiesToRequest(); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples); MOZ_ASSERT(NS_SUCCEEDED(rv)); newHttpChannelChild->GetClientSetCorsPreflightParameters(corsPreflightArgs); } /* If the redirect was canceled, bypass OMR and send an empty API * redirect URI */ SerializeURI(nullptr, redirectURI); - if (NS_SUCCEEDED(aResult)) { + if (NS_SUCCEEDED(result)) { // Note: this is where we would notify "http-on-modify-response" observers. // We have deliberately disabled this for child processes (see bug 806753) // // After we verify redirect, nsHttpChannel may hit the network: must give // "http-on-modify-request" observers the chance to cancel before that. // base->CallOnModifyRequestObservers(); nsCOMPtr<nsIHttpChannelInternal> newHttpChannelInternal = @@ -2093,56 +2345,56 @@ HttpChannelChild::OnRedirectVerifyCallba newChannelLoadInfo = newChannel->LoadInfo(); } ChildLoadInfoForwarderArgs targetLoadInfoForwarder; LoadInfoToChildLoadInfoForwarder(newChannelLoadInfo, &targetLoadInfoForwarder); if (CanSend()) - SendRedirect2Verify(aResult, *headerTuples, sourceRequestBlockingReason, + SendRedirect2Verify(result, *headerTuples, sourceRequestBlockingReason, targetLoadInfoForwarder, loadFlags, referrerInfo, redirectURI, corsPreflightArgs, chooseAppcache); return NS_OK; } //----------------------------------------------------------------------------- // HttpChannelChild::nsIRequest //----------------------------------------------------------------------------- NS_IMETHODIMP -HttpChannelChild::Cancel(nsresult aStatus) { +HttpChannelChild::Cancel(nsresult status) { LOG(("HttpChannelChild::Cancel [this=%p, status=%" PRIx32 "]\n", this, - static_cast<uint32_t>(aStatus))); + static_cast<uint32_t>(status))); LogCallingScriptLocation(this); MOZ_ASSERT(NS_IsMainThread()); if (!mCanceled) { // If this cancel occurs before nsHttpChannel has been set up, AsyncOpen // is responsible for cleaning up. mCanceled = true; - mStatus = aStatus; + mStatus = status; if (RemoteChannelExists()) { - SendCancel(aStatus); + SendCancel(status); } // If the channel is intercepted and already pumping, then just // cancel the pump. This will call OnStopRequest(). if (mSynthesizedResponsePump) { - mSynthesizedResponsePump->Cancel(aStatus); + mSynthesizedResponsePump->Cancel(status); } // If we are canceled while intercepting, but not yet pumping, then // we must call AsyncAbort() to trigger OnStopRequest(). else if (mInterceptListener) { mInterceptListener->Cleanup(); mInterceptListener = nullptr; - Unused << AsyncAbort(aStatus); + Unused << AsyncAbort(status); } } return NS_OK; } NS_IMETHODIMP HttpChannelChild::Suspend() { LOG(("HttpChannelChild::Suspend [this=%p, mSuspendCount=%" PRIu32 ", " @@ -3491,31 +3743,47 @@ nsresult HttpChannelChild::SetReferrerHe mClientSetRequestHeaders[i].mHeader)) { mClientSetRequestHeaders.RemoveElementAt(i); } } return HttpBaseChannel::SetReferrerHeader(aReferrer, aRespectBeforeConnect); } +class CancelEvent final : public NeckoTargetChannelEvent<HttpChannelChild> { + public: + CancelEvent(HttpChannelChild* aChild, nsresult aRv) + : NeckoTargetChannelEvent<HttpChannelChild>(aChild), mRv(aRv) { + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(aChild); + } + + void Run() override { + MOZ_ASSERT(NS_IsMainThread()); + mChild->Cancel(mRv); + } + + private: + const nsresult mRv; +}; + void HttpChannelChild::CancelOnMainThread(nsresult aRv) { LOG(("HttpChannelChild::CancelOnMainThread [this=%p]", this)); if (NS_IsMainThread()) { Cancel(aRv); return; } mEventQ->Suspend(); // Cancel is expected to preempt any other channel events, thus we put this // event in the front of mEventQ to make sure nsIStreamListener not receiving // any ODA/OnStopRequest callbacks. - RefPtr<HttpChannelChild> self = this; - mEventQ->PrependEvent(MakeUnique<NeckoTargetChannelFunctionEvent>( - this, [self, aRv]() { self->Cancel(aRv); })); + UniquePtr<ChannelEvent> cancelEvent = MakeUnique<CancelEvent>(this, aRv); + mEventQ->PrependEvent(cancelEvent); mEventQ->Resume(); } void HttpChannelChild::OverrideWithSynthesizedResponse( nsAutoPtr<nsHttpResponseHead>& aResponseHead, nsIInputStream* aSynthesizedInput, nsIInterceptedBodyCallback* aSynthesizedCallback, InterceptStreamListener* aStreamListener,
--- a/netwerk/protocol/http/HttpChannelChild.h +++ b/netwerk/protocol/http/HttpChannelChild.h @@ -177,36 +177,16 @@ class HttpChannelChild final : public PH const Maybe<IPCStream>& aStream) override; mozilla::ipc::IPCResult RecvAltDataCacheInputStreamAvailable( const Maybe<IPCStream>& aStream) override; mozilla::ipc::IPCResult RecvOverrideReferrerInfoDuringBeginConnect( nsIReferrerInfo* aReferrerInfo) override; - mozilla::ipc::IPCResult RecvNotifyChannelClassifierProtectionDisabled( - const uint32_t& aAcceptedReason) override; - - mozilla::ipc::IPCResult RecvNotifyCookieAllowed() override; - - mozilla::ipc::IPCResult RecvNotifyCookieBlocked( - const uint32_t& aRejectedReason) override; - - mozilla::ipc::IPCResult RecvNotifyClassificationFlags( - const uint32_t& aClassificationFlags, const bool& aIsThirdParty) override; - - mozilla::ipc::IPCResult RecvNotifyFlashPluginStateChanged( - const nsIHttpChannel::FlashPluginState& aState) override; - - mozilla::ipc::IPCResult RecvSetClassifierMatchedInfo( - const ClassifierInfo& info) override; - - mozilla::ipc::IPCResult RecvSetClassifierMatchedTrackingInfo( - const ClassifierInfo& info) override; - virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual void DoNotifyListenerCleanup() override; virtual void DoAsyncAbort(nsresult aStatus) override; nsresult AsyncCall( void (HttpChannelChild::*funcPtr)(), @@ -285,16 +265,29 @@ class HttpChannelChild final : public PH const uint64_t& aOffset, const uint32_t& aCount, const nsCString& aData); void ProcessOnStopRequest(const nsresult& aStatusCode, const ResourceTimingStruct& aTiming, const nsHttpHeaderArray& aResponseTrailers); void ProcessFlushedForDiversion(); void ProcessDivertMessages(); + void ProcessNotifyChannelClassifierProtectionDisabled( + uint32_t aAcceptedReason); + void ProcessNotifyCookieAllowed(); + void ProcessNotifyCookieBlocked(uint32_t aRejectedReason); + void ProcessNotifyClassificationFlags(uint32_t aClassificationFlags, + bool aIsThirdParty); + void ProcessNotifyFlashPluginStateChanged( + nsIHttpChannel::FlashPluginState aState); + void ProcessSetClassifierMatchedInfo(const nsCString& aList, + const nsCString& aProvider, + const nsCString& aFullHash); + void ProcessSetClassifierMatchedTrackingInfo(const nsCString& aLists, + const nsCString& aFullHashes); // Return true if we need to tell the parent the size of unreported received // data bool NeedToReportBytesRead(); int32_t mUnreportBytesRead = 0; void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext); void DoOnStatus(nsIRequest* aRequest, nsresult status); @@ -525,21 +518,36 @@ class HttpChannelChild final : public PH bool responseRedirected); // Override the default security info pointer during a non-IPC redirection. void OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo); // Collect telemetry for the successful rate of OMT. void CollectOMTTelemetry(); + friend class AssociateApplicationCacheEvent; + friend class StartRequestEvent; + friend class StopRequestEvent; + friend class TransportAndDataEvent; + friend class MaybeDivertOnDataHttpEvent; + friend class MaybeDivertOnStopHttpEvent; + friend class ProgressEvent; + friend class StatusEvent; + friend class FailedAsyncOpenEvent; + friend class Redirect1Event; + friend class Redirect3Event; + friend class DeleteSelfEvent; + friend class HttpFlushedForDiversionEvent; + friend class CancelEvent; friend class HttpAsyncAborter<HttpChannelChild>; friend class InterceptStreamListener; friend class InterceptedChannelContent; friend class HttpBackgroundChannelChild; - friend class NeckoTargetChannelFunctionEvent; + friend class NeckoTargetChannelEvent<HttpChannelChild>; + friend class ContinueDoNotifyListenerEvent; }; NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelChild, HTTP_CHANNEL_CHILD_IID) // A stream listener interposed between the nsInputStreamPump used for // intercepted channels and this channel's original listener. This is only used // to ensure the original listener sees the channel as the request object, and // to synthesize OnStatus and OnProgress notifications.
--- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -1849,90 +1849,92 @@ HttpChannelParent::SetParentListener(Par NS_IMETHODIMP HttpChannelParent::NotifyChannelClassifierProtectionDisabled( uint32_t aAcceptedReason) { LOG( ("HttpChannelParent::NotifyChannelClassifierProtectionDisabled [this=%p " "aAcceptedReason=%" PRIu32 "]\n", this, aAcceptedReason)); if (!mIPCClosed) { - Unused << SendNotifyChannelClassifierProtectionDisabled(aAcceptedReason); + MOZ_ASSERT(mBgParent); + Unused << NS_WARN_IF( + !mBgParent->OnNotifyChannelClassifierProtectionDisabled( + aAcceptedReason)); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::NotifyCookieAllowed() { LOG(("HttpChannelParent::NotifyCookieAllowed [this=%p]\n", this)); if (!mIPCClosed) { - Unused << SendNotifyCookieAllowed(); + MOZ_ASSERT(mBgParent); + Unused << NS_WARN_IF(!mBgParent->OnNotifyCookieAllowed()); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::NotifyCookieBlocked(uint32_t aRejectedReason) { LOG(("HttpChannelParent::NotifyCookieBlocked [this=%p]\n", this)); if (!mIPCClosed) { - Unused << SendNotifyCookieBlocked(aRejectedReason); + MOZ_ASSERT(mBgParent); + Unused << NS_WARN_IF(!mBgParent->OnNotifyCookieBlocked(aRejectedReason)); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::SetClassifierMatchedInfo(const nsACString& aList, const nsACString& aProvider, const nsACString& aFullHash) { LOG(("HttpChannelParent::SetClassifierMatchedInfo [this=%p]\n", this)); if (!mIPCClosed) { - ClassifierInfo info; - info.list() = aList; - info.provider() = aProvider; - info.fullhash() = aFullHash; - - Unused << SendSetClassifierMatchedInfo(info); + MOZ_ASSERT(mBgParent); + Unused << mBgParent->OnSetClassifierMatchedInfo(aList, aProvider, + aFullHash); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::SetClassifierMatchedTrackingInfo( const nsACString& aLists, const nsACString& aFullHashes) { LOG(("HttpChannelParent::SetClassifierMatchedTrackingInfo [this=%p]\n", this)); if (!mIPCClosed) { - ClassifierInfo info; - info.list() = aLists; - info.fullhash() = aFullHashes; - - Unused << SendSetClassifierMatchedTrackingInfo(info); + MOZ_ASSERT(mBgParent); + Unused << mBgParent->OnSetClassifierMatchedTrackingInfo(aLists, + aFullHashes); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags, bool aIsThirdParty) { LOG( ("HttpChannelParent::NotifyClassificationFlags " "classificationFlags=%" PRIu32 ", thirdparty=%d [this=%p]\n", aClassificationFlags, static_cast<int>(aIsThirdParty), this)); if (!mIPCClosed) { - Unused << SendNotifyClassificationFlags(aClassificationFlags, - aIsThirdParty); + MOZ_ASSERT(mBgParent); + Unused << mBgParent->OnNotifyClassificationFlags(aClassificationFlags, + aIsThirdParty); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::NotifyFlashPluginStateChanged( nsIHttpChannel::FlashPluginState aState) { LOG(("HttpChannelParent::NotifyFlashPluginStateChanged [this=%p]\n", this)); if (!mIPCClosed) { - Unused << SendNotifyFlashPluginStateChanged(aState); + MOZ_ASSERT(mBgParent); + Unused << mBgParent->OnNotifyFlashPluginStateChanged(aState); } return NS_OK; } NS_IMETHODIMP HttpChannelParent::Delete() { if (!mIPCClosed) Unused << DoSendDeleteSelf();
--- a/netwerk/protocol/http/PHttpBackgroundChannel.ipdl +++ b/netwerk/protocol/http/PHttpBackgroundChannel.ipdl @@ -2,21 +2,23 @@ /* 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 PBackground; include NeckoChannelParams; +include PURLClassifierInfo; include "mozilla/net/NeckoMessageUtils.h"; using class nsHttpHeaderArray from "nsHttpHeaderArray.h"; using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h"; +using nsIHttpChannel::FlashPluginState from "mozilla/net/NeckoMessageUtils.h"; namespace mozilla { namespace net { //------------------------------------------------------------------- async refcounted protocol PHttpBackgroundChannel { manager PBackground; @@ -43,14 +45,38 @@ child: // Parent has been suspended for diversion; no more events to be enqueued. async FlushedForDiversion(); // Child should resume processing the ChannelEventQueue, i.e. diverting any // OnDataAvailable and OnStopRequest messages in the queue back to the parent. async DivertMessages(); + // Tell the child that channel classifier protection was disabled for this + // load. + async NotifyChannelClassifierProtectionDisabled(uint32_t aAcceptedReason); + + // Tell the child that cookies are allowed for this load. + async NotifyCookieAllowed(); + + // Tell the child that tracking cookies are blocked for this load. + async NotifyCookieBlocked(uint32_t aRejectedReason); + + // Tell the child that the resource being loaded has been classified. + async NotifyClassificationFlags(uint32_t aClassificationFlags, bool aIsThirdParty); + + // Tell the child that the current channel's document is not allowed to load + // flash content. + async NotifyFlashPluginStateChanged(FlashPluginState aState); + + // Tell the child information of matched URL againts SafeBrowsing list + async SetClassifierMatchedInfo(ClassifierInfo info); + + // Tell the child information of matched URL againts SafeBrowsing tracking list + async SetClassifierMatchedTrackingInfo(ClassifierInfo info); + async __delete__(); }; + } // namespace net } // namespace mozilla
--- a/netwerk/protocol/http/PHttpChannel.ipdl +++ b/netwerk/protocol/http/PHttpChannel.ipdl @@ -8,25 +8,23 @@ include protocol PNecko; include protocol PStreamFilter; include InputStreamParams; include URIParams; include PBackgroundSharedTypes; include NeckoChannelParams; include IPCServiceWorkerDescriptor; include IPCStream; -include PURLClassifierInfo; include "mozilla/net/NeckoMessageUtils.h"; using class nsHttpHeaderArray from "nsHttpHeaderArray.h"; using mozilla::net::NetAddr from "mozilla/net/DNS.h"; using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h"; using refcounted class nsIReferrerInfo from "mozilla/dom/ReferrerInfoUtils.h"; -using nsIHttpChannel::FlashPluginState from "mozilla/net/NeckoMessageUtils.h"; namespace mozilla { namespace net { //------------------------------------------------------------------- refcounted protocol PHttpChannel { manager PNecko; @@ -191,39 +189,16 @@ child: async AltDataCacheInputStreamAvailable(IPCStream? stream); async OverrideReferrerInfoDuringBeginConnect(nsIReferrerInfo referrerInfo); async OnProgress(int64_t progress, int64_t progressMax); async OnStatus(nsresult status); - // Tell the child that channel classifier protection was disabled for this - // load. - async NotifyChannelClassifierProtectionDisabled(uint32_t aAcceptedReason); - - // Tell the child that cookies are allowed for this load. - async NotifyCookieAllowed(); - - // Tell the child that tracking cookies are blocked for this load. - async NotifyCookieBlocked(uint32_t aRejectedReason); - - // Tell the child that the resource being loaded has been classified. - async NotifyClassificationFlags(uint32_t aClassificationFlags, bool aIsThirdParty); - - // Tell the child that the current channel's document is not allowed to load - // flash content. - async NotifyFlashPluginStateChanged(FlashPluginState aState); - - // Tell the child information of matched URL againts SafeBrowsing list - async SetClassifierMatchedInfo(ClassifierInfo info); - - // Tell the child information of matched URL againts SafeBrowsing tracking list - async SetClassifierMatchedTrackingInfo(ClassifierInfo info); - both: // After receiving this message, the parent also calls // SendFinishInterceptedRedirect, and makes sure not to send any more messages // after that. When receiving this message, the child will call // Send__delete__() and complete the steps required to finish the redirect. async FinishInterceptedRedirect(); async SetPriority(int16_t priority);
--- a/toolkit/components/antitracking/test/browser/browser.ini +++ b/toolkit/components/antitracking/test/browser/browser.ini @@ -124,21 +124,21 @@ support-files = localStorageEvents.html skip-if = fission support-files = workerIframe.html [browser_cookieBetweenTabs.js] [browser_partitionedMessaging.js] skip-if = true #Bug 1588241 [browser_partitionedIndexedDB.js] skip-if = fission [browser_partitionedCookies.js] -skip-if = fission +skip-if = fission || os == "mac" || os == "win" #Bug 1590649 support-files = cookies.sjs [browser_partitionedDOMCache.js] skip-if = fission [browser_partitionedServiceWorkers.js] skip-if = fission support-files = matchAll.js [browser_partitionedSharedWorkers.js] -skip-if = fission +skip-if = fission || (os == 'win') || (os == 'mac') #Bug 1590608 support-files = sharedWorker.js partitionedSharedWorker.js [browser_socialtracking.js] skip-if = fission [browser_urlDecorationStripping.js]