☠☠ backed out by a25309077ac7 ☠ ☠ | |
author | Steve Workman <sworkman@mozilla.com> |
Thu, 28 Aug 2014 10:58:20 -0700 | |
changeset 225142 | 2f94e060bac3b2e4b22b047e10f993418edbb0f8 |
parent 225140 | c105712ba3e0d0257e6de4ea51d803fcefb7bfea |
child 225143 | fe22fccea4aea9abcf32727cc9b94c2606847250 |
push id | 583 |
push user | bhearsum@mozilla.com |
push date | Mon, 24 Nov 2014 19:04:58 +0000 |
treeherder | mozilla-release@c107e74250f4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | reuben, mayhemer |
bugs | 1012917 |
milestone | 34.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/netwerk/base/src/ChannelDiverterParent.cpp +++ b/netwerk/base/src/ChannelDiverterParent.cpp @@ -19,29 +19,33 @@ ChannelDiverterParent::ChannelDiverterPa { } ChannelDiverterParent::~ChannelDiverterParent() { } bool -ChannelDiverterParent::Init(const ChannelDiverterArgs& aChannel) +ChannelDiverterParent::Init(const ChannelDiverterArgs& aArgs) { - switch (aChannel.type()) { - case ChannelDiverterArgs::TPHttpChannelParent: + switch (aArgs.type()) { + case ChannelDiverterArgs::THttpChannelDiverterArgs: { - mDivertableChannelParent = static_cast<ADivertableParentChannel*>( - static_cast<HttpChannelParent*>(aChannel.get_PHttpChannelParent())); + auto httpParent = static_cast<HttpChannelParent*>( + aArgs.get_HttpChannelDiverterArgs().mChannelParent()); + httpParent->SetApplyConversion(aArgs.get_HttpChannelDiverterArgs().mApplyConversion()); + + mDivertableChannelParent = + static_cast<ADivertableParentChannel*>(httpParent); break; } case ChannelDiverterArgs::TPFTPChannelParent: { mDivertableChannelParent = static_cast<ADivertableParentChannel*>( - static_cast<FTPChannelParent*>(aChannel.get_PFTPChannelParent())); + static_cast<FTPChannelParent*>(aArgs.get_PFTPChannelParent())); break; } default: NS_NOTREACHED("unknown ChannelDiverterArgs type"); return false; } MOZ_ASSERT(mDivertableChannelParent);
--- a/netwerk/base/src/ChannelDiverterParent.h +++ b/netwerk/base/src/ChannelDiverterParent.h @@ -19,17 +19,17 @@ class ADivertableParentChannel; class ChannelDiverterParent : public PChannelDiverterParent { public: ChannelDiverterParent(); virtual ~ChannelDiverterParent(); - bool Init(const ChannelDiverterArgs& aChannel); + bool Init(const ChannelDiverterArgs& aArgs); void DivertTo(nsIStreamListener* newListener); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; private: nsRefPtr<ADivertableParentChannel> mDivertableChannelParent; };
--- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -80,19 +80,25 @@ struct FTPChannelConnectArgs }; union FTPChannelCreationArgs { FTPChannelOpenArgs; // For AsyncOpen: the common case. FTPChannelConnectArgs; // Used for redirected-to channels }; +struct HttpChannelDiverterArgs +{ + PHttpChannel mChannel; + bool mApplyConversion; +}; + union ChannelDiverterArgs { - PHttpChannel; + HttpChannelDiverterArgs; PFTPChannel; }; //----------------------------------------------------------------------------- // RTSP IPDL structs //----------------------------------------------------------------------------- struct RtspChannelConnectArgs
--- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -599,16 +599,25 @@ HttpBaseChannel::GetApplyConversion(bool NS_IMETHODIMP HttpBaseChannel::SetApplyConversion(bool value) { LOG(("HttpBaseChannel::SetApplyConversion [this=%p value=%d]\n", this, value)); mApplyConversion = value; return NS_OK; } +nsresult +HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener, + nsIStreamListener** aNewNextListener) +{ + return DoApplyContentConversions(aNextListener, + aNewNextListener, + mListenerContext); +} + NS_IMETHODIMP HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener, nsISupports *aCtxt) { *aNewNextListener = nullptr; nsCOMPtr<nsIStreamListener> nextListener = aNextListener; if (!mResponseHead) @@ -617,32 +626,29 @@ HttpBaseChannel::DoApplyContentConversio LOG(("HttpBaseChannel::DoApplyContentConversions [this=%p]\n", this)); if (!mApplyConversion) { LOG(("not applying conversion per mApplyConversion\n")); return NS_OK; } nsAutoCString contentEncoding; - char *cePtr, *val; - nsresult rv; - - rv = mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding); + nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding); if (NS_FAILED(rv) || contentEncoding.IsEmpty()) return NS_OK; // The encodings are listed in the order they were applied // (see rfc 2616 section 14.11), so they need to removed in reverse // order. This is accomplished because the converter chain ends up // being a stack with the last converter created being the first one // to accept the raw network data. - cePtr = contentEncoding.BeginWriting(); + char* cePtr = contentEncoding.BeginWriting(); uint32_t count = 0; - while ((val = nsCRT::strtok(cePtr, HTTP_LWS ",", &cePtr))) { + while (char* val = nsCRT::strtok(cePtr, HTTP_LWS ",", &cePtr)) { if (++count > 16) { // That's ridiculous. We only understand 2 different ones :) // but for compatibility with old code, we will just carry on without // removing the encodings LOG(("Too many Content-Encodings. Ignoring remainder.\n")); break; } @@ -667,25 +673,24 @@ HttpBaseChannel::DoApplyContentConversio aCtxt, getter_AddRefs(converter)); if (NS_FAILED(rv)) { LOG(("Unexpected failure of AsyncConvertData %s\n", val)); return rv; } LOG(("converter removed '%s' content-encoding\n", val)); - nextListener = converter; + nextListener = converter.forget(); } else { if (val) LOG(("Unknown content encoding '%s', ignoring\n", val)); } } - *aNewNextListener = nextListener; - NS_ADDREF(*aNewNextListener); + nextListener.forget(aNewNextListener); return NS_OK; } NS_IMETHODIMP HttpBaseChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings) { if (!mResponseHead) { *aEncodings = nullptr;
--- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -114,16 +114,19 @@ public: NS_IMETHOD GetContentLength(int64_t *aContentLength); NS_IMETHOD SetContentLength(int64_t aContentLength); NS_IMETHOD Open(nsIInputStream **aResult); // nsIEncodedChannel NS_IMETHOD GetApplyConversion(bool *value); NS_IMETHOD SetApplyConversion(bool value); NS_IMETHOD GetContentEncodings(nsIUTF8StringEnumerator** aEncodings); + NS_IMETHOD DoApplyContentConversions(nsIStreamListener *aNextListener, + nsIStreamListener **aNewNextListener, + nsISupports *aCtxt); // HttpBaseChannel::nsIHttpChannel NS_IMETHOD GetRequestMethod(nsACString& aMethod); NS_IMETHOD SetRequestMethod(const nsACString& aMethod); NS_IMETHOD GetReferrer(nsIURI **referrer); NS_IMETHOD SetReferrer(nsIURI *referrer); NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue); NS_IMETHOD SetRequestHeader(const nsACString& aHeader, @@ -225,30 +228,31 @@ public: public: /* Necko internal use only... */ // Return whether upon a redirect code of httpStatus for method, the // request method should be rewritten to GET. static bool ShouldRewriteRedirectToGET(uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method); + // Like nsIEncodedChannel::DoApplyConversions except context is set to + // mListenerContext. + nsresult DoApplyContentConversions(nsIStreamListener *aNextListener, + nsIStreamListener **aNewNextListener); + protected: nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages; // Handle notifying listener, removing from loadgroup if request failed. void DoNotifyListener(); virtual void DoNotifyListenerCleanup() = 0; // drop reference to listener, its callbacks, and the progress sink void ReleaseListeners(); - NS_IMETHOD DoApplyContentConversions(nsIStreamListener *aNextListener, - nsIStreamListener **aNewNextListener, - nsISupports *aCtxt); - void AddCookiesToRequest(); virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod); // bundle calling OMR observers and marking flag into one function inline void CallOnModifyRequestObservers() { gHttpHandler->OnModifyRequest(this);
--- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -333,18 +333,17 @@ HttpChannelChild::OnStartRequest(const n mLoadGroup->RemoveRequest(this, nullptr, mStatus); } } if (mResponseHead) SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie)); nsCOMPtr<nsIStreamListener> listener; - rv = DoApplyContentConversions(mListener, getter_AddRefs(listener), - mListenerContext); + rv = DoApplyContentConversions(mListener, getter_AddRefs(listener)); if (NS_FAILED(rv)) { Cancel(rv); } else if (listener) { mListener = listener; } mSelfAddr = selfAddr; mPeerAddr = peerAddr; @@ -1667,18 +1666,22 @@ HttpChannelChild::DivertToParent(Channel nsresult rv = Suspend(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Once this is set, it should not be unset before the child is taken down. mDivertingToParent = true; + HttpChannelDiverterArgs args; + args.mChannelChild() = this; + args.mApplyConversion() = mApplyConversion; + PChannelDiverterChild* diverter = - gNeckoChild->SendPChannelDiverterConstructor(this); + gNeckoChild->SendPChannelDiverterConstructor(args); MOZ_RELEASE_ASSERT(diverter); *aChild = static_cast<ChannelDiverterChild*>(diverter); return NS_OK; } }} // mozilla::net
--- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -493,17 +493,24 @@ HttpChannelParent::RecvDivertOnDataAvail if (NS_FAILED(rv)) { if (mChannel) { mChannel->Cancel(rv); } mStatus = rv; return true; } - rv = mParentListener->OnDataAvailable(mChannel, nullptr, stringStream, + nsCOMPtr<nsIStreamListener> listener; + if (mConverterListener) { + listener = mConverterListener; + } else { + listener = mParentListener; + MOZ_ASSERT(listener); + } + rv = listener->OnDataAvailable(mChannel, nullptr, stringStream, offset, count); stringStream->Close(); if (NS_FAILED(rv)) { if (mChannel) { mChannel->Cancel(rv); } mStatus = rv; return true; @@ -525,25 +532,33 @@ HttpChannelParent::RecvDivertOnStopReque // Honor the channel's status even if the underlying transaction completed. nsresult status = NS_FAILED(mStatus) ? mStatus : statusCode; // Reset fake pending status in case OnStopRequest has already been called. if (mChannel) { mChannel->ForcePending(false); } - mParentListener->OnStopRequest(mChannel, nullptr, status); + nsCOMPtr<nsIStreamListener> listener; + if (mConverterListener) { + listener = mConverterListener; + } else { + listener = mParentListener; + MOZ_ASSERT(listener); + } + listener->OnStopRequest(mChannel, nullptr, status); return true; } bool HttpChannelParent::RecvDivertComplete() { MOZ_ASSERT(mParentListener); mParentListener = nullptr; + mConverterListener = nullptr; if (NS_WARN_IF(!mDivertingFromChild)) { MOZ_ASSERT(mDivertingFromChild, "Cannot RecvDivertComplete if diverting is not set!"); FailDiversion(NS_ERROR_UNEXPECTED); return false; } nsresult rv = ResumeForDiversion(); @@ -910,18 +925,40 @@ HttpChannelParent::StartDiversion() if (NS_FAILED(rv)) { if (mChannel) { mChannel->Cancel(rv); } mStatus = rv; } mDivertedOnStartRequest = true; - // After OnStartRequest has been called, tell HttpChannelChild to divert the - // OnDataAvailables and OnStopRequest to this HttpChannelParent. + // After OnStartRequest has been called, setup content decoders if needed. + // + // We want to use the same decoders that the nsHttpChannel might use. There + // are two possible scenarios depending on whether OnStopRequest has been + // called or not. + // + // 1. nsHttpChannel has not called OnStopRequest yet. + // Create content conversion chain based on nsHttpChannel::mListener + // Get ptr to final listener and set that in mContentConverter, as well as + // nsHttpChannel::mListener. + // + // 2. nsHttpChannel has called OnStopRequest. + // Create a content conversion chain based on mParentListener. + // Get ptr to final listener and set that in mContentConverter. + + nsCOMPtr<nsIStreamListener> converterListener; + mChannel->DoApplyContentConversions(mParentListener, + getter_AddRefs(converterListener)); + if (converterListener) { + mConverterListener = converterListener.forget(); + } + + // The listener chain should now be setup; tell HttpChannelChild to divert + // the OnDataAvailables and OnStopRequest to this HttpChannelParent. if (NS_WARN_IF(mIPCClosed || !SendDivertMessages())) { FailDiversion(NS_ERROR_UNEXPECTED); return; } } class HTTPFailDiversionEvent : public nsRunnable { @@ -989,16 +1026,17 @@ HttpChannelParent::NotifyDiversionFailed mChannel->ForcePending(false); } // If the channel is pending, it will call OnStopRequest itself; otherwise, do // it here. if (!isPending) { mParentListener->OnStopRequest(mChannel, nullptr, aErrorCode); } mParentListener = nullptr; + mConverterListener = nullptr; mChannel = nullptr; if (!mIPCClosed) { unused << SendDeleteSelf(); } } NS_IMETHODIMP
--- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -65,16 +65,23 @@ public: // that it should divert OnDataAvailable and OnStopRequest calls to this // parent channel. void StartDiversion(); // Handles calling OnStart/Stop if there are errors during diversion. // Called asynchronously from FailDiversion. void NotifyDiversionFailed(nsresult aErrorCode, bool aSkipResume = true); + // Forwarded to nsHttpChannel::SetApplyConversion. + void SetApplyConversion(bool aApplyConversion) { + if (mChannel) { + mChannel->SetApplyConversion(aApplyConversion); + } + } + protected: // used to connect redirected-to channel in parent with just created // ChildChannel. Used during redirects. bool ConnectChannel(const uint32_t& channelId); bool DoAsyncOpen(const URIParams& uri, const OptionalURIParams& originalUri, const OptionalURIParams& docUri, @@ -148,16 +155,18 @@ private: bool mReceivedRedirect2Verify : 1; PBOverrideStatus mPBOverride; nsCOMPtr<nsILoadContext> mLoadContext; nsRefPtr<nsHttpHandler> mHttpHandler; nsRefPtr<HttpChannelParentListener> mParentListener; + // The first listener in the decode chain if channel decoding is applied. + nsCOMPtr<nsIStreamListener> mConverterListener; // Set to the canceled status value if the main channel was canceled. nsresult mStatus; // Once set, no OnStart/OnData/OnStop calls should be accepted; conversely, it // must be set when RecvDivertOnData/~DivertOnStop/~DivertComplete are // received from the child channel. bool mDivertingFromChild; // Set if OnStart|StopRequest was called during a diversion from the child.
--- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -917,18 +917,17 @@ nsHttpChannel::CallOnStartRequest() NS_WARNING("OnStartRequest skipped because of null listener"); } // Install stream converter if required. // If we use unknownDecoder, stream converters will be installed later (in // nsUnknownDecoder) after OnStartRequest is called for the real listener. if (!unknownDecoderStarted) { nsCOMPtr<nsIStreamListener> listener; - nsISupports *ctxt = mListenerContext; - rv = DoApplyContentConversions(mListener, getter_AddRefs(listener), ctxt); + rv = DoApplyContentConversions(mListener, getter_AddRefs(listener)); if (NS_FAILED(rv)) { return rv; } if (listener) { mListener = listener; } }
--- a/uriloader/exthandler/ExternalHelperAppChild.cpp +++ b/uriloader/exthandler/ExternalHelperAppChild.cpp @@ -88,25 +88,30 @@ ExternalHelperAppChild::OnStopRequest(ns SendOnStopRequest(status); NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED); } return NS_OK; } nsresult -ExternalHelperAppChild::DivertToParent(nsIDivertableChannel *divertable, nsIRequest *request) +ExternalHelperAppChild::DivertToParent(nsIDivertableChannel *divertable, + nsIRequest *request) { + // nsIDivertable must know about content conversions before being diverted. + MOZ_ASSERT(mHandler); + mHandler->MaybeApplyDecodingForExtension(request); + mozilla::net::ChannelDiverterChild *diverter = nullptr; nsresult rv = divertable->DivertToParent(&diverter); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + MOZ_ASSERT(diverter); - MOZ_ASSERT(diverter); if (SendDivertToParentUsing(diverter)) { mHandler->DidDivertRequest(request); mHandler = nullptr; return NS_OK; } return NS_ERROR_FAILURE; }
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -1491,16 +1491,61 @@ nsresult nsExternalAppHandler::SetUpTemp LOG(("Enabled hashing and signature verification")); rv = mSaver->SetTarget(mTempFile, false); NS_ENSURE_SUCCESS(rv, rv); return rv; } +void +nsExternalAppHandler::MaybeApplyDecodingForExtension(nsIRequest *aRequest) +{ + MOZ_ASSERT(aRequest); + + nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface(aRequest); + if (!encChannel) { + return; + } + + // Turn off content encoding conversions if needed + bool applyConversion = true; + + nsCOMPtr<nsIURL> sourceURL(do_QueryInterface(mSourceUrl)); + if (sourceURL) + { + nsAutoCString extension; + sourceURL->GetFileExtension(extension); + if (!extension.IsEmpty()) + { + nsCOMPtr<nsIUTF8StringEnumerator> encEnum; + encChannel->GetContentEncodings(getter_AddRefs(encEnum)); + if (encEnum) + { + bool hasMore; + nsresult rv = encEnum->HasMore(&hasMore); + if (NS_SUCCEEDED(rv) && hasMore) + { + nsAutoCString encType; + rv = encEnum->GetNext(encType); + if (NS_SUCCEEDED(rv) && !encType.IsEmpty()) + { + MOZ_ASSERT(mExtProtSvc); + mExtProtSvc->ApplyDecodingForExtension(extension, encType, + &applyConversion); + } + } + } + } + } + + encChannel->SetApplyConversion( applyConversion ); + return; +} + NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISupports * aCtxt) { NS_PRECONDITION(request, "OnStartRequest without request?"); // Set mTimeDownloadStarted here as the download has already started and // we want to record the start time before showing the filepicker. mTimeDownloadStarted = PR_Now(); @@ -1553,45 +1598,17 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt MaybeCloseWindow(); // In an IPC setting, we're allowing the child process, here, to make // decisions about decoding the channel (e.g. decompression). It will // still forward the decoded (uncompressed) data back to the parent. // Con: Uncompressed data means more IPC overhead. // Pros: ExternalHelperAppParent doesn't need to implement nsIEncodedChannel. // Parent process doesn't need to expect CPU time on decompression. - nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface( aChannel ); - if (encChannel) { - // Turn off content encoding conversions if needed - bool applyConversion = true; - - nsCOMPtr<nsIURL> sourceURL(do_QueryInterface(mSourceUrl)); - if (sourceURL) { - nsAutoCString extension; - sourceURL->GetFileExtension(extension); - if (!extension.IsEmpty()) { - nsCOMPtr<nsIUTF8StringEnumerator> encEnum; - encChannel->GetContentEncodings(getter_AddRefs(encEnum)); - if (encEnum) { - bool hasMore; - rv = encEnum->HasMore(&hasMore); - if (NS_SUCCEEDED(rv) && hasMore) { - nsAutoCString encType; - rv = encEnum->GetNext(encType); - if (NS_SUCCEEDED(rv) && !encType.IsEmpty()) { - mExtProtSvc->ApplyDecodingForExtension(extension, encType, - &applyConversion); - } - } - } - } - } - - encChannel->SetApplyConversion( applyConversion ); - } + MaybeApplyDecodingForExtension(aChannel); // At this point, the child process has done everything it can usefully do // for OnStartRequest. if (XRE_GetProcessType() == GeckoProcessType_Content) { return NS_OK; } rv = SetUpTempFile(aChannel);
--- a/uriloader/exthandler/nsExternalHelperAppService.h +++ b/uriloader/exthandler/nsExternalHelperAppService.h @@ -240,16 +240,21 @@ public: const nsAString& aFilename, uint32_t aReason, bool aForceSave); /** * Clean up after the request was diverted to the parent process. */ void DidDivertRequest(nsIRequest *request); + /** + * Apply content conversions if needed. + */ + void MaybeApplyDecodingForExtension(nsIRequest *request); + protected: ~nsExternalAppHandler(); nsIInterfaceRequestor* GetDialogParent() { return mWindowContext ? mWindowContext : mContentContext; } nsCOMPtr<nsIFile> mTempFile;