Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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 "mozilla/dom/XPathEvaluator.h"
7 #include "nsCOMPtr.h"
8 #include "nsIAtom.h"
9 #include "nsXPathExpression.h"
10 #include "nsXPathNSResolver.h"
11 #include "nsXPathResult.h"
12 #include "nsContentCID.h"
13 #include "txExpr.h"
14 #include "txExprParser.h"
15 #include "nsError.h"
16 #include "txURIUtils.h"
17 #include "nsIDocument.h"
18 #include "nsIDOMDocument.h"
19 #include "nsDOMString.h"
20 #include "nsNameSpaceManager.h"
21 #include "nsContentUtils.h"
22 #include "mozilla/dom/XPathEvaluatorBinding.h"
24 extern nsresult
25 TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
26 nsIAtom *aName, nsISupports *aState,
27 FunctionCall **aFunction);
29 namespace mozilla {
30 namespace dom {
32 // txIParseContext implementation
33 class XPathEvaluatorParseContext : public txIParseContext
34 {
35 public:
36 XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver,
37 bool aIsCaseSensitive)
38 : mResolver(aResolver),
39 mLastError(NS_OK),
40 mIsCaseSensitive(aIsCaseSensitive)
41 {
42 }
44 nsresult getError()
45 {
46 return mLastError;
47 }
49 nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID);
50 nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
51 FunctionCall** aFunction);
52 bool caseInsensitiveNameTests();
53 void SetErrorOffset(uint32_t aOffset);
55 private:
56 nsIDOMXPathNSResolver* mResolver;
57 nsresult mLastError;
58 bool mIsCaseSensitive;
59 };
61 NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator)
63 XPathEvaluator::XPathEvaluator(nsIDocument* aDocument)
64 : mDocument(do_GetWeakReference(aDocument))
65 {
66 }
68 NS_IMETHODIMP
69 XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver,
70 nsIDOMXPathNSResolver **aResult)
71 {
72 NS_ENSURE_ARG(aNodeResolver);
73 if (!nsContentUtils::CanCallerAccess(aNodeResolver))
74 return NS_ERROR_DOM_SECURITY_ERR;
76 *aResult = new nsXPathNSResolver(aNodeResolver);
77 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
79 NS_ADDREF(*aResult);
80 return NS_OK;
81 }
83 NS_IMETHODIMP
84 XPathEvaluator::Evaluate(const nsAString & aExpression,
85 nsIDOMNode *aContextNode,
86 nsIDOMXPathNSResolver *aResolver,
87 uint16_t aType,
88 nsISupports *aInResult,
89 nsISupports **aResult)
90 {
91 nsCOMPtr<nsIDOMXPathExpression> expression;
92 nsresult rv = CreateExpression(aExpression, aResolver,
93 getter_AddRefs(expression));
94 NS_ENSURE_SUCCESS(rv, rv);
96 return expression->Evaluate(aContextNode, aType, aInResult, aResult);
97 }
100 NS_IMETHODIMP
101 XPathEvaluator::CreateExpression(const nsAString & aExpression,
102 nsIDOMXPathNSResolver *aResolver,
103 nsIDOMXPathExpression **aResult)
104 {
105 nsresult rv;
106 if (!mRecycler) {
107 nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
108 NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
110 rv = recycler->init();
111 NS_ENSURE_SUCCESS(rv, rv);
113 mRecycler = recycler;
114 }
116 nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
117 XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML()));
119 nsAutoPtr<Expr> expression;
120 rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
121 getter_Transfers(expression));
122 if (NS_FAILED(rv)) {
123 if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
124 return NS_ERROR_DOM_NAMESPACE_ERR;
125 }
127 return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
128 }
130 nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument);
132 *aResult = new nsXPathExpression(expression, mRecycler, document);
133 if (!*aResult) {
134 return NS_ERROR_OUT_OF_MEMORY;
135 }
137 NS_ADDREF(*aResult);
138 return NS_OK;
139 }
141 JSObject*
142 XPathEvaluator::WrapObject(JSContext* aCx)
143 {
144 return dom::XPathEvaluatorBinding::Wrap(aCx, this);
145 }
147 /* static */
148 already_AddRefed<XPathEvaluator>
149 XPathEvaluator::Constructor(const GlobalObject& aGlobal,
150 ErrorResult& rv)
151 {
152 nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
153 return newObj.forget();
154 }
156 already_AddRefed<nsIDOMXPathExpression>
157 XPathEvaluator::CreateExpression(const nsAString& aExpression,
158 nsIDOMXPathNSResolver* aResolver,
159 ErrorResult& rv)
160 {
161 nsCOMPtr<nsIDOMXPathExpression> expr;
162 rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
163 return expr.forget();
164 }
166 already_AddRefed<nsIDOMXPathNSResolver>
167 XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver,
168 ErrorResult& rv)
169 {
170 nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
171 nsCOMPtr<nsIDOMXPathNSResolver> res;
172 rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
173 return res.forget();
174 }
176 already_AddRefed<nsISupports>
177 XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
178 nsIDOMXPathNSResolver* aResolver, uint16_t aType,
179 nsISupports* aResult, ErrorResult& rv)
180 {
181 nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
182 nsCOMPtr<nsISupports> res;
183 rv = Evaluate(aExpression, contextNode, aResolver, aType,
184 aResult, getter_AddRefs(res));
185 return res.forget();
186 }
189 /*
190 * Implementation of txIParseContext private to XPathEvaluator, based on a
191 * nsIDOMXPathNSResolver
192 */
194 nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
195 (nsIAtom* aPrefix, int32_t& aID)
196 {
197 aID = kNameSpaceID_Unknown;
199 if (!mResolver) {
200 return NS_ERROR_DOM_NAMESPACE_ERR;
201 }
203 nsAutoString prefix;
204 if (aPrefix) {
205 aPrefix->ToString(prefix);
206 }
208 nsVoidableString ns;
209 nsresult rv = mResolver->LookupNamespaceURI(prefix, ns);
210 NS_ENSURE_SUCCESS(rv, rv);
212 if (DOMStringIsNull(ns)) {
213 return NS_ERROR_DOM_NAMESPACE_ERR;
214 }
216 if (ns.IsEmpty()) {
217 aID = kNameSpaceID_None;
219 return NS_OK;
220 }
222 // get the namespaceID for the URI
223 return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
224 }
226 nsresult
227 XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
228 int32_t aID,
229 FunctionCall** aFn)
230 {
231 return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
232 }
234 bool XPathEvaluatorParseContext::caseInsensitiveNameTests()
235 {
236 return !mIsCaseSensitive;
237 }
239 void
240 XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
241 {
242 }
244 } // namespace dom
245 } // namespace mozilla