bug 265135: put internal referrers on channels to fix xpinstall whitelisting the right way. r=darin,sr=jst

This commit is contained in:
dveditz%cruzio.com 2004-10-28 22:52:45 +00:00
Родитель 120535f45d
Коммит 29050563b3
9 изменённых файлов: 86 добавлений и 81 удалений

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

@ -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<nsIDocShell> 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<nsIExternalProtocolService> 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<nsIProperties> 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, ...)

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

@ -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;

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

@ -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

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

@ -144,7 +144,8 @@ protected:
PRPackedBool mCanceled;
nsCOMPtr<nsIIOService> mIOService;
nsCOMPtr<nsISupports> mProperties;
nsCOMPtr<nsICacheSession> mCacheSession;
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
nsCOMPtr<nsIProxyInfo> mProxyInfo;

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

@ -1844,6 +1844,26 @@ nsHttpChannel::SetupReplacementChannel(nsIURI *newURI,
resumableChannel->ResumeAt(mStartPos, mEntityID);
}
// transfer any properties
if (mProperties) {
nsCOMPtr<nsIProperties> oldProps = do_QueryInterface(mProperties);
nsCOMPtr<nsIProperties> newProps = do_QueryInterface(newChannel);
if (newProps) {
PRUint32 count;
char **keys;
if (NS_SUCCEEDED(oldProps->GetKeys(&count, &keys))) {
nsCOMPtr<nsISupports> val;
for (PRUint32 i=0; i<count; ++i) {
oldProps->Get(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

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

@ -216,6 +216,8 @@ private:
nsCString mContentTypeHint;
nsCString mContentCharsetHint;
nsCOMPtr<nsISupports> mProperties;
// cache specific data
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;

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

@ -390,6 +390,17 @@ InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context)
LOG(("\tChannel Owner: %x\n", owner.get()));
}
nsCOMPtr<nsIProperties> props = do_QueryInterface(request);
if (props) {
nsCOMPtr<nsIURI> 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<nsIHttpChannelInternal> httpChannelInt(do_QueryInterface(request));
if (httpChannelInt) {
PRUint32 majorVer, minorVer;
@ -612,6 +623,12 @@ nsresult StartLoadingURL(const char* aUrlString)
return rv;
}
nsCOMPtr<nsIProperties> 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

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

@ -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

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

@ -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<nsISupports> owner;
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIURI> 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<nsIURI> referringURI;
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if ( httpChannel )
{
httpChannel->GetReferrer(getter_AddRefs(referringURI));
}
nsCOMPtr<nsIProperties> 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 );
}