Treat <xul:script> more like <html:script>. Bug 424188, r+sr=sicking, a=dsicore

This commit is contained in:
bzbarsky@mit.edu 2008-03-21 22:03:57 -07:00
parent 4b87fd803a
commit 284e074807
4 changed files with 71 additions and 58 deletions

View File

@ -70,48 +70,6 @@
#include "nsIParser.h"
#include "nsThreadUtils.h"
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
// If aMaybeCertPrincipal is a cert principal and aNewPrincipal is not the same
// as aMaybeCertPrincipal, downgrade aMaybeCertPrincipal to a codebase
// principal. Return the downgraded principal, or aMaybeCertPrincipal if no
// downgrade was needed.
static already_AddRefed<nsIPrincipal>
MaybeDowngradeToCodebase(nsIPrincipal *aMaybeCertPrincipal,
nsIPrincipal *aNewPrincipal)
{
NS_PRECONDITION(aMaybeCertPrincipal, "Null old principal!");
NS_PRECONDITION(aNewPrincipal, "Null new principal!");
nsIPrincipal *principal = aMaybeCertPrincipal;
PRBool hasCert;
aMaybeCertPrincipal->GetHasCertificate(&hasCert);
if (hasCert) {
PRBool equal;
aMaybeCertPrincipal->Equals(aNewPrincipal, &equal);
if (!equal) {
nsCOMPtr<nsIURI> uri, domain;
aMaybeCertPrincipal->GetURI(getter_AddRefs(uri));
aMaybeCertPrincipal->GetDomain(getter_AddRefs(domain));
nsContentUtils::GetSecurityManager()->GetCodebasePrincipal(uri,
&principal);
if (principal && domain) {
principal->SetDomain(domain);
}
return principal;
}
}
NS_ADDREF(principal);
return principal;
}
//////////////////////////////////////////////////////////////
// Per-request data structure
//////////////////////////////////////////////////////////////
@ -895,18 +853,8 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// -- Merge the principal of the script file with that of the document; if
// the script has a non-cert principal, the document's principal should be
// downgraded.
if (channel) {
nsCOMPtr<nsIPrincipal> channelPrincipal;
nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(channel, getter_AddRefs(channelPrincipal));
if (channelPrincipal) {
nsCOMPtr<nsIPrincipal> newPrincipal =
MaybeDowngradeToCodebase(mDocument->NodePrincipal(),
channelPrincipal);
mDocument->SetPrincipal(newPrincipal);
}
}
rv = DowngradePrincipalIfNeeded(mDocument, channel);
NS_ENSURE_SUCCESS(rv, rv);
}
// This assertion could fire errorously if we ran out of memory when
@ -921,3 +869,50 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
return NS_OK;
}
/* static */
nsresult
nsScriptLoader::DowngradePrincipalIfNeeded(nsIDocument* aDocument,
nsIChannel* aChannel)
{
if (!aChannel) {
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<nsIPrincipal> channelPrincipal;
nsresult rv = nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(aChannel, getter_AddRefs(channelPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(channelPrincipal, "Gotta have a principal here!");
// If the document principal is a cert principal and aNewPrincipal
// is not the same as the channel principal, downgrade the document
// principal to a codebase principal.
PRBool hasCert;
nsIPrincipal* docPrincipal = aDocument->NodePrincipal();
docPrincipal->GetHasCertificate(&hasCert);
if (hasCert) {
PRBool equal;
docPrincipal->Equals(channelPrincipal, &equal);
if (!equal) {
nsCOMPtr<nsIURI> uri, domain;
docPrincipal->GetURI(getter_AddRefs(uri));
docPrincipal->GetDomain(getter_AddRefs(domain));
nsCOMPtr<nsIPrincipal> newPrincipal;
rv = nsContentUtils::GetSecurityManager()->
GetCodebasePrincipal(uri, getter_AddRefs(newPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(newPrincipal, "Gotta have a new principal");
if (domain) {
newPrincipal->SetDomain(domain);
}
aDocument->SetPrincipal(newPrincipal);
}
}
return NS_OK;
}

View File

@ -180,6 +180,13 @@ public:
*/
void ProcessPendingRequests();
/**
* If needed, downgrade the principal of aDocument based on the
* principal of aChannel.
*/
static nsresult DowngradePrincipalIfNeeded(nsIDocument* aDocument,
nsIChannel* aChannel);
protected:
/**
* Process any pending requests asyncronously (i.e. off an event) if there

View File

@ -3206,6 +3206,9 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
// Use the enclosing document's principal
// XXX is this right? or should we use the
// protodoc's?
// If we start using the protodoc's, make sure
// the DowngradePrincipalIfNeeded stuff in
// nsXULDocument::OnStreamComplete still works!
aDocument->NodePrincipal(),
urlspec.get(),
aLineNo,

View File

@ -3335,9 +3335,15 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
nsString stringStr;
rv = nsScriptLoader::ConvertToUTF16(channel, string, stringLen,
EmptyString(), this, stringStr);
if (NS_SUCCEEDED(rv))
rv = scriptProto->Compile(stringStr.get(), stringStr.Length(), uri,
1, this, mCurrentPrototype);
if (NS_SUCCEEDED(rv)) {
// Downgrade _before_ compiling, since that's when the
// script saves its principal.
rv = nsScriptLoader::DowngradePrincipalIfNeeded(this, channel);
if (NS_SUCCEEDED(rv)) {
rv = scriptProto->Compile(stringStr.get(), stringStr.Length(),
uri, 1, this, mCurrentPrototype);
}
}
aStatus = rv;
if (NS_SUCCEEDED(rv)) {
@ -3422,7 +3428,9 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
doc->mNextSrcLoadWaiter = nsnull;
// Execute only if we loaded and compiled successfully, then resume
if (NS_SUCCEEDED(aStatus) && scriptProto->mScriptObject.mObject) {
if (NS_SUCCEEDED(aStatus) && scriptProto->mScriptObject.mObject &&
NS_SUCCEEDED(nsScriptLoader::DowngradePrincipalIfNeeded(doc,
channel))) {
doc->ExecuteScript(scriptProto);
}
doc->ResumeWalk();