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