Stylesheets should know what their principal is, and it should be based on the

URI the sheet was loaded from, its certificate (if any) and the loader
principal, not just on the page the sheet is being applied to.  Propagate this
principal as the loading principal to @import loads from stylesheets.  Change
sheet access checks to use this principal instead of the sheet URI.  Bug
221428, r+sr=peterv
This commit is contained in:
bzbarsky%mit.edu 2007-05-01 19:26:15 +00:00
Родитель 1de0c45d5a
Коммит d979f584e1
8 изменённых файлов: 476 добавлений и 196 удалений

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

@ -147,7 +147,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
nsICSSStyleSheet* aSheet,
nsIStyleSheetLinkingElement* aOwningElement,
PRBool aIsAlternate,
nsICSSLoaderObserver* aObserver)
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal)
: mLoader(aLoader),
mTitle(aTitle),
mURI(aURI),
@ -164,7 +165,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
mWasAlternate(aIsAlternate),
mAllowUnsafeRules(PR_FALSE),
mOwningElement(aOwningElement),
mObserver(aObserver)
mObserver(aObserver),
mLoaderPrincipal(aLoaderPrincipal)
{
NS_PRECONDITION(mLoader, "Must have a loader!");
@ -175,7 +177,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
SheetLoadData* aParentData,
nsICSSLoaderObserver* aObserver)
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal)
: mLoader(aLoader),
mURI(aURI),
mLineNumber(1),
@ -191,7 +194,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
mWasAlternate(PR_FALSE),
mAllowUnsafeRules(PR_FALSE),
mOwningElement(nsnull),
mObserver(aObserver)
mObserver(aObserver),
mLoaderPrincipal(aLoaderPrincipal)
{
NS_PRECONDITION(mLoader, "Must have a loader!");
@ -226,7 +230,8 @@ SheetLoadData::SheetLoadData(CSSLoaderImpl* aLoader,
mWasAlternate(PR_FALSE),
mAllowUnsafeRules(aAllowUnsafeRules),
mOwningElement(nsnull),
mObserver(aObserver)
mObserver(aObserver),
mLoaderPrincipal(nsnull)
{
NS_PRECONDITION(mLoader, "Must have a loader!");
@ -300,7 +305,9 @@ CSSLoaderImpl::Init(nsIDocument* aDocument)
}
PR_STATIC_CALLBACK(PLDHashOperator)
StartAlternateLoads(nsIURI *aKey, SheetLoadData* &aData, void* aClosure)
StartAlternateLoads(nsURIAndPrincipalHashKey *aKey,
SheetLoadData* &aData,
void* aClosure)
{
NS_STATIC_CAST(CSSLoaderImpl*,aClosure)->LoadSheet(aData, eSheetNeedsParser);
return PL_DHASH_REMOVE;
@ -333,7 +340,9 @@ CSSLoaderImpl::SetCompatibilityMode(nsCompatibility aCompatMode)
}
PR_STATIC_CALLBACK(PLDHashOperator)
StartNonAlternates(nsIURI *aKey, SheetLoadData* &aData, void* aClosure)
StartNonAlternates(nsURIAndPrincipalHashKey *aKey,
SheetLoadData* &aData,
void* aClosure)
{
NS_PRECONDITION(aData, "Must have a data");
NS_PRECONDITION(aClosure, "Must have a loader");
@ -753,23 +762,53 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
return NS_OK;
}
if (NS_FAILED(aStatus)) {
LOG_WARN((" Load failed: status 0x%x", aStatus));
mLoader->SheetComplete(this, aStatus);
return NS_OK;
}
nsCOMPtr<nsIChannel> channel;
nsresult result = aLoader->GetChannel(getter_AddRefs(channel));
if (NS_FAILED(result))
channel = nsnull;
if (NS_FAILED(result)) {
LOG_WARN((" No channel from loader"));
mLoader->SheetComplete(this, result);
return NS_OK;
}
nsCOMPtr<nsIURI> channelURI;
if (channel) {
// If the channel's original URI is "chrome:", we want that, since
// the observer code in nsXULPrototypeCache depends on chrome stylesheets
// having a chrome URI. (Whether or not chrome stylesheets come through
// this codepath seems nondeterministic.)
// Otherwise we want the potentially-HTTP-redirected URI.
channel->GetOriginalURI(getter_AddRefs(channelURI));
PRBool isChrome;
if (NS_FAILED(channelURI->SchemeIs("chrome", &isChrome)) || !isChrome)
channel->GetURI(getter_AddRefs(channelURI));
// If the channel's original URI is "chrome:", we want that, since
// the observer code in nsXULPrototypeCache depends on chrome stylesheets
// having a chrome URI. (Whether or not chrome stylesheets come through
// this codepath seems nondeterministic.)
// Otherwise we want the potentially-HTTP-redirected URI.
channel->GetOriginalURI(getter_AddRefs(channelURI));
PRBool isChrome;
if (NS_FAILED(channelURI->SchemeIs("chrome", &isChrome)) || !isChrome) {
channel->GetURI(getter_AddRefs(channelURI));
}
if (!channelURI) {
NS_ERROR("Someone just violated the nsIRequest contract");
LOG_WARN((" Channel without a URI. Bad!"));
mLoader->SheetComplete(this, NS_ERROR_UNEXPECTED);
return NS_OK;
}
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
result = NS_ERROR_NOT_AVAILABLE;
if (secMan) { // Could be null if we already shut down
result = secMan->GetChannelPrincipal(channel, getter_AddRefs(principal));
}
if (NS_FAILED(result)) {
LOG_WARN((" Couldn't get principal"));
mLoader->SheetComplete(this, result);
return NS_OK;
}
mSheet->SetPrincipal(principal);
#ifdef MOZ_TIMELINE
NS_TIMELINE_OUTDENT();
@ -801,9 +840,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
if (!validType) {
nsCAutoString spec;
if (channelURI) {
channelURI->GetSpec(spec);
}
channelURI->GetSpec(spec);
const nsAFlatString& specUTF16 = NS_ConvertUTF8toUTF16(spec);
const nsAFlatString& ctypeUTF16 = NS_ConvertASCIItoUTF16(contentType);
@ -831,23 +868,15 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
}
}
if (NS_FAILED(aStatus)) {
LOG_WARN((" Load failed: status 0x%x", aStatus));
mLoader->SheetComplete(this, aStatus);
return NS_OK;
}
if (!aDataStream) {
LOG_WARN((" No data stream; bailing"));
mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
return NS_OK;
}
if (channelURI) {
// Enough to set the URI on mSheet, since any sibling datas we have share
// the same mInner as mSheet and will thus get the same URI.
mSheet->SetURIs(channelURI, channelURI);
}
// Enough to set the URI on mSheet, since any sibling datas we have share
// the same mInner as mSheet and will thus get the same URI.
mSheet->SetURIs(channelURI, channelURI);
PRBool completed;
return mLoader->ParseSheet(aDataStream, this, completed);
@ -891,12 +920,15 @@ CSSLoaderImpl::IsAlternate(const nsAString& aTitle, PRBool aHasAlternateRel)
* failure otherwise.
*
* @param aSourceURI the uri of the document or parent sheet loading the sheet
* @param aSourcePrincipal the principal of the node or document or parent
* sheet loading the sheet
* @param aTargetURI the uri of the sheet to be loaded
* @param aContext the node owning the sheet. This is the element or document
* owning the stylesheet (possibly indirectly, for child sheets)
*/
nsresult
CSSLoaderImpl::CheckLoadAllowed(nsIURI* aSourceURI,
nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext)
{
@ -904,8 +936,9 @@ CSSLoaderImpl::CheckLoadAllowed(nsIURI* aSourceURI,
// Check with the security manager
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
nsresult rv = secMan->CheckLoadURI(aSourceURI, aTargetURI,
nsIScriptSecurityManager::ALLOW_CHROME);
nsresult rv =
secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI,
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_FAILED(rv)) { // failure is normal here; don't warn
return rv;
}
@ -944,6 +977,7 @@ CSSLoaderImpl::CheckLoadAllowed(nsIURI* aSourceURI,
nsresult
CSSLoaderImpl::CreateSheet(nsIURI* aURI,
nsIContent* aLinkingContent,
nsIPrincipal* aLoaderPrincipal,
PRBool aSyncLoad,
StyleSheetState& aSheetState,
nsICSSStyleSheet** aSheet)
@ -978,28 +1012,50 @@ CSSLoaderImpl::CreateSheet(nsIURI* aURI,
#endif
if (!sheet) {
// Then complete sheets
mCompleteSheets.Get(aURI, getter_AddRefs(sheet));
// Then complete sheets.
nsURIAndPrincipalHashKey key(aURI, aLoaderPrincipal);
mCompleteSheets.Get(&key, getter_AddRefs(sheet));
LOG((" From completed: %p", sheet.get()));
// Then loading sheets
if (!sheet && !aSyncLoad) {
aSheetState = eSheetLoading;
SheetLoadData* loadData = nsnull;
mLoadingDatas.Get(aURI, &loadData);
mLoadingDatas.Get(&key, &loadData);
if (loadData) {
sheet = loadData->mSheet;
LOG((" From loading: %p", sheet.get()));
#ifdef DEBUG
PRBool debugEqual;
NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
(aLoaderPrincipal && loadData->mLoaderPrincipal &&
NS_SUCCEEDED(aLoaderPrincipal->
Equals(loadData->mLoaderPrincipal,
&debugEqual)) && debugEqual),
"Principals should be the same");
#endif
}
// Then alternate sheets
if (!sheet) {
aSheetState = eSheetPending;
SheetLoadData* loadData = nsnull;
mPendingDatas.Get(aURI, &loadData);
mPendingDatas.Get(&key, &loadData);
if (loadData) {
sheet = loadData->mSheet;
LOG((" From pending: %p", sheet.get()));
#ifdef DEBUG
PRBool debugEqual;
NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
(aLoaderPrincipal && loadData->mLoaderPrincipal &&
NS_SUCCEEDED(aLoaderPrincipal->
Equals(loadData->mLoaderPrincipal,
&debugEqual)) && debugEqual),
"Principals should be the same");
#endif
}
}
}
@ -1243,13 +1299,30 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
// Just load it
nsCOMPtr<nsIInputStream> stream;
rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI);
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI, nsnull,
nsnull, nsnull, nsIRequest::LOAD_NORMAL,
getter_AddRefs(channel));
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to open URI synchronously"));
SheetComplete(aLoadData, rv);
return rv;
}
NS_ASSERTION(channel, "NS_OpenURI lied?");
// Get the principal for this channel
nsCOMPtr<nsIPrincipal> principal;
rv = nsContentUtils::GetSecurityManager()->
GetChannelPrincipal(channel, getter_AddRefs(principal));
if (NS_FAILED(rv)) {
LOG_ERROR((" Failed to get a principal for the sheet"));
SheetComplete(aLoadData, rv);
return rv;
}
aLoadData->mSheet->SetPrincipal(principal);
nsCOMPtr<nsIConverterInputStream> converterStream =
do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
@ -1283,12 +1356,13 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
SheetLoadData* existingData = nsnull;
nsURIAndPrincipalHashKey key(aLoadData->mURI, aLoadData->mLoaderPrincipal);
if (aSheetState == eSheetLoading) {
mLoadingDatas.Get(aLoadData->mURI, &existingData);
mLoadingDatas.Get(&key, &existingData);
NS_ASSERTION(existingData, "CreateSheet lied about the state");
}
else if (aSheetState == eSheetPending){
mPendingDatas.Get(aLoadData->mURI, &existingData);
mPendingDatas.Get(&key, &existingData);
NS_ASSERTION(existingData, "CreateSheet lied about the state");
}
@ -1304,12 +1378,12 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
#ifdef DEBUG
SheetLoadData* removedData;
NS_ASSERTION(mPendingDatas.Get(aLoadData->mURI, &removedData) &&
NS_ASSERTION(mPendingDatas.Get(&key, &removedData) &&
removedData == existingData,
"Bad pending table.");
#endif
mPendingDatas.Remove(aLoadData->mURI);
mPendingDatas.Remove(&key);
LOG((" Forcing load of pending data"));
return LoadSheet(existingData, eSheetNeedsParser);
@ -1360,6 +1434,16 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
// this before opening it, so it's only treated as a hint.
channel->SetContentType(NS_LITERAL_CSTRING("text/css"));
if (aLoadData->mLoaderPrincipal) {
PRBool inherit;
rv = NS_URIChainHasFlags(aLoadData->mURI,
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
&inherit);
if (NS_SUCCEEDED(rv) && inherit) {
channel->SetOwner(aLoadData->mLoaderPrincipal);
}
}
// We don't have to hold on to the stream loader. The ownership
// model is: Necko owns the stream loader, which owns the load data,
// which owns us
@ -1380,7 +1464,7 @@ CSSLoaderImpl::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
return rv;
}
if (!mLoadingDatas.Put(aLoadData->mURI, aLoadData)) {
if (!mLoadingDatas.Put(&key, aLoadData)) {
LOG_ERROR((" Failed to put data in loading table"));
aLoadData->mIsCancelled = PR_TRUE;
channel->Cancel(NS_ERROR_OUT_OF_MEMORY);
@ -1500,14 +1584,16 @@ CSSLoaderImpl::DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
LOG_URI(" Finished loading: '%s'", aLoadData->mURI);
// Remove the data from the list of loading datas
if (aLoadData->mIsLoading) {
nsURIAndPrincipalHashKey key(aLoadData->mURI,
aLoadData->mLoaderPrincipal);
#ifdef DEBUG
SheetLoadData *loadingData;
NS_ASSERTION(mLoadingDatas.Get(aLoadData->mURI, &loadingData) &&
NS_ASSERTION(mLoadingDatas.Get(&key, &loadingData) &&
loadingData == aLoadData,
"Bad loading table");
#endif
mLoadingDatas.Remove(aLoadData->mURI);
mLoadingDatas.Remove(&key);
aLoadData->mIsLoading = PR_FALSE;
}
}
@ -1559,7 +1645,9 @@ CSSLoaderImpl::DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
}
else {
#endif
mCompleteSheets.Put(aLoadData->mURI, aLoadData->mSheet);
nsURIAndPrincipalHashKey key(aLoadData->mURI,
aLoadData->mLoaderPrincipal);
mCompleteSheets.Put(&key, aLoadData->mSheet);
#ifdef MOZ_XUL
}
#endif
@ -1594,9 +1682,12 @@ CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement,
nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
NS_ASSERTION(owningElement, "Element is not a style linking element!");
// Since we're not planning to load a URI, no need to hand a principal to the
// load data or to CreateSheet().
StyleSheetState state;
nsCOMPtr<nsICSSStyleSheet> sheet;
nsresult rv = CreateSheet(nsnull, aElement, PR_FALSE, state,
nsresult rv = CreateSheet(nsnull, aElement, nsnull, PR_FALSE, state,
getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(state == eSheetNeedsParser,
@ -1613,13 +1704,16 @@ CSSLoaderImpl::LoadInlineStyle(nsIContent* aElement,
SheetLoadData* data = new SheetLoadData(this, aTitle, nsnull, sheet,
owningElement, *aIsAlternate,
aObserver);
aObserver, nsnull);
if (!data) {
sheet->SetComplete();
return NS_ERROR_OUT_OF_MEMORY;
}
// We never actually load this, so just set its principal directly
sheet->SetPrincipal(aElement->NodePrincipal());
NS_ADDREF(data);
data->mLineNumber = aLineNumber;
// Parse completion releases the load data
@ -1662,18 +1756,21 @@ CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
nsIURI *docURI = mDocument->GetDocumentURI();
if (!docURI) return NS_ERROR_FAILURE;
nsIPrincipal* principal =
aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
nsISupports* context = aElement;
if (!context) {
context = mDocument;
}
nsresult rv = CheckLoadAllowed(docURI, aURL, context);
nsresult rv = CheckLoadAllowed(docURI, principal, aURL, context);
if (NS_FAILED(rv)) return rv;
LOG((" Passed load check"));
StyleSheetState state;
nsCOMPtr<nsICSSStyleSheet> sheet;
rv = CreateSheet(aURL, aElement, PR_FALSE, state,
rv = CreateSheet(aURL, aElement, principal, PR_FALSE, state,
getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
@ -1702,7 +1799,7 @@ CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
// Now we need to actually load it
SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
owningElement, *aIsAlternate,
aObserver);
aObserver, principal);
if (!data) {
sheet->SetComplete();
return NS_ERROR_OUT_OF_MEMORY;
@ -1714,7 +1811,8 @@ CSSLoaderImpl::LoadStyleLink(nsIContent* aElement,
if (aURL && state == eSheetNeedsParser && mLoadingDatas.Count() != 0 &&
*aIsAlternate) {
LOG((" Deferring alternate sheet load"));
if (!mPendingDatas.Put(aURL, data)) {
nsURIAndPrincipalHashKey key(data->mURI, data->mLoaderPrincipal);
if (!mPendingDatas.Put(&key, data)) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -1738,6 +1836,7 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
{
LOG(("CSSLoaderImpl::LoadChildSheet"));
NS_PRECONDITION(aURL, "Must have a URI to load");
NS_PRECONDITION(aParentSheet, "Must have a parent sheet");
if (!mEnabled) {
LOG_WARN((" Not enabled"));
@ -1775,8 +1874,9 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
if (!context) {
context = mDocument;
}
rv = CheckLoadAllowed(sheetURI, aURL, context);
nsIPrincipal* principal = aParentSheet->Principal();
rv = CheckLoadAllowed(sheetURI, principal, aURL, context);
if (NS_FAILED(rv)) return rv;
LOG((" Passed load check"));
@ -1815,7 +1915,7 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
// loop) do so
nsCOMPtr<nsICSSStyleSheet> sheet;
StyleSheetState state;
rv = CreateSheet(aURL, nsnull,
rv = CreateSheet(aURL, nsnull, principal,
parentData ? parentData->mSyncLoad : PR_FALSE,
state, getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
@ -1837,7 +1937,7 @@ CSSLoaderImpl::LoadChildSheet(nsICSSStyleSheet* aParentSheet,
SheetLoadData* data = new SheetLoadData(this, aURL, sheet, parentData,
observer);
observer, principal);
if (!data) {
sheet->SetComplete();
@ -1907,7 +2007,7 @@ CSSLoaderImpl::InternalLoadNonDocumentSheet(nsIURI* aURL,
nsCOMPtr<nsICSSStyleSheet> sheet;
PRBool syncLoad = (aObserver == nsnull);
nsresult rv = CreateSheet(aURL, nsnull, syncLoad, state,
nsresult rv = CreateSheet(aURL, nsnull, nsnull, syncLoad, state,
getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
@ -1964,7 +2064,8 @@ CSSLoaderImpl::PostLoadEvent(nsIURI* aURI,
aSheet,
nsnull, // owning element doesn't matter here
aWasAlternate,
aObserver);
aObserver,
nsnull);
NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
if (!mPostedEvents.AppendElement(evt)) {
@ -2029,7 +2130,9 @@ nsresult NS_NewCSSLoader(nsICSSLoader** aLoader)
}
PR_STATIC_CALLBACK(PLDHashOperator)
StopLoadingSheetCallback(nsIURI* aKey, SheetLoadData*& aData, void* aClosure)
StopLoadingSheetCallback(nsURIAndPrincipalHashKey* aKey,
SheetLoadData*& aData,
void* aClosure)
{
NS_PRECONDITION(aData, "Must have a data!");
NS_PRECONDITION(aClosure, "Must have a loader");
@ -2046,12 +2149,14 @@ StopLoadingSheetCallback(nsIURI* aKey, SheetLoadData*& aData, void* aClosure)
NS_IMETHODIMP
CSSLoaderImpl::Stop()
{
if (mLoadingDatas.IsInitialized() && mLoadingDatas.Count() > 0) {
mLoadingDatas.Enumerate(StopLoadingSheetCallback, this);
}
// Do the pending datas first, since finishing up all the loading
// datas will try to start pending loads.
if (mPendingDatas.IsInitialized() && mPendingDatas.Count() > 0) {
mPendingDatas.Enumerate(StopLoadingSheetCallback, this);
}
if (mLoadingDatas.IsInitialized() && mLoadingDatas.Count() > 0) {
mLoadingDatas.Enumerate(StopLoadingSheetCallback, this);
}
for (PRUint32 i = 0; i < mPostedEvents.Length(); ++i) {
SheetLoadData* data = mPostedEvents[i];
data->mIsCancelled = PR_TRUE;
@ -2063,44 +2168,56 @@ CSSLoaderImpl::Stop()
return NS_OK;
}
PR_STATIC_CALLBACK(PLDHashOperator)
StopLoadingSheetByURICallback(nsURIAndPrincipalHashKey* aKey,
SheetLoadData*& aData,
void* aClosure)
{
NS_PRECONDITION(aData, "Must have a data!");
NS_PRECONDITION(aClosure, "Must have a loader");
PRBool equal;
if (NS_SUCCEEDED(aData->mURI->Equals(NS_STATIC_CAST(nsIURI*, aClosure),
&equal)) &&
equal) {
aData->mIsLoading = PR_FALSE; // we will handle the removal right here
aData->mIsCancelled = PR_TRUE;
aData->mLoader->SheetComplete(aData, NS_BINDING_ABORTED);
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
CSSLoaderImpl::StopLoadingSheet(nsIURI* aURL)
{
NS_ENSURE_TRUE(aURL, NS_ERROR_NULL_POINTER);
SheetLoadData* loadData = nsnull;
if (mLoadingDatas.IsInitialized()) {
mLoadingDatas.Get(aURL, &loadData);
// Do the pending datas first, since finishing up all the loading
// datas will try to start pending loads.
if (mPendingDatas.IsInitialized() && mPendingDatas.Count() > 0) {
mPendingDatas.Enumerate(StopLoadingSheetByURICallback, aURL);
}
if (!loadData && mPendingDatas.IsInitialized()) {
mPendingDatas.Get(aURL, &loadData);
if (loadData) {
// have to remove from mPendingDatas ourselves, since
// SheetComplete won't do that.
mPendingDatas.Remove(aURL);
}
}
if (!loadData) {
for (PRUint32 i = 0; i < mPostedEvents.Length(); ++i) {
SheetLoadData* curData = mPostedEvents[i];
PRBool equal;
if (curData->mURI && NS_SUCCEEDED(curData->mURI->Equals(aURL, &equal)) &&
equal) {
loadData = curData;
// SheetComplete() calls Release(), so give it an extra ref.
NS_ADDREF(curData);
mPostedEvents.RemoveElementAt(i);
break;
}
if (mLoadingDatas.IsInitialized() && mLoadingDatas.Count() > 0) {
mLoadingDatas.Enumerate(StopLoadingSheetByURICallback, aURL);
}
for (PRUint32 i = 0; i < mPostedEvents.Length(); ++i) {
SheetLoadData* curData = mPostedEvents[i-1];
PRBool equal;
if (curData->mURI && NS_SUCCEEDED(curData->mURI->Equals(aURL, &equal)) &&
equal) {
curData->mIsCancelled = PR_TRUE;
// SheetComplete() calls Release(), so give it an extra ref.
NS_ADDREF(curData);
SheetComplete(curData, NS_BINDING_ABORTED);
}
}
mPostedEvents.Clear();
if (loadData) {
loadData->mIsCancelled = PR_TRUE;
SheetComplete(loadData, NS_BINDING_ABORTED);
}
return NS_OK;
}

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

@ -71,6 +71,7 @@ class nsMediaList;
#include "nsDataHashtable.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIPrincipal.h"
/**
* OVERALL ARCHITECTURE
@ -116,14 +117,16 @@ public:
nsICSSStyleSheet* aSheet,
nsIStyleSheetLinkingElement* aOwningElement,
PRBool aIsAlternate,
nsICSSLoaderObserver* aObserver);
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a sheet linked from an @import rule
SheetLoadData(CSSLoaderImpl* aLoader,
nsIURI* aURI,
nsICSSStyleSheet* aSheet,
SheetLoadData* aParentData,
nsICSSLoaderObserver* aObserver);
nsICSSLoaderObserver* aObserver,
nsIPrincipal* aLoaderPrincipal);
// Data for loading a non-document sheet
SheetLoadData(CSSLoaderImpl* aLoader,
@ -209,8 +212,68 @@ public:
// The observer that wishes to be notified of load completion
nsCOMPtr<nsICSSLoaderObserver> mObserver;
// The principal that identifies who started loading us.
nsCOMPtr<nsIPrincipal> mLoaderPrincipal;
};
class nsURIAndPrincipalHashKey : public nsURIHashKey
{
public:
typedef nsURIAndPrincipalHashKey* KeyType;
typedef const nsURIAndPrincipalHashKey* KeyTypePointer;
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey* aKey)
: nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal)
: nsURIHashKey(aURI), mPrincipal(aPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey& toCopy)
: nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal)
{
MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
}
~nsURIAndPrincipalHashKey()
{
MOZ_COUNT_DTOR(nsURIAndPrincipalHashKey);
}
nsURIAndPrincipalHashKey* GetKey() const {
return NS_CONST_CAST(nsURIAndPrincipalHashKey*, this);
}
const nsURIAndPrincipalHashKey* GetKeyPointer() const { return this; }
PRBool KeyEquals(const nsURIAndPrincipalHashKey* aKey) const {
if (!nsURIHashKey::KeyEquals(aKey->mKey)) {
return PR_FALSE;
}
if (!mPrincipal != !aKey->mPrincipal) {
// One or the other has a principal, but not both... not equal
return PR_FALSE;
}
PRBool eq;
return !mPrincipal ||
NS_SUCCEEDED(mPrincipal->Equals(aKey->mPrincipal, &eq)) && eq;
}
static const nsURIAndPrincipalHashKey*
KeyToPointer(nsURIAndPrincipalHashKey* aKey) { return aKey; }
static PLDHashNumber HashKey(const nsURIAndPrincipalHashKey* aKey) {
return nsURIHashKey::HashKey(aKey->mKey);
}
enum { ALLOW_MEMMOVE = PR_TRUE };
protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
};
/***********************************************************************
* Enum that describes the state of the sheet returned by CreateSheet. *
@ -305,14 +368,17 @@ public:
private:
nsresult CheckLoadAllowed(nsIURI* aSourceURI,
nsIPrincipal* aSourcePrincipal,
nsIURI* aTargetURI,
nsISupports* aContext);
// For inline style, the aURI param is null, but the aLinkingContent
// must be non-null then.
// must be non-null then. The loader principal must never be null
// if aURI is not null.
nsresult CreateSheet(nsIURI* aURI,
nsIContent* aLinkingContent,
nsIPrincipal* aLoaderPrincipal,
PRBool aSyncLoad,
StyleSheetState& aSheetState,
nsICSSStyleSheet** aSheet);
@ -401,9 +467,12 @@ private:
nsCompatibility mCompatMode;
nsString mPreferredSheet; // title of preferred sheet
nsInterfaceHashtable<nsURIHashKey,nsICSSStyleSheet> mCompleteSheets;
nsDataHashtable<nsURIHashKey,SheetLoadData*> mLoadingDatas; // weak refs
nsDataHashtable<nsURIHashKey,SheetLoadData*> mPendingDatas; // weak refs
nsInterfaceHashtable<nsURIAndPrincipalHashKey,
nsICSSStyleSheet> mCompleteSheets;
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mLoadingDatas; // weak refs
nsDataHashtable<nsURIAndPrincipalHashKey,
SheetLoadData*> mPendingDatas; // weak refs
// We're not likely to have many levels of @import... But likely to have
// some. Allocate some storage, what the hell.

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

@ -496,9 +496,14 @@ static PRBool SetStyleSheetReference(nsICSSRule* aRule, void* aSheet)
nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsICSSStyleSheet* aParentSheet)
: mSheets(),
mComplete(PR_FALSE)
#ifdef DEBUG
, mPrincipalSet(PR_FALSE)
#endif
{
MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
mSheets.AppendElement(aParentSheet);
mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1");
}
static PRBool
@ -514,11 +519,15 @@ CloneRuleInto(nsICSSRule* aRule, void* aArray)
}
nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
nsICSSStyleSheet* aParentSheet)
nsICSSStyleSheet* aParentSheet)
: mSheets(),
mSheetURI(aCopy.mSheetURI),
mBaseURI(aCopy.mBaseURI),
mPrincipal(aCopy.mPrincipal),
mComplete(aCopy.mComplete)
#ifdef DEBUG
, mPrincipalSet(aCopy.mPrincipalSet)
#endif
{
MOZ_COUNT_CTOR(nsCSSStyleSheetInner);
mSheets.AppendElement(aParentSheet);
@ -629,10 +638,10 @@ nsCSSStyleSheet::nsCSSStyleSheet()
}
nsCSSStyleSheet::nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
nsICSSStyleSheet* aParentToUse,
nsICSSImportRule* aOwnerRuleToUse,
nsIDocument* aDocumentToUse,
nsIDOMNode* aOwningNodeToUse)
nsICSSStyleSheet* aParentToUse,
nsICSSImportRule* aOwnerRuleToUse,
nsIDocument* aDocumentToUse,
nsIDOMNode* aOwningNodeToUse)
: nsICSSStyleSheet(),
mRefCnt(0),
mTitle(aCopy.mTitle),
@ -766,10 +775,6 @@ nsCSSStyleSheet::SetURIs(nsIURI* aSheetURI, nsIURI* aBaseURI)
{
NS_PRECONDITION(aSheetURI && aBaseURI, "null ptr");
if (! mInner) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ASSERTION(mInner->mOrderedRules.Count() == 0 && !mInner->mComplete,
"Can't call SetURL on sheets that are complete or have rules");
@ -778,17 +783,36 @@ nsCSSStyleSheet::SetURIs(nsIURI* aSheetURI, nsIURI* aBaseURI)
return NS_OK;
}
void
nsCSSStyleSheet::SetPrincipal(nsIPrincipal* aPrincipal)
{
NS_PRECONDITION(!mInner->mPrincipalSet,
"Should have an inner whose principal has not yet been set");
if (aPrincipal) {
mInner->mPrincipal = aPrincipal;
#ifdef DEBUG
mInner->mPrincipalSet = PR_TRUE;
#endif
}
}
nsIPrincipal*
nsCSSStyleSheet::Principal() const
{
return mInner->mPrincipal;
}
NS_IMETHODIMP
nsCSSStyleSheet::GetSheetURI(nsIURI** aSheetURI) const
{
NS_IF_ADDREF(*aSheetURI = (mInner ? mInner->mSheetURI.get() : nsnull));
NS_IF_ADDREF(*aSheetURI = mInner->mSheetURI.get());
return NS_OK;
}
NS_IMETHODIMP
nsCSSStyleSheet::GetBaseURI(nsIURI** aBaseURI) const
{
NS_IF_ADDREF(*aBaseURI = (mInner ? mInner->mBaseURI.get() : nsnull));
NS_IF_ADDREF(*aBaseURI = mInner->mBaseURI.get());
return NS_OK;
}
@ -834,7 +858,7 @@ nsCSSStyleSheet::HasRules() const
NS_IMETHODIMP
nsCSSStyleSheet::GetApplicable(PRBool& aApplicable) const
{
aApplicable = !mDisabled && mInner && mInner->mComplete;
aApplicable = !mDisabled && mInner->mComplete;
return NS_OK;
}
@ -845,7 +869,7 @@ nsCSSStyleSheet::SetEnabled(PRBool aEnabled)
PRBool oldDisabled = mDisabled;
mDisabled = !aEnabled;
if (mDocument && mInner && mInner->mComplete && oldDisabled != mDisabled) {
if (mDocument && mInner->mComplete && oldDisabled != mDisabled) {
ClearRuleCascades();
mDocument->SetStyleSheetApplicableState(this, !mDisabled);
@ -857,15 +881,13 @@ nsCSSStyleSheet::SetEnabled(PRBool aEnabled)
NS_IMETHODIMP
nsCSSStyleSheet::GetComplete(PRBool& aComplete) const
{
aComplete = mInner && mInner->mComplete;
aComplete = mInner->mComplete;
return NS_OK;
}
NS_IMETHODIMP
nsCSSStyleSheet::SetComplete()
{
if (!mInner)
return NS_ERROR_UNEXPECTED;
NS_ASSERTION(!mDirty, "Can't set a dirty sheet complete!");
mInner->mComplete = PR_TRUE;
if (mDocument && !mDisabled) {
@ -931,7 +953,7 @@ nsCSSStyleSheet::ContainsStyleSheet(nsIURI* aURL, PRBool& aContains, nsIStyleShe
{
NS_PRECONDITION(nsnull != aURL, "null arg");
if (!mInner || !mInner->mSheetURI) {
if (!mInner->mSheetURI) {
// We're not yet far enough along in our load to know what our URL is (we
// may still get redirected and such). Assert (caller should really not be
// calling this on us at this stage) and return.
@ -1084,8 +1106,7 @@ NS_IMETHODIMP
nsCSSStyleSheet::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew)
{
NS_PRECONDITION(mInner->mOrderedRules.Count() != 0, "can't have old rule");
NS_PRECONDITION(mInner && mInner->mComplete,
"No replacing in an incomplete sheet!");
NS_PRECONDITION(mInner->mComplete, "No replacing in an incomplete sheet!");
if (NS_SUCCEEDED(WillDirty())) {
PRInt32 index = mInner->mOrderedRules.IndexOf(aOld);
@ -1109,10 +1130,7 @@ nsCSSStyleSheet::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew)
NS_IMETHODIMP
nsCSSStyleSheet::StyleRuleCount(PRInt32& aCount) const
{
aCount = 0;
if (mInner) {
aCount = mInner->mOrderedRules.Count();
}
aCount = mInner->mOrderedRules.Count();
return NS_OK;
}
@ -1121,27 +1139,19 @@ nsCSSStyleSheet::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const
{
// Important: If this function is ever made scriptable, we must add
// a security check here. See GetCSSRules below for an example.
nsresult result = NS_ERROR_ILLEGAL_VALUE;
aRule = mInner->mOrderedRules.SafeObjectAt(aIndex);
if (aRule) {
NS_ADDREF(aRule);
return NS_OK;
}
if (mInner) {
NS_IF_ADDREF(aRule = mInner->mOrderedRules.SafeObjectAt(aIndex));
if (nsnull != aRule) {
result = NS_OK;
}
}
else {
aRule = nsnull;
}
return result;
return NS_ERROR_ILLEGAL_VALUE;
}
nsXMLNameSpaceMap*
nsCSSStyleSheet::GetNameSpaceMap() const
{
if (mInner)
return mInner->mNameSpaceMap;
return nsnull;
return mInner->mNameSpaceMap;
}
NS_IMETHODIMP
@ -1186,9 +1196,6 @@ nsCSSStyleSheet::GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) cons
nsresult
nsCSSStyleSheet::EnsureUniqueInner()
{
if (! mInner) {
return NS_ERROR_NOT_INITIALIZED;
}
if (1 < mInner->mSheets.Count()) {
nsCSSStyleSheetInner* clone = mInner->CloneFor(this);
if (clone) {
@ -1249,11 +1256,6 @@ void nsCSSStyleSheet::List(FILE* out, PRInt32 aIndent) const
// Indent
for (index = aIndent; --index >= 0; ) fputs(" ", out);
if (! mInner) {
fputs("CSS Style Sheet - without inner data storage - ERROR\n", out);
return;
}
fputs("CSS Style Sheet: ", out);
nsCAutoString urlSpec;
nsresult rv = mInner->mSheetURI->GetSpec(urlSpec);
@ -1304,7 +1306,7 @@ nsCSSStyleSheet::ClearRuleCascades()
nsresult
nsCSSStyleSheet::WillDirty()
{
if (mInner && !mInner->mComplete) {
if (!mInner->mComplete) {
// Do nothing
return NS_OK;
}
@ -1388,7 +1390,7 @@ nsCSSStyleSheet::GetHref(nsAString& aHref)
nsCAutoString str;
// XXXldb The DOM spec says that this should be null for inline style sheets.
if (mInner && mInner->mSheetURI) {
if (mInner->mSheetURI) {
mInner->mSheetURI->GetSpec(str);
}
@ -1450,28 +1452,28 @@ nsCSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
//-- Security check: Only scripts from the same origin as the
// style sheet can access rule collections
//-- Security check: Only scripts whose principal subsumes that of the
// style sheet can access rule collections.
// Get JSContext from stack
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
NS_ENSURE_TRUE(stack, NS_ERROR_FAILURE);
JSContext *cx = nsnull;
nsresult rv = NS_OK;
rv = stack->Peek(&cx);
NS_ENSURE_SUCCESS(rv, rv);
if (!cx)
return NS_ERROR_FAILURE;
// Get the security manager and do the same-origin check
// Get the security manager and do the subsumes check
nsIScriptSecurityManager *securityManager =
nsContentUtils::GetSecurityManager();
rv = securityManager->CheckSameOrigin(cx, mInner->mSheetURI);
if (NS_FAILED(rv)) {
return rv;
nsCOMPtr<nsIPrincipal> subjectPrincipal;
securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
nsresult rv = NS_OK;
if (subjectPrincipal) {
PRBool subsumes;
rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
if (NS_SUCCEEDED(rv) && !subsumes &&
!nsContentUtils::IsCallerTrustedForRead()) {
rv = NS_ERROR_DOM_SECURITY_ERR;
}
if (NS_FAILED(rv)) {
return rv;
}
}
// OK, security check passed, so get the rule collection
@ -1494,7 +1496,6 @@ nsCSSStyleSheet::InsertRule(const nsAString& aRule,
PRUint32 aIndex,
PRUint32* aReturn)
{
NS_ENSURE_TRUE(mInner, NS_ERROR_FAILURE);
// No doing this if the sheet is not complete!
PRBool complete;
GetComplete(complete);
@ -1672,28 +1673,26 @@ nsCSSStyleSheet::DeleteRule(PRUint32 aIndex)
}
// XXX TBI: handle @rule types
if (mInner) {
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE);
result = WillDirty();
result = WillDirty();
if (NS_SUCCEEDED(result)) {
if (aIndex >= PRUint32(mInner->mOrderedRules.Count()))
return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (NS_SUCCEEDED(result)) {
if (aIndex >= PRUint32(mInner->mOrderedRules.Count()))
return NS_ERROR_DOM_INDEX_SIZE_ERR;
NS_ASSERTION(PRUint32(mInner->mOrderedRules.Count()) <= PR_INT32_MAX,
"Too many style rules!");
NS_ASSERTION(PRUint32(mInner->mOrderedRules.Count()) <= PR_INT32_MAX,
"Too many style rules!");
// Hold a strong ref to the rule so it doesn't die when we RemoveObjectAt
nsCOMPtr<nsICSSRule> rule = mInner->mOrderedRules.ObjectAt(aIndex);
if (rule) {
mInner->mOrderedRules.RemoveObjectAt(aIndex);
rule->SetStyleSheet(nsnull);
DidDirty();
// Hold a strong ref to the rule so it doesn't die when we RemoveObjectAt
nsCOMPtr<nsICSSRule> rule = mInner->mOrderedRules.ObjectAt(aIndex);
if (rule) {
mInner->mOrderedRules.RemoveObjectAt(aIndex);
rule->SetStyleSheet(nsnull);
DidDirty();
if (mDocument) {
mDocument->StyleRuleRemoved(this, rule);
}
if (mDocument) {
mDocument->StyleRuleRemoved(this, rule);
}
}
}
@ -1705,8 +1704,7 @@ NS_IMETHODIMP
nsCSSStyleSheet::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex)
{
NS_ENSURE_ARG_POINTER(aGroup);
NS_ASSERTION(mInner && mInner->mComplete,
"No deleting from an incomplete sheet!");
NS_ASSERTION(mInner->mComplete, "No deleting from an incomplete sheet!");
nsresult result;
nsCOMPtr<nsICSSRule> rule;
result = aGroup->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
@ -1745,8 +1743,7 @@ nsCSSStyleSheet::InsertRuleIntoGroup(const nsAString & aRule,
PRUint32* _retval)
{
nsresult result;
NS_ASSERTION(mInner && mInner->mComplete,
"No inserting into an incomplete sheet!");
NS_ASSERTION(mInner->mComplete, "No inserting into an incomplete sheet!");
// check that the group actually belongs to this sheet!
nsCOMPtr<nsIStyleSheet> groupSheet;
aGroup->GetStyleSheet(*getter_AddRefs(groupSheet));
@ -1831,8 +1828,7 @@ nsCSSStyleSheet::ReplaceRuleInGroup(nsICSSGroupRule* aGroup,
nsICSSRule* aOld, nsICSSRule* aNew)
{
nsresult result;
NS_PRECONDITION(mInner && mInner->mComplete,
"No replacing in an incomplete sheet!");
NS_PRECONDITION(mInner->mComplete, "No replacing in an incomplete sheet!");
#ifdef DEBUG
{
nsCOMPtr<nsIStyleSheet> groupSheet;
@ -1883,13 +1879,20 @@ nsCSSStyleSheet::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
nsresult
NS_NewCSSStyleSheet(nsICSSStyleSheet** aInstancePtrResult)
{
*aInstancePtrResult = nsnull;
nsCSSStyleSheet *it = new nsCSSStyleSheet();
if (nsnull == it) {
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(it);
if (!it->mInner || !it->mInner->mPrincipal) {
NS_RELEASE(it);
return NS_ERROR_OUT_OF_MEMORY;
}
*aInstancePtrResult = it;
return NS_OK;
}

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

@ -75,9 +75,14 @@ public:
nsAutoVoidArray mSheets;
nsCOMPtr<nsIURI> mSheetURI; // for error reports, etc.
nsCOMPtr<nsIURI> mBaseURI; // for resolving relative URIs
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMArray<nsICSSRule> mOrderedRules;
nsAutoPtr<nsXMLNameSpaceMap> mNameSpaceMap;
PRPackedBool mComplete;
PRBool mComplete;
#ifdef DEBUG
PRBool mPrincipalSet;
#endif
};
@ -132,6 +137,8 @@ public:
NS_IMETHOD StyleSheetCount(PRInt32& aCount) const;
NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const;
NS_IMETHOD SetURIs(nsIURI* aSheetURI, nsIURI* aBaseURI);
virtual NS_HIDDEN_(void) SetPrincipal(nsIPrincipal* aPrincipal);
virtual NS_HIDDEN_(nsIPrincipal*) Principal() const;
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetMedia(nsMediaList* aMedia);
NS_IMETHOD SetOwningNode(nsIDOMNode* aOwningNode);
@ -200,6 +207,7 @@ protected:
friend class nsMediaList;
friend PRBool CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData);
friend nsresult NS_NewCSSStyleSheet(nsICSSStyleSheet** aInstancePtrResult);
};
#endif /* !defined(nsCSSStyleSheet_h_) */

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

@ -50,11 +50,13 @@ class nsCSSRuleProcessor;
class nsMediaList;
class nsICSSGroupRule;
class nsICSSImportRule;
class nsIPrincipal;
// IID for the nsICSSStyleSheet interface
// 446df065-af5e-46b8-b32f-289bf5906876
// 36541c18-e735-48ef-8622-3a481275b757
#define NS_ICSS_STYLE_SHEET_IID \
{0x446df065, 0xaf5e, 0x46b8, {0xb3, 0x2f, 0x28, 0x9b, 0xf5, 0x90, 0x68, 0x76}}
{ 0x36541c18, 0xe735, 0x48ef, \
{ 0x86, 0x22, 0x3a, 0x48, 0x12, 0x75, 0xb7, 0x57 } }
class nsICSSStyleSheet : public nsIStyleSheet {
public:
@ -86,6 +88,17 @@ public:
* has no rules in it
*/
NS_IMETHOD SetURIs(nsIURI* aSheetURI, nsIURI* aBaseURI) = 0;
/**
* SetPrincipal should be called on all sheets before parsing into them.
* This can only be called once with a non-null principal. Calling this with
* a null pointer is allowed and is treated as a no-op.
*/
virtual NS_HIDDEN_(void) SetPrincipal(nsIPrincipal* aPrincipal) = 0;
// Principal() never returns a null pointer.
virtual NS_HIDDEN_(nsIPrincipal*) Principal() const = 0;
NS_IMETHOD SetTitle(const nsAString& aTitle) = 0;
NS_IMETHOD SetMedia(nsMediaList* aMedia) = 0;
NS_IMETHOD SetOwningNode(nsIDOMNode* aOwningNode) = 0;

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

@ -66,7 +66,8 @@ css_properties.js: host_ListCSSProperties$(HOST_BIN_SUFFIX) css_properties_like_
./host_ListCSSProperties$(HOST_BIN_SUFFIX) > $@
cat $(srcdir)/css_properties_like_longhand.js >> $@
_TEST_FILES = test_bug302186.html \
_TEST_FILES = test_bug221428.html \
test_bug302186.html \
test_bug319381.html \
test_bug365932.html \
test_bug372770.html \

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

@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=221428
-->
<head>
<title>Test for Bug 221428</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<link rel="stylesheet" href="data:text/css,body { color: green; }">
<style>
@import url("data:text/css,body { border: 1px solid transparent; }");
body { color: black; }
</style>
<script>
var executed = false;
</script>
<link rel="stylesheet" href="javascript:executed = true;">
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=221428">Mozilla Bug 221428</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 221428 **/
var exceptionThrown = false;
try {
is(document.styleSheets[1].cssRules[0].cssText, "body { color: green; }",
"Should get the color: green rule back");
} catch (e) {
exceptionThrown = true;
}
ok(!exceptionThrown, "Should be able to access data: <link> stylesheet");
exceptionThrown = false;
try {
is(document.styleSheets[2].cssRules[1].cssText, "body { color: black; }",
"Should get the color: black rule back");
} catch (e) {
exceptionThrown = true;
}
ok(!exceptionThrown, "Should be able to access <style> stylesheet");
exceptionThrown = false;
try {
is(document.styleSheets[2].cssRules[0].styleSheet.cssRules[0].cssText,
"body { border: 1px solid transparent; }",
"Should get the 'border: 1px solid transparent' rule back");
} catch (e) {
exceptionThrown = true;
}
ok(!exceptionThrown, "Should be able to access data: @import stylesheet");
ok(!executed,
"Shouldn't be executing stylesheet-link javascript: URIs against " +
"the page context");
</script>
</pre>
</body>
</html>

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

@ -77,7 +77,7 @@ public:
enum { ALLOW_MEMMOVE = PR_TRUE };
private:
protected:
nsCOMPtr<nsIURI> mKey;
};