Line data Source code
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 "txMozillaXSLTProcessor.h"
7 : #include "nsContentCID.h"
8 : #include "nsError.h"
9 : #include "nsIChannel.h"
10 : #include "mozilla/dom/Element.h"
11 : #include "nsIDOMElement.h"
12 : #include "nsIDOMText.h"
13 : #include "nsIDocument.h"
14 : #include "nsIDOMDocument.h"
15 : #include "nsIDOMDocumentFragment.h"
16 : #include "nsIDOMNodeList.h"
17 : #include "nsIIOService.h"
18 : #include "nsILoadGroup.h"
19 : #include "nsIStringBundle.h"
20 : #include "nsIURI.h"
21 : #include "XPathResult.h"
22 : #include "txExecutionState.h"
23 : #include "txMozillaTextOutput.h"
24 : #include "txMozillaXMLOutput.h"
25 : #include "txURIUtils.h"
26 : #include "txXMLUtils.h"
27 : #include "txUnknownHandler.h"
28 : #include "txXSLTProcessor.h"
29 : #include "nsIPrincipal.h"
30 : #include "nsThreadUtils.h"
31 : #include "jsapi.h"
32 : #include "txExprParser.h"
33 : #include "nsIErrorService.h"
34 : #include "nsIScriptSecurityManager.h"
35 : #include "nsJSUtils.h"
36 : #include "nsIXPConnect.h"
37 : #include "nsVariant.h"
38 : #include "nsTextNode.h"
39 : #include "mozilla/dom/DocumentFragment.h"
40 : #include "mozilla/dom/XSLTProcessorBinding.h"
41 :
42 : using namespace mozilla::dom;
43 :
44 : static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
45 :
46 : /**
47 : * Output Handler Factories
48 : */
49 0 : class txToDocHandlerFactory : public txAOutputHandlerFactory
50 : {
51 : public:
52 0 : txToDocHandlerFactory(txExecutionState* aEs,
53 : nsIDOMDocument* aSourceDocument,
54 : nsITransformObserver* aObserver,
55 : bool aDocumentIsData)
56 0 : : mEs(aEs), mSourceDocument(aSourceDocument), mObserver(aObserver),
57 0 : mDocumentIsData(aDocumentIsData)
58 : {
59 0 : }
60 :
61 : TX_DECL_TXAOUTPUTHANDLERFACTORY
62 :
63 : private:
64 : txExecutionState* mEs;
65 : nsCOMPtr<nsIDOMDocument> mSourceDocument;
66 : nsCOMPtr<nsITransformObserver> mObserver;
67 : bool mDocumentIsData;
68 : };
69 :
70 0 : class txToFragmentHandlerFactory : public txAOutputHandlerFactory
71 : {
72 : public:
73 0 : explicit txToFragmentHandlerFactory(nsIDOMDocumentFragment* aFragment)
74 0 : : mFragment(aFragment)
75 : {
76 0 : }
77 :
78 : TX_DECL_TXAOUTPUTHANDLERFACTORY
79 :
80 : private:
81 : nsCOMPtr<nsIDOMDocumentFragment> mFragment;
82 : };
83 :
84 : nsresult
85 0 : txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
86 : txAXMLEventHandler** aHandler)
87 : {
88 0 : *aHandler = nullptr;
89 0 : switch (aFormat->mMethod) {
90 : case eMethodNotSet:
91 : case eXMLOutput:
92 : {
93 0 : *aHandler = new txUnknownHandler(mEs);
94 0 : return NS_OK;
95 : }
96 :
97 : case eHTMLOutput:
98 : {
99 : nsAutoPtr<txMozillaXMLOutput> handler(
100 0 : new txMozillaXMLOutput(aFormat, mObserver));
101 :
102 0 : nsresult rv = handler->createResultDocument(EmptyString(),
103 : kNameSpaceID_None,
104 : mSourceDocument,
105 0 : mDocumentIsData);
106 0 : if (NS_SUCCEEDED(rv)) {
107 0 : *aHandler = handler.forget();
108 : }
109 :
110 0 : return rv;
111 : }
112 :
113 : case eTextOutput:
114 : {
115 : nsAutoPtr<txMozillaTextOutput> handler(
116 0 : new txMozillaTextOutput(mObserver));
117 :
118 0 : nsresult rv = handler->createResultDocument(mSourceDocument,
119 0 : mDocumentIsData);
120 0 : if (NS_SUCCEEDED(rv)) {
121 0 : *aHandler = handler.forget();
122 : }
123 :
124 0 : return rv;
125 : }
126 : }
127 :
128 0 : MOZ_CRASH("Unknown output method");
129 :
130 : return NS_ERROR_FAILURE;
131 : }
132 :
133 : nsresult
134 0 : txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
135 : const nsAString& aName,
136 : int32_t aNsID,
137 : txAXMLEventHandler** aHandler)
138 : {
139 0 : *aHandler = nullptr;
140 0 : switch (aFormat->mMethod) {
141 : case eMethodNotSet:
142 : {
143 0 : NS_ERROR("How can method not be known when root element is?");
144 0 : return NS_ERROR_UNEXPECTED;
145 : }
146 :
147 : case eXMLOutput:
148 : case eHTMLOutput:
149 : {
150 : nsAutoPtr<txMozillaXMLOutput> handler(
151 0 : new txMozillaXMLOutput(aFormat, mObserver));
152 :
153 0 : nsresult rv = handler->createResultDocument(aName, aNsID,
154 : mSourceDocument,
155 0 : mDocumentIsData);
156 0 : if (NS_SUCCEEDED(rv)) {
157 0 : *aHandler = handler.forget();
158 : }
159 :
160 0 : return rv;
161 : }
162 :
163 : case eTextOutput:
164 : {
165 : nsAutoPtr<txMozillaTextOutput> handler(
166 0 : new txMozillaTextOutput(mObserver));
167 :
168 0 : nsresult rv = handler->createResultDocument(mSourceDocument,
169 0 : mDocumentIsData);
170 0 : if (NS_SUCCEEDED(rv)) {
171 0 : *aHandler = handler.forget();
172 : }
173 :
174 0 : return rv;
175 : }
176 : }
177 :
178 0 : MOZ_CRASH("Unknown output method");
179 :
180 : return NS_ERROR_FAILURE;
181 : }
182 :
183 : nsresult
184 0 : txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
185 : txAXMLEventHandler** aHandler)
186 : {
187 0 : *aHandler = nullptr;
188 0 : switch (aFormat->mMethod) {
189 : case eMethodNotSet:
190 : {
191 0 : txOutputFormat format;
192 0 : format.merge(*aFormat);
193 0 : nsCOMPtr<nsIDOMDocument> domdoc;
194 0 : mFragment->GetOwnerDocument(getter_AddRefs(domdoc));
195 0 : NS_ASSERTION(domdoc, "unable to get ownerdocument");
196 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
197 :
198 0 : if (doc && doc->IsHTMLDocument()) {
199 0 : format.mMethod = eHTMLOutput;
200 : } else {
201 0 : format.mMethod = eXMLOutput;
202 : }
203 :
204 0 : *aHandler = new txMozillaXMLOutput(&format, mFragment, false);
205 0 : break;
206 : }
207 :
208 : case eXMLOutput:
209 : case eHTMLOutput:
210 : {
211 0 : *aHandler = new txMozillaXMLOutput(aFormat, mFragment, false);
212 0 : break;
213 : }
214 :
215 : case eTextOutput:
216 : {
217 0 : *aHandler = new txMozillaTextOutput(mFragment);
218 0 : break;
219 : }
220 : }
221 0 : NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
222 0 : return NS_OK;
223 : }
224 :
225 : nsresult
226 0 : txToFragmentHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
227 : const nsAString& aName,
228 : int32_t aNsID,
229 : txAXMLEventHandler** aHandler)
230 : {
231 0 : *aHandler = nullptr;
232 0 : NS_ASSERTION(aFormat->mMethod != eMethodNotSet,
233 : "How can method not be known when root element is?");
234 0 : NS_ENSURE_TRUE(aFormat->mMethod != eMethodNotSet, NS_ERROR_UNEXPECTED);
235 0 : return createHandlerWith(aFormat, aHandler);
236 : }
237 :
238 0 : class txVariable : public txIGlobalParameter
239 : {
240 : public:
241 0 : explicit txVariable(nsIVariant* aValue) : mValue(aValue)
242 : {
243 0 : NS_ASSERTION(aValue, "missing value");
244 0 : }
245 0 : explicit txVariable(txAExprResult* aValue) : mTxValue(aValue)
246 : {
247 0 : NS_ASSERTION(aValue, "missing value");
248 0 : }
249 0 : nsresult getValue(txAExprResult** aValue)
250 : {
251 0 : NS_ASSERTION(mValue || mTxValue, "variablevalue is null");
252 :
253 0 : if (!mTxValue) {
254 0 : nsresult rv = Convert(mValue, getter_AddRefs(mTxValue));
255 0 : NS_ENSURE_SUCCESS(rv, rv);
256 : }
257 :
258 0 : *aValue = mTxValue;
259 0 : NS_ADDREF(*aValue);
260 :
261 0 : return NS_OK;
262 : }
263 0 : nsresult getValue(nsIVariant** aValue)
264 : {
265 0 : *aValue = mValue;
266 0 : NS_ADDREF(*aValue);
267 0 : return NS_OK;
268 : }
269 : nsIVariant* getValue()
270 : {
271 : return mValue;
272 : }
273 0 : void setValue(nsIVariant* aValue)
274 : {
275 0 : NS_ASSERTION(aValue, "setting variablevalue to null");
276 0 : mValue = aValue;
277 0 : mTxValue = nullptr;
278 0 : }
279 0 : void setValue(txAExprResult* aValue)
280 : {
281 0 : NS_ASSERTION(aValue, "setting variablevalue to null");
282 0 : mValue = nullptr;
283 0 : mTxValue = aValue;
284 0 : }
285 :
286 : friend void ImplCycleCollectionUnlink(txVariable& aVariable);
287 : friend void ImplCycleCollectionTraverse(
288 : nsCycleCollectionTraversalCallback& aCallback, txVariable& aVariable,
289 : const char* aName, uint32_t aFlags);
290 :
291 : private:
292 : static nsresult Convert(nsIVariant *aValue, txAExprResult** aResult);
293 :
294 : nsCOMPtr<nsIVariant> mValue;
295 : RefPtr<txAExprResult> mTxValue;
296 : };
297 :
298 : inline void
299 0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
300 : txVariable& aVariable, const char* aName,
301 : uint32_t aFlags)
302 : {
303 0 : ImplCycleCollectionTraverse(aCallback, aVariable.mValue, aName, aFlags);
304 0 : }
305 :
306 : inline void
307 0 : ImplCycleCollectionUnlink(txOwningExpandedNameMap<txIGlobalParameter>& aMap)
308 : {
309 0 : aMap.clear();
310 0 : }
311 :
312 : inline void
313 0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
314 : txOwningExpandedNameMap<txIGlobalParameter>& aMap,
315 : const char* aName,
316 : uint32_t aFlags = 0)
317 : {
318 0 : aFlags |= CycleCollectionEdgeNameArrayFlag;
319 0 : txOwningExpandedNameMap<txIGlobalParameter>::iterator iter(aMap);
320 0 : while (iter.next()) {
321 : ImplCycleCollectionTraverse(aCallback,
322 0 : *static_cast<txVariable*>(iter.value()),
323 0 : aName, aFlags);
324 : }
325 0 : }
326 :
327 : /**
328 : * txMozillaXSLTProcessor
329 : */
330 :
331 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(txMozillaXSLTProcessor,
332 : mOwner, mEmbeddedStylesheetRoot,
333 : mSource, mVariables)
334 :
335 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(txMozillaXSLTProcessor)
336 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(txMozillaXSLTProcessor)
337 :
338 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(txMozillaXSLTProcessor)
339 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
340 0 : NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor)
341 0 : NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorPrivate)
342 0 : NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer)
343 0 : NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
344 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor)
345 0 : NS_INTERFACE_MAP_END
346 :
347 0 : txMozillaXSLTProcessor::txMozillaXSLTProcessor()
348 : : mOwner(nullptr),
349 : mStylesheetDocument(nullptr),
350 : mTransformResult(NS_OK),
351 : mCompileResult(NS_OK),
352 0 : mFlags(0)
353 : {
354 0 : }
355 :
356 0 : txMozillaXSLTProcessor::txMozillaXSLTProcessor(nsISupports* aOwner)
357 : : mOwner(aOwner),
358 : mStylesheetDocument(nullptr),
359 : mTransformResult(NS_OK),
360 : mCompileResult(NS_OK),
361 0 : mFlags(0)
362 : {
363 0 : }
364 :
365 0 : txMozillaXSLTProcessor::~txMozillaXSLTProcessor()
366 : {
367 0 : if (mStylesheetDocument) {
368 0 : mStylesheetDocument->RemoveMutationObserver(this);
369 : }
370 0 : }
371 :
372 : NS_IMETHODIMP
373 0 : txMozillaXSLTProcessor::SetTransformObserver(nsITransformObserver* aObserver)
374 : {
375 0 : mObserver = aObserver;
376 0 : return NS_OK;
377 : }
378 :
379 : nsresult
380 0 : txMozillaXSLTProcessor::SetSourceContentModel(nsIDOMNode* aSourceDOM)
381 : {
382 0 : mSource = aSourceDOM;
383 :
384 0 : if (NS_FAILED(mTransformResult)) {
385 0 : notifyError();
386 0 : return NS_OK;
387 : }
388 :
389 0 : if (mStylesheet) {
390 0 : return DoTransform();
391 : }
392 :
393 0 : return NS_OK;
394 : }
395 :
396 : NS_IMETHODIMP
397 0 : txMozillaXSLTProcessor::AddXSLTParamNamespace(const nsString& aPrefix,
398 : const nsString& aNamespace)
399 : {
400 0 : nsCOMPtr<nsIAtom> pre = NS_Atomize(aPrefix);
401 0 : return mParamNamespaceMap.mapNamespace(pre, aNamespace);
402 : }
403 :
404 :
405 0 : class txXSLTParamContext : public txIParseContext,
406 : public txIEvalContext
407 : {
408 : public:
409 0 : txXSLTParamContext(txNamespaceMap *aResolver, const txXPathNode& aContext,
410 : txResultRecycler* aRecycler)
411 0 : : mResolver(aResolver),
412 : mContext(aContext),
413 0 : mRecycler(aRecycler)
414 : {
415 0 : }
416 :
417 : // txIParseContext
418 0 : nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID)
419 : {
420 0 : aID = mResolver->lookupNamespace(aPrefix);
421 0 : return aID == kNameSpaceID_Unknown ? NS_ERROR_DOM_NAMESPACE_ERR :
422 0 : NS_OK;
423 : }
424 0 : nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
425 : FunctionCall** aFunction)
426 : {
427 0 : return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
428 : }
429 0 : bool caseInsensitiveNameTests()
430 : {
431 0 : return false;
432 : }
433 0 : void SetErrorOffset(uint32_t aOffset)
434 : {
435 0 : }
436 :
437 : // txIEvalContext
438 0 : nsresult getVariable(int32_t aNamespace, nsIAtom* aLName,
439 : txAExprResult*& aResult)
440 : {
441 0 : aResult = nullptr;
442 0 : return NS_ERROR_INVALID_ARG;
443 : }
444 0 : nsresult isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
445 : {
446 0 : aAllowed = false;
447 :
448 0 : return NS_OK;
449 : }
450 0 : void* getPrivateContext()
451 : {
452 0 : return nullptr;
453 : }
454 0 : txResultRecycler* recycler()
455 : {
456 0 : return mRecycler;
457 : }
458 0 : void receiveError(const nsAString& aMsg, nsresult aRes)
459 : {
460 0 : }
461 0 : const txXPathNode& getContextNode()
462 : {
463 0 : return mContext;
464 : }
465 0 : uint32_t size()
466 : {
467 0 : return 1;
468 : }
469 0 : uint32_t position()
470 : {
471 0 : return 1;
472 : }
473 :
474 : private:
475 : txNamespaceMap *mResolver;
476 : const txXPathNode& mContext;
477 : txResultRecycler* mRecycler;
478 : };
479 :
480 :
481 : NS_IMETHODIMP
482 0 : txMozillaXSLTProcessor::AddXSLTParam(const nsString& aName,
483 : const nsString& aNamespace,
484 : const nsString& aSelect,
485 : const nsString& aValue,
486 : nsIDOMNode* aContext)
487 : {
488 0 : nsresult rv = NS_OK;
489 :
490 0 : if (aSelect.IsVoid() == aValue.IsVoid()) {
491 : // Ignore if neither or both are specified
492 0 : return NS_ERROR_FAILURE;
493 : }
494 :
495 0 : RefPtr<txAExprResult> value;
496 0 : if (!aSelect.IsVoid()) {
497 :
498 : // Set up context
499 : nsAutoPtr<txXPathNode> contextNode(
500 0 : txXPathNativeNode::createXPathNode(aContext));
501 0 : NS_ENSURE_TRUE(contextNode, NS_ERROR_OUT_OF_MEMORY);
502 :
503 0 : if (!mRecycler) {
504 0 : mRecycler = new txResultRecycler;
505 : }
506 :
507 0 : txXSLTParamContext paramContext(&mParamNamespaceMap, *contextNode,
508 0 : mRecycler);
509 :
510 : // Parse
511 0 : nsAutoPtr<Expr> expr;
512 0 : rv = txExprParser::createExpr(aSelect, ¶mContext,
513 0 : getter_Transfers(expr));
514 0 : NS_ENSURE_SUCCESS(rv, rv);
515 :
516 : // Evaluate
517 0 : rv = expr->evaluate(¶mContext, getter_AddRefs(value));
518 0 : NS_ENSURE_SUCCESS(rv, rv);
519 : }
520 : else {
521 0 : value = new StringResult(aValue, nullptr);
522 : }
523 :
524 0 : nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
525 0 : int32_t nsId = kNameSpaceID_Unknown;
526 : rv = nsContentUtils::NameSpaceManager()->
527 0 : RegisterNameSpace(aNamespace, nsId);
528 0 : NS_ENSURE_SUCCESS(rv, rv);
529 :
530 0 : txExpandedName varName(nsId, name);
531 0 : txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
532 0 : if (var) {
533 0 : var->setValue(value);
534 :
535 0 : return NS_OK;
536 : }
537 :
538 0 : var = new txVariable(value);
539 0 : NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
540 :
541 0 : return mVariables.add(varName, var);
542 : }
543 :
544 : class nsTransformBlockerEvent : public mozilla::Runnable {
545 : public:
546 : RefPtr<txMozillaXSLTProcessor> mProcessor;
547 :
548 0 : explicit nsTransformBlockerEvent(txMozillaXSLTProcessor* processor)
549 0 : : mozilla::Runnable("nsTransformBlockerEvent")
550 0 : , mProcessor(processor)
551 0 : {}
552 :
553 0 : ~nsTransformBlockerEvent()
554 0 : {
555 : nsCOMPtr<nsIDocument> document =
556 0 : do_QueryInterface(mProcessor->GetSourceContentModel());
557 0 : document->UnblockOnload(true);
558 0 : }
559 :
560 0 : NS_IMETHOD Run() override
561 : {
562 0 : mProcessor->TransformToDoc(nullptr, false);
563 0 : return NS_OK;
564 : }
565 : };
566 :
567 : nsresult
568 0 : txMozillaXSLTProcessor::DoTransform()
569 : {
570 0 : NS_ENSURE_TRUE(mSource, NS_ERROR_UNEXPECTED);
571 0 : NS_ENSURE_TRUE(mStylesheet, NS_ERROR_UNEXPECTED);
572 0 : NS_ASSERTION(mObserver, "no observer");
573 0 : NS_ASSERTION(NS_IsMainThread(), "should only be on main thread");
574 :
575 : nsresult rv;
576 0 : nsCOMPtr<nsIDocument> document = do_QueryInterface(mSource, &rv);
577 0 : NS_ENSURE_SUCCESS(rv, rv);
578 :
579 0 : nsCOMPtr<nsIRunnable> event = new nsTransformBlockerEvent(this);
580 0 : document->BlockOnload();
581 0 : rv = NS_DispatchToCurrentThread(event);
582 0 : if (NS_FAILED(rv)) {
583 : // XXX Maybe we should just display the source document in this case?
584 : // Also, set up context information, see bug 204655.
585 0 : reportError(rv, nullptr, nullptr);
586 : }
587 :
588 0 : return rv;
589 : }
590 :
591 : NS_IMETHODIMP
592 0 : txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
593 : {
594 0 : NS_ENSURE_TRUE(aStyle, NS_ERROR_NULL_POINTER);
595 :
596 : // We don't support importing multiple stylesheets yet.
597 0 : NS_ENSURE_TRUE(!mStylesheetDocument && !mStylesheet,
598 : NS_ERROR_NOT_IMPLEMENTED);
599 :
600 0 : nsCOMPtr<nsINode> node = do_QueryInterface(aStyle);
601 0 : if (!node || !nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()->Subsumes(node->NodePrincipal())) {
602 0 : return NS_ERROR_DOM_SECURITY_ERR;
603 : }
604 :
605 0 : nsCOMPtr<nsINode> styleNode = do_QueryInterface(aStyle);
606 0 : NS_ENSURE_TRUE(styleNode &&
607 : (styleNode->IsElement() ||
608 : styleNode->IsNodeOfType(nsINode::eDOCUMENT)),
609 : NS_ERROR_INVALID_ARG);
610 :
611 0 : nsresult rv = TX_CompileStylesheet(styleNode, this,
612 0 : getter_AddRefs(mStylesheet));
613 : // XXX set up exception context, bug 204658
614 0 : NS_ENSURE_SUCCESS(rv, rv);
615 :
616 0 : if (styleNode->IsElement()) {
617 0 : mStylesheetDocument = styleNode->OwnerDoc();
618 0 : NS_ENSURE_TRUE(mStylesheetDocument, NS_ERROR_UNEXPECTED);
619 :
620 0 : mEmbeddedStylesheetRoot = static_cast<nsIContent*>(styleNode.get());
621 : }
622 : else {
623 0 : mStylesheetDocument = static_cast<nsIDocument*>(styleNode.get());
624 : }
625 :
626 0 : mStylesheetDocument->AddMutationObserver(this);
627 :
628 0 : return NS_OK;
629 : }
630 :
631 : NS_IMETHODIMP
632 0 : txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
633 : nsIDOMDocument **aResult)
634 : {
635 0 : NS_ENSURE_ARG(aSource);
636 0 : NS_ENSURE_ARG_POINTER(aResult);
637 0 : NS_ENSURE_SUCCESS(mCompileResult, mCompileResult);
638 :
639 0 : if (!nsContentUtils::CanCallerAccess(aSource)) {
640 0 : return NS_ERROR_DOM_SECURITY_ERR;
641 : }
642 :
643 0 : nsresult rv = ensureStylesheet();
644 0 : NS_ENSURE_SUCCESS(rv, rv);
645 :
646 0 : mSource = aSource;
647 :
648 0 : return TransformToDoc(aResult, true);
649 : }
650 :
651 : nsresult
652 0 : txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult,
653 : bool aCreateDataDocument)
654 : {
655 0 : nsAutoPtr<txXPathNode> sourceNode(txXPathNativeNode::createXPathNode(mSource));
656 0 : if (!sourceNode) {
657 0 : return NS_ERROR_OUT_OF_MEMORY;
658 : }
659 :
660 0 : nsCOMPtr<nsIDOMDocument> sourceDOMDocument;
661 0 : mSource->GetOwnerDocument(getter_AddRefs(sourceDOMDocument));
662 0 : if (!sourceDOMDocument) {
663 0 : sourceDOMDocument = do_QueryInterface(mSource);
664 : }
665 :
666 0 : txExecutionState es(mStylesheet, IsLoadDisabled());
667 :
668 : // XXX Need to add error observers
669 :
670 : // If aResult is non-null, we're a data document
671 : txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, mObserver,
672 0 : aCreateDataDocument);
673 0 : es.mOutputHandlerFactory = &handlerFactory;
674 :
675 0 : nsresult rv = es.init(*sourceNode, &mVariables);
676 :
677 : // Process root of XML source document
678 0 : if (NS_SUCCEEDED(rv)) {
679 0 : rv = txXSLTProcessor::execute(es);
680 : }
681 :
682 0 : nsresult endRv = es.end(rv);
683 0 : if (NS_SUCCEEDED(rv)) {
684 0 : rv = endRv;
685 : }
686 :
687 0 : if (NS_SUCCEEDED(rv)) {
688 0 : if (aResult) {
689 : txAOutputXMLEventHandler* handler =
690 0 : static_cast<txAOutputXMLEventHandler*>(es.mOutputHandler);
691 0 : handler->getOutputDocument(aResult);
692 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(*aResult);
693 0 : MOZ_ASSERT(doc->GetReadyStateEnum() ==
694 : nsIDocument::READYSTATE_INTERACTIVE, "Bad readyState");
695 0 : doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
696 : }
697 : }
698 0 : else if (mObserver) {
699 : // XXX set up context information, bug 204655
700 0 : reportError(rv, nullptr, nullptr);
701 : }
702 :
703 0 : return rv;
704 : }
705 :
706 : NS_IMETHODIMP
707 0 : txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
708 : nsIDOMDocument *aOutput,
709 : nsIDOMDocumentFragment **aResult)
710 : {
711 0 : NS_ENSURE_ARG(aSource);
712 0 : NS_ENSURE_ARG(aOutput);
713 0 : NS_ENSURE_ARG_POINTER(aResult);
714 0 : NS_ENSURE_SUCCESS(mCompileResult, mCompileResult);
715 :
716 0 : nsCOMPtr<nsINode> node = do_QueryInterface(aSource);
717 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(aOutput);
718 0 : NS_ENSURE_TRUE(node && doc, NS_ERROR_DOM_SECURITY_ERR);
719 0 : nsIPrincipal* subject = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
720 0 : if (!subject->Subsumes(node->NodePrincipal()) ||
721 0 : !subject->Subsumes(doc->NodePrincipal()))
722 : {
723 0 : return NS_ERROR_DOM_SECURITY_ERR;
724 : }
725 :
726 0 : nsresult rv = ensureStylesheet();
727 0 : NS_ENSURE_SUCCESS(rv, rv);
728 :
729 0 : nsAutoPtr<txXPathNode> sourceNode(txXPathNativeNode::createXPathNode(aSource));
730 0 : if (!sourceNode) {
731 0 : return NS_ERROR_OUT_OF_MEMORY;
732 : }
733 :
734 0 : txExecutionState es(mStylesheet, IsLoadDisabled());
735 :
736 : // XXX Need to add error observers
737 :
738 0 : rv = aOutput->CreateDocumentFragment(aResult);
739 0 : NS_ENSURE_SUCCESS(rv, rv);
740 0 : txToFragmentHandlerFactory handlerFactory(*aResult);
741 0 : es.mOutputHandlerFactory = &handlerFactory;
742 :
743 0 : rv = es.init(*sourceNode, &mVariables);
744 :
745 : // Process root of XML source document
746 0 : if (NS_SUCCEEDED(rv)) {
747 0 : rv = txXSLTProcessor::execute(es);
748 : }
749 : // XXX setup exception context, bug 204658
750 0 : nsresult endRv = es.end(rv);
751 0 : if (NS_SUCCEEDED(rv)) {
752 0 : rv = endRv;
753 : }
754 :
755 0 : return rv;
756 : }
757 :
758 : NS_IMETHODIMP
759 0 : txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
760 : const nsAString & aLocalName,
761 : nsIVariant *aValue)
762 : {
763 0 : NS_ENSURE_ARG(aValue);
764 :
765 0 : nsCOMPtr<nsIVariant> value = aValue;
766 :
767 : uint16_t dataType;
768 0 : value->GetDataType(&dataType);
769 0 : switch (dataType) {
770 : // Number
771 : case nsIDataType::VTYPE_INT8:
772 : case nsIDataType::VTYPE_INT16:
773 : case nsIDataType::VTYPE_INT32:
774 : case nsIDataType::VTYPE_INT64:
775 : case nsIDataType::VTYPE_UINT8:
776 : case nsIDataType::VTYPE_UINT16:
777 : case nsIDataType::VTYPE_UINT32:
778 : case nsIDataType::VTYPE_UINT64:
779 : case nsIDataType::VTYPE_FLOAT:
780 : case nsIDataType::VTYPE_DOUBLE:
781 :
782 : // Boolean
783 : case nsIDataType::VTYPE_BOOL:
784 :
785 : // String
786 : case nsIDataType::VTYPE_CHAR:
787 : case nsIDataType::VTYPE_WCHAR:
788 : case nsIDataType::VTYPE_DOMSTRING:
789 : case nsIDataType::VTYPE_CHAR_STR:
790 : case nsIDataType::VTYPE_WCHAR_STR:
791 : case nsIDataType::VTYPE_STRING_SIZE_IS:
792 : case nsIDataType::VTYPE_WSTRING_SIZE_IS:
793 : case nsIDataType::VTYPE_UTF8STRING:
794 : case nsIDataType::VTYPE_CSTRING:
795 : case nsIDataType::VTYPE_ASTRING:
796 : {
797 0 : break;
798 : }
799 :
800 : // Nodeset
801 : case nsIDataType::VTYPE_INTERFACE:
802 : case nsIDataType::VTYPE_INTERFACE_IS:
803 : {
804 0 : nsCOMPtr<nsISupports> supports;
805 0 : nsresult rv = value->GetAsISupports(getter_AddRefs(supports));
806 0 : NS_ENSURE_SUCCESS(rv, rv);
807 :
808 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
809 0 : if (node) {
810 0 : if (!nsContentUtils::CanCallerAccess(node)) {
811 0 : return NS_ERROR_DOM_SECURITY_ERR;
812 : }
813 :
814 0 : break;
815 : }
816 :
817 0 : nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(supports);
818 0 : if (xpathResult) {
819 0 : RefPtr<txAExprResult> result;
820 0 : nsresult rv = xpathResult->GetExprResult(getter_AddRefs(result));
821 0 : NS_ENSURE_SUCCESS(rv, rv);
822 :
823 0 : if (result->getResultType() == txAExprResult::NODESET) {
824 : txNodeSet *nodeSet =
825 : static_cast<txNodeSet*>
826 0 : (static_cast<txAExprResult*>(result));
827 :
828 0 : nsCOMPtr<nsIDOMNode> node;
829 0 : int32_t i, count = nodeSet->size();
830 0 : for (i = 0; i < count; ++i) {
831 0 : rv = txXPathNativeNode::getNode(nodeSet->get(i),
832 0 : getter_AddRefs(node));
833 0 : NS_ENSURE_SUCCESS(rv, rv);
834 :
835 0 : if (!nsContentUtils::CanCallerAccess(node)) {
836 0 : return NS_ERROR_DOM_SECURITY_ERR;
837 : }
838 : }
839 : }
840 :
841 : // Clone the XPathResult so that mutations don't affect this
842 : // variable.
843 0 : nsCOMPtr<nsIXPathResult> clone;
844 0 : rv = xpathResult->Clone(getter_AddRefs(clone));
845 0 : NS_ENSURE_SUCCESS(rv, rv);
846 :
847 0 : RefPtr<nsVariant> variant = new nsVariant();
848 :
849 0 : rv = variant->SetAsISupports(clone);
850 0 : NS_ENSURE_SUCCESS(rv, rv);
851 :
852 0 : value = variant;
853 :
854 0 : break;
855 : }
856 :
857 0 : nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
858 0 : if (nodeList) {
859 : uint32_t length;
860 0 : nodeList->GetLength(&length);
861 :
862 0 : nsCOMPtr<nsIDOMNode> node;
863 : uint32_t i;
864 0 : for (i = 0; i < length; ++i) {
865 0 : nodeList->Item(i, getter_AddRefs(node));
866 :
867 0 : if (!nsContentUtils::CanCallerAccess(node)) {
868 0 : return NS_ERROR_DOM_SECURITY_ERR;
869 : }
870 : }
871 :
872 0 : break;
873 : }
874 :
875 : // Random JS Objects will be converted to a string.
876 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
877 0 : do_QueryInterface(supports);
878 0 : if (holder) {
879 0 : break;
880 : }
881 :
882 : // We don't know how to handle this type of param.
883 0 : return NS_ERROR_ILLEGAL_VALUE;
884 : }
885 :
886 : case nsIDataType::VTYPE_ARRAY:
887 : {
888 : uint16_t type;
889 : nsIID iid;
890 : uint32_t count;
891 : void* array;
892 0 : nsresult rv = value->GetAsArray(&type, &iid, &count, &array);
893 0 : NS_ENSURE_SUCCESS(rv, rv);
894 :
895 0 : if (type != nsIDataType::VTYPE_INTERFACE &&
896 0 : type != nsIDataType::VTYPE_INTERFACE_IS) {
897 0 : free(array);
898 :
899 : // We only support arrays of DOM nodes.
900 0 : return NS_ERROR_ILLEGAL_VALUE;
901 : }
902 :
903 0 : nsISupports** values = static_cast<nsISupports**>(array);
904 :
905 : uint32_t i;
906 0 : for (i = 0; i < count; ++i) {
907 0 : nsISupports *supports = values[i];
908 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
909 :
910 0 : if (node) {
911 0 : rv = nsContentUtils::CanCallerAccess(node) ? NS_OK :
912 : NS_ERROR_DOM_SECURITY_ERR;
913 : }
914 : else {
915 : // We only support arrays of DOM nodes.
916 0 : rv = NS_ERROR_ILLEGAL_VALUE;
917 : }
918 :
919 0 : if (NS_FAILED(rv)) {
920 0 : while (i < count) {
921 0 : NS_IF_RELEASE(values[i]);
922 0 : ++i;
923 : }
924 0 : free(array);
925 :
926 0 : return rv;
927 : }
928 :
929 0 : NS_RELEASE(supports);
930 : }
931 :
932 0 : free(array);
933 :
934 0 : break;
935 : }
936 :
937 : default:
938 : {
939 0 : return NS_ERROR_FAILURE;
940 : }
941 : }
942 :
943 0 : int32_t nsId = kNameSpaceID_Unknown;
944 : nsresult rv = nsContentUtils::NameSpaceManager()->
945 0 : RegisterNameSpace(aNamespaceURI, nsId);
946 0 : NS_ENSURE_SUCCESS(rv, rv);
947 0 : nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
948 0 : txExpandedName varName(nsId, localName);
949 :
950 0 : txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
951 0 : if (var) {
952 0 : var->setValue(value);
953 0 : return NS_OK;
954 : }
955 :
956 0 : var = new txVariable(value);
957 0 : return mVariables.add(varName, var);
958 : }
959 :
960 : NS_IMETHODIMP
961 0 : txMozillaXSLTProcessor::GetParameter(const nsAString& aNamespaceURI,
962 : const nsAString& aLocalName,
963 : nsIVariant **aResult)
964 : {
965 0 : int32_t nsId = kNameSpaceID_Unknown;
966 : nsresult rv = nsContentUtils::NameSpaceManager()->
967 0 : RegisterNameSpace(aNamespaceURI, nsId);
968 0 : NS_ENSURE_SUCCESS(rv, rv);
969 0 : nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
970 0 : txExpandedName varName(nsId, localName);
971 :
972 0 : txVariable* var = static_cast<txVariable*>(mVariables.get(varName));
973 0 : if (var) {
974 0 : return var->getValue(aResult);
975 : }
976 0 : return NS_OK;
977 : }
978 :
979 : NS_IMETHODIMP
980 0 : txMozillaXSLTProcessor::RemoveParameter(const nsAString& aNamespaceURI,
981 : const nsAString& aLocalName)
982 : {
983 0 : int32_t nsId = kNameSpaceID_Unknown;
984 : nsresult rv = nsContentUtils::NameSpaceManager()->
985 0 : RegisterNameSpace(aNamespaceURI, nsId);
986 0 : NS_ENSURE_SUCCESS(rv, rv);
987 0 : nsCOMPtr<nsIAtom> localName = NS_Atomize(aLocalName);
988 0 : txExpandedName varName(nsId, localName);
989 :
990 0 : mVariables.remove(varName);
991 0 : return NS_OK;
992 : }
993 :
994 : NS_IMETHODIMP
995 0 : txMozillaXSLTProcessor::ClearParameters()
996 : {
997 0 : mVariables.clear();
998 :
999 0 : return NS_OK;
1000 : }
1001 :
1002 : NS_IMETHODIMP
1003 0 : txMozillaXSLTProcessor::Reset()
1004 : {
1005 0 : if (mStylesheetDocument) {
1006 0 : mStylesheetDocument->RemoveMutationObserver(this);
1007 : }
1008 0 : mStylesheet = nullptr;
1009 0 : mStylesheetDocument = nullptr;
1010 0 : mEmbeddedStylesheetRoot = nullptr;
1011 0 : mCompileResult = NS_OK;
1012 0 : mVariables.clear();
1013 :
1014 0 : return NS_OK;
1015 : }
1016 :
1017 : void
1018 0 : txMozillaXSLTProcessor::SetFlags(uint32_t aFlags, SystemCallerGuarantee)
1019 : {
1020 0 : mFlags = aFlags;
1021 0 : }
1022 :
1023 : uint32_t
1024 0 : txMozillaXSLTProcessor::Flags(SystemCallerGuarantee)
1025 : {
1026 0 : return mFlags;
1027 : }
1028 :
1029 : NS_IMETHODIMP
1030 0 : txMozillaXSLTProcessor::LoadStyleSheet(nsIURI* aUri,
1031 : nsIDocument* aLoaderDocument)
1032 : {
1033 0 : mozilla::net::ReferrerPolicy refpol = mozilla::net::RP_Unset;
1034 0 : if (mStylesheetDocument) {
1035 0 : refpol = mStylesheetDocument->GetReferrerPolicy();
1036 : }
1037 :
1038 0 : nsresult rv = TX_LoadSheet(aUri, this, aLoaderDocument, refpol);
1039 0 : if (NS_FAILED(rv) && mObserver) {
1040 : // This is most likely a network or security error, just
1041 : // use the uri as context.
1042 0 : nsAutoCString spec;
1043 0 : aUri->GetSpec(spec);
1044 0 : CopyUTF8toUTF16(spec, mSourceText);
1045 0 : nsresult status = NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_XSLT ? rv :
1046 0 : NS_ERROR_XSLT_NETWORK_ERROR;
1047 0 : reportError(status, nullptr, nullptr);
1048 : }
1049 0 : return rv;
1050 : }
1051 :
1052 : nsresult
1053 0 : txMozillaXSLTProcessor::setStylesheet(txStylesheet* aStylesheet)
1054 : {
1055 0 : mStylesheet = aStylesheet;
1056 0 : if (mSource) {
1057 0 : return DoTransform();
1058 : }
1059 0 : return NS_OK;
1060 : }
1061 :
1062 : void
1063 0 : txMozillaXSLTProcessor::reportError(nsresult aResult,
1064 : const char16_t *aErrorText,
1065 : const char16_t *aSourceText)
1066 : {
1067 0 : if (!mObserver) {
1068 0 : return;
1069 : }
1070 :
1071 0 : mTransformResult = aResult;
1072 :
1073 0 : if (aErrorText) {
1074 0 : mErrorText.Assign(aErrorText);
1075 : }
1076 : else {
1077 : nsCOMPtr<nsIStringBundleService> sbs =
1078 0 : mozilla::services::GetStringBundleService();
1079 0 : if (sbs) {
1080 0 : nsXPIDLString errorText;
1081 0 : sbs->FormatStatusMessage(aResult, EmptyString().get(),
1082 0 : getter_Copies(errorText));
1083 :
1084 0 : nsXPIDLString errorMessage;
1085 0 : nsCOMPtr<nsIStringBundle> bundle;
1086 0 : sbs->CreateBundle(XSLT_MSGS_URL, getter_AddRefs(bundle));
1087 :
1088 0 : if (bundle) {
1089 0 : const char16_t* error[] = { errorText.get() };
1090 0 : if (mStylesheet) {
1091 0 : bundle->FormatStringFromName(u"TransformError",
1092 : error, 1,
1093 0 : getter_Copies(errorMessage));
1094 : }
1095 : else {
1096 0 : bundle->FormatStringFromName(u"LoadingError",
1097 : error, 1,
1098 0 : getter_Copies(errorMessage));
1099 : }
1100 : }
1101 0 : mErrorText.Assign(errorMessage);
1102 : }
1103 : }
1104 :
1105 0 : if (aSourceText) {
1106 0 : mSourceText.Assign(aSourceText);
1107 : }
1108 :
1109 0 : if (mSource) {
1110 0 : notifyError();
1111 : }
1112 : }
1113 :
1114 : void
1115 0 : txMozillaXSLTProcessor::notifyError()
1116 : {
1117 0 : nsCOMPtr<nsIDocument> document = do_CreateInstance(kXMLDocumentCID);
1118 0 : if (!document) {
1119 0 : return;
1120 : }
1121 :
1122 0 : URIUtils::ResetWithSource(document, mSource);
1123 :
1124 0 : MOZ_ASSERT(document->GetReadyStateEnum() ==
1125 : nsIDocument::READYSTATE_UNINITIALIZED,
1126 : "Bad readyState.");
1127 0 : document->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
1128 :
1129 0 : NS_NAMED_LITERAL_STRING(ns, "http://www.mozilla.org/newlayout/xml/parsererror.xml");
1130 :
1131 0 : IgnoredErrorResult rv;
1132 0 : ElementCreationOptionsOrString options;
1133 0 : options.SetAsString();
1134 :
1135 : nsCOMPtr<Element> element =
1136 0 : document->CreateElementNS(ns, NS_LITERAL_STRING("parsererror"),
1137 0 : options, rv);
1138 0 : if (rv.Failed()) {
1139 0 : return;
1140 : }
1141 :
1142 0 : document->AppendChild(*element, rv);
1143 0 : if (rv.Failed()) {
1144 0 : return;
1145 : }
1146 :
1147 0 : RefPtr<nsTextNode> text = document->CreateTextNode(mErrorText);
1148 :
1149 0 : element->AppendChild(*text, rv);
1150 0 : if (rv.Failed()) {
1151 0 : return;
1152 : }
1153 :
1154 0 : if (!mSourceText.IsEmpty()) {
1155 0 : ElementCreationOptionsOrString options;
1156 0 : options.SetAsString();
1157 :
1158 : nsCOMPtr<Element> sourceElement =
1159 0 : document->CreateElementNS(ns, NS_LITERAL_STRING("sourcetext"),
1160 0 : options, rv);
1161 0 : if (rv.Failed()) {
1162 0 : return;
1163 : }
1164 :
1165 0 : element->AppendChild(*sourceElement, rv);
1166 0 : if (rv.Failed()) {
1167 0 : return;
1168 : }
1169 :
1170 0 : text = document->CreateTextNode(mSourceText);
1171 :
1172 0 : sourceElement->AppendChild(*text, rv);
1173 0 : if (rv.Failed()) {
1174 0 : return;
1175 : }
1176 : }
1177 :
1178 0 : MOZ_ASSERT(document->GetReadyStateEnum() ==
1179 : nsIDocument::READYSTATE_LOADING,
1180 : "Bad readyState.");
1181 0 : document->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
1182 :
1183 0 : mObserver->OnTransformDone(mTransformResult, document);
1184 : }
1185 :
1186 : nsresult
1187 0 : txMozillaXSLTProcessor::ensureStylesheet()
1188 : {
1189 0 : if (mStylesheet) {
1190 0 : return NS_OK;
1191 : }
1192 :
1193 0 : NS_ENSURE_TRUE(mStylesheetDocument, NS_ERROR_NOT_INITIALIZED);
1194 :
1195 0 : nsINode* style = mEmbeddedStylesheetRoot;
1196 0 : if (!style) {
1197 0 : style = mStylesheetDocument;
1198 : }
1199 :
1200 0 : return TX_CompileStylesheet(style, this, getter_AddRefs(mStylesheet));
1201 : }
1202 :
1203 : void
1204 0 : txMozillaXSLTProcessor::NodeWillBeDestroyed(const nsINode* aNode)
1205 : {
1206 0 : nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
1207 0 : if (NS_FAILED(mCompileResult)) {
1208 0 : return;
1209 : }
1210 :
1211 0 : mCompileResult = ensureStylesheet();
1212 0 : mStylesheetDocument = nullptr;
1213 0 : mEmbeddedStylesheetRoot = nullptr;
1214 : }
1215 :
1216 : void
1217 0 : txMozillaXSLTProcessor::CharacterDataChanged(nsIDocument* aDocument,
1218 : nsIContent *aContent,
1219 : CharacterDataChangeInfo* aInfo)
1220 : {
1221 0 : mStylesheet = nullptr;
1222 0 : }
1223 :
1224 : void
1225 0 : txMozillaXSLTProcessor::AttributeChanged(nsIDocument* aDocument,
1226 : Element* aElement,
1227 : int32_t aNameSpaceID,
1228 : nsIAtom* aAttribute,
1229 : int32_t aModType,
1230 : const nsAttrValue* aOldValue)
1231 : {
1232 0 : mStylesheet = nullptr;
1233 0 : }
1234 :
1235 : void
1236 0 : txMozillaXSLTProcessor::ContentAppended(nsIDocument* aDocument,
1237 : nsIContent* aContainer,
1238 : nsIContent* aFirstNewContent,
1239 : int32_t /* unused */)
1240 : {
1241 0 : mStylesheet = nullptr;
1242 0 : }
1243 :
1244 : void
1245 0 : txMozillaXSLTProcessor::ContentInserted(nsIDocument* aDocument,
1246 : nsIContent* aContainer,
1247 : nsIContent* aChild,
1248 : int32_t /* unused */)
1249 : {
1250 0 : mStylesheet = nullptr;
1251 0 : }
1252 :
1253 : void
1254 0 : txMozillaXSLTProcessor::ContentRemoved(nsIDocument* aDocument,
1255 : nsIContent* aContainer,
1256 : nsIContent* aChild,
1257 : int32_t aIndexInContainer,
1258 : nsIContent* aPreviousSibling)
1259 : {
1260 0 : mStylesheet = nullptr;
1261 0 : }
1262 :
1263 : /* virtual */ JSObject*
1264 0 : txMozillaXSLTProcessor::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
1265 : {
1266 0 : return XSLTProcessorBinding::Wrap(aCx, this, aGivenProto);
1267 : }
1268 :
1269 :
1270 : /* static */ already_AddRefed<txMozillaXSLTProcessor>
1271 0 : txMozillaXSLTProcessor::Constructor(const GlobalObject& aGlobal,
1272 : mozilla::ErrorResult& aRv)
1273 : {
1274 : RefPtr<txMozillaXSLTProcessor> processor =
1275 0 : new txMozillaXSLTProcessor(aGlobal.GetAsSupports());
1276 0 : return processor.forget();
1277 : }
1278 :
1279 : void
1280 0 : txMozillaXSLTProcessor::ImportStylesheet(nsINode& stylesheet,
1281 : mozilla::ErrorResult& aRv)
1282 : {
1283 0 : aRv = ImportStylesheet(stylesheet.AsDOMNode());
1284 0 : }
1285 :
1286 : already_AddRefed<DocumentFragment>
1287 0 : txMozillaXSLTProcessor::TransformToFragment(nsINode& source,
1288 : nsIDocument& docVal,
1289 : mozilla::ErrorResult& aRv)
1290 : {
1291 0 : nsCOMPtr<nsIDOMDocumentFragment> fragment;
1292 0 : nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(&docVal);
1293 0 : if (!domDoc) {
1294 0 : aRv.Throw(NS_ERROR_FAILURE);
1295 0 : return nullptr;
1296 : }
1297 0 : aRv = TransformToFragment(source.AsDOMNode(), domDoc, getter_AddRefs(fragment));
1298 0 : return fragment.forget().downcast<DocumentFragment>();
1299 : }
1300 :
1301 : already_AddRefed<nsIDocument>
1302 0 : txMozillaXSLTProcessor::TransformToDocument(nsINode& source,
1303 : mozilla::ErrorResult& aRv)
1304 : {
1305 0 : nsCOMPtr<nsIDOMDocument> document;
1306 0 : aRv = TransformToDocument(source.AsDOMNode(), getter_AddRefs(document));
1307 0 : nsCOMPtr<nsIDocument> domDoc = do_QueryInterface(document);
1308 0 : return domDoc.forget();
1309 : }
1310 :
1311 : void
1312 0 : txMozillaXSLTProcessor::SetParameter(JSContext* aCx,
1313 : const nsAString& aNamespaceURI,
1314 : const nsAString& aLocalName,
1315 : JS::Handle<JS::Value> aValue,
1316 : mozilla::ErrorResult& aRv)
1317 : {
1318 0 : nsCOMPtr<nsIVariant> val;
1319 0 : aRv = nsContentUtils::XPConnect()->JSToVariant(aCx, aValue,
1320 0 : getter_AddRefs(val));
1321 0 : if (aRv.Failed()) {
1322 0 : return;
1323 : }
1324 0 : aRv = SetParameter(aNamespaceURI, aLocalName, val);
1325 : }
1326 :
1327 : nsIVariant*
1328 0 : txMozillaXSLTProcessor::GetParameter(const nsAString& aNamespaceURI,
1329 : const nsAString& aLocalName,
1330 : mozilla::ErrorResult& aRv)
1331 : {
1332 0 : nsCOMPtr<nsIVariant> val;
1333 0 : aRv = GetParameter(aNamespaceURI, aLocalName, getter_AddRefs(val));
1334 0 : return val;
1335 : }
1336 :
1337 : /* static*/
1338 : nsresult
1339 3 : txMozillaXSLTProcessor::Startup()
1340 : {
1341 3 : if (!txXSLTProcessor::init()) {
1342 0 : return NS_ERROR_OUT_OF_MEMORY;
1343 : }
1344 :
1345 : nsCOMPtr<nsIErrorService> errorService =
1346 6 : do_GetService(NS_ERRORSERVICE_CONTRACTID);
1347 3 : if (errorService) {
1348 3 : errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_XSLT,
1349 3 : XSLT_MSGS_URL);
1350 : }
1351 :
1352 3 : return NS_OK;
1353 : }
1354 :
1355 : /* static*/
1356 : void
1357 0 : txMozillaXSLTProcessor::Shutdown()
1358 : {
1359 0 : txXSLTProcessor::shutdown();
1360 :
1361 : nsCOMPtr<nsIErrorService> errorService =
1362 0 : do_GetService(NS_ERRORSERVICE_CONTRACTID);
1363 0 : if (errorService) {
1364 0 : errorService->UnregisterErrorStringBundle(NS_ERROR_MODULE_XSLT);
1365 : }
1366 0 : }
1367 :
1368 : /* static*/
1369 : nsresult
1370 0 : txVariable::Convert(nsIVariant *aValue, txAExprResult** aResult)
1371 : {
1372 0 : *aResult = nullptr;
1373 :
1374 : uint16_t dataType;
1375 0 : aValue->GetDataType(&dataType);
1376 0 : switch (dataType) {
1377 : // Number
1378 : case nsIDataType::VTYPE_INT8:
1379 : case nsIDataType::VTYPE_INT16:
1380 : case nsIDataType::VTYPE_INT32:
1381 : case nsIDataType::VTYPE_INT64:
1382 : case nsIDataType::VTYPE_UINT8:
1383 : case nsIDataType::VTYPE_UINT16:
1384 : case nsIDataType::VTYPE_UINT32:
1385 : case nsIDataType::VTYPE_UINT64:
1386 : case nsIDataType::VTYPE_FLOAT:
1387 : case nsIDataType::VTYPE_DOUBLE:
1388 : {
1389 : double value;
1390 0 : nsresult rv = aValue->GetAsDouble(&value);
1391 0 : NS_ENSURE_SUCCESS(rv, rv);
1392 :
1393 0 : *aResult = new NumberResult(value, nullptr);
1394 0 : NS_ADDREF(*aResult);
1395 :
1396 0 : return NS_OK;
1397 : }
1398 :
1399 : // Boolean
1400 : case nsIDataType::VTYPE_BOOL:
1401 : {
1402 : bool value;
1403 0 : nsresult rv = aValue->GetAsBool(&value);
1404 0 : NS_ENSURE_SUCCESS(rv, rv);
1405 :
1406 0 : *aResult = new BooleanResult(value);
1407 0 : NS_ADDREF(*aResult);
1408 :
1409 0 : return NS_OK;
1410 : }
1411 :
1412 : // String
1413 : case nsIDataType::VTYPE_CHAR:
1414 : case nsIDataType::VTYPE_WCHAR:
1415 : case nsIDataType::VTYPE_DOMSTRING:
1416 : case nsIDataType::VTYPE_CHAR_STR:
1417 : case nsIDataType::VTYPE_WCHAR_STR:
1418 : case nsIDataType::VTYPE_STRING_SIZE_IS:
1419 : case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1420 : case nsIDataType::VTYPE_UTF8STRING:
1421 : case nsIDataType::VTYPE_CSTRING:
1422 : case nsIDataType::VTYPE_ASTRING:
1423 : {
1424 0 : nsAutoString value;
1425 0 : nsresult rv = aValue->GetAsAString(value);
1426 0 : NS_ENSURE_SUCCESS(rv, rv);
1427 :
1428 0 : *aResult = new StringResult(value, nullptr);
1429 0 : NS_ADDREF(*aResult);
1430 :
1431 0 : return NS_OK;
1432 : }
1433 :
1434 : // Nodeset
1435 : case nsIDataType::VTYPE_INTERFACE:
1436 : case nsIDataType::VTYPE_INTERFACE_IS:
1437 : {
1438 0 : nsCOMPtr<nsISupports> supports;
1439 0 : nsresult rv = aValue->GetAsISupports(getter_AddRefs(supports));
1440 0 : NS_ENSURE_SUCCESS(rv, rv);
1441 :
1442 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
1443 0 : if (node) {
1444 0 : nsAutoPtr<txXPathNode> xpathNode(txXPathNativeNode::createXPathNode(node));
1445 0 : if (!xpathNode) {
1446 0 : return NS_ERROR_FAILURE;
1447 : }
1448 :
1449 0 : *aResult = new txNodeSet(*xpathNode, nullptr);
1450 0 : if (!*aResult) {
1451 0 : return NS_ERROR_OUT_OF_MEMORY;
1452 : }
1453 :
1454 0 : NS_ADDREF(*aResult);
1455 :
1456 0 : return NS_OK;
1457 : }
1458 :
1459 0 : nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(supports);
1460 0 : if (xpathResult) {
1461 0 : return xpathResult->GetExprResult(aResult);
1462 : }
1463 :
1464 0 : nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
1465 0 : if (nodeList) {
1466 0 : RefPtr<txNodeSet> nodeSet = new txNodeSet(nullptr);
1467 0 : if (!nodeSet) {
1468 0 : return NS_ERROR_OUT_OF_MEMORY;
1469 : }
1470 :
1471 : uint32_t length;
1472 0 : nodeList->GetLength(&length);
1473 :
1474 0 : nsCOMPtr<nsIDOMNode> node;
1475 : uint32_t i;
1476 0 : for (i = 0; i < length; ++i) {
1477 0 : nodeList->Item(i, getter_AddRefs(node));
1478 :
1479 : nsAutoPtr<txXPathNode> xpathNode(
1480 0 : txXPathNativeNode::createXPathNode(node));
1481 0 : if (!xpathNode) {
1482 0 : return NS_ERROR_FAILURE;
1483 : }
1484 :
1485 0 : nodeSet->add(*xpathNode);
1486 : }
1487 :
1488 0 : NS_ADDREF(*aResult = nodeSet);
1489 :
1490 0 : return NS_OK;
1491 : }
1492 :
1493 : // Convert random JS Objects to a string.
1494 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
1495 0 : do_QueryInterface(supports);
1496 0 : if (holder) {
1497 0 : JSContext* cx = nsContentUtils::GetCurrentJSContext();
1498 0 : NS_ENSURE_TRUE(cx, NS_ERROR_NOT_AVAILABLE);
1499 :
1500 0 : JS::Rooted<JSObject*> jsobj(cx, holder->GetJSObject());
1501 0 : NS_ENSURE_STATE(jsobj);
1502 :
1503 0 : JS::Rooted<JS::Value> v(cx, JS::ObjectValue(*jsobj));
1504 0 : JS::Rooted<JSString*> str(cx, JS::ToString(cx, v));
1505 0 : NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
1506 :
1507 0 : nsAutoJSString value;
1508 0 : NS_ENSURE_TRUE(value.init(cx, str), NS_ERROR_FAILURE);
1509 :
1510 0 : *aResult = new StringResult(value, nullptr);
1511 0 : NS_ADDREF(*aResult);
1512 :
1513 0 : return NS_OK;
1514 : }
1515 :
1516 0 : break;
1517 : }
1518 :
1519 : case nsIDataType::VTYPE_ARRAY:
1520 : {
1521 : uint16_t type;
1522 : nsIID iid;
1523 : uint32_t count;
1524 : void* array;
1525 0 : nsresult rv = aValue->GetAsArray(&type, &iid, &count, &array);
1526 0 : NS_ENSURE_SUCCESS(rv, rv);
1527 :
1528 0 : NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE ||
1529 : type == nsIDataType::VTYPE_INTERFACE_IS,
1530 : "Huh, we checked this in SetParameter?");
1531 :
1532 0 : nsISupports** values = static_cast<nsISupports**>(array);
1533 :
1534 0 : RefPtr<txNodeSet> nodeSet = new txNodeSet(nullptr);
1535 0 : if (!nodeSet) {
1536 0 : NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, values);
1537 :
1538 0 : return NS_ERROR_OUT_OF_MEMORY;
1539 : }
1540 :
1541 : uint32_t i;
1542 0 : for (i = 0; i < count; ++i) {
1543 0 : nsISupports *supports = values[i];
1544 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
1545 0 : NS_ASSERTION(node, "Huh, we checked this in SetParameter?");
1546 :
1547 : nsAutoPtr<txXPathNode> xpathNode(
1548 0 : txXPathNativeNode::createXPathNode(node));
1549 0 : if (!xpathNode) {
1550 0 : while (i < count) {
1551 0 : NS_RELEASE(values[i]);
1552 0 : ++i;
1553 : }
1554 0 : free(array);
1555 :
1556 0 : return NS_ERROR_FAILURE;
1557 : }
1558 :
1559 0 : nodeSet->add(*xpathNode);
1560 :
1561 0 : NS_RELEASE(supports);
1562 : }
1563 :
1564 0 : free(array);
1565 :
1566 0 : NS_ADDREF(*aResult = nodeSet);
1567 :
1568 0 : return NS_OK;
1569 : }
1570 : }
1571 :
1572 0 : return NS_ERROR_ILLEGAL_VALUE;
1573 : }
|