commit 08991021207bcc7c982fa5ae5a9984a12ec7bf5f Author: Arthur Edelstein arthuredelstein@gmail.com Date: Tue Oct 21 02:15:25 2014 -0700
Bug #3455.1: Allow proxy settings to be set per URL bar domain. --- dom/plugins/base/moz.build | 1 + dom/plugins/base/nsPluginHost.cpp | 27 ++-- netwerk/base/public/nsIProtocolProxyCallback.idl | 10 +- netwerk/base/public/nsIProtocolProxyFilter.idl | 34 ++++- netwerk/base/public/nsIProtocolProxyService.idl | 32 +++- netwerk/base/public/nsIProtocolProxyService2.idl | 13 +- netwerk/base/src/nsIOService.cpp | 18 ++- netwerk/base/src/nsPACMan.cpp | 9 +- netwerk/base/src/nsPACMan.h | 10 +- netwerk/base/src/nsProtocolProxyService.cpp | 157 +++++++++++++------- netwerk/base/src/nsProtocolProxyService.h | 49 ++++-- netwerk/protocol/ftp/nsFtpConnectionThread.cpp | 11 +- netwerk/protocol/http/HttpBaseChannel.cpp | 10 ++ netwerk/protocol/http/HttpBaseChannel.h | 1 + netwerk/protocol/http/nsHttpChannel.cpp | 6 +- netwerk/protocol/http/nsIHttpChannel.idl | 6 + .../protocol/viewsource/nsViewSourceChannel.cpp | 6 + netwerk/protocol/websocket/WebSocketChannel.cpp | 4 +- 18 files changed, 281 insertions(+), 123 deletions(-)
diff --git a/dom/plugins/base/moz.build b/dom/plugins/base/moz.build index ded5fb5..25bae79 100644 --- a/dom/plugins/base/moz.build +++ b/dom/plugins/base/moz.build @@ -103,6 +103,7 @@ LOCAL_INCLUDES += [ '/gfx/skia/include/core', '/layout/generic', '/layout/xul', + '/netwerk/base/src', '/widget/android', '/widget/xpwidgets', '/xpcom/base', diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index bc6bf72..1efe59f 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -30,7 +30,7 @@ #include "nsIURL.h" #include "nsTArray.h" #include "nsReadableUtils.h" -#include "nsIProtocolProxyService2.h" +#include "nsProtocolProxyService.h" #include "nsIStreamConverterService.h" #include "nsIFile.h" #if defined(XP_MACOSX) @@ -583,32 +583,29 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result) } nsresult res;
- nsCOMPtr<nsIURI> uriIn; - nsCOMPtr<nsIProtocolProxyService> proxyService; - nsCOMPtr<nsIProtocolProxyService2> proxyService2; - nsCOMPtr<nsIIOService> ioService; - - proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res); + nsCOMPtr<nsIProtocolProxyService> proxyService = + do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res); if (NS_FAILED(res) || !proxyService) return res;
- proxyService2 = do_QueryInterface(proxyService, &res); - if (NS_FAILED(res) || !proxyService2) - return res; + nsRefPtr<nsProtocolProxyService> rawProxyService = do_QueryObject(proxyService); + if (!rawProxyService) + return NS_ERROR_FAILURE;
- ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res); + nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res); if (NS_FAILED(res) || !ioService) return res;
- // make an nsURI from the argument url - res = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn)); + // make a temporary channel from the argument url + nsCOMPtr<nsIChannel> tempChannel; + res = ioService->NewChannel(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(tempChannel)); if (NS_FAILED(res)) return res;
nsCOMPtr<nsIProxyInfo> pi;
- // Remove this with bug 778201 - res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi)); + // Remove this deprecated call in the future (see Bug 778201): + res = rawProxyService->DeprecatedBlockingResolve(tempChannel, 0, getter_AddRefs(pi)); if (NS_FAILED(res)) return res;
diff --git a/netwerk/base/public/nsIProtocolProxyCallback.idl b/netwerk/base/public/nsIProtocolProxyCallback.idl index ca1ab51..96c2181 100644 --- a/netwerk/base/public/nsIProtocolProxyCallback.idl +++ b/netwerk/base/public/nsIProtocolProxyCallback.idl @@ -6,7 +6,7 @@
#include "nsISupports.idl"
-interface nsIURI; +interface nsIChannel; interface nsIProxyInfo; interface nsICancelable;
@@ -14,7 +14,7 @@ interface nsICancelable; * This interface serves as a closure for nsIProtocolProxyService's * asyncResolve method. */ -[scriptable, uuid(a9967200-f95e-45c2-beb3-9b060d874bfd)] +[scriptable, uuid(fbb6eff6-0cc2-4d99-8d6f-0a12b462bdeb)] interface nsIProtocolProxyCallback : nsISupports { /** @@ -23,8 +23,8 @@ interface nsIProtocolProxyCallback : nsISupports * * @param aRequest * The value returned from asyncResolve. - * @param aURI - * The URI passed to asyncResolve. + * @param aChannel + * The channel passed to asyncResolve. * @param aProxyInfo * The resulting proxy info or null if there is no associated proxy * info for aURI. As with the result of nsIProtocolProxyService's @@ -36,7 +36,7 @@ interface nsIProtocolProxyCallback : nsISupports * indicates the reason for the failure and aProxyInfo will be null. */ void onProxyAvailable(in nsICancelable aRequest, - in nsIURI aURI, + in nsIChannel aChannel, in nsIProxyInfo aProxyInfo, in nsresult aStatus); }; diff --git a/netwerk/base/public/nsIProtocolProxyFilter.idl b/netwerk/base/public/nsIProtocolProxyFilter.idl index 8ad6ca4..8798a49 100644 --- a/netwerk/base/public/nsIProtocolProxyFilter.idl +++ b/netwerk/base/public/nsIProtocolProxyFilter.idl @@ -6,6 +6,7 @@
#include "nsISupports.idl"
+interface nsIChannel; interface nsIProtocolProxyService; interface nsIProxyInfo; interface nsIURI; @@ -13,7 +14,7 @@ interface nsIURI; /** * This interface is used to apply filters to the proxies selected for a given * URI. Use nsIProtocolProxyService::registerFilter to hook up instances of - * this interface. + * this interface. See also nsIProtocolProxyChannelFilter. */ [scriptable, uuid(f424abd3-32b4-456c-9f45-b7e3376cb0d1)] interface nsIProtocolProxyFilter : nsISupports @@ -40,3 +41,34 @@ interface nsIProtocolProxyFilter : nsISupports nsIProxyInfo applyFilter(in nsIProtocolProxyService aProxyService, in nsIURI aURI, in nsIProxyInfo aProxy); }; + +/** + * This interface is used to apply filters to the proxies selected for a given + * channel. Use nsIProtocolProxyService::registerChannelFilter to hook up instances of + * this interface. See also nsIProtocolProxyFilter. + */ +[scriptable, uuid(245b0880-82c5-4e6e-be6d-bc586aa55a90)] +interface nsIProtocolProxyChannelFilter : nsISupports +{ + /** + * This method is called to apply proxy filter rules for the given channel + * and proxy object (or list of proxy objects). + * + * @param aProxyService + * A reference to the Protocol Proxy Service. This is passed so that + * implementations may easily access methods such as newProxyInfo. + * @param aChannel + * The channel for which these proxy settings apply. + * @param aProxy + * The proxy (or list of proxies) that would be used by default for + * the given channel. This may be null. + * + * @return The proxy (or list of proxies) that should be used in place of + * aProxy. This can be just be aProxy if the filter chooses not to + * modify the proxy. It can also be null to indicate that a direct + * connection should be used. Use aProxyService.newProxyInfo to + * construct nsIProxyInfo objects. + */ + nsIProxyInfo applyFilter(in nsIProtocolProxyService aProxyService, + in nsIChannel aChannel, in nsIProxyInfo aProxy); +}; diff --git a/netwerk/base/public/nsIProtocolProxyService.idl b/netwerk/base/public/nsIProtocolProxyService.idl index 526eab8..9365658 100644 --- a/netwerk/base/public/nsIProtocolProxyService.idl +++ b/netwerk/base/public/nsIProtocolProxyService.idl @@ -9,6 +9,7 @@ interface nsICancelable; interface nsIProtocolProxyCallback; interface nsIProtocolProxyFilter; +interface nsIProtocolProxyChannelFilter; interface nsIProxyInfo; interface nsIChannel; interface nsIURI; @@ -17,7 +18,7 @@ interface nsIURI; * nsIProtocolProxyService provides methods to access information about * various network proxies. */ -[scriptable, uuid(e77c642b-026f-41ce-9b23-f829a6e3f300)] +[scriptable, uuid(ab363090-c331-489f-aabb-7fe4481795b8)] interface nsIProtocolProxyService : nsISupports { /** Flag 1 << 0 is unused **/ @@ -64,11 +65,11 @@ interface nsIProtocolProxyService : nsISupports
/** * This method returns via callback a nsIProxyInfo instance that identifies - * a proxy to be used for loading the given URI. Otherwise, this method returns + * a proxy to be used for the given channel. Otherwise, this method returns * null indicating that a direct connection should be used. * - * @param aURI - * The URI to test. + * @param aChannel + * The channel for which a proxy is to be found. * @param aFlags * A bit-wise combination of the RESOLVE_ flags defined above. Pass * 0 to specify the default behavior. Any additional bits that do @@ -94,7 +95,7 @@ interface nsIProtocolProxyService : nsISupports * * @see nsIProxiedProtocolHandler::newProxiedChannel */ - nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags, + nsICancelable asyncResolve(in nsIChannel aChannel, in unsigned long aFlags, in nsIProtocolProxyCallback aCallback);
/** @@ -191,6 +192,18 @@ interface nsIProtocolProxyService : nsISupports in unsigned long aPosition);
/** + * Similar to registerFilter, but accepts an nsIProtocolProxyChannelFilter, + * which selects proxies according to channel rather than URI. + * + * @param aFilter + * The nsIProtocolProxyChannelFilter instance to be registered. + * @param aPosition + * The position of the filter. + */ + void registerChannelFilter(in nsIProtocolProxyChannelFilter aFilter, + in unsigned long aPosition); + + /** * This method may be used to unregister a proxy filter instance. All * filters will be automatically unregistered at XPCOM shutdown. * @@ -199,6 +212,15 @@ interface nsIProtocolProxyService : nsISupports */ void unregisterFilter(in nsIProtocolProxyFilter aFilter);
+ /** + * This method may be used to unregister a proxy channel filter instance. All + * filters will be automatically unregistered at XPCOM shutdown. + * + * @param aFilter + * The nsIProtocolProxyChannelFilter instance to be unregistered. + */ + void unregisterChannelFilter(in nsIProtocolProxyChannelFilter aFilter); + /** * These values correspond to the possible integer values for the * network.proxy.type preference. diff --git a/netwerk/base/public/nsIProtocolProxyService2.idl b/netwerk/base/public/nsIProtocolProxyService2.idl index cb39a33..9e4f548 100644 --- a/netwerk/base/public/nsIProtocolProxyService2.idl +++ b/netwerk/base/public/nsIProtocolProxyService2.idl @@ -9,7 +9,7 @@ /** * An extension of nsIProtocolProxyService */ -[scriptable, uuid(bb52e571-4a0e-4363-83d0-52034910dd14)] +[scriptable, uuid(b2e5b2c0-e21e-4845-b336-be6d60a38951)] interface nsIProtocolProxyService2 : nsIProtocolProxyService { /** @@ -18,21 +18,12 @@ interface nsIProtocolProxyService2 : nsIProtocolProxyService */ void reloadPAC();
- /** - * This exists so Java(tm) can migrate to an asynchronous interface. - * Do not use this unless you are the plugin interface, and even then you - * ought to feel horribly guilty because you will create main thread jank. - * - * No documentation - it is deprecated! - **/ - nsIProxyInfo deprecatedBlockingResolve(in nsIURI aURI, in unsigned long aFlags); - /** * This method is identical to asyncResolve() except it may execute the * callback function immediately (i.e from the stack of asyncResolve2()) if * it is immediately ready to run. The nsICancelable return value will be * null in that case. */ - nsICancelable asyncResolve2(in nsIURI aURI, in unsigned long aFlags, + nsICancelable asyncResolve2(in nsIChannel aChannel, in unsigned long aFlags, in nsIProtocolProxyCallback aCallback); }; diff --git a/netwerk/base/src/nsIOService.cpp b/netwerk/base/src/nsIOService.cpp index b64e7d3..99efa57 100644 --- a/netwerk/base/src/nsIOService.cpp +++ b/netwerk/base/src/nsIOService.cpp @@ -1197,7 +1197,7 @@ private: NS_IMPL_ISUPPORTS(IOServiceProxyCallback, nsIProtocolProxyCallback)
NS_IMETHODIMP -IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI, +IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIChannel *channel, nsIProxyInfo *pi, nsresult status) { // Checking proxy status for speculative connect @@ -1209,8 +1209,13 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI, return NS_OK; }
+ nsCOMPtr<nsIURI> uri; + nsresult rv = channel->GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) + return NS_OK; + nsAutoCString scheme; - nsresult rv = aURI->GetScheme(scheme); + rv = uri->GetScheme(scheme); if (NS_FAILED(rv)) return NS_OK;
@@ -1225,7 +1230,7 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI, if (!speculativeHandler) return NS_OK;
- speculativeHandler->SpeculativeConnect(aURI, + speculativeHandler->SpeculativeConnect(uri, mCallbacks); return NS_OK; } @@ -1243,8 +1248,13 @@ nsIOService::SpeculativeConnect(nsIURI *aURI, if (NS_FAILED(rv)) return rv;
+ nsCOMPtr<nsIChannel> channel; + rv = NewChannelFromURI(aURI, getter_AddRefs(channel)); + if (NS_FAILED(rv)) + return rv; + nsCOMPtr<nsICancelable> cancelable; nsRefPtr<IOServiceProxyCallback> callback = new IOServiceProxyCallback(aCallbacks, this); - return pps->AsyncResolve(aURI, 0, callback, getter_AddRefs(cancelable)); + return pps->AsyncResolve(channel, 0, callback, getter_AddRefs(cancelable)); } diff --git a/netwerk/base/src/nsPACMan.cpp b/netwerk/base/src/nsPACMan.cpp index 81bc17e..e8b0b2d 100644 --- a/netwerk/base/src/nsPACMan.cpp +++ b/netwerk/base/src/nsPACMan.cpp @@ -320,8 +320,8 @@ nsPACMan::Shutdown() }
nsresult -nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback, - bool mainThreadResponse) +nsPACMan::AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback, + bool mainThreadResponse) { NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread"); if (mShutdown) @@ -332,6 +332,11 @@ nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback, TimeStamp::Now() > mScheduledReload) LoadPACFromURI(EmptyCString());
+ nsCOMPtr<nsIURI> uri; + nsresult rv = channel->GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) + return rv; + nsRefPtr<PendingPACQuery> query = new PendingPACQuery(this, uri, callback, mainThreadResponse);
diff --git a/netwerk/base/src/nsPACMan.h b/netwerk/base/src/nsPACMan.h index 410ae5641..6f95d97 100644 --- a/netwerk/base/src/nsPACMan.h +++ b/netwerk/base/src/nsPACMan.h @@ -27,13 +27,13 @@ class nsIThread; class WaitForThreadShutdown;
/** - * This class defines a callback interface used by AsyncGetProxyForURI. + * This class defines a callback interface used by AsyncGetProxyForChannel. */ class NS_NO_VTABLE nsPACManCallback : public nsISupports { public: /** - * This method is invoked on the same thread that called AsyncGetProxyForURI. + * This method is invoked on the same thread that called AsyncGetProxyForChannel. * * @param status * This parameter indicates whether or not the PAC query succeeded. @@ -101,14 +101,14 @@ public: * will queue up the request, and complete it once the PAC file has been * loaded. * - * @param uri - * The URI to query. + * @param channel + * The channel to query. * @param callback * The callback to run once the PAC result is available. * @param mustCallbackOnMainThread * If set to false the callback can be made from the PAC thread */ - nsresult AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback, + nsresult AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback, bool mustCallbackOnMainThread);
/** diff --git a/netwerk/base/src/nsProtocolProxyService.cpp b/netwerk/base/src/nsProtocolProxyService.cpp index 98ea68b..3878c58d 100644 --- a/netwerk/base/src/nsProtocolProxyService.cpp +++ b/netwerk/base/src/nsProtocolProxyService.cpp @@ -14,6 +14,7 @@ #include "nsIObserverService.h" #include "nsIProtocolHandler.h" #include "nsIProtocolProxyCallback.h" +#include "nsIChannel.h" #include "nsICancelable.h" #include "nsIDNSService.h" #include "nsPIDNSService.h" @@ -67,7 +68,7 @@ struct nsProtocolInfo { //----------------------------------------------------------------------------
// The nsPACManCallback portion of this implementation should be run -// on the main thread - so call nsPACMan::AsyncGetProxyForURI() with +// on the main thread - so call nsPACMan::AsyncGetProxyForChannel() with // a true mainThreadResponse parameter. class nsAsyncResolveRequest MOZ_FINAL : public nsIRunnable , public nsPACManCallback @@ -76,7 +77,7 @@ class nsAsyncResolveRequest MOZ_FINAL : public nsIRunnable public: NS_DECL_THREADSAFE_ISUPPORTS
- nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIURI *uri, + nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIChannel *channel, uint32_t aResolveFlags, nsIProtocolProxyCallback *callback) : mStatus(NS_OK) @@ -84,7 +85,7 @@ public: , mResolveFlags(aResolveFlags) , mPPS(pps) , mXPComPPS(pps) - , mURI(uri) + , mChannel(channel) , mCallback(callback) { NS_ASSERTION(mCallback, "null callback"); @@ -100,9 +101,9 @@ public: nsCOMPtr<nsIThread> mainThread; NS_GetMainThread(getter_AddRefs(mainThread));
- if (mURI) { - nsIURI *forgettable; - mURI.forget(&forgettable); + if (mChannel) { + nsIChannel *forgettable; + mChannel.forget(&forgettable); NS_ProxyRelease(mainThread, forgettable, false); }
@@ -207,19 +208,21 @@ private: if (NS_SUCCEEDED(mStatus) && !mProxyInfo && !mPACString.IsEmpty()) { mPPS->ProcessPACString(mPACString, mResolveFlags, getter_AddRefs(mProxyInfo)); + nsCOMPtr<nsIURI> uri; + mChannel->GetURI(getter_AddRefs(uri));
// Now apply proxy filters nsProtocolInfo info; - mStatus = mPPS->GetProtocolInfo(mURI, &info); + mStatus = mPPS->GetProtocolInfo(uri, &info); if (NS_SUCCEEDED(mStatus)) - mPPS->ApplyFilters(mURI, info, mProxyInfo); + mPPS->ApplyFilters(mChannel, info, mProxyInfo); else mProxyInfo = nullptr;
LOG(("pac thread callback %s\n", mPACString.get())); if (NS_SUCCEEDED(mStatus)) mPPS->MaybeDisableDNSPrefetch(mProxyInfo); - mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus); + mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus); } else if (NS_SUCCEEDED(mStatus) && !mPACURL.IsEmpty()) { LOG(("pac thread callback indicates new pac file load\n")); @@ -229,12 +232,12 @@ private: if (NS_SUCCEEDED(rv)) { // now that the load is triggered, we can resubmit the query nsRefPtr<nsAsyncResolveRequest> newRequest = - new nsAsyncResolveRequest(mPPS, mURI, mResolveFlags, mCallback); - rv = mPPS->mPACMan->AsyncGetProxyForURI(mURI, newRequest, true); + new nsAsyncResolveRequest(mPPS, mChannel, mResolveFlags, mCallback); + rv = mPPS->mPACMan->AsyncGetProxyForChannel(mChannel, newRequest, true); }
if (NS_FAILED(rv)) - mCallback->OnProxyAvailable(this, mURI, nullptr, rv); + mCallback->OnProxyAvailable(this, mChannel, nullptr, rv);
// do not call onproxyavailable() in SUCCESS case - the newRequest will // take care of that @@ -243,7 +246,7 @@ private: LOG(("pac thread callback did not provide information %X\n", mStatus)); if (NS_SUCCEEDED(mStatus)) mPPS->MaybeDisableDNSPrefetch(mProxyInfo); - mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus); + mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus); }
// We are on the main thread now and don't need these any more so @@ -252,7 +255,7 @@ private: mCallback = nullptr; // in case the callback holds an owning ref to us mPPS = nullptr; mXPComPPS = nullptr; - mURI = nullptr; + mChannel = nullptr; mProxyInfo = nullptr; }
@@ -266,7 +269,7 @@ private:
nsProtocolProxyService *mPPS; nsCOMPtr<nsIProtocolProxyService> mXPComPPS; - nsCOMPtr<nsIURI> mURI; + nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIProtocolProxyCallback> mCallback; nsCOMPtr<nsIProxyInfo> mProxyInfo; }; @@ -964,7 +967,7 @@ nsProtocolProxyService::ReloadPAC() // The nsPACManCallback portion of this implementation should be run // off the main thread, because it uses a condvar for signaling and // the main thread is blocking on that condvar - -// so call nsPACMan::AsyncGetProxyForURI() with +// so call nsPACMan::AsyncGetProxyForChannel() with // a false mainThreadResponse parameter. class nsAsyncBridgeRequest MOZ_FINAL : public nsPACManCallback { @@ -1010,16 +1013,19 @@ private: }; NS_IMPL_ISUPPORTS0(nsAsyncBridgeRequest)
-// nsIProtocolProxyService2 +// nsProtocolProxyService NS_IMETHODIMP -nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI, +nsProtocolProxyService::DeprecatedBlockingResolve(nsIChannel *aChannel, uint32_t aFlags, nsIProxyInfo **retval) { - NS_ENSURE_ARG_POINTER(aURI); + NS_ENSURE_ARG_POINTER(aChannel); + + nsCOMPtr<nsIURI> uri; + aChannel->GetURI(getter_AddRefs(uri));
nsProtocolInfo info; - nsresult rv = GetProtocolInfo(aURI, &info); + nsresult rv = GetProtocolInfo(uri, &info); if (NS_FAILED(rv)) return rv;
@@ -1030,12 +1036,12 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI, // but if neither of them are in use, we can just do the work // right here and directly invoke the callback
- rv = Resolve_Internal(aURI, info, aFlags, &usePACThread, getter_AddRefs(pi)); + rv = Resolve_Internal(aChannel, info, aFlags, &usePACThread, getter_AddRefs(pi)); if (NS_FAILED(rv)) return rv;
if (!usePACThread || !mPACMan) { - ApplyFilters(aURI, info, pi); + ApplyFilters(aChannel, info, pi); pi.forget(retval); return NS_OK; } @@ -1044,7 +1050,7 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI, // code, but block this thread on that completion. nsRefPtr<nsAsyncBridgeRequest> ctx = new nsAsyncBridgeRequest(); ctx->Lock(); - if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForURI(aURI, ctx, false))) { + if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForChannel(aChannel, ctx, false))) { // this can really block the main thread, so cap it at 3 seconds ctx->Wait(); } @@ -1060,7 +1066,7 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI, if (!ctx->mPACString.IsEmpty()) { LOG(("sync pac thread callback %s\n", ctx->mPACString.get())); ProcessPACString(ctx->mPACString, 0, getter_AddRefs(pi)); - ApplyFilters(aURI, info, pi); + ApplyFilters(aChannel, info, pi); pi.forget(retval); return NS_OK; } @@ -1084,17 +1090,20 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI, }
nsresult -nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags, +nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags, nsIProtocolProxyCallback *callback, nsICancelable **result, bool isSyncOK) { - NS_ENSURE_ARG_POINTER(uri); + NS_ENSURE_ARG_POINTER(channel); NS_ENSURE_ARG_POINTER(callback);
+ nsCOMPtr<nsIURI> uri; + channel->GetURI(getter_AddRefs(uri)); + *result = nullptr; nsRefPtr<nsAsyncResolveRequest> ctx = - new nsAsyncResolveRequest(this, uri, flags, callback); + new nsAsyncResolveRequest(this, channel, flags, callback);
nsProtocolInfo info; nsresult rv = GetProtocolInfo(uri, &info); @@ -1108,13 +1117,13 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags, // but if neither of them are in use, we can just do the work // right here and directly invoke the callback
- rv = Resolve_Internal(uri, info, flags, &usePACThread, getter_AddRefs(pi)); + rv = Resolve_Internal(channel, info, flags, &usePACThread, getter_AddRefs(pi)); if (NS_FAILED(rv)) return rv;
if (!usePACThread || !mPACMan) { // we can do it locally - ApplyFilters(uri, info, pi); + ApplyFilters(channel, info, pi); ctx->SetResult(NS_OK, pi); if (isSyncOK) { ctx->Run(); @@ -1129,7 +1138,7 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
// else kick off a PAC thread query
- rv = mPACMan->AsyncGetProxyForURI(uri, ctx, true); + rv = mPACMan->AsyncGetProxyForChannel(channel, ctx, true); if (NS_SUCCEEDED(rv)) ctx.forget(result); return rv; @@ -1137,19 +1146,19 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
// nsIProtocolProxyService NS_IMETHODIMP -nsProtocolProxyService::AsyncResolve2(nsIURI *uri, uint32_t flags, +nsProtocolProxyService::AsyncResolve2(nsIChannel *channel, uint32_t flags, nsIProtocolProxyCallback *callback, nsICancelable **result) { - return AsyncResolveInternal(uri, flags, callback, result, true); + return AsyncResolveInternal(channel, flags, callback, result, true); }
NS_IMETHODIMP -nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags, +nsProtocolProxyService::AsyncResolve(nsIChannel *channel, uint32_t flags, nsIProtocolProxyCallback *callback, nsICancelable **result) { - return AsyncResolveInternal(uri, flags, callback, result, false); + return AsyncResolveInternal(channel, flags, callback, result, false); }
NS_IMETHODIMP @@ -1221,16 +1230,9 @@ nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo *aProxy, return NS_OK; }
-NS_IMETHODIMP -nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter, - uint32_t position) +nsresult +nsProtocolProxyService::InsertFilterLink(FilterLink *link, uint32_t position) { - UnregisterFilter(filter); // remove this filter if we already have it - - FilterLink *link = new FilterLink(position, filter); - if (!link) - return NS_ERROR_OUT_OF_MEMORY; - if (!mFilters) { mFilters = link; return NS_OK; @@ -1258,11 +1260,32 @@ nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter, }
NS_IMETHODIMP -nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter) +nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter, + uint32_t position) { - // QI to nsISupports so we can safely test object identity. - nsCOMPtr<nsISupports> givenObject = do_QueryInterface(filter); + UnregisterFilter(filter); // remove this filter if we already have it + + FilterLink *link = new FilterLink(position, filter); + if (!link) + return NS_ERROR_OUT_OF_MEMORY; + return InsertFilterLink(link, position); +}
+NS_IMETHODIMP +nsProtocolProxyService::RegisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter, + uint32_t position) +{ + UnregisterChannelFilter(channelFilter); // remove this filter if we already have it + + FilterLink *link = new FilterLink(position, channelFilter); + if (!link) + return NS_ERROR_OUT_OF_MEMORY; + return InsertFilterLink(link, position); +} + +nsresult +nsProtocolProxyService::RemoveFilterLink(nsISupports* givenObject) +{ FilterLink *last = nullptr; for (FilterLink *iter = mFilters; iter; iter = iter->next) { nsCOMPtr<nsISupports> object = do_QueryInterface(iter->filter); @@ -1283,6 +1306,20 @@ nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter) }
NS_IMETHODIMP +nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter) { + // QI to nsISupports so we can safely test object identity. + nsCOMPtr<nsISupports> givenObject = do_QueryInterface(filter); + return RemoveFilterLink(givenObject); +} + +NS_IMETHODIMP +nsProtocolProxyService::UnregisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter) { + // QI to nsISupports so we can safely test object identity. + nsCOMPtr<nsISupports> givenObject = do_QueryInterface(channelFilter); + return RemoveFilterLink(givenObject); +} + +NS_IMETHODIMP nsProtocolProxyService::GetProxyConfigType(uint32_t* aProxyConfigType) { *aProxyConfigType = mProxyConfig; @@ -1489,13 +1526,13 @@ nsProtocolProxyService::NewProxyInfo_Internal(const char *aType, }
nsresult -nsProtocolProxyService::Resolve_Internal(nsIURI *uri, +nsProtocolProxyService::Resolve_Internal(nsIChannel *channel, const nsProtocolInfo &info, uint32_t flags, bool *usePACThread, nsIProxyInfo **result) { - NS_ENSURE_ARG_POINTER(uri); + NS_ENSURE_ARG_POINTER(channel); nsresult rv = SetupPACThread(); if (NS_FAILED(rv)) return rv; @@ -1506,6 +1543,9 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri, if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY)) return NS_OK; // Can't proxy this (filters may not override)
+ nsCOMPtr<nsIURI> uri; + channel->GetURI(getter_AddRefs(uri)); + // See bug #586908. // Avoid endless loop if |uri| is the current PAC-URI. Returning OK // here means that we will not use a proxy for this connection. @@ -1675,7 +1715,7 @@ nsProtocolProxyService::MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy) }
void -nsProtocolProxyService::ApplyFilters(nsIURI *uri, const nsProtocolInfo &info, +nsProtocolProxyService::ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info, nsIProxyInfo **list) { if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY)) @@ -1690,9 +1730,22 @@ nsProtocolProxyService::ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
for (FilterLink *iter = mFilters; iter; iter = iter->next) { PruneProxyInfo(info, list); - - rv = iter->filter->ApplyFilter(this, uri, *list, - getter_AddRefs(result)); + if (!!iter->filter) { + nsCOMPtr<nsIURI> uri; + channel->GetURI(getter_AddRefs(uri)); + if (!!uri) { + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel); + nsCOMPtr<nsIURI> proxyURI = nullptr; + if (!!httpChannel) { + httpChannel->GetProxyURI(getter_AddRefs(proxyURI)); + } + rv = iter->filter->ApplyFilter(this, proxyURI ? proxyURI : uri, *list, + getter_AddRefs(result)); + } + } else if (!!iter->channelFilter) { + rv = iter->channelFilter->ApplyFilter(this, channel, *list, + getter_AddRefs(result)); + } if (NS_FAILED(rv)) continue; result.swap(*list); diff --git a/netwerk/base/src/nsProtocolProxyService.h b/netwerk/base/src/nsProtocolProxyService.h index 4108e30..9ef68b9 100644 --- a/netwerk/base/src/nsProtocolProxyService.h +++ b/netwerk/base/src/nsProtocolProxyService.h @@ -27,6 +27,12 @@ class nsIPrefBranch; class nsISystemProxySettings; class nsPACMan;
+// CID for the nsProtocolProxyService class +// 091eedd8-8bae-4fe3-ad62-0c87351e640d +#define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID \ +{ 0x091eedd8, 0x8bae, 0x4fe3, \ + { 0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d } } + class nsProtocolProxyService MOZ_FINAL : public nsIProtocolProxyService2 , public nsIObserver { @@ -36,9 +42,14 @@ public: NS_DECL_NSIPROTOCOLPROXYSERVICE NS_DECL_NSIOBSERVER
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID) + nsProtocolProxyService() NS_HIDDEN;
NS_HIDDEN_(nsresult) Init(); + nsresult DeprecatedBlockingResolve(nsIChannel *aChannel, + uint32_t aFlags, + nsIProxyInfo **retval);
protected: friend class nsAsyncResolveRequest; @@ -192,8 +203,8 @@ protected: * caller with either the proxy info result or a flag to instruct the * caller to use PAC instead. * - * @param uri - * The URI to test. + * @param channel + * The channel to test. * @param info * Information about the URI's protocol. * @param flags @@ -204,7 +215,7 @@ protected: * @param result * The resulting proxy info or null. */ - NS_HIDDEN_(nsresult) Resolve_Internal(nsIURI *uri, + NS_HIDDEN_(nsresult) Resolve_Internal(nsIChannel *channel, const nsProtocolInfo &info, uint32_t flags, bool *usePAC, @@ -214,26 +225,26 @@ protected: * This method applies the registered filters to the given proxy info * list, and returns a possibly modified list. * - * @param uri - * The URI corresponding to this proxy info list. + * @param channel + * The channel corresponding to this proxy info list. * @param info * Information about the URI's protocol. * @param proxyInfo * The proxy info list to be modified. This is an inout param. */ - NS_HIDDEN_(void) ApplyFilters(nsIURI *uri, const nsProtocolInfo &info, + NS_HIDDEN_(void) ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info, nsIProxyInfo **proxyInfo);
/** * This method is a simple wrapper around ApplyFilters that takes the * proxy info list inout param as a nsCOMPtr. */ - inline void ApplyFilters(nsIURI *uri, const nsProtocolInfo &info, + inline void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info, nsCOMPtr<nsIProxyInfo> &proxyInfo) { nsIProxyInfo *pi = nullptr; proxyInfo.swap(pi); - ApplyFilters(uri, info, &pi); + ApplyFilters(channel, info, &pi); proxyInfo.swap(pi); }
@@ -317,19 +328,27 @@ protected: } };
- // This structure is allocated for each registered nsIProtocolProxyFilter. + // An instance of this struct is allocated for each registered + // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter. struct FilterLink { struct FilterLink *next; uint32_t position; - nsCOMPtr<nsIProtocolProxyFilter> filter; - + nsCOMPtr<nsIProtocolProxyFilter> filter; + nsCOMPtr<nsIProtocolProxyChannelFilter> channelFilter; FilterLink(uint32_t p, nsIProtocolProxyFilter *f) - : next(nullptr), position(p), filter(f) {} - + : next(nullptr), position(p), filter(f), channelFilter(nullptr) {} + FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf) + : next(nullptr), position(p), filter(nullptr), channelFilter(cf) {} // Chain deletion to simplify cleaning up the filter links ~FilterLink() { if (next) delete next; } };
+private: + // Private methods to insert and remove FilterLinks from the FilterLink chain. + nsresult InsertFilterLink(FilterLink *link, uint32_t position); + nsresult RemoveFilterLink(nsISupports *givenObject); + +protected: // Indicates if local hosts (plain hostnames, no dots) should use the proxy bool mFilterLocalHosts;
@@ -364,11 +383,13 @@ protected: int32_t mFailedProxyTimeout;
private: - nsresult AsyncResolveInternal(nsIURI *uri, uint32_t flags, + nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags, nsIProtocolProxyCallback *callback, nsICancelable **result, bool isSyncOK);
};
+NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID) + #endif // !nsProtocolProxyService_h__ diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp index 6d8d9f1..5073dbb 100644 --- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp +++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp @@ -1872,7 +1872,7 @@ nsFtpState::Init(nsFtpChannel *channel) do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
if (pps && !mChannel->ProxyInfo()) { - pps->AsyncResolve(mChannel->URI(), 0, this, + pps->AsyncResolve(mChannel, 0, this, getter_AddRefs(mProxyRequest)); }
@@ -2358,7 +2358,7 @@ nsFtpState::CloseWithStatus(nsresult status) }
static nsresult -CreateHTTPProxiedChannel(nsIURI *uri, nsIProxyInfo *pi, nsIChannel **newChannel) +CreateHTTPProxiedChannel(nsIChannel *channel, nsIProxyInfo *pi, nsIChannel **newChannel) { nsresult rv; nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); @@ -2374,11 +2374,14 @@ CreateHTTPProxiedChannel(nsIURI *uri, nsIProxyInfo *pi, nsIChannel **newChannel) if (NS_FAILED(rv)) return rv;
+ nsCOMPtr<nsIURI> uri; + channel->GetURI(getter_AddRefs(uri)); + return pph->NewProxiedChannel(uri, pi, 0, nullptr, newChannel); }
NS_IMETHODIMP -nsFtpState::OnProxyAvailable(nsICancelable *request, nsIURI *uri, +nsFtpState::OnProxyAvailable(nsICancelable *request, nsIChannel *channel, nsIProxyInfo *pi, nsresult status) { mProxyRequest = nullptr; @@ -2395,7 +2398,7 @@ nsFtpState::OnProxyAvailable(nsICancelable *request, nsIURI *uri, LOG(("FTP:(%p) Configured to use a HTTP proxy channel\n", this));
nsCOMPtr<nsIChannel> newChannel; - if (NS_SUCCEEDED(CreateHTTPProxiedChannel(uri, pi, + if (NS_SUCCEEDED(CreateHTTPProxiedChannel(channel, pi, getter_AddRefs(newChannel))) && NS_SUCCEEDED(mChannel->Redirect(newChannel, nsIChannelEventSink::REDIRECT_INTERNAL, diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 40123da..64b202a 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -68,6 +68,7 @@ HttpBaseChannel::HttpBaseChannel() , mContentDispositionHint(UINT32_MAX) , mHttpHandler(gHttpHandler) , mRedirectCount(0) + , mProxyURI(nullptr) { LOG(("Creating HttpBaseChannel @%x\n", this));
@@ -1075,6 +1076,15 @@ HttpBaseChannel::SetReferrer(nsIURI *referrer) }
NS_IMETHODIMP +HttpBaseChannel::GetProxyURI(nsIURI** proxyURI) +{ + NS_ENSURE_ARG_POINTER(proxyURI); + *proxyURI = mProxyURI; + NS_IF_ADDREF(*proxyURI); + return NS_OK; +} + +NS_IMETHODIMP HttpBaseChannel::GetRequestHeader(const nsACString& aHeader, nsACString& aValue) { diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index e177a39..abaf789 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -115,6 +115,7 @@ public: NS_IMETHOD SetRequestMethod(const nsACString& aMethod); NS_IMETHOD GetReferrer(nsIURI **referrer); NS_IMETHOD SetReferrer(nsIURI *referrer); + NS_IMETHOD GetProxyURI(nsIURI **proxyURI); NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue); NS_IMETHOD SetRequestHeader(const nsACString& aHeader, const nsACString& aValue, bool aMerge); diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 6449769..41ef8bb 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -1823,10 +1823,10 @@ nsHttpChannel::ResolveProxy() // then it is ok to use that version. nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps); if (pps2) { - rv = pps2->AsyncResolve2(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags, + rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, getter_AddRefs(mProxyRequest)); } else { - rv = pps->AsyncResolve(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags, + rv = pps->AsyncResolve(this, mProxyResolveFlags, this, getter_AddRefs(mProxyRequest)); }
@@ -4707,7 +4707,7 @@ nsHttpChannel::SetPriority(int32_t value) //-----------------------------------------------------------------------------
NS_IMETHODIMP -nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri, +nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIChannel *channel, nsIProxyInfo *pi, nsresult status) { LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%x mStatus=%x]\n", diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl index abb2ee4..24df18b 100644 --- a/netwerk/protocol/http/nsIHttpChannel.idl +++ b/netwerk/protocol/http/nsIHttpChannel.idl @@ -56,6 +56,12 @@ interface nsIHttpChannel : nsIChannel attribute nsIURI referrer;
/** + * Read the proxy URI, which, if non-null, will be used to resolve + * proxies for this channel. + */ + readonly attribute nsIURI proxyURI; + + /** * Get the value of a particular request header. * * @param aHeader diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp index f92c36e..350c920 100644 --- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp @@ -115,6 +115,12 @@ nsViewSourceChannel::GetName(nsACString &result) }
NS_IMETHODIMP +nsViewSourceChannel::GetProxyURI(nsIURI** proxyURI) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsViewSourceChannel::IsPending(bool *result) { NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 90f023c..5e14f97 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -2292,7 +2292,7 @@ WebSocketChannel::ApplyForAdmission()
MOZ_ASSERT(!mCancelable);
- return pps->AsyncResolve(mURI, + return pps->AsyncResolve(mHttpChannel, nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY | nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL, this, getter_AddRefs(mCancelable)); @@ -2406,7 +2406,7 @@ WebSocketChannel::OnLookupComplete(nsICancelable *aRequest,
// nsIProtocolProxyCallback NS_IMETHODIMP -WebSocketChannel::OnProxyAvailable(nsICancelable *aRequest, nsIURI *aURI, +WebSocketChannel::OnProxyAvailable(nsICancelable *aRequest, nsIChannel *aChannel, nsIProxyInfo *pi, nsresult status) { if (mStopped) {