diff --git a/rdf/base/idl/nsIRDFService.idl b/rdf/base/idl/nsIRDFService.idl index 54444f56d2a..3f143885954 100644 --- a/rdf/base/idl/nsIRDFService.idl +++ b/rdf/base/idl/nsIRDFService.idl @@ -38,6 +38,8 @@ interface nsIRDFService : nsISupports { // be converted to a single-byte representation internally. nsIRDFResource GetUnicodeResource(in wstring aURI); + nsIRDFResource GetAnonymousResource(); + // Construct an RDF literal from a Unicode string. nsIRDFLiteral GetLiteral(in wstring aValue); @@ -47,6 +49,8 @@ interface nsIRDFService : nsISupports { // Construct an RDF literal from an int. nsIRDFInt GetIntLiteral(in long aValue); + boolean IsAnonymousResource(in nsIRDFResource aResource); + // Registers a resource with the RDF system, making it unique w.r.t. // GetResource. // diff --git a/rdf/base/src/nsRDFContentSink.cpp b/rdf/base/src/nsRDFContentSink.cpp index 404ed92ff01..1a3db4185db 100644 --- a/rdf/base/src/nsRDFContentSink.cpp +++ b/rdf/base/src/nsRDFContentSink.cpp @@ -1031,7 +1031,7 @@ RDFContentSinkImpl::GetIdAboutAttribute(const nsIParserNode& aNode, } // Otherwise, we couldn't find anything, so just gensym one... - rv = rdf_CreateAnonymousResource(nsCAutoString(docURI), aResource); + rv = gRDFService->GetAnonymousResource(aResource); return rv; } diff --git a/rdf/base/src/nsRDFService.cpp b/rdf/base/src/nsRDFService.cpp index 5bddcadd7d8..4a5cb0814d0 100644 --- a/rdf/base/src/nsRDFService.cpp +++ b/rdf/base/src/nsRDFService.cpp @@ -622,6 +622,69 @@ ServiceImpl::GetUnicodeResource(const PRUnichar* aURI, nsIRDFResource** aResourc } +NS_IMETHODIMP +ServiceImpl::GetAnonymousResource(nsIRDFResource** aResult) +{ +static PRUint32 gCounter = 0; +static char gChars[] = "0123456789abcdef" + "ghijklmnopqrstuv" + "wxyzABCDEFGHIJKL" + "MNOPQRSTUVWXYZ.+"; + +static PRInt32 kMask = 0x003f; +static PRInt32 kShift = 6; + + if (! gCounter) { + // Start it at a semi-unique value, just to minimize the + // chance that we get into a situation where + // + // 1. An anonymous resource gets serialized out in a graph + // 2. Reboot + // 3. The same anonymous resource gets requested, and refers + // to something completely different. + // 4. The serialization is read back in. + LL_L2UI(gCounter, PR_Now()); + } + + nsresult rv; + nsCAutoString s; + + do { + // Ugh, this is a really sloppy way to do this; I copied the + // implementation from the days when it lived outside the RDF + // service. Now that it's a member we can be more cleverer. + + s.Truncate(); + s.Append("rdf:#$"); + + PRUint32 id = ++gCounter; + while (id) { + char ch = gChars[(id & kMask)]; + s.Append(ch); + id >>= kShift; + } + + nsIRDFResource* resource; + rv = GetResource((const char*) s, &resource); + if (NS_FAILED(rv)) return rv; + + // XXX an ugly but effective way to make sure that this + // resource is really unique in the world. + resource->AddRef(); + nsrefcnt refcnt = resource->Release(); + + if (refcnt == 1) { + *aResult = resource; + break; + } + + NS_RELEASE(resource); + } while (1); + + return NS_OK; +} + + NS_IMETHODIMP ServiceImpl::GetLiteral(const PRUnichar* aValue, nsIRDFLiteral** aLiteral) { @@ -679,6 +742,35 @@ ServiceImpl::GetIntLiteral(PRInt32 value, nsIRDFInt** literal) return NS_OK; } + +NS_IMETHODIMP +ServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, PRBool* _result) +{ + NS_PRECONDITION(aResource != nsnull, "null ptr"); + if (! aResource) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + const char* uri; + rv = aResource->GetValueConst(&uri); + if (NS_FAILED(rv)) return rv; + + if ((uri[0] == 'r') && + (uri[1] == 'd') && + (uri[2] == 'f') && + (uri[3] == ':') && + (uri[4] == '#') && + (uri[5] == '$')) { + *_result = PR_TRUE; + } + else { + *_result = PR_FALSE; + } + + return NS_OK; +} + NS_IMETHODIMP ServiceImpl::RegisterResource(nsIRDFResource* aResource, PRBool replace) { diff --git a/rdf/base/src/rdfutil.cpp b/rdf/base/src/rdfutil.cpp index b54c00f99c4..d38c8ad0124 100644 --- a/rdf/base/src/rdfutil.cpp +++ b/rdf/base/src/rdfutil.cpp @@ -50,100 +50,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "prtime.h" #include "rdfutil.h" -#include "rdf.h" -static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI; - //////////////////////////////////////////////////////////////////////// -static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); - -//////////////////////////////////////////////////////////////////////// - -nsresult -rdf_CreateAnonymousResource(const nsCString& aContextURI, nsIRDFResource** aResult) -{ -static PRUint32 gCounter = 0; - - if (! gCounter) { - // Start it at a semi-unique value, just to minimize the - // chance that we get into a situation where - // - // 1. An anonymous resource gets serialized out in a graph - // 2. Reboot - // 3. The same anonymous resource gets requested, and refers - // to something completely different. - // 4. The serialization is read back in. - LL_L2UI(gCounter, PR_Now()); - } - - nsresult rv; - NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - do { - char buf[128]; - CBufDescriptor desc(buf, PR_TRUE, sizeof(buf)); - nsCAutoString s(desc); - - s = aContextURI; - s.Append("#$"); - s.Append(++gCounter, 16); - - nsIRDFResource* resource; - rv = rdf->GetResource((const char*) s, &resource); - if (NS_FAILED(rv)) return rv; - - // XXX an ugly but effective way to make sure that this - // resource is really unique in the world. - resource->AddRef(); - nsrefcnt refcnt = resource->Release(); - - if (refcnt == 1) { - *aResult = resource; - break; - } - - NS_RELEASE(resource); - } while (1); - - return NS_OK; -} - -PRBool -rdf_IsAnonymousResource(const nsCString& aContextURI, nsIRDFResource* aResource) -{ - nsresult rv; - const char* p; - rv = aResource->GetValueConst(&p); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource URI"); - if (NS_FAILED(rv)) - return PR_FALSE; - - { - CBufDescriptor desc(NS_CONST_CAST(char*, p), PR_TRUE, -1); - nsCAutoString uri(desc); - - if (uri.Find(aContextURI) != 0) - return PR_FALSE; - } - - { - CBufDescriptor desc(NS_CONST_CAST(char*, p + aContextURI.Length()), PR_TRUE, -1); - nsCAutoString id(desc); - - if (id.CharAt(0) != '#' || id.CharAt(1) != '$') - return PR_FALSE; - - for (PRInt32 i = id.Length() - 1; i >= 1; --i) { - if (id.CharAt(i) < '0' || id.CharAt(i) > '9') - return PR_FALSE; - } - } - - return PR_TRUE; -} - - nsresult rdf_MakeRelativeRef(const nsString& aBaseURI, nsString& aURI) { diff --git a/rdf/base/src/rdfutil.h b/rdf/base/src/rdfutil.h index 7ae9b68e844..972455d46c4 100644 --- a/rdf/base/src/rdfutil.h +++ b/rdf/base/src/rdfutil.h @@ -38,25 +38,10 @@ #include "prtypes.h" -class nsIRDFResource; class nsCString; class nsString; class nsIURI; -/** - * Construct a new, "anonymous" node; that is, a node with an internal - * resource URI. - */ -nsresult -rdf_CreateAnonymousResource(const nsCString& aContextURI, nsIRDFResource** result); - -/** - * Determine if a resource is an "anonymous" resource that we've constructed - * ourselves. - */ -PRBool -rdf_IsAnonymousResource(const nsCString& aContextURI, nsIRDFResource* aResource); - nsresult rdf_MakeRelativeRef(const nsString& aBaseURI, nsString& aURI); diff --git a/rdf/content/src/nsRDFXULBuilder.cpp b/rdf/content/src/nsRDFXULBuilder.cpp index 89c357a5b9a..ec83859195d 100644 --- a/rdf/content/src/nsRDFXULBuilder.cpp +++ b/rdf/content/src/nsRDFXULBuilder.cpp @@ -622,7 +622,7 @@ RDFXULBuilderImpl::CreateContents(nsIContent* aElement) NS_ASSERTION(NS_SUCCEEDED(rv), "unable to test contents-generated attribute"); if (NS_FAILED(rv)) return rv; - if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.EqualsIgnoreCase("true"))) + if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.Equals("true"))) return NS_OK; #ifdef PR_LOGGING @@ -902,7 +902,7 @@ RDFXULBuilderImpl::OnAssert(nsIRDFResource* aSource, if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE) continue; - if (! contentsGenerated.EqualsIgnoreCase("true")) + if (! contentsGenerated.Equals("true")) continue; // Okay, it's a "live" element, so go ahead and insert the @@ -1030,7 +1030,7 @@ RDFXULBuilderImpl::OnUnassert(nsIRDFResource* aSource, if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE) continue; - if (! contentsGenerated.EqualsIgnoreCase("true")) + if (! contentsGenerated.Equals("true")) continue; // Okay, it's a "live" element, so go ahead and remove the @@ -1155,7 +1155,7 @@ RDFXULBuilderImpl::OnChange(nsIRDFResource* aSource, if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE) continue; - if (! contentsGenerated.EqualsIgnoreCase("true")) + if (! contentsGenerated.Equals("true")) continue; // Okay, it's a "live" element, so go ahead and insert the @@ -1614,25 +1614,35 @@ RDFXULBuilderImpl::CreateHTMLElement(nsINameSpace* aContainingNameSpace, if (NS_FAILED(rv)) return rv; if (aResource) { - // Set the 'id' attribute - nsXPIDLCString uri; - rv = aResource->GetValue( getter_Copies(uri) ); +#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS + PRBool isAnonymous; + rv = gRDFService->IsAnonymousResource(aResource, &isAnonymous); if (NS_FAILED(rv)) return rv; - nsAutoString id; - rv = nsRDFContentUtils::MakeElementID(doc, nsAutoString(uri), id); - if (NS_FAILED(rv)) return rv; + if (! isAnonymous) { +#endif + // Set the 'id' attribute + nsXPIDLCString uri; + rv = aResource->GetValue( getter_Copies(uri) ); + if (NS_FAILED(rv)) return rv; + + nsAutoString id; + rv = nsRDFContentUtils::MakeElementID(doc, nsAutoString(uri), id); + if (NS_FAILED(rv)) return rv; - rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's ID"); - if (NS_FAILED(rv)) return rv; + rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE); + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's ID"); + if (NS_FAILED(rv)) return rv; - // Since we didn't notify when setting the 'id' attribute, we - // need to explicitly add ourselves to the resource-to-element - // map. XUL elements don't need to do this, because they've - // got a hacked SetAttribute() method... - rv = mDocument->AddElementForResource(aResource, element); - if (NS_FAILED(rv)) return rv; + // Since we didn't notify when setting the 'id' attribute, we + // need to explicitly add ourselves to the resource-to-element + // map. XUL elements don't need to do this, because they've + // got a hacked SetAttribute() method... + rv = mDocument->AddElementForResource(aResource, element); + if (NS_FAILED(rv)) return rv; +#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS + } +#endif // Now iterate through all the properties and add them as // attributes on the element. First, create a cursor that'll @@ -1785,26 +1795,36 @@ RDFXULBuilderImpl::CreateXULElement(nsINameSpace* aContainingNameSpace, if (NS_FAILED(rv)) return rv; if (aResource) { - // Set the element's ID. The XUL document will be listening - // for 'id' and 'ref' attribute changes, so we're sure that - // this will get properly hashed into the document's - // resource-to-element map. - nsXPIDLCString uri; - rv = aResource->GetValue( getter_Copies(uri) ); +#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS + PRBool isAnonymous; + rv = gRDFService->IsAnonymousResource(aResource, &isAnonymous); if (NS_FAILED(rv)) return rv; - nsAutoString id; - rv = nsRDFContentUtils::MakeElementID(document, nsAutoString(uri), id); - if (NS_FAILED(rv)) return rv; + if (! isAnonymous) { +#endif + // Set the element's ID. The XUL document will be listening + // for 'id' and 'ref' attribute changes, so we're sure that + // this will get properly hashed into the document's + // resource-to-element map. + nsXPIDLCString uri; + rv = aResource->GetValue( getter_Copies(uri) ); + if (NS_FAILED(rv)) return rv; - rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE); - if (NS_FAILED(rv)) return rv; + nsAutoString id; + rv = nsRDFContentUtils::MakeElementID(document, nsAutoString(uri), id); + if (NS_FAILED(rv)) return rv; - // The XUL element's implementation has a hacked - // SetAttribute() method that'll be smart enough to add the - // element to the document's element-to-resource map, so no - // need to do it ourselves. N.B. that this is _different_ from - // an HTML element... + rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE); + if (NS_FAILED(rv)) return rv; + + // The XUL element's implementation has a hacked + // SetAttribute() method that'll be smart enough to add the + // element to the document's element-to-resource map, so no + // need to do it ourselves. N.B. that this is _different_ from + // an HTML element... +#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS + } +#endif // Now iterate through all the properties and add them as // attributes on the element. First, create a cursor that'll diff --git a/rdf/datasource/src/nsXULContentSink.cpp b/rdf/datasource/src/nsXULContentSink.cpp index 224e0a3b9fd..e0e932f1f75 100644 --- a/rdf/datasource/src/nsXULContentSink.cpp +++ b/rdf/datasource/src/nsXULContentSink.cpp @@ -183,6 +183,7 @@ protected: static nsIRDFResource* kRDF_instanceOf; static nsIRDFResource* kXUL_element; static nsIRDFResource* kXUL_tag; + static nsIRDFResource* kPosition; // Text management nsresult FlushText(PRBool aCreateTextNode=PR_TRUE, @@ -274,6 +275,7 @@ nsIRDFResource* XULContentSinkImpl::kRDF_child; nsIRDFResource* XULContentSinkImpl::kRDF_instanceOf; nsIRDFResource* XULContentSinkImpl::kXUL_element; nsIRDFResource* XULContentSinkImpl::kXUL_tag; +nsIRDFResource* XULContentSinkImpl::kPosition; //////////////////////////////////////////////////////////////////////// @@ -316,6 +318,7 @@ XULContentSinkImpl::XULContentSinkImpl() gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_instanceOf); gRDFService->GetResource(XUL_NAMESPACE_URI "#element", &kXUL_element); gRDFService->GetResource(XUL_NAMESPACE_URI "#tag", &kXUL_tag); + gRDFService->GetResource("position", &kPosition); } } @@ -445,6 +448,7 @@ XULContentSinkImpl::~XULContentSinkImpl() NS_IF_RELEASE(kRDF_instanceOf); NS_IF_RELEASE(kXUL_tag); NS_IF_RELEASE(kXUL_element); + NS_IF_RELEASE(kPosition); } // Delete all the elements from our overlay array @@ -1274,7 +1278,7 @@ XULContentSinkImpl::GetXULIDAttribute(const nsIParserNode& aNode, // Otherwise, we couldn't find anything, so just gensym one... nsXPIDLCString url; mDocumentURL->GetSpec(getter_Copies(url)); - return rdf_CreateAnonymousResource(nsCAutoString(url), aResource); + return gRDFService->GetAnonymousResource(aResource); } nsresult @@ -1459,14 +1463,8 @@ XULContentSinkImpl::OpenTag(const nsIParserNode& aNode) // Find out if a position is specified. If so, we use that as the arc // label instead of appending the object to the end. // Add the attribute to RDF - nsCOMPtr property; - nsAutoString attr("#position"); - - rv = gRDFService->GetUnicodeResource(attr.GetUnicode(), getter_AddRefs(property)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr positionValue; - rv = mDataSource->GetTarget(rdfResource, property, PR_TRUE, getter_AddRefs(positionValue)); + rv = mDataSource->GetTarget(rdfResource, kPosition, PR_TRUE, getter_AddRefs(positionValue)); if (NS_FAILED(rv)) return rv; if (positionValue) {