Propagate stylesheet principals through to XBL binding loads; streamline load

security checks in the XBL code (so that all the security checks are gated
through LoadBindingDocumentInfo).  Bug 204140, r=dbaron for the CSS changes,
r=sicking for the XBL changes, sr=sicking.

In particular, this change allows user stylesheets loaded from local files to
link to local files.
This commit is contained in:
bzbarsky@mit.edu 2007-07-18 14:56:57 -07:00
parent 65e081a7db
commit d074804c35
17 changed files with 178 additions and 74 deletions

View File

@ -3605,6 +3605,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
const nsACString& aMimeGuess,
nsISupports* aExtra)
{
// XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
nsCOMPtr<nsIURI> loadingURI;
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -3406,8 +3406,22 @@ nsDocument::AddBinding(nsIDOMElement* aContent, const nsAString& aURI)
if (NS_FAILED(rv)) {
return rv;
}
// Figure out the right principal to use
nsCOMPtr<nsIPrincipal> subject;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (secMan) {
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!subject) {
// Fall back to our principal. Or should we fall back to the null
// principal? The latter would just mean no binding loads....
subject = NodePrincipal();
}
return mBindingManager->AddLayeredBinding(content, uri);
return mBindingManager->AddLayeredBinding(content, uri, subject);
}
NS_IMETHODIMP
@ -3439,7 +3453,21 @@ nsDocument::LoadBindingDocument(const nsAString& aURI)
static_cast<nsIDocument *>(this)->GetBaseURI());
NS_ENSURE_SUCCESS(rv, rv);
mBindingManager->LoadBindingDocument(this, uri);
// Figure out the right principal to use
nsCOMPtr<nsIPrincipal> subject;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (secMan) {
rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!subject) {
// Fall back to our principal. Or should we fall back to the null
// principal? The latter would just mean no binding loads....
subject = NodePrincipal();
}
mBindingManager->LoadBindingDocument(this, uri, subject);
return NS_OK;
}

View File

@ -55,10 +55,11 @@ class nsXBLBinding;
class nsIXBLDocumentInfo;
class nsIURI;
class nsIAtom;
class nsIPrincipal;
#define NS_IXBLSERVICE_IID \
{ 0xefda61b3, 0x5d04, 0x43b0, \
{ 0x98, 0x0c, 0x32, 0x62, 0x72, 0xc8, 0x5c, 0x68 } }
{ 0x98b28f4e, 0x698f, 0x4f77, \
{ 0xa8, 0x9e, 0x65, 0xf5, 0xd0, 0xde, 0x6a, 0xbf } }
class nsIXBLService : public nsISupports
{
@ -66,8 +67,9 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXBLSERVICE_IID)
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFlag,
// onto the element. aOriginPrincipal must not be null here.
NS_IMETHOD LoadBindings(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal, PRBool aAugmentFlag,
nsXBLBinding** aBinding, PRBool* aResolveStyle) = 0;
// Indicates whether or not a binding is fully loaded.
@ -76,10 +78,15 @@ public:
// Retrieves our base class (e.g., tells us what type of frame and content node to build)
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult) = 0;
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
NS_IMETHOD LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
// This method checks the hashtable and then calls FetchBindingDocument on a
// miss. aOriginPrincipal or aBoundDocument may be null to bypass security
// checks.
NS_IMETHOD LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsIDocument* aBoundDocument,
nsIURI* aBindingURI,
PRBool aForceSyncLoad, nsIXBLDocumentInfo** aResult) = 0;
nsIPrincipal* aOriginPrincipal,
PRBool aForceSyncLoad,
nsIXBLDocumentInfo** aResult) = 0;
// Hooks up the global key event handlers to the document root.
NS_IMETHOD AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget)=0;

View File

