commit 1d1fdea85218586354a1294cb94026279e74a0e3 Author: Kathy Brade brade@pearlcrescent.com Date: Fri May 19 11:25:31 2017 -0400
fixup! Bug 19273: Avoid JavaScript patching of the external app helper dialog.
For e10s compatibility, send the "external-app-requested" observer notification later in the download process, and suspend active requests while doing so. Fixes bug 21766.
This change also fixes a problem in the esr52-based browser where downloads stalled when e10s was disabled. Fixes bug 21886. --- netwerk/protocol/http/HttpBaseChannel.cpp | 7 ++++ netwerk/protocol/http/HttpBaseChannel.h | 1 + netwerk/protocol/http/NullHttpChannel.cpp | 6 ++++ netwerk/protocol/http/nsIHttpChannel.idl | 9 ++++- .../protocol/viewsource/nsViewSourceChannel.cpp | 11 ++++++ .../exthandler/nsExternalHelperAppService.cpp | 41 +++++++++++++++++----- 6 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index e0f7ede..5ea6a00 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -1233,6 +1233,13 @@ NS_IMETHODIMP HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId) return NS_OK; }
+NS_IMETHODIMP HttpBaseChannel::IsPendingUnforced(bool *aIsPendingUnforced) +{ + NS_ENSURE_ARG_POINTER(aIsPendingUnforced); + *aIsPendingUnforced = mIsPending; + return NS_OK; +} + NS_IMETHODIMP HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize) { diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index c8184a6..3a1a8ba 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -190,6 +190,7 @@ public: NS_IMETHOD SetChannelId(const nsACString& aChannelId) override; NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override; NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override; + NS_IMETHOD IsPendingUnforced(bool *aIsPendingUnforced) override;
// nsIHttpChannelInternal NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override; diff --git a/netwerk/protocol/http/NullHttpChannel.cpp b/netwerk/protocol/http/NullHttpChannel.cpp index 8c048a6..8b362cb 100644 --- a/netwerk/protocol/http/NullHttpChannel.cpp +++ b/netwerk/protocol/http/NullHttpChannel.cpp @@ -82,6 +82,12 @@ NullHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId) }
NS_IMETHODIMP +NullHttpChannel::IsPendingUnforced(bool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP NullHttpChannel::GetTransferSize(uint64_t *aTransferSize) { return NS_ERROR_NOT_IMPLEMENTED; diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl index 75ec2c7..0de0676 100644 --- a/netwerk/protocol/http/nsIHttpChannel.idl +++ b/netwerk/protocol/http/nsIHttpChannel.idl @@ -14,7 +14,7 @@ interface nsIHttpHeaderVisitor; * the inspection of the resulting HTTP response status and headers when they * become available. */ -[builtinclass, scriptable, uuid(c5a4a073-4539-49c7-a3f2-cec3f0619c6c)] +[builtinclass, scriptable, uuid(e0d8071b-5389-48c2-92c7-6708c968044d)] interface nsIHttpChannel : nsIChannel { /************************************************************************** @@ -469,4 +469,11 @@ interface nsIHttpChannel : nsIChannel * this channels is being load in. */ attribute uint64_t topLevelContentWindowId; + + /** + * Returns true if a request is pending due to "natural" causes and + * not just because ForcePending() has been called. See isPending() + * in nsIRequest.idl for more details about pending requests. + */ + boolean isPendingUnforced(); }; diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp index 9ed71c4..9f9b894 100644 --- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp @@ -740,6 +740,17 @@ nsViewSourceChannel::SetTopLevelContentWindowId(uint64_t aWindowId) }
NS_IMETHODIMP +nsViewSourceChannel::IsPendingUnforced(bool *result) +{ + if (mHttpChannel) { + return mHttpChannel->IsPendingUnforced(result); + } + + NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); + return mChannel->IsPending(result); +} + +NS_IMETHODIMP nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod) { return !mHttpChannel ? NS_ERROR_NULL_POINTER : diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index dfaa218..4c25ae2 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -106,6 +106,7 @@
#include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" +#include "mozilla/Unused.h"
using namespace mozilla; using namespace mozilla::ipc; @@ -731,14 +732,6 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte aForceSave, aWindowContext, aStreamListener); }
- // Give other modules, including extensions, a chance to cancel. - bool doCancel = false; - nsresult rv = shouldCancel(&doCancel); - NS_ENSURE_SUCCESS(rv, rv); - if (doCancel) { - return NS_ERROR_FAILURE; - } - nsAutoString fileName; nsAutoCString fileExtension; uint32_t reason = nsIHelperAppLauncherDialog::REASON_CANTHANDLE; @@ -775,6 +768,7 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const nsACString& aMimeConte nsAutoCString query;
// We only care about the query for HTTP and HTTPS URLs + nsresult rv; bool isHTTP, isHTTPS; rv = uri->SchemeIs("http", &isHTTP); if (NS_FAILED(rv)) { @@ -1675,6 +1669,37 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest *request, nsISuppo return NS_OK; }
+ // Give other modules, including extensions, a chance to cancel. + // To avoid a problem where OnDataAvailable fires but is not handled + // correctly while a modal dialog displayed by Torbutton is open, we + // suspend and then we either cancel or resume active requests. + // See bugs 21766 and 21886. + bool isPending = false; + nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(request); + if (httpChan) { + rv = httpChan->IsPendingUnforced(&isPending); + } else { + rv = request->IsPending(&isPending); + } + NS_ENSURE_SUCCESS(rv, rv); + + if (isPending) { + Unused << request->Suspend(); // Best effort: ignore failures. + } + + bool doCancel = false; + rv = shouldCancel(&doCancel); + NS_ENSURE_SUCCESS(rv, rv); + if (doCancel) { + mCanceled = true; + request->Cancel(NS_BINDING_ABORTED); + return NS_OK; + } + + if (isPending) { + Unused << request->Resume(); // Best effort: ignore failures. + } + rv = SetUpTempFile(aChannel); if (NS_FAILED(rv)) { nsresult transferError = rv;
tor-commits@lists.torproject.org