Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xslt/xpath/XPathEvaluator.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
5
6
#include "mozilla/dom/XPathEvaluator.h"
7
#include "mozilla/Move.h"
8
#include "nsCOMPtr.h"
9
#include "nsAtom.h"
10
#include "mozilla/dom/XPathExpression.h"
11
#include "XPathResult.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 "nsDOMString.h"
19
#include "nsNameSpaceManager.h"
20
#include "nsContentUtils.h"
21
#include "txIXPathContext.h"
22
#include "mozilla/dom/XPathEvaluatorBinding.h"
23
#include "mozilla/dom/BindingUtils.h"
24
#include "mozilla/dom/XPathNSResolverBinding.h"
25
26
namespace mozilla {
27
namespace dom {
28
29
// txIParseContext implementation
30
class XPathEvaluatorParseContext : public txIParseContext
31
{
32
public:
33
    XPathEvaluatorParseContext(XPathNSResolver* aResolver,
34
                               bool aIsCaseSensitive)
35
        : mResolver(aResolver),
36
          mResolverNode(nullptr),
37
          mLastError(NS_OK),
38
          mIsCaseSensitive(aIsCaseSensitive)
39
0
    {
40
0
    }
41
    XPathEvaluatorParseContext(nsINode* aResolver,
42
                               bool aIsCaseSensitive)
43
        : mResolver(nullptr),
44
          mResolverNode(aResolver),
45
          mLastError(NS_OK),
46
          mIsCaseSensitive(aIsCaseSensitive)
47
0
    {
48
0
    }
49
50
    nsresult getError()
51
0
    {
52
0
        return mLastError;
53
0
    }
54
55
    nsresult resolveNamespacePrefix(nsAtom* aPrefix, int32_t& aID) override;
56
    nsresult resolveFunctionCall(nsAtom* aName, int32_t aID,
57
                                 FunctionCall** aFunction) override;
58
    bool caseInsensitiveNameTests() override;
59
    void SetErrorOffset(uint32_t aOffset) override;
60
61
private:
62
    XPathNSResolver* mResolver;
63
    nsINode* mResolverNode;
64
    nsresult mLastError;
65
    bool mIsCaseSensitive;
66
};
67
68
XPathEvaluator::XPathEvaluator(nsIDocument* aDocument)
69
    : mDocument(do_GetWeakReference(aDocument))
70
0
{
71
0
}
72
73
XPathEvaluator::~XPathEvaluator()
74
0
{
75
0
}
76
77
XPathExpression*
78
XPathEvaluator::CreateExpression(const nsAString& aExpression,
79
                                 XPathNSResolver* aResolver, ErrorResult& aRv)
80
0
{
81
0
    nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
82
0
    XPathEvaluatorParseContext pContext(aResolver,
83
0
                                        !(doc && doc->IsHTMLDocument()));
84
0
    return CreateExpression(aExpression, &pContext, doc, aRv);
85
0
}
86
87
XPathExpression*
88
XPathEvaluator::CreateExpression(const nsAString& aExpression,
89
                                 nsINode* aResolver, ErrorResult& aRv)
90
0
{
91
0
    nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
92
0
    XPathEvaluatorParseContext pContext(aResolver,
93
0
                                        !(doc && doc->IsHTMLDocument()));
94
0
    return CreateExpression(aExpression, &pContext, doc, aRv);
95
0
}
96
97
XPathExpression*
98
XPathEvaluator::CreateExpression(const nsAString & aExpression,
99
                                 txIParseContext* aContext,
100
                                 nsIDocument* aDocument,
101
                                 ErrorResult& aRv)
102
0
{
103
0
    if (!mRecycler) {
104
0
        mRecycler = new txResultRecycler;
105
0
    }
106
0
107
0
    nsAutoPtr<Expr> expression;
108
0
    aRv = txExprParser::createExpr(PromiseFlatString(aExpression), aContext,
109
0
                                   getter_Transfers(expression));
110
0
    if (aRv.Failed()) {
111
0
        if (!aRv.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR)) {
112
0
            aRv.SuppressException();
113
0
            aRv.Throw(NS_ERROR_DOM_INVALID_EXPRESSION_ERR);
114
0
        }
115
0
116
0
        return nullptr;
117
0
    }
118
0
119
0
    return new XPathExpression(std::move(expression), mRecycler, aDocument);
120
0
}
121
122
bool
123
XPathEvaluator::WrapObject(JSContext* aCx,
124
                           JS::Handle<JSObject*> aGivenProto,
125
                           JS::MutableHandle<JSObject*> aReflector)
126
0
{
127
0
    return dom::XPathEvaluator_Binding::Wrap(aCx, this, aGivenProto, aReflector);
128
0
}
129
130
/* static */ XPathEvaluator*
131
XPathEvaluator::Constructor(const GlobalObject& aGlobal,
132
                            ErrorResult& rv)
133
0
{
134
0
    return new XPathEvaluator(nullptr);
135
0
}
136
137
already_AddRefed<XPathResult>
138
XPathEvaluator::Evaluate(JSContext* aCx, const nsAString& aExpression,
139
                         nsINode& aContextNode, XPathNSResolver* aResolver,
140
                         uint16_t aType, JS::Handle<JSObject*> aResult,
141
                         ErrorResult& rv)
142
0
{
143
0
    nsAutoPtr<XPathExpression> expression(CreateExpression(aExpression,
144
0
                                                           aResolver, rv));
145
0
    if (rv.Failed()) {
146
0
        return nullptr;
147
0
    }
148
0
    return expression->Evaluate(aCx, aContextNode, aType, aResult, rv);
149
0
}
150
151
152
/*
153
 * Implementation of txIParseContext private to XPathEvaluator, based on a
154
 * XPathNSResolver
155
 */
156
157
nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
158
    (nsAtom* aPrefix, int32_t& aID)
159
0
{
160
0
    aID = kNameSpaceID_Unknown;
161
0
162
0
    if (!mResolver && !mResolverNode) {
163
0
        return NS_ERROR_DOM_NAMESPACE_ERR;
164
0
    }
165
0
166
0
    nsAutoString prefix;
167
0
    if (aPrefix) {
168
0
        aPrefix->ToString(prefix);
169
0
    }
170
0
171
0
    nsAutoString ns;
172
0
    if (mResolver) {
173
0
        ErrorResult rv;
174
0
        mResolver->LookupNamespaceURI(prefix, ns, rv);
175
0
        if (rv.Failed()) {
176
0
            return rv.StealNSResult();
177
0
        }
178
0
    } else {
179
0
        if (aPrefix == nsGkAtoms::xml) {
180
0
            ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
181
0
        } else {
182
0
            mResolverNode->LookupNamespaceURI(prefix, ns);
183
0
        }
184
0
    }
185
0
186
0
    if (DOMStringIsNull(ns)) {
187
0
        return NS_ERROR_DOM_NAMESPACE_ERR;
188
0
    }
189
0
190
0
    if (ns.IsEmpty()) {
191
0
        aID = kNameSpaceID_None;
192
0
193
0
        return NS_OK;
194
0
    }
195
0
196
0
    // get the namespaceID for the URI
197
0
    return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
198
0
}
199
200
nsresult
201
XPathEvaluatorParseContext::resolveFunctionCall(nsAtom* aName,
202
                                                int32_t aID,
203
                                                FunctionCall** aFn)
204
0
{
205
0
    return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
206
0
}
207
208
bool XPathEvaluatorParseContext::caseInsensitiveNameTests()
209
0
{
210
0
    return !mIsCaseSensitive;
211
0
}
212
213
void
214
XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
215
0
{
216
0
}
217
218
} // namespace dom
219
} // namespace mozilla