@ -690,7 +690,8 @@ nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent,
}
nsresult
nsBindingManager::AddLayeredBinding(nsIContent* aContent, nsIURI* aURL)
nsBindingManager::AddLayeredBinding(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal)
{
// First we need to load our binding.
nsresult rv;
@ -702,8 +703,8 @@ nsBindingManager::AddLayeredBinding(nsIContent* aContent, nsIURI* aURL)
// Load the bindings.
nsRefPtr<nsXBLBinding> binding;
PRBool dummy;
xblService->LoadBindings(aContent, aURL, PR_TRUE, getter_AddRefs(binding),
&dummy);
xblService->LoadBindings(aContent, aURL, aOriginPrincipal, PR_TRUE,
getter_AddRefs(binding), &dummy);
if (binding) {
AddToAttachedQueue(binding);
ProcessAttachedQueue();
@ -766,7 +767,8 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL)
nsresult
nsBindingManager::LoadBindingDocument(nsIDocument* aBoundDoc,
nsIURI* aURL)
nsIURI* aURL,
nsIPrincipal* aOriginPrincipal)
{
NS_PRECONDITION(aURL, "Must have a URI to load!");
@ -780,7 +782,8 @@ nsBindingManager::LoadBindingDocument(nsIDocument* aBoundDoc,
// Load the binding doc.
nsCOMPtr<nsIXBLDocumentInfo> info;
xblService->LoadBindingDocumentInfo(nsnull, aBoundDoc, aURL,
PR_TRUE, getter_AddRefs(info));
aOriginPrincipal, PR_TRUE,
getter_AddRefs(info));
if (!info)
return NS_ERROR_FAILURE;

View File

@ -62,6 +62,7 @@ class nsXBLBinding;
template<class E> class nsRefPtr;
typedef nsTArray<nsRefPtr<nsXBLBinding> > nsBindingList;
template<class T> class nsRunnableMethod;
class nsIPrincipal;
class nsBindingManager : public nsIMutationObserver
{
@ -154,9 +155,11 @@ public:
nsIContent* GetSingleInsertionPoint(nsIContent* aParent, PRUint32* aIndex,
PRBool* aMultipleInsertionPoints);
nsresult AddLayeredBinding(nsIContent* aContent, nsIURI* aURL);
nsresult AddLayeredBinding(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal);
nsresult RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL);
nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL);
nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal);
nsresult AddToAttachedQueue(nsXBLBinding* aBinding);
void ProcessAttachedQueue();

View File

