Sat, 03 Jan 2015 20:18:00 +0100
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 }