diff --git a/layout/style/nsCSSLoader.cpp b/layout/style/nsCSSLoader.cpp index 4a65f36828e..c2f844d7e22 100644 --- a/layout/style/nsCSSLoader.cpp +++ b/layout/style/nsCSSLoader.cpp @@ -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 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 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 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 stream; - rv = NS_OpenURI(getter_AddRefs(stream), aLoadData->mURI); + nsCOMPtr 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 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 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 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 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 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 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 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; } diff --git a/layout/style/nsCSSLoader.h b/layout/style/nsCSSLoader.h index 9a23c99c196..5ba23d790e2 100644 --- a/layout/style/nsCSSLoader.h +++ b/layout/style/nsCSSLoader.h @@ -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 mObserver; + + // The principal that identifies who started loading us. + nsCOMPtr 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 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 mCompleteSheets; - nsDataHashtable mLoadingDatas; // weak refs - nsDataHashtable mPendingDatas; // weak refs + nsInterfaceHashtable mCompleteSheets; + nsDataHashtable mLoadingDatas; // weak refs + nsDataHashtable mPendingDatas; // weak refs // We're not likely to have many levels of @import... But likely to have // some. Allocate some storage, what the hell. diff --git a/layout/style/nsCSSStyleSheet.cpp b/layout/style/nsCSSStyleSheet.cpp index 3c332cd10c5..72e693e79e0 100644 --- a/layout/style/nsCSSStyleSheet.cpp +++ b/layout/style/nsCSSStyleSheet.cpp @@ -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 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 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 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 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 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 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 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; } diff --git a/layout/style/nsCSSStyleSheet.h b/layout/style/nsCSSStyleSheet.h index 6cfcc9eaa06..d7cf9c34b91 100644 --- a/layout/style/nsCSSStyleSheet.h +++ b/layout/style/nsCSSStyleSheet.h @@ -75,9 +75,14 @@ public: nsAutoVoidArray mSheets; nsCOMPtr mSheetURI; // for error reports, etc. nsCOMPtr mBaseURI; // for resolving relative URIs + nsCOMPtr mPrincipal; nsCOMArray mOrderedRules; nsAutoPtr 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_) */ diff --git a/layout/style/nsICSSStyleSheet.h b/layout/style/nsICSSStyleSheet.h index 0c68cbbf143..77df3fa9ed9 100644 --- a/layout/style/nsICSSStyleSheet.h +++ b/layout/style/nsICSSStyleSheet.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; diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index c660335beb8..64171cfb8d8 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -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 \ diff --git a/layout/style/test/test_bug221428.html b/layout/style/test/test_bug221428.html new file mode 100644 index 00000000000..b48d276996f --- /dev/null +++ b/layout/style/test/test_bug221428.html @@ -0,0 +1,69 @@ + + + + + Test for Bug 221428 + + + + + + + + + +Mozilla Bug 221428 +

+ +
+
+
+ + + diff --git a/netwerk/base/public/nsURIHashKey.h b/netwerk/base/public/nsURIHashKey.h index ade618662d7..cd4984b2101 100644 --- a/netwerk/base/public/nsURIHashKey.h +++ b/netwerk/base/public/nsURIHashKey.h @@ -77,7 +77,7 @@ public: enum { ALLOW_MEMMOVE = PR_TRUE }; -private: +protected: nsCOMPtr mKey; };