Bug 546606 - Make redirect API async - part 2; r=honzab.moz,cbiesinger,bjarne,jst sr=jst

This commit is contained in:
Bjarne 2010-08-04 22:15:55 -04:00
Родитель b64f460e63
Коммит 06924ec766
38 изменённых файлов: 804 добавлений и 233 удалений

Просмотреть файл

@ -95,6 +95,7 @@
#include "nsIChromeRegistry.h"
#include "nsPrintfCString.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIAsyncVerifyRedirectCallback.h"
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
@ -3257,9 +3258,10 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
// Method implementing nsIChannelEventSink //
/////////////////////////////////////////////
NS_IMETHODIMP
nsScriptSecurityManager::OnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel,
PRUint32 redirFlags)
nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel,
PRUint32 redirFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
nsCOMPtr<nsIPrincipal> oldPrincipal;
GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
@ -3278,7 +3280,12 @@ nsScriptSecurityManager::OnChannelRedirect(nsIChannel* oldChannel,
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
rv = CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
}
return rv;
if (NS_FAILED(rv))
return rv;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -53,6 +53,8 @@
#include "nsIWritablePropertyBag2.h"
#include "nsNetError.h"
#include "nsChannelProperties.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsAsyncRedirectVerifyHelper.h"
/* Keeps track of whether or not CSP is enabled */
PRBool CSPService::sCSPEnabled = PR_TRUE;
@ -203,10 +205,13 @@ CSPService::ShouldProcess(PRUint32 aContentType,
/* nsIChannelEventSink implementation */
NS_IMETHODIMP
CSPService::OnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags)
CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
nsAsyncRedirectAutoCallback autoCallback(callback);
// get the Content Security Policy and load type from the property bag
nsCOMPtr<nsISupports> policyContainer;
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(oldChannel));
@ -257,19 +262,22 @@ CSPService::OnChannelRedirect(nsIChannel *oldChannel,
nsCAutoString newUriSpec("None");
newUri->GetSpec(newUriSpec);
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
("CSPService::OnChannelRedirect called for %s", newUriSpec.get()));
("CSPService::AsyncOnChannelRedirect called for %s",
newUriSpec.get()));
}
if (aDecision == 1)
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
("CSPService::OnChannelRedirect ALLOWING request."));
("CSPService::AsyncOnChannelRedirect ALLOWING request."));
else
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
("CSPService::OnChannelRedirect CANCELLING request."));
("CSPService::AsyncOnChannelRedirect CANCELLING request."));
#endif
// if ShouldLoad doesn't accept the load, cancel the request
if (aDecision != 1)
if (aDecision != 1) {
autoCallback.DontCallback();
return NS_BINDING_FAILED;
}
// the redirect is permitted, so propagate the Content Security Policy
// and load type to the redirecting channel

Просмотреть файл