@ -486,9 +486,12 @@ nsXBLService::~nsXBLService(void)
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHODIMP
nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFlag,
nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal, PRBool aAugmentFlag,
nsXBLBinding** aBinding, PRBool* aResolveStyle)
{
{
NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal");
*aBinding = nsnull;
*aResolveStyle = PR_FALSE;
@ -522,26 +525,10 @@ nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFl
}
}
// Security check - Enforce same-origin policy, except to chrome.
// We have to be careful to not pass aContent as the context here.
// Otherwise, if there is a JS-implemented content policy, we will attempt
// to wrap the content node, which will try to load XBL bindings for it, if
// any. Since we're not done loading this binding yet, that will reenter
// this method and we'll end up creating a binding and then immediately
// clobbering it in our table. That makes things very confused, leading to
// misbehavior and crashes.
rv = nsContentUtils::CheckSecurityBeforeLoad(aURL,
document->NodePrincipal(),
nsIScriptSecurityManager::ALLOW_CHROME,
PR_TRUE,
nsIContentPolicy::TYPE_XBL,
document);
NS_ENSURE_SUCCESS(rv, rv);
PRBool ready;
nsRefPtr<nsXBLBinding> newBinding;
if (NS_FAILED(rv = GetBinding(aContent, aURL, PR_FALSE, &ready,
getter_AddRefs(newBinding)))) {
if (NS_FAILED(rv = GetBinding(aContent, aURL, PR_FALSE, aOriginPrincipal,
&ready, getter_AddRefs(newBinding)))) {
return rv;
}
@ -757,23 +744,25 @@ NS_IMETHODIMP nsXBLService::BindingReady(nsIContent* aBoundElement,
nsIURI* aURI,
PRBool* aIsReady)
{
return GetBinding(aBoundElement, aURI, PR_TRUE, aIsReady, nsnull);
// Don't do a security check here; we know this binding is set to go.
return GetBinding(aBoundElement, aURI, PR_TRUE, nsnull, aIsReady, nsnull);
}
nsresult
nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekOnly, PRBool* aIsReady,
nsXBLBinding** aResult)
PRBool aPeekOnly, nsIPrincipal* aOriginPrincipal,
PRBool* aIsReady, nsXBLBinding** aResult)
{
// More than 6 binding URIs are rare, see bug 55070 comment 18.
nsTArray<nsIURI*> uris(6);
return GetBinding(aBoundElement, aURI, aPeekOnly, aIsReady, aResult, uris);
return GetBinding(aBoundElement, aURI, aPeekOnly, aOriginPrincipal, aIsReady,
aResult, uris);
}
nsresult
nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekOnly, PRBool* aIsReady,
nsXBLBinding** aResult,
PRBool aPeekOnly, nsIPrincipal* aOriginPrincipal,
PRBool* aIsReady, nsXBLBinding** aResult,
nsTArray<nsIURI*>& aDontExtendURIs)
{
NS_ASSERTION(aPeekOnly || aResult,
@ -796,8 +785,11 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc();
nsCOMPtr<nsIXBLDocumentInfo> docInfo;
LoadBindingDocumentInfo(aBoundElement, boundDocument, aURI, PR_FALSE,
getter_AddRefs(docInfo));
nsresult rv = LoadBindingDocumentInfo(aBoundElement, boundDocument, aURI,
aOriginPrincipal,
PR_FALSE, getter_AddRefs(docInfo));
NS_ENSURE_SUCCESS(rv, rv);
if (!docInfo)
return NS_ERROR_FAILURE;
@ -830,9 +822,11 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool hasBase = protoBinding->HasBasePrototype();
nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
if (baseProto) {
nsresult rv = GetBinding(aBoundElement, baseProto->BindingURI(), aPeekOnly,
aIsReady, getter_AddRefs(baseBinding),
aDontExtendURIs);
// Use the NodePrincipal() of the <binding> element in question
// for the security check.
rv = GetBinding(aBoundElement, baseProto->BindingURI(), aPeekOnly,
child->NodePrincipal(), aIsReady,
getter_AddRefs(baseBinding), aDontExtendURIs);
if (NS_FAILED(rv))
return rv; // We aren't ready yet.
}
@ -899,10 +893,9 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
// Look up the prefix.
// We have a base class binding. Load it right now.
nsCOMPtr<nsIURI> bindingURI;
nsresult rv =
NS_NewURI(getter_AddRefs(bindingURI), value,
doc->GetDocumentCharacterSet().get(),
doc->GetBaseURI());
rv = NS_NewURI(getter_AddRefs(bindingURI), value,
doc->GetDocumentCharacterSet().get(),
doc->GetBaseURI());
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 count = aDontExtendURIs.Length();
@ -926,7 +919,10 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
}
}
rv = GetBinding(aBoundElement, bindingURI, aPeekOnly, aIsReady,
// Use the NodePrincipal() of the <binding> element in question
// for the security check.
rv = GetBinding(aBoundElement, bindingURI, aPeekOnly,
child->NodePrincipal(), aIsReady,
getter_AddRefs(baseBinding), aDontExtendURIs);
if (NS_FAILED(rv))
return rv; // Binding not yet ready or an error occurred.
@ -960,15 +956,26 @@ NS_IMETHODIMP
nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsIDocument* aBoundDocument,
nsIURI* aBindingURI,
nsIPrincipal* aOriginPrincipal,
PRBool aForceSyncLoad,
nsIXBLDocumentInfo** aResult)
{
NS_PRECONDITION(aBindingURI, "Must have a binding URI");
NS_PRECONDITION(!aOriginPrincipal || aBoundDocument,
"If we're doing a security check, we better have a document!");
nsresult rv;
if (aBoundDocument) {
if (aOriginPrincipal) {
// Security check - Enforce same-origin policy, except to chrome.
// We have to be careful to not pass aContent as the context here.
// Otherwise, if there is a JS-implemented content policy, we will attempt
// to wrap the content node, which will try to load XBL bindings for it, if
// any. Since we're not done loading this binding yet, that will reenter
// this method and we'll end up creating a binding and then immediately
// clobbering it in our table. That makes things very confused, leading to
// misbehavior and crashes.
rv = nsContentUtils::
CheckSecurityBeforeLoad(aBindingURI, aBoundDocument->NodePrincipal(),
CheckSecurityBeforeLoad(aBindingURI, aOriginPrincipal,
nsIScriptSecurityManager::ALLOW_CHROME,
PR_TRUE,
nsIContentPolicy::TYPE_XBL,

View File

@ -65,8 +65,9 @@ class nsXBLService : public nsIXBLService,
NS_DECL_ISUPPORTS
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
NS_IMETHOD LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFlag,
// onto the element. aOriginPrincipal must not be null here.
NS_IMETHOD LoadBindings(nsIContent* aContent, nsIURI* aURL,
nsIPrincipal* aOriginPrincipal, PRBool aAugmentFlag,
nsXBLBinding** aBinding, PRBool* aResolveStyle);
// Indicates whether or not a binding is fully loaded.
@ -75,10 +76,15 @@ class nsXBLService : public nsIXBLService,
// Gets the object's base class type.
NS_IMETHOD ResolveTag(nsIContent* aContent, PRInt32* aNameSpaceID, nsIAtom** aResult);
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
NS_IMETHOD LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
// This method checks the hashtable and then calls FetchBindingDocument on a
// miss. aOriginPrincipal or aBoundDocument may be null to bypass security
// checks.
NS_IMETHOD LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsIDocument* aBoundDocument,
nsIURI* aBindingURI,
PRBool aForceSyncLoad, nsIXBLDocumentInfo** aResult);
nsIPrincipal* aOriginPrincipal,
PRBool aForceSyncLoad,
nsIXBLDocumentInfo** aResult);
// Used by XUL key bindings and for window XBL.
NS_IMETHOD AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget);
@ -108,8 +114,8 @@ protected:
* This method calls the one below with an empty |aDontExtendURIs| array.
*/
nsresult GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekFlag, PRBool* aIsReady,
nsXBLBinding** aResult);
PRBool aPeekFlag, nsIPrincipal* aOriginPrincipal,
PRBool* aIsReady, nsXBLBinding** aResult);
/**
* This method loads a binding doc and then builds the specific binding
@ -124,10 +130,13 @@ protected:
* element. If a binding extends any of these then further loading
* is aborted (because it would lead to the binding extending itself)
* and NS_ERROR_ILLEGAL_VALUE is returned.
*
* @note This method always calls LoadBindingDocumentInfo(), so it's
* enough to funnel all security checks through that function.
*/
nsresult GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekFlag, PRBool* aIsReady,
nsXBLBinding** aResult,
PRBool aPeekFlag, nsIPrincipal* aOriginPrincipal,
PRBool* aIsReady, nsXBLBinding** aResult,
nsTArray<nsIURI*>& aDontExtendURIs);
// MEMBER VARIABLES

