content/xul/templates/src/nsRDFConMemberTestNode.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsRDFConMemberTestNode.h"
michael@0 7 #include "nsIRDFContainer.h"
michael@0 8 #include "nsIRDFContainerUtils.h"
michael@0 9 #include "nsRDFCID.h"
michael@0 10 #include "nsIServiceManager.h"
michael@0 11 #include "nsResourceSet.h"
michael@0 12 #include "nsString.h"
michael@0 13 #include "nsXULContentUtils.h"
michael@0 14
michael@0 15 #include "prlog.h"
michael@0 16 #ifdef PR_LOGGING
michael@0 17 extern PRLogModuleInfo* gXULTemplateLog;
michael@0 18 #endif
michael@0 19
michael@0 20 nsRDFConMemberTestNode::nsRDFConMemberTestNode(TestNode* aParent,
michael@0 21 nsXULTemplateQueryProcessorRDF* aProcessor,
michael@0 22 nsIAtom *aContainerVariable,
michael@0 23 nsIAtom *aMemberVariable)
michael@0 24 : nsRDFTestNode(aParent),
michael@0 25 mProcessor(aProcessor),
michael@0 26 mContainerVariable(aContainerVariable),
michael@0 27 mMemberVariable(aMemberVariable)
michael@0 28 {
michael@0 29 #ifdef PR_LOGGING
michael@0 30 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 31 nsAutoCString props;
michael@0 32
michael@0 33 nsResourceSet& containmentProps = aProcessor->ContainmentProperties();
michael@0 34 nsResourceSet::ConstIterator last = containmentProps.Last();
michael@0 35 nsResourceSet::ConstIterator first = containmentProps.First();
michael@0 36 nsResourceSet::ConstIterator iter;
michael@0 37
michael@0 38 for (iter = first; iter != last; ++iter) {
michael@0 39 if (iter != first)
michael@0 40 props += " ";
michael@0 41
michael@0 42 const char* str;
michael@0 43 iter->GetValueConst(&str);
michael@0 44
michael@0 45 props += str;
michael@0 46 }
michael@0 47
michael@0 48 nsAutoString cvar(NS_LITERAL_STRING("(none)"));
michael@0 49 if (mContainerVariable)
michael@0 50 mContainerVariable->ToString(cvar);
michael@0 51
michael@0 52 nsAutoString mvar(NS_LITERAL_STRING("(none)"));
michael@0 53 if (mMemberVariable)
michael@0 54 mMemberVariable->ToString(mvar);
michael@0 55
michael@0 56 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 57 ("nsRDFConMemberTestNode[%p]: parent=%p member-props=(%s) container-var=%s member-var=%s",
michael@0 58 this,
michael@0 59 aParent,
michael@0 60 props.get(),
michael@0 61 NS_ConvertUTF16toUTF8(cvar).get(),
michael@0 62 NS_ConvertUTF16toUTF8(mvar).get()));
michael@0 63 }
michael@0 64 #endif
michael@0 65 }
michael@0 66
michael@0 67 nsresult
michael@0 68 nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
michael@0 69 bool* aCantHandleYet) const
michael@0 70 {
michael@0 71 // XXX Uh, factor me, please!
michael@0 72 nsresult rv;
michael@0 73
michael@0 74 if (aCantHandleYet)
michael@0 75 *aCantHandleYet = false;
michael@0 76
michael@0 77 nsCOMPtr<nsIRDFContainerUtils> rdfc =
michael@0 78 do_GetService("@mozilla.org/rdf/container-utils;1");
michael@0 79
michael@0 80 if (! rdfc)
michael@0 81 return NS_ERROR_FAILURE;
michael@0 82
michael@0 83 nsIRDFDataSource* ds = mProcessor->GetDataSource();
michael@0 84
michael@0 85 InstantiationSet::Iterator last = aInstantiations.Last();
michael@0 86 for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
michael@0 87 bool hasContainerBinding;
michael@0 88 nsCOMPtr<nsIRDFNode> containerValue;
michael@0 89 hasContainerBinding = inst->mAssignments.GetAssignmentFor(mContainerVariable,
michael@0 90 getter_AddRefs(containerValue));
michael@0 91
michael@0 92 nsCOMPtr<nsIRDFResource> containerRes = do_QueryInterface(containerValue);
michael@0 93
michael@0 94 nsCOMPtr<nsIRDFContainer> rdfcontainer;
michael@0 95
michael@0 96 if (hasContainerBinding && containerRes) {
michael@0 97 // If we have a container assignment, then see if the
michael@0 98 // container is an RDF container (bag, seq, alt), and if
michael@0 99 // so, wrap it.
michael@0 100 bool isRDFContainer;
michael@0 101 rv = rdfc->IsContainer(ds, containerRes, &isRDFContainer);
michael@0 102 if (NS_FAILED(rv)) return rv;
michael@0 103
michael@0 104 if (isRDFContainer) {
michael@0 105 rdfcontainer = do_CreateInstance("@mozilla.org/rdf/container;1", &rv);
michael@0 106 if (NS_FAILED(rv)) return rv;
michael@0 107
michael@0 108 rv = rdfcontainer->Init(ds, containerRes);
michael@0 109 if (NS_FAILED(rv)) return rv;
michael@0 110 }
michael@0 111 }
michael@0 112
michael@0 113 bool hasMemberBinding;
michael@0 114 nsCOMPtr<nsIRDFNode> memberValue;
michael@0 115 hasMemberBinding = inst->mAssignments.GetAssignmentFor(mMemberVariable,
michael@0 116 getter_AddRefs(memberValue));
michael@0 117
michael@0 118 #ifdef PR_LOGGING
michael@0 119 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 120 const char* container = "(unbound)";
michael@0 121 if (hasContainerBinding)
michael@0 122 containerRes->GetValueConst(&container);
michael@0 123
michael@0 124 nsAutoString member(NS_LITERAL_STRING("(unbound)"));
michael@0 125 if (hasMemberBinding)
michael@0 126 nsXULContentUtils::GetTextForNode(memberValue, member);
michael@0 127
michael@0 128 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 129 ("nsRDFConMemberTestNode[%p]: FilterInstantiations() container=[%s] member=[%s]",
michael@0 130 this, container, NS_ConvertUTF16toUTF8(member).get()));
michael@0 131 }
michael@0 132 #endif
michael@0 133
michael@0 134 if (hasContainerBinding && hasMemberBinding) {
michael@0 135 // it's a consistency check. see if we have a assignment that is consistent
michael@0 136 bool isconsistent = false;
michael@0 137
michael@0 138 if (rdfcontainer) {
michael@0 139 // RDF containers are easy. Just use the container API.
michael@0 140 int32_t index;
michael@0 141 rv = rdfcontainer->IndexOf(memberValue, &index);
michael@0 142 if (NS_FAILED(rv)) return rv;
michael@0 143
michael@0 144 if (index >= 0)
michael@0 145 isconsistent = true;
michael@0 146 }
michael@0 147
michael@0 148 // XXXwaterson oof. if we *are* an RDF container, why do
michael@0 149 // we still need to grovel through all the containment
michael@0 150 // properties if the thing we're looking for wasn't there?
michael@0 151
michael@0 152 if (! isconsistent) {
michael@0 153 // Othewise, we'll need to grovel through the
michael@0 154 // membership properties to see if we have an
michael@0 155 // assertion that indicates membership.
michael@0 156 nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
michael@0 157 for (nsResourceSet::ConstIterator property = containmentProps.First();
michael@0 158 property != containmentProps.Last();
michael@0 159 ++property) {
michael@0 160 bool hasAssertion;
michael@0 161 rv = ds->HasAssertion(containerRes,
michael@0 162 *property,
michael@0 163 memberValue,
michael@0 164 true,
michael@0 165 &hasAssertion);
michael@0 166 if (NS_FAILED(rv)) return rv;
michael@0 167
michael@0 168 if (hasAssertion) {
michael@0 169 // it's consistent. leave it in the set and we'll
michael@0 170 // run it up to our parent.
michael@0 171 isconsistent = true;
michael@0 172 break;
michael@0 173 }
michael@0 174 }
michael@0 175 }
michael@0 176
michael@0 177 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 178 (" consistency check => %s", isconsistent ? "passed" : "failed"));
michael@0 179
michael@0 180 if (isconsistent) {
michael@0 181 // Add a memory element to our set-of-support.
michael@0 182 Element* element =
michael@0 183 new nsRDFConMemberTestNode::Element(containerRes,
michael@0 184 memberValue);
michael@0 185
michael@0 186 if (! element)
michael@0 187 return NS_ERROR_OUT_OF_MEMORY;
michael@0 188
michael@0 189 inst->AddSupportingElement(element);
michael@0 190 }
michael@0 191 else {
michael@0 192 // it's inconsistent. remove it.
michael@0 193 aInstantiations.Erase(inst--);
michael@0 194 }
michael@0 195
michael@0 196 // We're done, go on to the next instantiation
michael@0 197 continue;
michael@0 198 }
michael@0 199
michael@0 200 if (hasContainerBinding && rdfcontainer) {
michael@0 201 // We've got a container assignment, and the container is
michael@0 202 // bound to an RDF container. Add each member as a new
michael@0 203 // instantiation.
michael@0 204 nsCOMPtr<nsISimpleEnumerator> elements;
michael@0 205 rv = rdfcontainer->GetElements(getter_AddRefs(elements));
michael@0 206 if (NS_FAILED(rv)) return rv;
michael@0 207
michael@0 208 while (1) {
michael@0 209 bool hasmore;
michael@0 210 rv = elements->HasMoreElements(&hasmore);
michael@0 211 if (NS_FAILED(rv)) return rv;
michael@0 212
michael@0 213 if (! hasmore)
michael@0 214 break;
michael@0 215
michael@0 216 nsCOMPtr<nsISupports> isupports;
michael@0 217 rv = elements->GetNext(getter_AddRefs(isupports));
michael@0 218 if (NS_FAILED(rv)) return rv;
michael@0 219
michael@0 220 nsCOMPtr<nsIRDFNode> node = do_QueryInterface(isupports);
michael@0 221 if (! node)
michael@0 222 return NS_ERROR_UNEXPECTED;
michael@0 223
michael@0 224 #ifdef PR_LOGGING
michael@0 225 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 226 nsAutoString member;
michael@0 227 nsXULContentUtils::GetTextForNode(node, member);
michael@0 228
michael@0 229 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 230 (" member => %s", NS_ConvertUTF16toUTF8(member).get()));
michael@0 231 }
michael@0 232 #endif
michael@0 233
michael@0 234 Instantiation newinst = *inst;
michael@0 235 newinst.AddAssignment(mMemberVariable, node);
michael@0 236
michael@0 237 Element* element =
michael@0 238 new nsRDFConMemberTestNode::Element(containerRes, node);
michael@0 239
michael@0 240 if (! element)
michael@0 241 return NS_ERROR_OUT_OF_MEMORY;
michael@0 242
michael@0 243 newinst.AddSupportingElement(element);
michael@0 244 aInstantiations.Insert(inst, newinst);
michael@0 245 }
michael@0 246 }
michael@0 247
michael@0 248 if (hasMemberBinding) {
michael@0 249 // Oh, this is so nasty. If we have a member assignment, then
michael@0 250 // grovel through each one of our inbound arcs to see if
michael@0 251 // any of them are ordinal properties (like an RDF
michael@0 252 // container might have). If so, walk it backwards to get
michael@0 253 // the container we're in.
michael@0 254 nsCOMPtr<nsISimpleEnumerator> arcsin;
michael@0 255 rv = ds->ArcLabelsIn(memberValue, getter_AddRefs(arcsin));
michael@0 256 if (NS_FAILED(rv)) return rv;
michael@0 257
michael@0 258 while (1) {
michael@0 259 nsCOMPtr<nsIRDFResource> property;
michael@0 260
michael@0 261 {
michael@0 262 bool hasmore;
michael@0 263 rv = arcsin->HasMoreElements(&hasmore);
michael@0 264 if (NS_FAILED(rv)) return rv;
michael@0 265
michael@0 266 if (! hasmore)
michael@0 267 break;
michael@0 268
michael@0 269 nsCOMPtr<nsISupports> isupports;
michael@0 270 rv = arcsin->GetNext(getter_AddRefs(isupports));
michael@0 271 if (NS_FAILED(rv)) return rv;
michael@0 272
michael@0 273 property = do_QueryInterface(isupports);
michael@0 274 if (! property)
michael@0 275 return NS_ERROR_UNEXPECTED;
michael@0 276 }
michael@0 277
michael@0 278 // Ordinal properties automagically indicate container
michael@0 279 // membership as far as we're concerned. Note that
michael@0 280 // we're *only* concerned with ordinal properties
michael@0 281 // here: the next block will worry about the other
michael@0 282 // membership properties.
michael@0 283 bool isordinal;
michael@0 284 rv = rdfc->IsOrdinalProperty(property, &isordinal);
michael@0 285 if (NS_FAILED(rv)) return rv;
michael@0 286
michael@0 287 if (isordinal) {
michael@0 288 // If we get here, we've found a property that
michael@0 289 // indicates container membership leading *into* a
michael@0 290 // member node. Find all the people that point to
michael@0 291 // it, and call them containers.
michael@0 292 nsCOMPtr<nsISimpleEnumerator> sources;
michael@0 293 rv = ds->GetSources(property, memberValue, true,
michael@0 294 getter_AddRefs(sources));
michael@0 295 if (NS_FAILED(rv)) return rv;
michael@0 296
michael@0 297 while (1) {
michael@0 298 bool hasmore;
michael@0 299 rv = sources->HasMoreElements(&hasmore);
michael@0 300 if (NS_FAILED(rv)) return rv;
michael@0 301
michael@0 302 if (! hasmore)
michael@0 303 break;
michael@0 304
michael@0 305 nsCOMPtr<nsISupports> isupports;
michael@0 306 rv = sources->GetNext(getter_AddRefs(isupports));
michael@0 307 if (NS_FAILED(rv)) return rv;
michael@0 308
michael@0 309 nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports);
michael@0 310 if (! source)
michael@0 311 return NS_ERROR_UNEXPECTED;
michael@0 312
michael@0 313 #ifdef PR_LOGGING
michael@0 314 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 315 const char* container;
michael@0 316 source->GetValueConst(&container);
michael@0 317
michael@0 318 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 319 (" container => %s", container));
michael@0 320 }
michael@0 321 #endif
michael@0 322
michael@0 323 // Add a new instantiation
michael@0 324 Instantiation newinst = *inst;
michael@0 325 newinst.AddAssignment(mContainerVariable, source);
michael@0 326
michael@0 327 Element* element =
michael@0 328 new nsRDFConMemberTestNode::Element(source,
michael@0 329 memberValue);
michael@0 330
michael@0 331 if (! element)
michael@0 332 return NS_ERROR_OUT_OF_MEMORY;
michael@0 333
michael@0 334 newinst.AddSupportingElement(element);
michael@0 335
michael@0 336 aInstantiations.Insert(inst, newinst);
michael@0 337 }
michael@0 338 }
michael@0 339 }
michael@0 340 }
michael@0 341
michael@0 342 if ((hasContainerBinding && ! hasMemberBinding) ||
michael@0 343 (! hasContainerBinding && hasMemberBinding)) {
michael@0 344 // it's an open ended query on the container or member. go
michael@0 345 // through our containment properties to see if anything
michael@0 346 // applies.
michael@0 347 nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
michael@0 348 for (nsResourceSet::ConstIterator property = containmentProps.First();
michael@0 349 property != containmentProps.Last();
michael@0 350 ++property) {
michael@0 351 nsCOMPtr<nsISimpleEnumerator> results;
michael@0 352 if (hasContainerBinding) {
michael@0 353 rv = ds->GetTargets(containerRes, *property, true,
michael@0 354 getter_AddRefs(results));
michael@0 355 }
michael@0 356 else {
michael@0 357 rv = ds->GetSources(*property, memberValue, true,
michael@0 358 getter_AddRefs(results));
michael@0 359 }
michael@0 360 if (NS_FAILED(rv)) return rv;
michael@0 361
michael@0 362 while (1) {
michael@0 363 bool hasmore;
michael@0 364 rv = results->HasMoreElements(&hasmore);
michael@0 365 if (NS_FAILED(rv)) return rv;
michael@0 366
michael@0 367 if (! hasmore)
michael@0 368 break;
michael@0 369
michael@0 370 nsCOMPtr<nsISupports> isupports;
michael@0 371 rv = results->GetNext(getter_AddRefs(isupports));
michael@0 372 if (NS_FAILED(rv)) return rv;
michael@0 373
michael@0 374 nsIAtom* variable;
michael@0 375 nsCOMPtr<nsIRDFNode> value;
michael@0 376 nsCOMPtr<nsIRDFResource> valueRes;
michael@0 377
michael@0 378 if (hasContainerBinding) {
michael@0 379 variable = mMemberVariable;
michael@0 380
michael@0 381 value = do_QueryInterface(isupports);
michael@0 382 NS_ASSERTION(value != nullptr, "member is not an nsIRDFNode");
michael@0 383 if (! value) continue;
michael@0 384
michael@0 385 #ifdef PR_LOGGING
michael@0 386 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 387 nsAutoString s;
michael@0 388 nsXULContentUtils::GetTextForNode(value, s);
michael@0 389
michael@0 390 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 391 (" member => %s", NS_ConvertUTF16toUTF8(s).get()));
michael@0 392 }
michael@0 393 #endif
michael@0 394 }
michael@0 395 else {
michael@0 396 variable = mContainerVariable;
michael@0 397
michael@0 398 valueRes = do_QueryInterface(isupports);
michael@0 399 NS_ASSERTION(valueRes != nullptr, "container is not an nsIRDFResource");
michael@0 400 if (! valueRes) continue;
michael@0 401
michael@0 402 value = valueRes;
michael@0 403
michael@0 404 #ifdef PR_LOGGING
michael@0 405 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 406 const char* s;
michael@0 407 valueRes->GetValueConst(&s);
michael@0 408
michael@0 409 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 410 (" container => %s", s));
michael@0 411 }
michael@0 412 #endif
michael@0 413 }
michael@0 414
michael@0 415 // Copy the original instantiation, and add it to the
michael@0 416 // instantiation set with the new assignment that we've
michael@0 417 // introduced. Ownership will be transferred to the
michael@0 418 Instantiation newinst = *inst;
michael@0 419 newinst.AddAssignment(variable, value);
michael@0 420
michael@0 421 Element* element;
michael@0 422 if (hasContainerBinding) {
michael@0 423 element =
michael@0 424 new nsRDFConMemberTestNode::Element(containerRes, value);
michael@0 425 }
michael@0 426 else {
michael@0 427 element =
michael@0 428 new nsRDFConMemberTestNode::Element(valueRes, memberValue);
michael@0 429 }
michael@0 430
michael@0 431 if (! element)
michael@0 432 return NS_ERROR_OUT_OF_MEMORY;
michael@0 433
michael@0 434 newinst.AddSupportingElement(element);
michael@0 435
michael@0 436 aInstantiations.Insert(inst, newinst);
michael@0 437 }
michael@0 438 }
michael@0 439 }
michael@0 440
michael@0 441 if (! hasContainerBinding && ! hasMemberBinding) {
michael@0 442 // Neither container nor member assignment!
michael@0 443 if (!aCantHandleYet) {
michael@0 444 nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_MEMBER_UNBOUND);
michael@0 445 return NS_ERROR_UNEXPECTED;
michael@0 446 }
michael@0 447
michael@0 448 *aCantHandleYet = true;
michael@0 449 return NS_OK;
michael@0 450 }
michael@0 451
michael@0 452 // finally, remove the "under specified" instantiation.
michael@0 453 aInstantiations.Erase(inst--);
michael@0 454 }
michael@0 455
michael@0 456 return NS_OK;
michael@0 457 }
michael@0 458
michael@0 459 bool
michael@0 460 nsRDFConMemberTestNode::CanPropagate(nsIRDFResource* aSource,
michael@0 461 nsIRDFResource* aProperty,
michael@0 462 nsIRDFNode* aTarget,
michael@0 463 Instantiation& aInitialBindings) const
michael@0 464 {
michael@0 465 nsresult rv;
michael@0 466
michael@0 467 bool canpropagate = false;
michael@0 468
michael@0 469 nsCOMPtr<nsIRDFContainerUtils> rdfc =
michael@0 470 do_GetService("@mozilla.org/rdf/container-utils;1");
michael@0 471
michael@0 472 if (! rdfc)
michael@0 473 return false;
michael@0 474
michael@0 475 // We can certainly propagate ordinal properties
michael@0 476 rv = rdfc->IsOrdinalProperty(aProperty, &canpropagate);
michael@0 477 if (NS_FAILED(rv)) return false;
michael@0 478
michael@0 479 if (! canpropagate) {
michael@0 480 canpropagate = mProcessor->ContainmentProperties().Contains(aProperty);
michael@0 481 }
michael@0 482
michael@0 483 #ifdef PR_LOGGING
michael@0 484 if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
michael@0 485 const char* source;
michael@0 486 aSource->GetValueConst(&source);
michael@0 487
michael@0 488 const char* property;
michael@0 489 aProperty->GetValueConst(&property);
michael@0 490
michael@0 491 nsAutoString target;
michael@0 492 nsXULContentUtils::GetTextForNode(aTarget, target);
michael@0 493
michael@0 494 PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
michael@0 495 ("nsRDFConMemberTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
michael@0 496 this, source, property, NS_ConvertUTF16toUTF8(target).get(),
michael@0 497 canpropagate ? "true" : "false"));
michael@0 498 }
michael@0 499 #endif
michael@0 500
michael@0 501 if (canpropagate) {
michael@0 502 aInitialBindings.AddAssignment(mContainerVariable, aSource);
michael@0 503 aInitialBindings.AddAssignment(mMemberVariable, aTarget);
michael@0 504 return true;
michael@0 505 }
michael@0 506
michael@0 507 return false;
michael@0 508 }
michael@0 509
michael@0 510 void
michael@0 511 nsRDFConMemberTestNode::Retract(nsIRDFResource* aSource,
michael@0 512 nsIRDFResource* aProperty,
michael@0 513 nsIRDFNode* aTarget) const
michael@0 514 {
michael@0 515 bool canretract = false;
michael@0 516
michael@0 517 nsCOMPtr<nsIRDFContainerUtils> rdfc =
michael@0 518 do_GetService("@mozilla.org/rdf/container-utils;1");
michael@0 519
michael@0 520 if (! rdfc)
michael@0 521 return;
michael@0 522
michael@0 523 // We can certainly retract ordinal properties
michael@0 524 nsresult rv;
michael@0 525 rv = rdfc->IsOrdinalProperty(aProperty, &canretract);
michael@0 526 if (NS_FAILED(rv)) return;
michael@0 527
michael@0 528 if (! canretract) {
michael@0 529 canretract = mProcessor->ContainmentProperties().Contains(aProperty);
michael@0 530 }
michael@0 531
michael@0 532 if (canretract) {
michael@0 533 mProcessor->RetractElement(Element(aSource, aTarget));
michael@0 534 }
michael@0 535 }

mercurial