@ -162,6 +162,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIUGenCategory.h"
#include "nsIDragService.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIInterfaceRequestor.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsCPrefetchService.h"
@ -5149,14 +5150,14 @@ NS_IMPL_ISUPPORTS2(nsSameOriginChecker,
nsIInterfaceRequestor)
NS_IMETHODIMP
nsSameOriginChecker::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsSameOriginChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
if (!nsContentUtils::GetSecurityManager()) {
if (!nsContentUtils::GetSecurityManager())
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIPrincipal> oldPrincipal;
nsContentUtils::GetSecurityManager()->
@ -5173,7 +5174,12 @@ nsSameOriginChecker::OnChannelRedirect(nsIChannel *aOldChannel,
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
}
return rv;
if (NS_FAILED(rv))
return rv;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -52,8 +52,10 @@
#include "nsGkAtoms.h"
#include "nsWhitespaceTokenizer.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsXMLHttpRequest.h"
#include "nsAsyncRedirectVerifyHelper.h"
static PRBool gDisableCORS = PR_FALSE;
static PRBool gDisableCORSPrivateData = PR_FALSE;
@ -81,9 +83,9 @@ private:
nsIChannel* mChannel;
};
NS_IMPL_ISUPPORTS4(nsCrossSiteListenerProxy, nsIStreamListener,
NS_IMPL_ISUPPORTS5(nsCrossSiteListenerProxy, nsIStreamListener,
nsIRequestObserver, nsIChannelEventSink,
nsIInterfaceRequestor)
nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback)
/* static */
void
@ -370,11 +372,11 @@ nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
}
NS_IMETHODIMP
nsCrossSiteListenerProxy::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsCrossSiteListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
nsChannelCanceller canceller(aOldChannel);
nsresult rv;
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
rv = CheckRequestApproved(aOldChannel, PR_TRUE);
@ -387,22 +389,57 @@ nsCrossSiteListenerProxy::OnChannelRedirect(nsIChannel *aOldChannel,
RemoveEntries(oldURI, mRequestingPrincipal);
}
}
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
return NS_ERROR_DOM_BAD_URI;
}
}
// Prepare to receive callback
mRedirectCallback = cb;
mOldRedirectChannel = aOldChannel;
mNewRedirectChannel = aNewChannel;
nsCOMPtr<nsIChannelEventSink> outer =
do_GetInterface(mOuterNotificationCallbacks);
if (outer) {
rv = outer->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
NS_ENSURE_SUCCESS(rv, rv);
rv = outer->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, this);
if (NS_FAILED(rv)) {
aOldChannel->Cancel(rv); // is this necessary...?
mRedirectCallback = nsnull;
mOldRedirectChannel = nsnull;
mNewRedirectChannel = nsnull;
}
return rv;
}
rv = UpdateChannel(aNewChannel);
NS_ENSURE_SUCCESS(rv, rv);
(void) OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
canceller.DontCancel();
NS_IMETHODIMP
nsCrossSiteListenerProxy::OnRedirectVerifyCallback(nsresult result)
{
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ASSERTION(mOldRedirectChannel, "mOldRedirectChannel not set in callback");
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
if (NS_SUCCEEDED(result)) {
nsresult rv = UpdateChannel(mNewRedirectChannel);
if (NS_FAILED(rv)) {
NS_WARNING("nsCrossSiteListenerProxy::OnRedirectVerifyCallback: "
"UpdateChannel() returned failure");
}
result = rv;
}
if (NS_FAILED(result)) {
mOldRedirectChannel->Cancel(result);
}
mOldRedirectChannel = nsnull;
mNewRedirectChannel = nsnull;
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
return NS_OK;
}

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsTArray.h"
#include "nsIInterfaceRequestor.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
class nsIURI;
class nsIParser;
@ -56,7 +57,8 @@ IsValidHTTPToken(const nsCSubstring& aToken);
class nsCrossSiteListenerProxy : public nsIStreamListener,
public nsIInterfaceRequestor,
public nsIChannelEventSink
public nsIChannelEventSink,
public nsIAsyncVerifyRedirectCallback
{
public:
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
@ -77,6 +79,7 @@ public:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
// Must be called at startup.
static void Startup();
@ -100,6 +103,9 @@ private:
nsCString mPreflightMethod;
nsTArray<nsCString> mPreflightHeaders;
nsTArray<PRUint32> mAllowedHTTPErrors;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIChannel> mOldRedirectChannel;
nsCOMPtr<nsIChannel> mNewRedirectChannel;
};
#endif

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsIWebNavigationInfo.h"
#include "nsIScriptChannel.h"
#include "nsIBlocklistService.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsPluginError.h"
@ -1025,9 +1026,10 @@ nsObjectLoadingContent::GetInterface(const nsIID & aIID, void **aResult)
// nsIChannelEventSink
NS_IMETHODIMP
nsObjectLoadingContent::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsObjectLoadingContent::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
// If we're already busy with a new load, cancel the redirect
if (aOldChannel != mChannel) {
@ -1035,6 +1037,7 @@ nsObjectLoadingContent::OnChannelRedirect(nsIChannel *aOldChannel,
}
mChannel = aNewChannel;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsIChannel.h"
#include "nsIDOMLoadListener.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIInterfaceRequestor.h"
#include "nsString.h"
#include "nsWeakReference.h"
@ -360,14 +361,16 @@ nsSyncLoader::Error(nsIDOMEvent* aEvent)
}
NS_IMETHODIMP
nsSyncLoader::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsSyncLoader::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
mChannel = aNewChannel;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -99,6 +99,7 @@
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsAsyncRedirectVerifyHelper.h"
#define LOAD_STR "load"
#define ERROR_STR "error"
@ -486,13 +487,17 @@ nsACProxyListener::OnDataAvailable(nsIRequest *aRequest,
}
NS_IMETHODIMP
nsACProxyListener::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsACProxyListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
// Only internal redirects allowed for now.
return NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) ?
NS_OK : NS_ERROR_DOM_BAD_URI;
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags))
return NS_ERROR_DOM_BAD_URI;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
@ -2988,13 +2993,60 @@ nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast)
return rv;
}
/*
* Simple helper class that just forwards the redirect callback back
* to the nsXMLHttpRequest.
*/
class AsyncVerifyRedirectCallbackForwarder : public nsIAsyncVerifyRedirectCallback
{
public:
AsyncVerifyRedirectCallbackForwarder(nsXMLHttpRequest *xhr)
: mXHR(xhr)
{
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(AsyncVerifyRedirectCallbackForwarder)
// nsIAsyncVerifyRedirectCallback implementation
NS_IMETHOD OnRedirectVerifyCallback(nsresult result)
{
mXHR->OnRedirectVerifyCallback(result);
return NS_OK;
}
private:
nsRefPtr<nsXMLHttpRequest> mXHR;
};
NS_IMPL_CYCLE_COLLECTION_CLASS(AsyncVerifyRedirectCallbackForwarder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AsyncVerifyRedirectCallbackForwarder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mXHR, nsIDOMEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AsyncVerifyRedirectCallbackForwarder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXHR)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackForwarder)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncVerifyRedirectCallbackForwarder)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncVerifyRedirectCallbackForwarder)
/////////////////////////////////////////////////////
// nsIChannelEventSink methods:
//
NS_IMETHODIMP
nsXMLHttpRequest::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsXMLHttpRequest::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
@ -3002,7 +3054,11 @@ nsXMLHttpRequest::OnChannelRedirect(nsIChannel *aOldChannel,
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
rv = CheckChannelForCrossSiteRequest(aNewChannel);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
NS_WARNING("nsXMLHttpRequest::OnChannelRedirect: "
"CheckChannelForCrossSiteRequest returned failure");
return rv;
}
// Disable redirects for preflighted cross-site requests entirely for now
// Note, do this after the call to CheckChannelForCrossSiteRequest
@ -3012,20 +3068,44 @@ nsXMLHttpRequest::OnChannelRedirect(nsIChannel *aOldChannel,
}
}
// Prepare to receive callback
mRedirectCallback = callback;
mNewRedirectChannel = aNewChannel;
if (mChannelEventSink) {
rv =
mChannelEventSink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
nsRefPtr<AsyncVerifyRedirectCallbackForwarder> fwd =
new AsyncVerifyRedirectCallbackForwarder(this);
rv = mChannelEventSink->AsyncOnChannelRedirect(aOldChannel,
aNewChannel,
aFlags, fwd);
if (NS_FAILED(rv)) {
mErrorLoad = PR_TRUE;
return rv;
mRedirectCallback = nsnull;
mNewRedirectChannel = nsnull;
}
return rv;
}
mChannel = aNewChannel;
OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
void
nsXMLHttpRequest::OnRedirectVerifyCallback(nsresult result)
{
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
if (NS_SUCCEEDED(result))
mChannel = mNewRedirectChannel;
else
mErrorLoad = PR_TRUE;
mNewRedirectChannel = nsnull;
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
}
/////////////////////////////////////////////////////
// nsIProgressEventSink methods:
//

Просмотреть файл

@ -51,6 +51,7 @@
#include "jsapi.h"
#include "nsIScriptContext.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIInterfaceRequestor.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIProgressEventSink.h"
@ -70,6 +71,7 @@
#include "nsDOMEventTargetWrapperCache.h"
class nsILoadGroup;
class AsyncVerifyRedirectCallbackForwarder;
class nsAccessControlLRUCache
{
@ -340,6 +342,9 @@ protected:
void StartProgressEventTimer();
friend class AsyncVerifyRedirectCallbackForwarder;
void OnRedirectVerifyCallback(nsresult result);
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
@ -413,6 +418,9 @@ protected:
nsCOMPtr<nsITimer> mProgressNotifier;
PRPackedBool mFirstStartRequestSeen;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIChannel> mNewRedirectChannel;
};
// helper class to expose a progress DOM Event

Просмотреть файл

