content/xul/templates/src/nsXULTemplateQueryProcessorXML.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 "nsCOMPtr.h"
     7 #include "nsAutoPtr.h"
     8 #include "nsIDOMDocument.h"
     9 #include "nsIDOMNode.h"
    10 #include "nsIDOMElement.h"
    11 #include "nsIDOMEvent.h"
    12 #include "nsIDOMXPathNSResolver.h"
    13 #include "nsIDocument.h"
    14 #include "nsIContent.h"
    15 #include "nsComponentManagerUtils.h"
    16 #include "nsGkAtoms.h"
    17 #include "nsIURI.h"
    18 #include "nsIArray.h"
    19 #include "nsIScriptContext.h"
    20 #include "nsArrayUtils.h"
    21 #include "nsPIDOMWindow.h"
    22 #include "nsXULContentUtils.h"
    23 #include "nsXMLHttpRequest.h"
    25 #include "nsXULTemplateQueryProcessorXML.h"
    26 #include "nsXULTemplateResultXML.h"
    27 #include "nsXULSortService.h"
    29 using namespace mozilla::dom;
    31 NS_IMPL_ISUPPORTS(nsXMLQuery, nsXMLQuery)
    33 //----------------------------------------------------------------------
    34 //
    35 // nsXULTemplateResultSetXML
    36 //
    38 NS_IMPL_ISUPPORTS(nsXULTemplateResultSetXML, nsISimpleEnumerator)
    40 NS_IMETHODIMP
    41 nsXULTemplateResultSetXML::HasMoreElements(bool *aResult)
    42 {
    43     // if GetSnapshotLength failed, then the return type was not a set of
    44     // nodes, so just return false in this case.
    45     uint32_t length;
    46     if (NS_SUCCEEDED(mResults->GetSnapshotLength(&length)))
    47         *aResult = (mPosition < length);
    48     else
    49         *aResult = false;
    51     return NS_OK;
    52 }
    54 NS_IMETHODIMP
    55 nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
    56 {
    57     nsCOMPtr<nsIDOMNode> node;
    58     nsresult rv = mResults->SnapshotItem(mPosition, getter_AddRefs(node));
    59     NS_ENSURE_SUCCESS(rv, rv);
    61     nsXULTemplateResultXML* result =
    62         new nsXULTemplateResultXML(mQuery, node, mBindingSet);
    63     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
    65     ++mPosition;
    66     *aResult = result;
    67     NS_ADDREF(result);
    68     return NS_OK;
    69 }
    72 //----------------------------------------------------------------------
    73 //
    74 // nsXULTemplateQueryProcessorXML
    75 //
    77 static PLDHashOperator
    78 TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext)
    79 {
    80     nsCycleCollectionTraversalCallback *cb =
    81         static_cast<nsCycleCollectionTraversalCallback*>(aContext);
    82     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
    83     cb->NoteXPCOMChild(aKey);
    84     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
    85     cb->NoteNativeChild(aMatch, NS_CYCLE_COLLECTION_PARTICIPANT(nsXMLBindingSet));
    86     return PL_DHASH_NEXT;
    87 }
    89 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
    91 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
    92     tmp->mRuleToBindingsMap.Clear();
    93     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
    94     NS_IMPL_CYCLE_COLLECTION_UNLINK(mEvaluator)
    95     NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateBuilder)
    96     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
    97 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    98 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
    99     tmp->mRuleToBindingsMap.EnumerateRead(TraverseRuleToBindingsMap, &cb);
   100     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
   101     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvaluator)
   102     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateBuilder)
   103     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
   104 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   105 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateQueryProcessorXML)
   106 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateQueryProcessorXML)
   107 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorXML)
   108     NS_INTERFACE_MAP_ENTRY(nsIXULTemplateQueryProcessor)
   109     NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   110     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
   111 NS_INTERFACE_MAP_END
   113 /*
   114  * Only the first datasource in aDataSource is used, which should be either an
   115  * nsIURI of an XML document, or a DOM node. If the former, GetDatasource will
   116  * load the document asynchronously and return null in aResult. Once the
   117  * document has loaded, the builder's datasource will be set to the XML
   118  * document. If the datasource is a DOM node, the node will be returned in
   119  * aResult.
   120  */
   121 NS_IMETHODIMP
   122 nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
   123                                               nsIDOMNode* aRootNode,
   124                                               bool aIsTrusted,
   125                                               nsIXULTemplateBuilder* aBuilder,
   126                                               bool* aShouldDelayBuilding,
   127                                               nsISupports** aResult)
   128 {
   129     *aResult = nullptr;
   130     *aShouldDelayBuilding = false;
   132     nsresult rv;
   133     uint32_t length;
   135     aDataSources->GetLength(&length);
   136     if (length == 0)
   137         return NS_OK;
   139     // we get only the first item, because the query processor supports only
   140     // one document as a datasource
   142     nsCOMPtr<nsIDOMNode> node = do_QueryElementAt(aDataSources, 0);
   143     if (node) {
   144         return CallQueryInterface(node, aResult);
   145     }
   147     nsCOMPtr<nsIURI> uri = do_QueryElementAt(aDataSources, 0);
   148     if (!uri)
   149         return NS_ERROR_UNEXPECTED;
   151     nsAutoCString uriStr;
   152     rv = uri->GetSpec(uriStr);
   153     NS_ENSURE_SUCCESS(rv, rv);
   155     nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
   156     if (!root)
   157         return NS_ERROR_UNEXPECTED;
   159     nsCOMPtr<nsIDocument> doc = root->GetCurrentDoc();
   160     if (!doc)
   161         return NS_ERROR_UNEXPECTED;
   163     nsIPrincipal *docPrincipal = doc->NodePrincipal();
   165     bool hasHadScriptObject = true;
   166     nsIScriptGlobalObject* scriptObject =
   167       doc->GetScriptHandlingObject(hasHadScriptObject);
   168     NS_ENSURE_STATE(scriptObject);
   170     nsIScriptContext *context = scriptObject->GetContext();
   171     NS_ENSURE_TRUE(context, NS_OK);
   173     nsCOMPtr<nsIXMLHttpRequest> req =
   174         do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
   175     NS_ENSURE_SUCCESS(rv, rv);
   177     rv = req->Init(docPrincipal, context,
   178                    scriptObject ? scriptObject : doc->GetScopeObject(),
   179                    nullptr);
   180     NS_ENSURE_SUCCESS(rv, rv);
   182     rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, true,
   183                    EmptyString(), EmptyString());
   184     NS_ENSURE_SUCCESS(rv, rv);
   186     nsCOMPtr<EventTarget> target(do_QueryInterface(req));
   187     rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
   188     NS_ENSURE_SUCCESS(rv, rv);
   190     rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, false);
   191     NS_ENSURE_SUCCESS(rv, rv);
   193     rv = req->Send(nullptr);
   194     NS_ENSURE_SUCCESS(rv, rv);
   196     mTemplateBuilder = aBuilder;
   197     mRequest = req;
   199     *aShouldDelayBuilding = true;
   200     return NS_OK;
   201 }
   203 NS_IMETHODIMP
   204 nsXULTemplateQueryProcessorXML::InitializeForBuilding(nsISupports* aDatasource,
   205                                                       nsIXULTemplateBuilder* aBuilder,
   206                                                       nsIDOMNode* aRootNode)
   207 {
   208     if (mGenerationStarted)
   209         return NS_ERROR_UNEXPECTED;
   211     // the datasource is either a document or a DOM element
   212     nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
   213     if (doc)
   214         doc->GetDocumentElement(getter_AddRefs(mRoot));
   215     else
   216       mRoot = do_QueryInterface(aDatasource);
   217     NS_ENSURE_STATE(mRoot);
   219     mEvaluator = do_CreateInstance("@mozilla.org/dom/xpath-evaluator;1");
   220     NS_ENSURE_TRUE(mEvaluator, NS_ERROR_OUT_OF_MEMORY);
   222     return NS_OK;
   223 }
   225 NS_IMETHODIMP
   226 nsXULTemplateQueryProcessorXML::Done()
   227 {
   228     mGenerationStarted = false;
   230     mRuleToBindingsMap.Clear();
   232     return NS_OK;
   233 }
   235 NS_IMETHODIMP
   236 nsXULTemplateQueryProcessorXML::CompileQuery(nsIXULTemplateBuilder* aBuilder,
   237                                              nsIDOMNode* aQueryNode,
   238                                              nsIAtom* aRefVariable,
   239                                              nsIAtom* aMemberVariable,
   240                                              nsISupports** _retval)
   241 {
   242     nsresult rv = NS_OK;
   244     *_retval = nullptr;
   246     nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
   248     nsAutoString expr;
   249     content->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
   251     // if an expression is not specified, then the default is to
   252     // just take all of the children
   253     if (expr.IsEmpty())
   254         expr.AssignLiteral("*");
   256     nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
   257     rv = CreateExpression(expr, aQueryNode, getter_AddRefs(compiledexpr));
   258     if (NS_FAILED(rv)) {
   259         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_XPATH);
   260         return rv;
   261     }
   263     nsRefPtr<nsXMLQuery> query =
   264         new nsXMLQuery(this, aMemberVariable, compiledexpr);
   265     NS_ENSURE_TRUE(query, NS_ERROR_OUT_OF_MEMORY);
   267     for (nsIContent* condition = content->GetFirstChild();
   268          condition;
   269          condition = condition->GetNextSibling()) {
   271         if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
   272                                           kNameSpaceID_XUL)) {
   273             nsAutoString var;
   274             condition->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
   276             nsAutoString expr;
   277             condition->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
   279             // ignore assignments without a variable or an expression
   280             if (!var.IsEmpty() && !expr.IsEmpty()) {
   281                 nsCOMPtr<nsIDOMNode> conditionNode =
   282                     do_QueryInterface(condition);
   283                 rv = CreateExpression(expr, conditionNode,
   284                                       getter_AddRefs(compiledexpr));
   285                 if (NS_FAILED(rv)) {
   286                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
   287                     return rv;
   288                 }
   290                 nsCOMPtr<nsIAtom> varatom = do_GetAtom(var);
   292                 rv = query->AddBinding(varatom, compiledexpr);
   293                 NS_ENSURE_SUCCESS(rv, rv);
   294             }
   295         }
   296     }
   298     *_retval = query;
   299     NS_ADDREF(*_retval);
   301     return rv;
   302 }
   304 NS_IMETHODIMP
   305 nsXULTemplateQueryProcessorXML::GenerateResults(nsISupports* aDatasource,
   306                                                 nsIXULTemplateResult* aRef,
   307                                                 nsISupports* aQuery,
   308                                                 nsISimpleEnumerator** aResults)
   309 {
   310     if (!aQuery)
   311         return NS_ERROR_INVALID_ARG;
   313     mGenerationStarted = true;
   315     nsCOMPtr<nsXMLQuery> xmlquery = do_QueryInterface(aQuery);
   316     if (!xmlquery)
   317         return NS_ERROR_INVALID_ARG;
   319     nsCOMPtr<nsISupports> supports;
   320     nsCOMPtr<nsIDOMNode> context;
   321     if (aRef)
   322       aRef->GetBindingObjectFor(xmlquery->GetMemberVariable(),
   323                                 getter_AddRefs(supports));
   324     context = do_QueryInterface(supports);
   325     if (!context)
   326         context = mRoot;
   328     nsIDOMXPathExpression* expr = xmlquery->GetResultsExpression();
   329     if (!expr)
   330         return NS_ERROR_FAILURE;
   332     nsCOMPtr<nsISupports> exprsupportsresults;
   333     nsresult rv = expr->Evaluate(context,
   334                                  nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
   335                                  nullptr, getter_AddRefs(exprsupportsresults));
   336     NS_ENSURE_SUCCESS(rv, rv);
   338     nsCOMPtr<nsIDOMXPathResult> exprresults =
   339         do_QueryInterface(exprsupportsresults);
   341     nsXULTemplateResultSetXML* results =
   342         new nsXULTemplateResultSetXML(xmlquery, exprresults,
   343                                       xmlquery->GetBindingSet());
   344     NS_ENSURE_TRUE(results, NS_ERROR_OUT_OF_MEMORY);
   346     *aResults = results;
   347     NS_ADDREF(*aResults);
   349     return NS_OK;
   350 }
   352 NS_IMETHODIMP
   353 nsXULTemplateQueryProcessorXML::AddBinding(nsIDOMNode* aRuleNode,
   354                                            nsIAtom* aVar,
   355                                            nsIAtom* aRef,
   356                                            const nsAString& aExpr)
   357 {
   358     if (mGenerationStarted)
   359         return NS_ERROR_FAILURE;
   361     nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
   362     if (!bindings) {
   363         bindings = new nsXMLBindingSet();
   364         mRuleToBindingsMap.Put(aRuleNode, bindings);
   365     }
   367     nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
   368     nsresult rv =
   369         CreateExpression(aExpr, aRuleNode, getter_AddRefs(compiledexpr));
   370     if (NS_FAILED(rv)) {
   371         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH);
   372         return NS_OK;
   373     }
   375     // aRef isn't currently used for XML query processors
   376     return bindings->AddBinding(aVar, compiledexpr);
   377 }
   379 NS_IMETHODIMP
   380 nsXULTemplateQueryProcessorXML::TranslateRef(nsISupports* aDatasource,
   381                                              const nsAString& aRefString,
   382                                              nsIXULTemplateResult** aRef)
   383 {
   384     *aRef = nullptr;
   386     // the datasource is either a document or a DOM element
   387     nsCOMPtr<nsIDOMElement> rootElement;
   388     nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
   389     if (doc)
   390         doc->GetDocumentElement(getter_AddRefs(rootElement));
   391     else
   392         rootElement = do_QueryInterface(aDatasource);
   394     // if no root element, just return. The document may not have loaded yet
   395     if (!rootElement)
   396         return NS_OK;
   398     nsXULTemplateResultXML* result =
   399         new nsXULTemplateResultXML(nullptr, rootElement, nullptr);
   400     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
   402     *aRef = result;
   403     NS_ADDREF(*aRef);
   405     return NS_OK;
   406 }
   409 NS_IMETHODIMP
   410 nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
   411                                                nsIXULTemplateResult* aRight,
   412                                                nsIAtom* aVar,
   413                                                uint32_t aSortHints,
   414                                                int32_t* aResult)
   415 {
   416     *aResult = 0;
   417     if (!aVar)
   418         return NS_OK;
   420     nsAutoString leftVal;
   421     if (aLeft)
   422         aLeft->GetBindingFor(aVar, leftVal);
   424     nsAutoString rightVal;
   425     if (aRight)
   426         aRight->GetBindingFor(aVar, rightVal);
   428     *aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
   429     return NS_OK;
   430 }
   432 nsXMLBindingSet*
   433 nsXULTemplateQueryProcessorXML::GetOptionalBindingsForRule(nsIDOMNode* aRuleNode)
   434 {
   435     return mRuleToBindingsMap.GetWeak(aRuleNode);
   436 }
   438 nsresult
   439 nsXULTemplateQueryProcessorXML::CreateExpression(const nsAString& aExpr,
   440                                                  nsIDOMNode* aNode,
   441                                                  nsIDOMXPathExpression** aCompiledExpr)
   442 {
   443     nsCOMPtr<nsIDOMXPathNSResolver> nsResolver;
   445     nsCOMPtr<nsIDOMDocument> doc;
   446     aNode->GetOwnerDocument(getter_AddRefs(doc));
   448     nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
   449     if (eval) {
   450         nsresult rv =
   451              eval->CreateNSResolver(aNode, getter_AddRefs(nsResolver));
   452         NS_ENSURE_SUCCESS(rv, rv);
   453     }
   455     return mEvaluator->CreateExpression(aExpr, nsResolver, aCompiledExpr);
   456 }
   458 NS_IMETHODIMP
   459 nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
   460 {
   461     NS_PRECONDITION(aEvent, "aEvent null");
   462     nsAutoString eventType;
   463     aEvent->GetType(eventType);
   465     if (eventType.EqualsLiteral("load") && mTemplateBuilder) {
   466         NS_ASSERTION(mRequest, "request was not set");
   467         nsCOMPtr<nsIDOMDocument> doc;
   468         if (NS_SUCCEEDED(mRequest->GetResponseXML(getter_AddRefs(doc))))
   469             mTemplateBuilder->SetDatasource(doc);
   471         // to avoid leak. we don't need it after...
   472         mTemplateBuilder = nullptr;
   473         mRequest = nullptr;
   474     }
   475     else if (eventType.EqualsLiteral("error")) {
   476         mTemplateBuilder = nullptr;
   477         mRequest = nullptr;
   478     }
   480     return NS_OK;
   481 }

mercurial