View File

@ -119,6 +119,7 @@ void nsXBLSpecialDocInfo::LoadDocInfo()
}
xblService->LoadBindingDocumentInfo(nsnull, nsnull,
bindingURI,
nsnull,
PR_TRUE,
getter_AddRefs(mHTMLBindings));
@ -132,6 +133,7 @@ void nsXBLSpecialDocInfo::LoadDocInfo()
xblService->LoadBindingDocumentInfo(nsnull, nsnull,
bindingURI,
nsnull,
PR_TRUE,
getter_AddRefs(mUserHTMLBindings));
}

View File

@ -58,6 +58,7 @@
#include "xptcall.h"
#include "prprf.h"
#include "nsTArray.h"
#include "nsCSSValue.h"
// JavaScript includes
#include "jsapi.h"
@ -6954,7 +6955,7 @@ nsElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsnull);
NS_ENSURE_TRUE(sc, NS_ERROR_FAILURE);
nsIURI *bindingURL = sc->GetStyleDisplay()->mBinding;
nsCSSValue::URL *bindingURL = sc->GetStyleDisplay()->mBinding;
if (!bindingURL) {
// No binding, nothing left to do here.
return NS_OK;
@ -6966,7 +6967,8 @@ nsElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXBLService> xblService(do_GetService("@mozilla.org/xbl;1"));
NS_ENSURE_TRUE(xblService, NS_ERROR_NOT_AVAILABLE);
xblService->LoadBindings(content, bindingURL, PR_FALSE,
xblService->LoadBindings(content, bindingURL->mURI,
bindingURL->mOriginPrincipal, PR_FALSE,
getter_AddRefs(binding), &dummy);
}

View File

@ -78,6 +78,7 @@ REQUIRES = xpcom \
windowwatcher \
accessibility \
shistory \
caps \
$(NULL)
ifdef MOZ_ENABLE_CAIRO_GFX

View File

@ -117,7 +117,7 @@
#include "nsImageFrame.h"
#include "nsIObjectLoadingContent.h"
#include "nsContentErrors.h"
#include "nsIPrincipal.h"
#include "nsIDOMWindowInternal.h"
#include "nsBox.h"
@ -4209,8 +4209,10 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
return NS_ERROR_FAILURE;
nsRefPtr<nsXBLBinding> binding;
rv = xblService->LoadBindings(aDocElement, display->mBinding, PR_FALSE,
getter_AddRefs(binding), &resolveStyle);
rv = xblService->LoadBindings(aDocElement, display->mBinding->mURI,
display->mBinding->mOriginPrincipal,
PR_FALSE, getter_AddRefs(binding),
&resolveStyle);
if (NS_FAILED(rv))
return NS_OK; // Binding will load asynchronously.
@ -7460,8 +7462,9 @@ nsCSSFrameConstructor::ConstructFrameInternal( nsFrameConstructorState& aState,
if (!xblService)
return NS_ERROR_FAILURE;
rv = xblService->LoadBindings(aContent, display->mBinding, PR_FALSE,
getter_AddRefs(binding.mBinding),
rv = xblService->LoadBindings(aContent, display->mBinding->mURI,
display->mBinding->mOriginPrincipal,
PR_FALSE, getter_AddRefs(binding.mBinding),
&resolveStyle);
if (NS_FAILED(rv))
return NS_OK;

View File

@ -232,6 +232,14 @@ public:
mValue.mURL->mURI : mValue.mImage->mURI;
}
URL* GetURLStructValue() const
{
// Not allowing this for Image values, because if the caller takes
// a ref to them they won't be able to delete them properly.
NS_ASSERTION(mUnit == eCSSUnit_URL, "not a URL value");
return mValue.mURL;
}
const PRUnichar* GetOriginalURLValue() const
{
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
@ -388,6 +396,12 @@ public:
NS_HIDDEN_(PRBool) operator==(const URL& aOther) const;
// URIEquals only compares URIs and principals (unlike operator==, which
// also compares the original strings). URIEquals also assumes that the
// mURI member of both URL objects is non-null. Do NOT call this method
// unless you're sure this is the case.
NS_HIDDEN_(PRBool) URIEquals(const URL& aOther) const;
nsCOMPtr<nsIURI> mURI; // null == invalid URL
nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
// null-checks; this is never null.

View File

@ -431,7 +431,7 @@ nsComputedDOMStyle::GetBinding(nsIDOMCSSValue** aValue)
const nsStyleDisplay* display = GetStyleDisplay();
if (display->mBinding) {
val->SetURI(display->mBinding);
val->SetURI(display->mBinding->mURI);
} else {
val->SetIdent(nsGkAtoms::none);
}

View File

@ -2728,7 +2728,14 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct,
// binding: url, none, inherit
if (eCSSUnit_URL == displayData.mBinding.GetUnit()) {
display->mBinding = displayData.mBinding.GetURLValue();
nsCSSValue::URL* url = displayData.mBinding.GetURLStructValue();
NS_ASSERTION(url, "What's going on here?");
if (NS_LIKELY(url->mURI)) {
display->mBinding = url;
} else {
display->mBinding = nsnull;
}
}
else if (eCSSUnit_None == displayData.mBinding.GetUnit()) {
display->mBinding = nsnull;

View File

@ -551,6 +551,15 @@ public:
Assign("[none]");
}
}
URICString(nsCSSValue::URL* aURI) {
if (aURI) {
NS_ASSERTION(aURI->mURI, "Must have URI here!");
aURI->mURI->GetSpec(*this);
} else {
Assign("[none]");
}
}
URICString& operator=(const URICString& aOther) {
Assign(aOther);

View File

@ -76,6 +76,12 @@ static PRBool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
eq);
}
static PRBool EqualURIs(nsCSSValue::URL *aURI1, nsCSSValue::URL *aURI2)
{
return aURI1 == aURI2 || // handle null==null, and optimize
(aURI1 && aURI2 && aURI1->URIEquals(*aURI2));
}
static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
{
if (aImage1 == aImage2) {

View File

@ -760,8 +760,10 @@ struct nsStyleDisplay : public nsStyleStruct {
#ifdef DEBUG
static nsChangeHint MaxDifference();
#endif
nsCOMPtr<nsIURI> mBinding; // [reset]
// We guarantee that if mBinding is non-null, so are mBinding->mURI and
// mBinding->mOriginPrincipal.
nsRefPtr<nsCSSValue::URL> mBinding; // [reset]
#if 0
// XXX This is how it is defined in the CSS2 spec, but the errata
// changed it to be consistent with the positioning draft and how