@ -86,6 +86,7 @@
#include "BasicLayers.h"
#include <limits>
#include "nsIDocShellTreeItem.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#ifdef MOZ_OGG
#include "nsOggDecoder.h"
@ -352,15 +353,19 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest*
return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
}
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags)
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback* cb)
{
// TODO is this really correct?? See bug #579329.
if (mElement)
mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
nsCOMPtr<nsIChannelEventSink> sink = do_QueryInterface(mNextListener);
if (sink)
return sink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
return sink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, cb);
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -56,6 +56,7 @@
#include "nsDOMError.h"
#include "nsICachingChannel.h"
#include "nsURILoader.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#define HTTP_OK_CODE 200
#define HTTP_PARTIAL_RESPONSE_CODE 206
@ -126,13 +127,20 @@ nsMediaChannelStream::Listener::OnDataAvailable(nsIRequest* aRequest,
}
nsresult
nsMediaChannelStream::Listener::OnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags)
nsMediaChannelStream::Listener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback* cb)
{
if (!mStream)
return NS_OK;
return mStream->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
nsresult rv = NS_OK;
if (mStream)
rv = mStream->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
if (NS_FAILED(rv))
return rv;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
nsresult

Просмотреть файл

@ -85,6 +85,7 @@
#include "nsIAuthPrompt2.h"
#include "nsTextFormatter.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIUploadChannel.h"
#include "nsISecurityEventSink.h"
#include "mozilla/FunctionTimer.h"
@ -502,8 +503,9 @@ nsPingListener::GetInterface(const nsIID &iid, void **result)
}
NS_IMETHODIMP
nsPingListener::OnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
PRUint32 flags)
nsPingListener::AsyncOnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
nsCOMPtr<nsIURI> newURI;
newChan->GetURI(getter_AddRefs(newURI));
@ -511,8 +513,10 @@ nsPingListener::OnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
if (!CheckPingURI(newURI, mContent))
return NS_ERROR_ABORT;
if (!mRequireSameHost)
if (!mRequireSameHost) {
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
// XXXbz should this be using something more like the nsContentUtils
// same-origin checker?
@ -523,6 +527,7 @@ nsPingListener::OnChannelRedirect(nsIChannel *oldChan, nsIChannel *newChan,
if (!IsSameHost(oldURI, newURI))
return NS_ERROR_ABORT;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsIPrefService.h"
#include "nsIProgressEventSink.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIProxyObjectManager.h"
#include "nsIServiceManager.h"
#include "nsIFileURL.h"
@ -319,9 +320,10 @@ nsProgressNotificationProxy::OnStatus(nsIRequest* request,
}
NS_IMETHODIMP
nsProgressNotificationProxy::OnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags) {
nsProgressNotificationProxy::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *cb) {
// The 'old' channel should match the current one
NS_ABORT_IF_FALSE(oldChannel == mChannel,
"old channel doesn't match current!");
@ -337,9 +339,13 @@ nsProgressNotificationProxy::OnChannelRedirect(nsIChannel *oldChannel,
loadGroup,
NS_GET_IID(nsIChannelEventSink),
getter_AddRefs(target));
if (!target)
return NS_OK;
return target->OnChannelRedirect(oldChannel, newChannel, flags);
if (!target) {
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
// Delegate to |target| if set, reusing |cb|
return target->AsyncOnChannelRedirect(oldChannel, newChannel, flags, cb);
}
NS_IMETHODIMP

Просмотреть файл

@ -83,6 +83,7 @@
#include "nsIPrefBranch2.h"
#include "imgDiscardTracker.h"
#include "nsAsyncRedirectVerifyHelper.h"
#define DISCARD_PREF "image.mem.discardable"
#define DECODEONDRAW_PREF "image.mem.decodeondraw"
@ -158,12 +159,13 @@ imgRequestPrefObserver::Observe(nsISupports *aSubject,
PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest");
#endif
NS_IMPL_ISUPPORTS7(imgRequest,
NS_IMPL_ISUPPORTS8(imgRequest,
imgIDecoderObserver, imgIContainerObserver,
nsIStreamListener, nsIRequestObserver,
nsISupportsWeakReference,
nsIChannelEventSink,
nsIInterfaceRequestor)
nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
imgRequest::imgRequest() :
mCacheId(0), mValidator(nsnull), mImageSniffers("image-sniffing-services"),
@ -1119,24 +1121,49 @@ imgRequest::GetInterface(const nsIID & aIID, void **aResult)
}
/** nsIChannelEventSink methods **/
/* void onChannelRedirect (in nsIChannel oldChannel, in nsIChannel newChannel, in unsigned long flags); */
NS_IMETHODIMP
imgRequest::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PRUint32 flags)
imgRequest::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel, PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
NS_ASSERTION(mRequest && mChannel, "Got an OnChannelRedirect after we nulled out mRequest!");
NS_ASSERTION(mRequest && mChannel, "Got a channel redirect after we nulled out mRequest!");
NS_ASSERTION(mChannel == oldChannel, "Got a channel redirect for an unknown channel!");
NS_ASSERTION(newChannel, "Got a redirect to a NULL channel!");
nsresult rv = NS_OK;
// Prepare for callback
mRedirectCallback = callback;
mNewRedirectChannel = newChannel;
nsCOMPtr<nsIChannelEventSink> sink(do_GetInterface(mPrevChannelSink));
if (sink) {
rv = sink->OnChannelRedirect(oldChannel, newChannel, flags);
if (NS_FAILED(rv))
return rv;
nsresult rv = sink->AsyncOnChannelRedirect(oldChannel, newChannel, flags,
this);
if (NS_FAILED(rv)) {
mRedirectCallback = nsnull;
mNewRedirectChannel = nsnull;
}
return rv;
}
(void) OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
imgRequest::OnRedirectVerifyCallback(nsresult result)
{
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
if (NS_FAILED(result)) {
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
mNewRedirectChannel = nsnull;
return NS_OK;
}
mChannel = newChannel;
mChannel = mNewRedirectChannel;
mNewRedirectChannel = nsnull;
// Don't make any cache changes if we're going to point to the same thing. We
// compare specs and not just URIs here because URIs that compare as
@ -1149,17 +1176,23 @@ imgRequest::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PR
// make sure we have a protocol that returns data rather than opens
// an external application, e.g. mailto:
nsCOMPtr<nsIURI> uri;
newChannel->GetURI(getter_AddRefs(uri));
mChannel->GetURI(getter_AddRefs(uri));
PRBool doesNotReturnData = PR_FALSE;
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
if (NS_FAILED(rv))
return rv;
if (doesNotReturnData)
return NS_ERROR_ABORT;
nsresult rv =
NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
if (NS_SUCCEEDED(rv) && doesNotReturnData)
rv = NS_ERROR_ABORT;
if (NS_FAILED(rv)) {
mRedirectCallback->OnRedirectVerifyCallback(rv);
mRedirectCallback = nsnull;
return NS_OK;
}
nsCOMPtr<nsIURI> newURI;
newChannel->GetOriginalURI(getter_AddRefs(newURI));
mChannel->GetOriginalURI(getter_AddRefs(newURI));
nsCAutoString newspec;
if (newURI)
newURI->GetSpec(newspec);
@ -1186,5 +1219,7 @@ imgRequest::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PR
}
}
return rv;
mRedirectCallback->OnRedirectVerifyCallback(NS_OK);
mRedirectCallback = nsnull;
return NS_OK;
}

