From cda3a7d10ce9f5a4875ec83f39ec1c9eb5f39fc4 Mon Sep 17 00:00:00 2001 From: "dveditz%cruzio.com" Date: Thu, 28 Oct 2004 22:52:45 +0000 Subject: [PATCH] bug 265135: put internal referrers on channels to fix xpinstall whitelisting the right way. r=darin,sr=jst git-svn-id: svn://10.0.0.236/trunk@164582 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/docshell/base/nsDocShell.cpp | 50 +++---------------- mozilla/docshell/base/nsDocShell.h | 7 --- .../netwerk/protocol/ftp/src/nsFTPChannel.cpp | 9 ++++ .../netwerk/protocol/ftp/src/nsFTPChannel.h | 3 +- .../protocol/http/src/nsHttpChannel.cpp | 29 +++++++++++ .../netwerk/protocol/http/src/nsHttpChannel.h | 2 + mozilla/netwerk/test/TestProtocols.cpp | 17 +++++++ mozilla/xpcom/ds/nsProperties.cpp | 2 +- mozilla/xpinstall/src/nsInstallTrigger.cpp | 48 +++++++----------- 9 files changed, 86 insertions(+), 81 deletions(-) diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 7d0e246c72e..5da840e2d9c 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -257,7 +257,6 @@ nsDocShell::nsDocShell(): mEODForCurrentDocument(PR_FALSE), mURIResultedInDocument(PR_FALSE), mIsBeingDestroyed(PR_FALSE), - mUseExternalProtocolHandler(PR_FALSE), mDisallowPopupWindows(PR_FALSE), mValidateOrigin(PR_TRUE), // validate frame origins by default mIsExecutingOnLoadHandler(PR_FALSE), @@ -3092,13 +3091,6 @@ nsDocShell::Create() PRBool tmpbool; - // i don't want to read this pref in every time we load a url - // so read it in once here and be done with it... - rv = mPrefs->GetBoolPref("network.protocols.useSystemDefaults", - &tmpbool); - if (NS_SUCCEEDED(rv)) - mUseExternalProtocolHandler = tmpbool; - rv = mPrefs->GetBoolPref("browser.block.target_new_window", &tmpbool); if (NS_SUCCEEDED(rv)) mDisallowPopupWindows = tmpbool; @@ -5091,40 +5083,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, nsCOMPtr targetDocShell; nsAutoString name(aWindowTarget); - // - // This is a hack for Shrimp :-( - // - // if the load cmd is a user click....and we are supposed to try using - // external default protocol handlers....then try to see if we have one for - // this protocol - // - // See bug #52182 - // - if (mUseExternalProtocolHandler && aLoadType == LOAD_LINK) { - // don't do it for javascript urls! - // _main is an IE target which should be case-insensitive but isn't - // see bug 217886 for details - if (!bIsJavascript && - (name.LowerCaseEqualsLiteral("_content") || name.EqualsLiteral("_main") || - name.LowerCaseEqualsLiteral("_blank"))) - { - nsCOMPtr extProtService; - nsCAutoString urlScheme; - - extProtService = do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID); - if (extProtService) { - PRBool haveHandler = PR_FALSE; - aURI->GetScheme(urlScheme); - - extProtService->ExternalProtocolHandlerExists(urlScheme.get(), - &haveHandler); - if (haveHandler) { - return extProtService->LoadUrl(aURI); - } - } - } - } - // // This is a hack to prevent top-level windows from ever being // created. It really doesn't belong here, but until there is a @@ -5526,6 +5484,14 @@ nsDocShell::DoURILoad(nsIURI * aURI, } } + nsCOMPtr props(do_QueryInterface(channel)); + if (props) + { + // save true referrer for those who need it (e.g. xpinstall whitelisting) + // Currently only http and ftp channels support this. + props->Set("docshell.internalReferrer", aReferrerURI); + } + // // If this is a HTTP channel, then set up the HTTP specific information // (ie. POST data, referrer, ...) diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index bc2ad746026..094ca7da35a 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -355,13 +355,6 @@ protected: PRPackedBool mIsBeingDestroyed; - // used to keep track of whether user click links should be handle - // by us or immediately kicked out to an external - // application. mscott: eventually i'm going to try to fold this - // up into the uriloader where it belongs but i haven't figured - // out how to do that yet. - PRPackedBool mUseExternalProtocolHandler; - // Disallow popping up new windows with target= PRPackedBool mDisallowPopupWindows; diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp index dde28ced44b..0dfb758ba37 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.cpp @@ -116,6 +116,15 @@ NS_INTERFACE_MAP_BEGIN(nsFTPChannel) NS_INTERFACE_MAP_ENTRY(nsIStreamListener) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsICacheListener) + if (aIID.Equals(NS_GET_IID(nsIProperties))) { + if (!mProperties) { + mProperties = + do_CreateInstance(NS_PROPERTIES_CONTRACTID, (nsIChannel *) this); + NS_ENSURE_STATE(mProperties); + } + return mProperties->QueryInterface(aIID, aInstancePtr); + } + else NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel) NS_INTERFACE_MAP_END diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h index 11739213f97..166d5556ebb 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h @@ -144,7 +144,8 @@ protected: PRPackedBool mCanceled; nsCOMPtr mIOService; - + nsCOMPtr mProperties; + nsCOMPtr mCacheSession; nsCOMPtr mCacheEntry; nsCOMPtr mProxyInfo; diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp index 619cf762a9c..1ab8fabaec8 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -1844,6 +1844,26 @@ nsHttpChannel::SetupReplacementChannel(nsIURI *newURI, resumableChannel->ResumeAt(mStartPos, mEntityID); } + // transfer any properties + if (mProperties) { + nsCOMPtr oldProps = do_QueryInterface(mProperties); + nsCOMPtr newProps = do_QueryInterface(newChannel); + if (newProps) { + PRUint32 count; + char **keys; + if (NS_SUCCEEDED(oldProps->GetKeys(&count, &keys))) { + nsCOMPtr val; + for (PRUint32 i=0; iGet(keys[i], + NS_GET_IID(nsISupports), + getter_AddRefs(val)); + newProps->Set(keys[i], val); + } + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, keys); + } + } + } + return NS_OK; } @@ -2770,6 +2790,15 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel) NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal) NS_INTERFACE_MAP_ENTRY(nsIResumableChannel) NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) + if (aIID.Equals(NS_GET_IID(nsIProperties))) { + if (!mProperties) { + mProperties = + do_CreateInstance(NS_PROPERTIES_CONTRACTID, (nsIChannel *) this); + NS_ENSURE_STATE(mProperties); + } + return mProperties->QueryInterface(aIID, aInstancePtr); + } + else NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel) NS_INTERFACE_MAP_END diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h index 330c64ba9fe..ca72e40423b 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.h @@ -216,6 +216,8 @@ private: nsCString mContentTypeHint; nsCString mContentCharsetHint; + + nsCOMPtr mProperties; // cache specific data nsCOMPtr mCacheEntry; diff --git a/mozilla/netwerk/test/TestProtocols.cpp b/mozilla/netwerk/test/TestProtocols.cpp index 1df71c3bf62..849490d49f3 100644 --- a/mozilla/netwerk/test/TestProtocols.cpp +++ b/mozilla/netwerk/test/TestProtocols.cpp @@ -390,6 +390,17 @@ InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context) LOG(("\tChannel Owner: %x\n", owner.get())); } + nsCOMPtr props = do_QueryInterface(request); + if (props) { + nsCOMPtr foo; + props->Get("test.foo", NS_GET_IID(nsIURI), getter_AddRefs(foo)); + if (foo) { + nsCAutoString spec; + foo->GetSpec(spec); + LOG(("\ttest.foo: %s\n", spec.get())); + } + } + nsCOMPtr httpChannelInt(do_QueryInterface(request)); if (httpChannelInt) { PRUint32 majorVer, minorVer; @@ -612,6 +623,12 @@ nsresult StartLoadingURL(const char* aUrlString) return rv; } + nsCOMPtr props = do_QueryInterface(pChannel); + if (props) { + if (NS_SUCCEEDED(props->Set("test.foo", pURL))) + LOG(("set prop 'test.foo'\n")); + } + /* You may optionally add/set other headers on this request object. This is done by QI for the specific diff --git a/mozilla/xpcom/ds/nsProperties.cpp b/mozilla/xpcom/ds/nsProperties.cpp index a2c1dcab519..ff68bf72563 100644 --- a/mozilla/xpcom/ds/nsProperties.cpp +++ b/mozilla/xpcom/ds/nsProperties.cpp @@ -67,7 +67,7 @@ nsProperties::Get(const char* prop, const nsIID & uuid, void* *result) if (!nsProperties_HashBase::Get(prop, getter_AddRefs(value))) { return NS_ERROR_FAILURE; } - return value->QueryInterface(uuid, result); + return (value) ? value->QueryInterface(uuid, result) : NS_ERROR_NO_INTERFACE; } NS_IMETHODIMP diff --git a/mozilla/xpinstall/src/nsInstallTrigger.cpp b/mozilla/xpinstall/src/nsInstallTrigger.cpp index e0bf2cb4391..14da97bf434 100644 --- a/mozilla/xpinstall/src/nsInstallTrigger.cpp +++ b/mozilla/xpinstall/src/nsInstallTrigger.cpp @@ -146,36 +146,23 @@ nsInstallTrigger::HandleContent(const char * aContentType, return NS_ERROR_ILLEGAL_VALUE; -#ifdef NS_DEBUG - // XXX: if only the owner weren't always null this is what I'd want to do - - // Get the owner of the channel to perform permission checks. - // - // It's OK if owner is null, this means it was a top level - // load and we want to allow installs in that case. - nsCOMPtr owner; - nsCOMPtr principal; - nsCOMPtr ownerURI; - - channel->GetOwner( getter_AddRefs( owner ) ); - if ( owner ) - { - principal = do_QueryInterface( owner ); - if ( principal ) - { - principal->GetURI( getter_AddRefs( ownerURI ) ); - } - } -#endif - // Save the referrer if any, for permission checks + static const char kReferrerProperty[] = "docshell.internalReferrer"; + PRBool useReferrer = PR_FALSE; nsCOMPtr referringURI; - nsCOMPtr httpChannel(do_QueryInterface(channel)); - if ( httpChannel ) - { - httpChannel->GetReferrer(getter_AddRefs(referringURI)); - } + nsCOMPtr channelprops(do_QueryInterface(channel)); + if (channelprops && + NS_SUCCEEDED(channelprops->Has(kReferrerProperty, &useReferrer)) && + useReferrer) + { + // channel may have the property but set to null. In that case we know + // it was a typed URL or bookmark and can bypass site whitelisting, as + // opposed to not knowing the origin and going with the fallback plan. + channelprops->Get(kReferrerProperty, + NS_GET_IID(nsIURI), + getter_AddRefs(referringURI)); + } // Cancel the current request. nsXPInstallManager restarts the download // under its control (shared codepath with InstallTrigger) @@ -198,14 +185,15 @@ nsInstallTrigger::HandleContent(const char * aContentType, // going to honor this request based on PermissionManager settings PRBool enabled = PR_FALSE; - if ( referringURI ) + if ( useReferrer ) { - // easiest and most common case: base decision on http referrer + // easiest and most common case: base decision on the page that + // contained the link // // NOTE: the XPI itself may be from elsewhere; the user can decide if // they trust the actual source when they get the install confirmation // dialog. The decision we're making here is whether the triggering - // site is one which is allowed to annoy the user with modal dialogs + // site is one which is allowed to annoy the user with modal dialogs. enabled = AllowInstall( referringURI ); }