Pass through loader principal and URI to LoadSheet(). Bug 387317, r+sr=peterv

This commit is contained in:
bzbarsky@mit.edu 2007-07-11 12:44:27 -07:00
parent 5b43f48b37
commit a7014a42ea
8 changed files with 132 additions and 59 deletions

View File

@ -139,6 +139,7 @@ nsXBLResourceLoader::LoadResources(PRBool* aResult)
// Kick off the load of the stylesheet.
// Always load chrome synchronously
// XXXbz should that still do a content policy check?
PRBool chrome;
nsresult rv;
if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
@ -154,7 +155,7 @@ nsXBLResourceLoader::LoadResources(PRBool* aResult)
}
else
{
rv = cssLoader->LoadSheet(url, this);
rv = cssLoader->LoadSheet(url, docURL, doc->NodePrincipal(), this);
if (NS_SUCCEEDED(rv))
++mPendingSheets;
}

View File

@ -199,8 +199,8 @@ struct BroadcastListener {
nsXULDocument::nsXULDocument(void)
: nsXMLDocument("application/vnd.mozilla.xul+xml"),
mResolutionPhase(nsForwardReference::eStart),
mState(eState_Master)
mState(eState_Master),
mResolutionPhase(nsForwardReference::eStart)
{
// NOTE! nsDocument::operator new() zeroes out all members, so don't
@ -2594,9 +2594,6 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
*aShouldReturn = PR_FALSE;
*aFailureFromContent = PR_FALSE;
nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef PR_LOGGING
if (PR_LOG_TEST(gXULLog, PR_LOG_DEBUG)) {
nsCAutoString urlspec;
@ -2610,6 +2607,9 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
if (aIsDynamic)
mResolutionPhase = nsForwardReference::eStart;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
// Chrome documents are allowed to load overlays from anywhere.
// Also, any document may load a chrome:// overlay.
// In all other cases, the overlay is only allowed to load if
@ -2675,10 +2675,9 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
// Not there. Initiate a load.
PR_LOG(gXULLog, PR_LOG_DEBUG, ("xul: overlay was not cached"));
// No one ever uses overlay principals for anything, so it's OK to give
// them the null principal. Too bad this code insists on the sort of
// syncloading that can't provide us the right principal from the
// channel...
// We'll set the right principal on the proto doc when we get
// OnStartRequest from the parser, so just pass in a null principal for
// now.
nsCOMPtr<nsIParser> parser;
rv = PrepareToLoadPrototype(aURI, "view", nsnull, getter_AddRefs(parser));
if (NS_FAILED(rv)) return rv;
@ -2695,7 +2694,8 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
// Add an observer to the parser; this'll get called when
// Necko fires its On[Start|Stop]Request() notifications,
// and will let us recover from a missing overlay.
ParserObserver* parserObserver = new ParserObserver(this);
ParserObserver* parserObserver =
new ParserObserver(this, mCurrentPrototype);
if (! parserObserver)
return NS_ERROR_OUT_OF_MEMORY;
@ -3699,7 +3699,9 @@ nsXULDocument::AddPrototypeSheets()
nsCOMPtr<nsIURI> uri = sheets[i];
nsCOMPtr<nsICSSStyleSheet> incompleteSheet;
rv = CSSLoader()->LoadSheet(uri, this, getter_AddRefs(incompleteSheet));
rv = CSSLoader()->LoadSheet(uri, mCurrentPrototype->GetURI(),
mCurrentPrototype->DocumentPrincipal(),
this, getter_AddRefs(incompleteSheet));
// XXXldb We need to prevent bogus sheets from being held in the
// prototype's list, but until then, don't propagate the failure
@ -4332,15 +4334,14 @@ nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request,
// ParserObserver
//
nsXULDocument::ParserObserver::ParserObserver(nsXULDocument* aDocument)
: mDocument(aDocument)
nsXULDocument::ParserObserver::ParserObserver(nsXULDocument* aDocument,
nsXULPrototypeDocument* aPrototype)
: mDocument(aDocument), mPrototype(aPrototype)
{
NS_ADDREF(mDocument);
}
nsXULDocument::ParserObserver::~ParserObserver()
{
NS_IF_RELEASE(mDocument);
}
NS_IMPL_ISUPPORTS1(nsXULDocument::ParserObserver, nsIRequestObserver)
@ -4349,6 +4350,22 @@ NS_IMETHODIMP
nsXULDocument::ParserObserver::OnStartRequest(nsIRequest *request,
nsISupports* aContext)
{
// Guard against buggy channels calling OnStartRequest multiple times.
if (mPrototype) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (channel && secMan) {
nsCOMPtr<nsIPrincipal> principal;
secMan->GetChannelPrincipal(channel, getter_AddRefs(principal));
// Failure there is ok -- it'll just set a (safe) null principal
mPrototype->SetDocumentPrincipal(principal);
}
// Make sure to avoid cycles
mPrototype = nsnull;
}
return NS_OK;
}
@ -4377,7 +4394,7 @@ nsXULDocument::ParserObserver::OnStopRequest(nsIRequest *request,
// Drop the reference to the document to break cycle between the
// document, the parser, the content sink, and the parser
// observer.
NS_RELEASE(mDocument);
mDocument = nsnull;
return rv;
}

View File

@ -658,11 +658,13 @@ protected:
class ParserObserver : public nsIRequestObserver {
protected:
nsXULDocument* mDocument;
nsRefPtr<nsXULDocument> mDocument;
nsRefPtr<nsXULPrototypeDocument> mPrototype;
virtual ~ParserObserver();
public:
ParserObserver(nsXULDocument* aDocument);
ParserObserver(nsXULDocument* aDocument,
nsXULPrototypeDocument* aPrototype);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER

View File

@ -541,6 +541,11 @@ nsXULPrototypeDocument::DocumentPrincipal()
return mNodeInfoManager->DocumentPrincipal();
}
void
nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
{
mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
}
nsNodeInfoManager*
nsXULPrototypeDocument::GetNodeInfoManager()

View File

@ -3552,7 +3552,7 @@ nsHTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
NS_ENSURE_SUCCESS(rv, rv);
rv = cssLoader->LoadSheet(uaURI, this);
rv = cssLoader->LoadSheet(uaURI, nsnull, nsnull, this);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

View File

@ -214,7 +214,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
nsICSSStyleSheet* aSheet,
PRBool aSyncLoad,
PRBool aAllowUnsafeRules,
nsICSSLoaderObserver* aObserver)
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal)
: mLoader(aLoader),
mURI(aURI),
mLineNumber(1),
@ -231,7 +232,7 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
mAllowUnsafeRules(aAllowUnsafeRules),
mOwningElement(nsnull),
mObserver(aObserver),
mLoaderPrincipal(nsnull)
mLoaderPrincipal(aLoaderPrincipal)
{
NS_PRECONDITION(mLoader, "Must have a loader!");
@ -933,36 +934,42 @@ CSSLoaderImpl::CheckLoadAllowed(nsIURI* aSourceURI,
nsISupports* aContext)
{
LOG(("CSSLoaderImpl::CheckLoadAllowed"));
nsresult rv;
// Check with the security manager
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
nsresult rv =
secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI,
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_FAILED(rv)) { // failure is normal here; don't warn
return rv;
if (aSourcePrincipal) {
// Check with the security manager
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
rv =
secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI,
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_FAILED(rv)) { // failure is normal here; don't warn
return rv;
}
}
LOG((" Passed security check"));
// Check with content policy
if (aSourceURI) {
// Check with content policy
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
aTargetURI,
aSourceURI,
aContext,
NS_LITERAL_CSTRING("text/css"),
nsnull, //extra param
&shouldLoad,
nsContentUtils::GetContentPolicy());
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
aTargetURI,
aSourceURI,
aContext,
NS_LITERAL_CSTRING("text/css"),
nsnull, //extra param
&shouldLoad,
nsContentUtils::GetContentPolicy());
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
LOG((" Load blocked by content policy"));
return NS_ERROR_CONTENT_BLOCKED;
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
LOG((" Load blocked by content policy"));
return NS_ERROR_CONTENT_BLOCKED;
}
}
return rv;
return NS_OK;
}
/**
@ -1976,28 +1983,39 @@ CSSLoaderImpl::LoadSheetSync(nsIURI* aURL, PRBool aAllowUnsafeRules,
nsICSSStyleSheet** aSheet)
{
LOG(("CSSLoaderImpl::LoadSheetSync"));
return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules, aSheet, nsnull);
return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules, nsnull,
nsnull, aSheet, nsnull);
}
NS_IMETHODIMP
CSSLoaderImpl::LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver,
CSSLoaderImpl::LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver,
nsICSSStyleSheet** aSheet)
{
LOG(("CSSLoaderImpl::LoadSheet(aURL, aObserver, aSheet) api call"));
NS_PRECONDITION(aSheet, "aSheet is null");
return InternalLoadNonDocumentSheet(aURL, PR_FALSE, aSheet, aObserver);
return InternalLoadNonDocumentSheet(aURL, PR_FALSE, aOriginURI,
aOriginPrincipal, aSheet, aObserver);
}
NS_IMETHODIMP
CSSLoaderImpl::LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver)
CSSLoaderImpl::LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver)
{
LOG(("CSSLoaderImpl::LoadSheet(aURL, aObserver) api call"));
return InternalLoadNonDocumentSheet(aURL, PR_FALSE, nsnull, aObserver);
return InternalLoadNonDocumentSheet(aURL, PR_FALSE, aOriginURI,
aOriginPrincipal, nsnull, aObserver);
}
nsresult
CSSLoaderImpl::InternalLoadNonDocumentSheet(nsIURI* aURL,
PRBool aAllowUnsafeRules,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSStyleSheet** aSheet,
nsICSSLoaderObserver* aObserver)
{
@ -2016,12 +2034,17 @@ CSSLoaderImpl::InternalLoadNonDocumentSheet(nsIURI* aURL,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = CheckLoadAllowed(aOriginURI, aOriginPrincipal, aURL, mDocument);
if (NS_FAILED(rv)) {
return rv;
}
StyleSheetState state;
nsCOMPtr<nsICSSStyleSheet> sheet;
PRBool syncLoad = (aObserver == nsnull);
nsresult rv = CreateSheet(aURL, nsnull, nsnull, syncLoad, state,
getter_AddRefs(sheet));
rv = CreateSheet(aURL, nsnull, nsnull, syncLoad, state,
getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
const nsSubstring& empty = EmptyString();
@ -2040,7 +2063,8 @@ CSSLoaderImpl::InternalLoadNonDocumentSheet(nsIURI* aURL,
}
SheetLoadData* data =
new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules, aObserver);
new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules,
aObserver, aOriginPrincipal);
if (!data) {
sheet->SetComplete();

View File

@ -135,7 +135,8 @@ public:
nsICSSStyleSheet* aSheet,
PRBool aSyncLoad,
PRBool aAllowUnsafeRules,
nsICSSLoaderObserver* aObserver);
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
already_AddRefed<nsIURI> GetReferrerURI();
@ -340,10 +341,16 @@ public:
NS_IMETHOD LoadSheetSync(nsIURI* aURL, PRBool aAllowUnsafeRules,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver,
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver,
nsICSSStyleSheet** aSheet);
NS_IMETHOD LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver);
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver);
// stop loading all sheets
NS_IMETHOD Stop(void);
@ -372,6 +379,8 @@ public:
PRBool IsAlternate(const nsAString& aTitle, PRBool aHasAlternateRel);
private:
// Note: null aSourceURI or aSourcePrincipal indicates that the content
// policy or CheckLoadURI checks (respectively) should be skipped.
nsresult CheckLoadAllowed(nsIURI* aSourceURI,
nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
@ -409,6 +418,8 @@ private:
nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
PRBool aAllowUnsafeRules,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSStyleSheet** aSheet,
nsICSSLoaderObserver* aObserver);

View File

@ -55,12 +55,13 @@ class nsIUnicharInputStream;
class nsICSSLoaderObserver;
class nsMediaList;
class nsICSSImportRule;
class nsIPrincipal;
// IID for the nsICSSLoader interface
// 5da3a869-270c-4f10-97d1-99eaa150eb4e
// eed4ac28-0add-43a7-84bf-fb53109ae40c
#define NS_ICSS_LOADER_IID \
{ 0x5da3a869, 0x270c, 0x4f10, \
{ 0x97, 0xd1, 0x99, 0xea, 0xa1, 0x50, 0xeb, 0x4e } }
{ 0xeed4ac28, 0x0add, 0x43a7, \
{ 0x84, 0xbf, 0xfb, 0x53, 0x10, 0x9a, 0xe4, 0x0c } }
typedef void (*nsCSSLoaderCallbackFunc)(nsICSSStyleSheet* aSheet, void *aData, PRBool aDidNotify);
@ -202,19 +203,31 @@ public:
* sheets not associated with a document.
*
* @param aURL the URL of the sheet to load
* @param aOriginURI the URI the load originated from, for content policy
* checks. This can be null to indicate that these checks
* should be skipped.
* @param aOriginPrincipal the principal to use for security checks. This
* can be null to indicate that these checks should
* be skipped.
* @param aObserver the observer to notify when the load completes.
* Must not be null.
* @param [out] aSheet the sheet to load. Note that the sheet may well
* not be loaded by the time this method returns.
*/
NS_IMETHOD LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver,
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver,
nsICSSStyleSheet** aSheet) = 0;
/**
* Same as above, to be used when the caller doesn't care about the
* not-yet-loaded sheet.
*/
NS_IMETHOD LoadSheet(nsIURI* aURL, nsICSSLoaderObserver* aObserver) = 0;
NS_IMETHOD LoadSheet(nsIURI* aURL,
nsIURI* aOriginURI,
nsIPrincipal* aOriginPrincipal,
nsICSSLoaderObserver* aObserver) = 0;
/**
* Stop loading all sheets. All nsICSSLoaderObservers involved will be