Просмотреть файл

@ -62,6 +62,7 @@
#include "ImageErrors.h"
#include "imgIRequest.h"
#include "imgContainer.h"
#include "nsIAsyncVerifyRedirectCallback.h"
class imgCacheValidator;
@ -74,7 +75,8 @@ class imgRequest : public imgIDecoderObserver,
public nsIStreamListener,
public nsSupportsWeakReference,
public nsIChannelEventSink,
public nsIInterfaceRequestor
public nsIInterfaceRequestor,
public nsIAsyncVerifyRedirectCallback
{
public:
imgRequest();
@ -182,6 +184,7 @@ public:
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
private:
friend class imgMemoryReporter;
@ -211,7 +214,8 @@ private:
imgCacheValidator *mValidator;
nsCategoryCache<nsIContentSniffer> mImageSniffers;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIChannel> mNewRedirectChannel;
// Sometimes consumers want to do things before the image is ready. Let them,
// and apply the action when the image becomes available.
PRPackedBool mDecodeRequested : 1;

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -20,6 +21,7 @@
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
* Bjarne Geir Herland <bjarne@runitsoft.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,8 +41,13 @@
#define nsAsyncRedirectVerifyHelper_h
#include "nsIRunnable.h"
#include "nsIThread.h"
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
class nsIChannel;
@ -49,14 +56,27 @@ class nsIChannel;
* the sink bound with the channel being redirected while the result of
* redirect decision is returned through the callback.
*/
class nsAsyncRedirectVerifyHelper : public nsIRunnable
class nsAsyncRedirectVerifyHelper : public nsIRunnable,
public nsIAsyncVerifyRedirectCallback
{
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
public:
nsAsyncRedirectVerifyHelper();
/*
* Calls AsyncOnChannelRedirect() on the given sink with the given
* channels and flags. Keeps track of number of async callbacks to expect.
*/
nsresult DelegateOnChannelRedirect(nsIChannelEventSink *sink,
nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags);
/**
* Initialize and runs the chain of OnChannelRedirect calls. OldChannel
* Initialize and run the chain of AsyncOnChannelRedirect calls. OldChannel
* is QI'ed for nsIAsyncVerifyRedirectCallback. The result of the redirect
* decision is passed through this interface back to the oldChannel.
*
@ -81,8 +101,57 @@ protected:
nsCOMPtr<nsIChannel> mNewChan;
PRUint32 mFlags;
PRBool mWaitingForRedirectCallback;
nsCOMPtr<nsIThread> mCallbackThread;
PRBool mCallbackInitiated;
PRInt32 mExpectedCallbacks;
nsresult mResult; // value passed to callback
void Callback(nsresult result);
void InitCallback();
/**
* Calls back to |oldChan| as described in Init()
*/
void ExplicitCallback(nsresult result);
private:
~nsAsyncRedirectVerifyHelper();
bool IsOldChannelCanceled();
};
/*
* Helper to make the call-stack handle some control-flow for us
*/
class nsAsyncRedirectAutoCallback
{
public:
nsAsyncRedirectAutoCallback(nsIAsyncVerifyRedirectCallback* aCallback)
: mCallback(aCallback)
{
mResult = NS_OK;
}
~nsAsyncRedirectAutoCallback()
{
if (mCallback)
mCallback->OnRedirectVerifyCallback(mResult);
}
/*
* Call this is you want it to call back with a different result-code
*/
void SetResult(nsresult aRes)
{
mResult = aRes;
}
/*
* Call this is you want to avoid the callback
*/
void DontCallback()
{
mCallback = nsnull;
}
private:
nsIAsyncVerifyRedirectCallback* mCallback;
nsresult mResult;
};
#endif

Просмотреть файл

@ -24,6 +24,7 @@
* Gagan Saksena <gagan@netscape.com> (original author)
* Darin Fisher <darin@netscape.com>
* Christian Biesinger <cbiesinger@web.de>
* Bjarne Geir Herland <bjarne@runitsoft.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -42,6 +43,7 @@
#include "nsISupports.idl"
interface nsIChannel;
interface nsIAsyncVerifyRedirectCallback;
/**
* Implement this interface to receive control over various channel events.
@ -49,10 +51,9 @@ interface nsIChannel;
* notificationCallbacks or, if not available there, from the loadGroup's
* notificationCallbacks.
*
* These methods are called before onStartRequest, and should be handled
* SYNCHRONOUSLY.
* These methods are called before onStartRequest.
*/
[scriptable, uuid(6757d790-2916-498e-aaca-6b668a956875)]
[scriptable, uuid(a430d870-df77-4502-9570-d46a8de33154)]
interface nsIChannelEventSink : nsISupports
{
/**
@ -82,7 +83,30 @@ interface nsIChannelEventSink : nsISupports
/**
* Called when a redirect occurs. This may happen due to an HTTP 3xx status
* code.
* code. The purpose of this method is to notify the sink that a redirect
* is about to happen, but also to give the sink the right to veto the
* redirect by throwing or passing a failure-code in the callback.
*
* Note that vetoing the redirect simply means that |newChannel| will not
* be opened. It is important to understand that |oldChannel| will continue
* loading as if it received a HTTP 200, which includes notifying observers
* and possibly display or process content attached to the HTTP response.
* If the sink wants to prevent this loading it must explicitly deal with
* it, e.g. by calling |oldChannel->Cancel()|
*
* There is a certain freedom in implementing this method:
*
* If the return-value indicates success, a callback on |callback| is
* required. This callback can be done from within asyncOnChannelRedirect
* (effectively making the call synchronous) or at some point later
* (making the call asynchronous). Repeat: A callback must be done
* if this method returns successfully.
*
* If the return value indicates error (method throws an exception)
* the redirect is vetoed and no callback must be done. Repeat: No
* callback must be done if this method throws!
*
* @see nsIAsyncVerifyRedirectCallback::onRedirectVerifyCallback()
*
* @param oldChannel
* The channel that's being redirected.
@ -93,11 +117,14 @@ interface nsIChannelEventSink : nsISupports
* of flags from above.
* One of REDIRECT_TEMPORARY and REDIRECT_PERMANENT will always be
* set.
* @param callback
* Object to inform about the async result of this method
*
* @throw <any> Throwing an exception will cancel the load. No network
* request for the new channel will be made.
* @throw <any> Throwing an exception will cause the redirect to be
* cancelled
*/
void onChannelRedirect(in nsIChannel oldChannel,
in nsIChannel newChannel,
in unsigned long flags);
void asyncOnChannelRedirect(in nsIChannel oldChannel,
in nsIChannel newChannel,
in unsigned long flags,
in nsIAsyncVerifyRedirectCallback callback);
};

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -20,6 +21,7 @@
*
* Contributor(s):
* Honza Bambas <honzab@firemni.cz>
* Bjarne Geir Herland <bjarnw@runitsoft.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -35,6 +37,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "prlog.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
@ -44,15 +47,60 @@
#include "nsIHttpChannelInternal.h"
#include "nsIAsyncVerifyRedirectCallback.h"
NS_IMPL_ISUPPORTS1(nsAsyncRedirectVerifyHelper, nsIRunnable)
#ifdef PR_LOGGING
static PRLogModuleInfo *gLog = PR_NewLogModule("nsRedirect");
#define LOG(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
#else
#define LOG(args)
#endif
NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncRedirectVerifyHelper,
nsIAsyncVerifyRedirectCallback,
nsIRunnable)
class nsAsyncVerifyRedirectCallbackEvent : public nsRunnable {
public:
nsAsyncVerifyRedirectCallbackEvent(nsIAsyncVerifyRedirectCallback *cb,
nsresult result)
: mCallback(cb), mResult(result) {
}
NS_IMETHOD Run()
{
LOG(("nsAsyncVerifyRedirectCallbackEvent::Run() "
"callback to %p with result %x",
mCallback.get(), mResult));
(void) mCallback->OnRedirectVerifyCallback(mResult);
return NS_OK;
}
private:
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mCallback;
nsresult mResult;
};
nsAsyncRedirectVerifyHelper::nsAsyncRedirectVerifyHelper()
: mCallbackInitiated(PR_FALSE),
mExpectedCallbacks(0),
mResult(NS_OK)
{
}
nsAsyncRedirectVerifyHelper::~nsAsyncRedirectVerifyHelper()
{
NS_ASSERTION(NS_FAILED(mResult) || mExpectedCallbacks == 0,
"Did not receive all required callbacks!");
}
nsresult
nsAsyncRedirectVerifyHelper::Init(nsIChannel* oldChan, nsIChannel* newChan,
PRUint32 flags, PRBool synchronize)
{
mOldChan = oldChan;
mNewChan = newChan;
mFlags = flags;
LOG(("nsAsyncRedirectVerifyHelper::Init() "
"oldChan=%p newChan=%p", oldChan, newChan));
mOldChan = oldChan;
mNewChan = newChan;
mFlags = flags;
mCallbackThread = do_GetCurrentThread();
if (synchronize)
mWaitingForRedirectCallback = PR_TRUE;
@ -73,55 +121,172 @@ nsAsyncRedirectVerifyHelper::Init(nsIChannel* oldChan, nsIChannel* newChan,
return NS_OK;
}
void
nsAsyncRedirectVerifyHelper::Callback(nsresult result)
NS_IMETHODIMP
nsAsyncRedirectVerifyHelper::OnRedirectVerifyCallback(nsresult result)
{
// TODO E10S OnRedirectCallback has to be called on the original process
nsCOMPtr<nsIAsyncVerifyRedirectCallback> callback(do_QueryInterface(mOldChan));
NS_ASSERTION(callback, "nsAsyncRedirectVerifyHelper: oldChannel doesn't"
" implement nsIAsyncVerifyRedirectCallback");
LOG(("nsAsyncRedirectVerifyHelper::OnRedirectVerifyCallback() "
"result=%x expectedCBs=%u mResult=%x",
result, mExpectedCallbacks, mResult));
if (callback)
callback->OnRedirectVerifyCallback(result);
--mExpectedCallbacks;
// If response indicates failure we may call back immediately
if (NS_FAILED(result)) {
// We chose to store the first failure-value (as opposed to the last)
if (NS_SUCCEEDED(mResult))
mResult = result;
// If InitCallback() has been called, just invoke the callback and
// return. Otherwise it will be invoked from InitCallback()
if (mCallbackInitiated) {
ExplicitCallback(mResult);
return NS_OK;
}
}
// If the expected-counter is in balance and InitCallback() was called, all
// sinks have agreed that the redirect is ok and we can invoke our callback
if (mCallbackInitiated && mExpectedCallbacks == 0) {
ExplicitCallback(mResult);
}
return NS_OK;
}
nsresult
nsAsyncRedirectVerifyHelper::DelegateOnChannelRedirect(nsIChannelEventSink *sink,
nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags)
{
LOG(("nsAsyncRedirectVerifyHelper::DelegateOnChannelRedirect() "
"sink=%p expectedCBs=%u mResult=%x",
sink, mExpectedCallbacks, mResult));
++mExpectedCallbacks;
if (IsOldChannelCanceled()) {
LOG((" old channel has been canceled, cancel the redirect by "
"emulating OnRedirectVerifyCallback..."));
(void) OnRedirectVerifyCallback(NS_BINDING_ABORTED);
return NS_BINDING_ABORTED;
}
nsresult rv =
sink->AsyncOnChannelRedirect(oldChannel, newChannel, flags, this);
LOG((" result=%x expectedCBs=%u", rv, mExpectedCallbacks));
// If the sink returns failure from this call the redirect is vetoed. We
// emulate a callback from the sink in this case in order to perform all
// the necessary logic.
if (NS_FAILED(rv)) {
LOG((" emulating OnRedirectVerifyCallback..."));
(void) OnRedirectVerifyCallback(rv);
}
return rv; // Return the actual status since our caller may need it
}
void
nsAsyncRedirectVerifyHelper::ExplicitCallback(nsresult result)
{
LOG(("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
"result=%x expectedCBs=%u mCallbackInitiated=%u mResult=%x",
result, mExpectedCallbacks, mCallbackInitiated, mResult));
nsCOMPtr<nsIAsyncVerifyRedirectCallback>
callback(do_QueryInterface(mOldChan));
if (!callback || !mCallbackThread) {
LOG(("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
"callback=%p mCallbackThread=%p", callback, mCallbackThread));
return;
}
mCallbackInitiated = PR_FALSE; // reset to ensure only one callback
mWaitingForRedirectCallback = PR_FALSE;
// Now, dispatch the callback on the event-target which called Init()
nsRefPtr<nsIRunnable> event =
new nsAsyncVerifyRedirectCallbackEvent(callback, result);
if (!event) {
NS_WARNING("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
"failed creating callback event!");
return;
}
nsresult rv = mCallbackThread->Dispatch(event, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
NS_WARNING("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
"failed dispatching callback event!");
} else {
LOG(("nsAsyncRedirectVerifyHelper::ExplicitCallback() "
"dispatched callback event=%p", event.get()));
}
}
void
nsAsyncRedirectVerifyHelper::InitCallback()
{
LOG(("nsAsyncRedirectVerifyHelper::InitCallback() "
"expectedCBs=%d mResult=%x", mExpectedCallbacks, mResult));
mCallbackInitiated = PR_TRUE;
// Invoke the callback if we are done
if (mExpectedCallbacks == 0)
ExplicitCallback(mResult);
}
NS_IMETHODIMP
nsAsyncRedirectVerifyHelper::Run()
{
/* If the channel got canceled after it fired AsyncOnChannelRedirect
* (bug 546606) and before we got here, mostly because docloader
* load has been canceled, we must completely ignore this notification
* and prevent any further notification.
*
* TODO Bug 546606, this must be checked before every single call!
* and before we got here, mostly because docloader load has been canceled,
* we must completely ignore this notification and prevent any further
* notification.
*/
PRBool canceled;
nsCOMPtr<nsIHttpChannelInternal> oldChannelInternal =
do_QueryInterface(mOldChan);
if (oldChannelInternal) {
oldChannelInternal->GetCanceled(&canceled);
if (canceled) {
Callback(NS_BINDING_ABORTED);
return NS_OK;
}
if (IsOldChannelCanceled()) {
ExplicitCallback(NS_BINDING_ABORTED);
return NS_OK;
}
// First, the global observer
NS_ASSERTION(gIOService, "Must have an IO service at this point");
nsresult rv = gIOService->OnChannelRedirect(mOldChan, mNewChan, mFlags);
LOG(("nsAsyncRedirectVerifyHelper::Run() calling gIOService..."));
nsresult rv = gIOService->AsyncOnChannelRedirect(mOldChan, mNewChan,
mFlags, this);
if (NS_FAILED(rv)) {
Callback(rv);
ExplicitCallback(rv);
return NS_OK;
}
// Now, the per-channel observers
nsCOMPtr<nsIChannelEventSink> sink;
NS_QueryNotificationCallbacks(mOldChan, sink);
if (sink)
rv = sink->OnChannelRedirect(mOldChan, mNewChan, mFlags);
if (sink) {
LOG(("nsAsyncRedirectVerifyHelper::Run() calling sink..."));
rv = DelegateOnChannelRedirect(sink, mOldChan, mNewChan, mFlags);
}
Callback(rv);
// All invocations to AsyncOnChannelRedirect has been done - call
// InitCallback() to flag this
InitCallback();
return NS_OK;
}
bool
nsAsyncRedirectVerifyHelper::IsOldChannelCanceled()
{
PRBool canceled;
nsCOMPtr<nsIHttpChannelInternal> oldChannelInternal =
do_QueryInterface(mOldChan);
if (oldChannelInternal) {
oldChannelInternal->GetCanceled(&canceled);
if (canceled)
return true;
}
return false;
}

Просмотреть файл

@ -324,13 +324,15 @@ NS_IMPL_THREADSAFE_ISUPPORTS5(nsIOService,
////////////////////////////////////////////////////////////////////////////////
nsresult
nsIOService::OnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
PRUint32 flags)
nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
PRUint32 flags,
nsAsyncRedirectVerifyHelper *helper)
{
nsCOMPtr<nsIChannelEventSink> sink =
do_GetService(NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID);
if (sink) {
nsresult rv = sink->OnChannelRedirect(oldChan, newChan, flags);
nsresult rv = helper->DelegateOnChannelRedirect(sink, oldChan,
newChan, flags);
if (NS_FAILED(rv))
return rv;
}
@ -340,11 +342,11 @@ nsIOService::OnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
mChannelEventSinks.GetEntries();
PRInt32 len = entries.Count();
for (PRInt32 i = 0; i < len; ++i) {
nsresult rv = entries[i]->OnChannelRedirect(oldChan, newChan, flags);
nsresult rv = helper->DelegateOnChannelRedirect(entries[i], oldChan,
newChan, flags);
if (NS_FAILED(rv))
return rv;
}
return NS_OK;
}

Просмотреть файл

@ -57,6 +57,7 @@
#include "nsIContentSniffer.h"
#include "nsCategoryCache.h"
#include "nsINetworkLinkService.h"
#include "nsAsyncRedirectVerifyHelper.h"
#define NS_N(x) (sizeof(x)/sizeof(*x))
@ -95,8 +96,9 @@ public:
// Called by channels before a redirect happens. This notifies the global
// redirect observers.
nsresult OnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
PRUint32 flags);
nsresult AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
PRUint32 flags,
nsAsyncRedirectVerifyHelper *helper);
// Gets the array of registered content sniffers
const nsCOMArray<nsIContentSniffer>& GetContentSniffers() {

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsIRequestObserver.h"
#include "nsIProgressEventSink.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserverService.h"
#include "nsIObserver.h"
@ -126,6 +127,7 @@ class nsIncrementalDownload : public nsIIncrementalDownload
, public nsIInterfaceRequestor
, public nsIChannelEventSink
, public nsSupportsWeakReference
, public nsIAsyncVerifyRedirectCallback
{
public:
NS_DECL_ISUPPORTS
@ -136,6 +138,7 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
nsIncrementalDownload();
@ -150,26 +153,28 @@ private:
nsresult ReadCurrentSize();
nsresult ClearRequestHeader(nsIHttpChannel *channel);
nsCOMPtr<nsIRequestObserver> mObserver;
nsCOMPtr<nsISupports> mObserverContext;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mFinalURI;
nsCOMPtr<nsILocalFile> mDest;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsITimer> mTimer;
nsAutoArrayPtr<char> mChunk;
PRInt32 mChunkLen;
PRInt32 mChunkSize;
PRInt32 mInterval;
nsInt64 mTotalSize;
nsInt64 mCurrentSize;
PRUint32 mLoadFlags;
PRInt32 mNonPartialCount;
nsresult mStatus;
PRPackedBool mIsPending;
PRPackedBool mDidOnStartRequest;
PRTime mLastProgressUpdate;
nsCOMPtr<nsIRequestObserver> mObserver;
nsCOMPtr<nsISupports> mObserverContext;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mFinalURI;
nsCOMPtr<nsILocalFile> mDest;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsITimer> mTimer;
nsAutoArrayPtr<char> mChunk;
PRInt32 mChunkLen;
PRInt32 mChunkSize;
PRInt32 mInterval;
nsInt64 mTotalSize;
nsInt64 mCurrentSize;
PRUint32 mLoadFlags;
PRInt32 mNonPartialCount;
nsresult mStatus;
PRPackedBool mIsPending;
PRPackedBool mDidOnStartRequest;
PRTime mLastProgressUpdate;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIChannel> mNewRedirectChannel;
};
nsIncrementalDownload::nsIncrementalDownload()
@ -184,6 +189,8 @@ nsIncrementalDownload::nsIncrementalDownload()
, mIsPending(PR_FALSE)
, mDidOnStartRequest(PR_FALSE)
, mLastProgressUpdate(0)
, mRedirectCallback(nsnull)
, mNewRedirectChannel(nsnull)
{
}
@ -328,7 +335,7 @@ nsIncrementalDownload::ReadCurrentSize()
// nsISupports
NS_IMPL_ISUPPORTS8(nsIncrementalDownload,
NS_IMPL_ISUPPORTS9(nsIncrementalDownload,
nsIIncrementalDownload,
nsIRequest,
nsIStreamListener,
@ -336,7 +343,8 @@ NS_IMPL_ISUPPORTS8(nsIncrementalDownload,
nsIObserver,
nsIInterfaceRequestor,
nsIChannelEventSink,
nsISupportsWeakReference)
nsISupportsWeakReference,
nsIAsyncVerifyRedirectCallback)
// nsIRequest
@ -765,9 +773,10 @@ nsIncrementalDownload::ClearRequestHeader(nsIHttpChannel *channel)
// nsIChannelEventSink
NS_IMETHODIMP
nsIncrementalDownload::OnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags)
nsIncrementalDownload::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *cb)
{
// In response to a redirect, we need to propagate the Range header. See bug
// 311595. Any failure code returned from this function aborts the redirect.
@ -792,16 +801,38 @@ nsIncrementalDownload::OnChannelRedirect(nsIChannel *oldChannel,
NS_ENSURE_SUCCESS(rv, rv);
}
// Prepare to receive callback
mRedirectCallback = cb;
mNewRedirectChannel = newChannel;
// Give the observer a chance to see this redirect notification.
nsCOMPtr<nsIChannelEventSink> sink = do_GetInterface(mObserver);
if (sink)
rv = sink->OnChannelRedirect(oldChannel, newChannel, flags);
if (sink) {
rv = sink->AsyncOnChannelRedirect(oldChannel, newChannel, flags, this);
if (NS_FAILED(rv)) {
mRedirectCallback = nsnull;
mNewRedirectChannel = nsnull;
}
return rv;
}
(void) OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
nsIncrementalDownload::OnRedirectVerifyCallback(nsresult result)
{
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
// Update mChannel, so we can Cancel the new channel.
if (NS_SUCCEEDED(rv))
mChannel = newChannel;
if (NS_SUCCEEDED(result))
mChannel = mNewRedirectChannel;
return rv;
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
mNewRedirectChannel = nsnull;
return NS_OK;
}
extern nsresult

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsAutoPtr.h"
#include "nsCRT.h"
#include "prmon.h"
#include "nsIAsyncVerifyRedirectCallback.h"
//-----------------------------------------------------------------------------
@ -486,8 +487,14 @@ nsPACMan::GetInterface(const nsIID &iid, void **result)
}
NS_IMETHODIMP
nsPACMan::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel,
PRUint32 flags)
nsPACMan::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
return newChannel->GetURI(getter_AddRefs(mPACURI));
nsresult rv = NS_OK;
if (NS_FAILED((rv = newChannel->GetURI(getter_AddRefs(mPACURI)))))
return rv;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -43,6 +43,7 @@
#include "nsIHttpChannel.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsIAsyncVerifyRedirectCallback.h"
//-----------------------------------------------------------------------------
@ -367,11 +368,13 @@ nsURIChecker::GetInterface(const nsIID & aIID, void **aResult)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsURIChecker::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsURIChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
// We have a new channel
mChannel = aNewChannel;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -3044,6 +3044,7 @@ nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv)
nsresult
nsHttpChannel::ContinueProcessRedirection(nsresult rv)
{
LOG(("ContinueProcessRedirection [rv=%x]\n", rv));
if (NS_FAILED(rv))
return rv;
@ -4366,6 +4367,9 @@ nsHttpChannel::WaitForRedirectCallback()
NS_IMETHODIMP
nsHttpChannel::OnRedirectVerifyCallback(nsresult result)
{
LOG(("nsHttpChannel::OnRedirectVerifyCallback [this=%p] "
"result=%x stack=%d mWaitingForRedirectCallback=%u\n",
this, result, mRedirectFuncStack.Length(), mWaitingForRedirectCallback));
NS_ASSERTION(mWaitingForRedirectCallback,
"Someone forgot to call WaitForRedirectCallback() ?!");
mWaitingForRedirectCallback = PR_FALSE;

Просмотреть файл

@ -70,6 +70,7 @@
#include "nsIHttpChannelInternal.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIDNSService.h"
@ -239,12 +240,14 @@ TestChannelEventSink::~TestChannelEventSink()
NS_IMPL_ISUPPORTS1(TestChannelEventSink, nsIChannelEventSink)
NS_IMETHODIMP
TestChannelEventSink::OnChannelRedirect(nsIChannel *channel,
nsIChannel *newChannel,
PRUint32 flags)
TestChannelEventSink::AsyncOnChannelRedirect(nsIChannel *channel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
LOG(("\n+++ TestChannelEventSink::OnChannelRedirect (with flags %x) +++\n",
flags));
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -149,9 +149,10 @@ ChannelEventSink.prototype = {
throw Cr.NS_ERROR_NO_INTERFACE;
},
onChannelRedirect: function(oldChannel, newChannel, flags) {
if (this._flags & ES_ABORT_REDIRECT) {
asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
if (this._flags & ES_ABORT_REDIRECT)
throw Cr.NS_BINDING_ABORTED;
}
callback.onRedirectVerifyCallback(Cr.NS_OK);
}
};

Просмотреть файл

@ -40,7 +40,7 @@ NotificationCallbacks.prototype = {
{
return this.QueryInterface(iid);
},
onChannelRedirect: function(oldChan, newChan, flags)
asyncOnChannelRedirect: function(oldChan, newChan, flags, callback)
{
do_check_eq(oldChan.URI.spec, this._origURI.spec);
do_check_eq(oldChan.URI, this._origURI);

Просмотреть файл

@ -31,7 +31,7 @@ var eventsink = {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
onChannelRedirect: function eventsink_onredir(oldChan, newChan, flags) {
asyncOnChannelRedirect: function eventsink_onredir(oldChan, newChan, flags, callback) {
// veto
this.called = true;
throw NS_BINDING_ABORTED;

Просмотреть файл

@ -125,6 +125,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIScriptSecurityManager.h"
#include "nsIChannelEventSink.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsNetUtil.h"
#include "rdfIDataSource.h"
@ -901,32 +902,38 @@ RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
// This code is copied from nsSameOriginChecker::OnChannelRedirect. See
// bug 475940 on providing this code in a shared location.
NS_IMETHODIMP
RDFXMLDataSourceImpl::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
RDFXMLDataSourceImpl::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
nsresult rv;
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv;
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> oldPrincipal;
secMan->GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
nsCOMPtr<nsIPrincipal> oldPrincipal;
secMan->GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
nsCOMPtr<nsIURI> newURI;
aNewChannel->GetURI(getter_AddRefs(newURI));
nsCOMPtr<nsIURI> newOriginalURI;
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
nsCOMPtr<nsIURI> newURI;
aNewChannel->GetURI(getter_AddRefs(newURI));
nsCOMPtr<nsIURI> newOriginalURI;
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
}
return rv;
rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
}
if (NS_FAILED(rv))
return rv;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsNavHistory.h"
#include "nsNavBookmarks.h"
#include "nsFaviconService.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsCycleCollectionParticipant.h"
@ -758,11 +759,13 @@ FetchNetworkIconStep::GetInterface(const nsIID& uuid,
NS_IMETHODIMP
FetchNetworkIconStep::OnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel,
PRUint32 flags)
FetchNetworkIconStep::AsyncOnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *cb)
{
mChannel = newChannel;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -111,11 +111,12 @@ StreamListener.prototype = {
},
// nsIChannelEventSink
onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
asyncOnChannelRedirect: function (aOldChannel, aNewChannel, aFlags, callback) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ghist3.addDocumentRedirect(aOldChannel, aNewChannel, aFlags, true);
// If redirecting, store the new channel
this.mChannel = aNewChannel;
callback.onRedirectVerifyCallback(Components.results.NS_OK);
},
// nsIInterfaceRequestor

Просмотреть файл

@ -219,9 +219,10 @@ ChannelListener.prototype = {
},
// nsIChannelEventSink
onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
asyncOnChannelRedirect: function (aOldChannel, aNewChannel, aFlags, callback) {
print("onChannelRedirect");
this._got_onchannelredirect = true;
ghist3.addDocumentRedirect(aOldChannel, aNewChannel, aFlags, true);
callback.onRedirectVerifyCallback(Components.results.NS_OK);
},
};

Просмотреть файл

@ -375,9 +375,10 @@ loadListener.prototype = {
},
// nsIChannelEventSink
onChannelRedirect: function SRCH_loadCRedirect(aOldChannel, aNewChannel,
aFlags) {
asyncOnChannelRedirect: function SRCH_loadCRedirect(aOldChannel, aNewChannel,
aFlags, callback) {
this._channel = aNewChannel;
callback.onRedirectVerifyCallback(Components.results.NS_OK);
},
// nsIInterfaceRequestor

Просмотреть файл

@ -143,7 +143,7 @@ function BadCertHandler(aAllowNonBuiltInCerts) {
BadCertHandler.prototype = {
// nsIChannelEventSink
onChannelRedirect: function(oldChannel, newChannel, flags) {
asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
if (this.allowNonBuiltInCerts)
return;
@ -152,7 +152,9 @@ BadCertHandler.prototype = {
// Don't call checkCert for internal redirects. See bug 569648.
if (!(flags & Ci.nsIChannelEventSink.REDIRECT_INTERNAL))
checkCert(oldChannel);
},
callback.onRedirectVerifyCallback(Components.results.NS_OK);
},
// Suppress any certificate errors
notifyCertProblem: function(socketInfo, status, targetSite) {

Просмотреть файл

@ -64,6 +64,7 @@
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsPresContext.h"
#include "nsIAsyncVerifyRedirectCallback.h"
static NS_DEFINE_CID(kThisImplCID, NS_THIS_DOCLOADER_IMPL_CID);
@ -1584,9 +1585,10 @@ PRInt64 nsDocLoader::CalculateMaxProgress()
return max;
}
NS_IMETHODIMP nsDocLoader::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
NS_IMETHODIMP nsDocLoader::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
if (aOldChannel)
{
@ -1611,6 +1613,7 @@ NS_IMETHODIMP nsDocLoader::OnChannelRedirect(nsIChannel *aOldChannel,
FireOnStateChange(this, aOldChannel, stateFlags, NS_OK);
}
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -70,6 +70,7 @@
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "prlog.h"
#include "nsIAsyncVerifyRedirectCallback.h"
static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nsnull;
@ -283,13 +284,16 @@ nsManifestCheck::GetInterface(const nsIID &aIID, void **aResult)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsManifestCheck::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsManifestCheck::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
// Redirects should cause the load (and therefore the update) to fail.
if (aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)
if (aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
aOldChannel->Cancel(NS_ERROR_ABORT);
return NS_ERROR_ABORT;
}
@ -491,9 +495,10 @@ nsOfflineCacheUpdateItem::GetInterface(const nsIID &aIID, void **aResult)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsOfflineCacheUpdateItem::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsOfflineCacheUpdateItem::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *cb)
{
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
// Don't allow redirect in case of non-internal redirect and cancel
@ -539,6 +544,7 @@ nsOfflineCacheUpdateItem::OnChannelRedirect(nsIChannel *aOldChannel,
mChannel = aNewChannel;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -60,6 +60,7 @@
#include "prtime.h"
#include "prlog.h"
#include "plstr.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#if defined(PR_LOGGING)
//
@ -363,9 +364,10 @@ nsPrefetchNode::GetInterface(const nsIID &aIID, void **aResult)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsPrefetchNode::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
nsPrefetchNode::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback *callback)
{
nsCOMPtr<nsIURI> newURI;
nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI));
@ -395,6 +397,7 @@ nsPrefetchNode::OnChannelRedirect(nsIChannel *aOldChannel,
mChannel = aNewChannel;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}

Просмотреть файл

@ -91,6 +91,7 @@
#include "CertReader.h"
#include "nsEmbedCID.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#define PREF_XPINSTALL_ENABLED "xpinstall.enabled"
#define PREF_XPINSTALL_CONFIRM_DLG "xpinstall.dialog.confirm"
@ -1323,11 +1324,19 @@ nsXPInstallManager::GetInterface(const nsIID & eventSinkIID, void* *_retval)
// nsIChannelEventSink method
NS_IMETHODIMP
nsXPInstallManager::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PRUint32 flags)
nsXPInstallManager::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
// Chrome triggered installs need to have their certificates checked
if (mFromChrome)
return CheckCert(oldChannel);
if (mFromChrome) {
nsresult rv = CheckCert(oldChannel);
if (NS_FAILED(rv()))
return rv;
}
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}