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.

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

mercurial