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 "nsCOMArray.h"
7 : #include "nsIAuthPrompt.h"
8 : #include "nsIDOMNode.h"
9 : #include "nsIDOMDocument.h"
10 : #include "nsIDocument.h"
11 : #include "nsIExpatSink.h"
12 : #include "nsIChannelEventSink.h"
13 : #include "nsIInterfaceRequestor.h"
14 : #include "nsILoadGroup.h"
15 : #include "nsIParser.h"
16 : #include "nsCharsetSource.h"
17 : #include "nsIRequestObserver.h"
18 : #include "nsIScriptSecurityManager.h"
19 : #include "nsContentPolicyUtils.h"
20 : #include "nsIStreamConverterService.h"
21 : #include "nsSyncLoadService.h"
22 : #include "nsIURI.h"
23 : #include "nsIPrincipal.h"
24 : #include "nsIWindowWatcher.h"
25 : #include "nsIXMLContentSink.h"
26 : #include "nsMimeTypes.h"
27 : #include "nsNetUtil.h"
28 : #include "nsParserCIID.h"
29 : #include "nsGkAtoms.h"
30 : #include "txLog.h"
31 : #include "txMozillaXSLTProcessor.h"
32 : #include "txStylesheetCompiler.h"
33 : #include "txXMLUtils.h"
34 : #include "nsAttrName.h"
35 : #include "nsIScriptError.h"
36 : #include "nsIURL.h"
37 : #include "nsError.h"
38 : #include "mozilla/Attributes.h"
39 : #include "mozilla/dom/Element.h"
40 : #include "mozilla/Encoding.h"
41 : #include "mozilla/UniquePtr.h"
42 :
43 : using namespace mozilla;
44 : using mozilla::net::ReferrerPolicy;
45 :
46 : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
47 :
48 : static void
49 0 : getSpec(nsIChannel* aChannel, nsAString& aSpec)
50 : {
51 0 : if (!aChannel) {
52 0 : return;
53 : }
54 :
55 0 : nsCOMPtr<nsIURI> uri;
56 0 : aChannel->GetOriginalURI(getter_AddRefs(uri));
57 0 : if (!uri) {
58 0 : return;
59 : }
60 :
61 0 : nsAutoCString spec;
62 0 : uri->GetSpec(spec);
63 0 : AppendUTF8toUTF16(spec, aSpec);
64 : }
65 :
66 : class txStylesheetSink final : public nsIXMLContentSink,
67 : public nsIExpatSink,
68 : public nsIStreamListener,
69 : public nsIInterfaceRequestor
70 : {
71 : public:
72 : txStylesheetSink(txStylesheetCompiler* aCompiler, nsIParser* aParser);
73 :
74 : NS_DECL_ISUPPORTS
75 : NS_DECL_NSIEXPATSINK
76 : NS_DECL_NSISTREAMLISTENER
77 : NS_DECL_NSIREQUESTOBSERVER
78 : NS_DECL_NSIINTERFACEREQUESTOR
79 :
80 : // nsIContentSink
81 0 : NS_IMETHOD WillParse(void) override { return NS_OK; }
82 : NS_IMETHOD DidBuildModel(bool aTerminated) override;
83 0 : NS_IMETHOD WillInterrupt(void) override { return NS_OK; }
84 0 : NS_IMETHOD WillResume(void) override { return NS_OK; }
85 0 : NS_IMETHOD SetParser(nsParserBase* aParser) override { return NS_OK; }
86 0 : virtual void FlushPendingNotifications(mozilla::FlushType aType) override { }
87 0 : virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding)
88 0 : override { }
89 0 : virtual nsISupports *GetTarget() override { return nullptr; }
90 :
91 : private:
92 : RefPtr<txStylesheetCompiler> mCompiler;
93 : nsCOMPtr<nsIStreamListener> mListener;
94 : nsCOMPtr<nsIParser> mParser;
95 : bool mCheckedForXML;
96 :
97 : protected:
98 0 : ~txStylesheetSink() {}
99 :
100 : // This exists solely to suppress a warning from nsDerivedSafe
101 : txStylesheetSink();
102 : };
103 :
104 0 : txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler,
105 0 : nsIParser* aParser)
106 : : mCompiler(aCompiler)
107 : , mParser(aParser)
108 0 : , mCheckedForXML(false)
109 : {
110 0 : mListener = do_QueryInterface(aParser);
111 0 : }
112 :
113 0 : NS_IMPL_ISUPPORTS(txStylesheetSink,
114 : nsIXMLContentSink,
115 : nsIContentSink,
116 : nsIExpatSink,
117 : nsIStreamListener,
118 : nsIRequestObserver,
119 : nsIInterfaceRequestor)
120 :
121 : NS_IMETHODIMP
122 0 : txStylesheetSink::HandleStartElement(const char16_t *aName,
123 : const char16_t **aAtts,
124 : uint32_t aAttsCount,
125 : uint32_t aLineNumber)
126 : {
127 0 : NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
128 :
129 : nsresult rv =
130 0 : mCompiler->startElement(aName, aAtts, aAttsCount / 2);
131 0 : if (NS_FAILED(rv)) {
132 0 : mCompiler->cancel(rv);
133 :
134 0 : return rv;
135 : }
136 :
137 0 : return NS_OK;
138 : }
139 :
140 : NS_IMETHODIMP
141 0 : txStylesheetSink::HandleEndElement(const char16_t *aName)
142 : {
143 0 : nsresult rv = mCompiler->endElement();
144 0 : if (NS_FAILED(rv)) {
145 0 : mCompiler->cancel(rv);
146 :
147 0 : return rv;
148 : }
149 :
150 0 : return NS_OK;
151 : }
152 :
153 : NS_IMETHODIMP
154 0 : txStylesheetSink::HandleComment(const char16_t *aName)
155 : {
156 0 : return NS_OK;
157 : }
158 :
159 : NS_IMETHODIMP
160 0 : txStylesheetSink::HandleCDataSection(const char16_t *aData,
161 : uint32_t aLength)
162 : {
163 0 : return HandleCharacterData(aData, aLength);
164 : }
165 :
166 : NS_IMETHODIMP
167 0 : txStylesheetSink::HandleDoctypeDecl(const nsAString & aSubset,
168 : const nsAString & aName,
169 : const nsAString & aSystemId,
170 : const nsAString & aPublicId,
171 : nsISupports *aCatalogData)
172 : {
173 0 : return NS_OK;
174 : }
175 :
176 : NS_IMETHODIMP
177 0 : txStylesheetSink::HandleCharacterData(const char16_t *aData,
178 : uint32_t aLength)
179 : {
180 0 : nsresult rv = mCompiler->characters(Substring(aData, aData + aLength));
181 0 : if (NS_FAILED(rv)) {
182 0 : mCompiler->cancel(rv);
183 0 : return rv;
184 : }
185 :
186 0 : return NS_OK;
187 : }
188 :
189 : NS_IMETHODIMP
190 0 : txStylesheetSink::HandleProcessingInstruction(const char16_t *aTarget,
191 : const char16_t *aData)
192 : {
193 0 : return NS_OK;
194 : }
195 :
196 : NS_IMETHODIMP
197 0 : txStylesheetSink::HandleXMLDeclaration(const char16_t *aVersion,
198 : const char16_t *aEncoding,
199 : int32_t aStandalone)
200 : {
201 0 : return NS_OK;
202 : }
203 :
204 : NS_IMETHODIMP
205 0 : txStylesheetSink::ReportError(const char16_t *aErrorText,
206 : const char16_t *aSourceText,
207 : nsIScriptError *aError,
208 : bool *_retval)
209 : {
210 0 : NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
211 :
212 : // The expat driver should report the error.
213 0 : *_retval = true;
214 :
215 0 : mCompiler->cancel(NS_ERROR_FAILURE, aErrorText, aSourceText);
216 :
217 0 : return NS_OK;
218 : }
219 :
220 : NS_IMETHODIMP
221 0 : txStylesheetSink::DidBuildModel(bool aTerminated)
222 : {
223 0 : return mCompiler->doneLoading();
224 : }
225 :
226 : NS_IMETHODIMP
227 0 : txStylesheetSink::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
228 : nsIInputStream *aInputStream,
229 : uint64_t aOffset, uint32_t aCount)
230 : {
231 0 : if (!mCheckedForXML) {
232 0 : nsCOMPtr<nsIDTD> dtd;
233 0 : mParser->GetDTD(getter_AddRefs(dtd));
234 0 : if (dtd) {
235 0 : mCheckedForXML = true;
236 0 : if (!(dtd->GetType() & NS_IPARSER_FLAG_XML)) {
237 0 : nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
238 0 : nsAutoString spec;
239 0 : getSpec(channel, spec);
240 0 : mCompiler->cancel(NS_ERROR_XSLT_WRONG_MIME_TYPE, nullptr,
241 0 : spec.get());
242 :
243 0 : return NS_ERROR_XSLT_WRONG_MIME_TYPE;
244 : }
245 : }
246 : }
247 :
248 0 : return mListener->OnDataAvailable(aRequest, mParser, aInputStream,
249 0 : aOffset, aCount);
250 : }
251 :
252 : NS_IMETHODIMP
253 0 : txStylesheetSink::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
254 : {
255 0 : int32_t charsetSource = kCharsetFromDocTypeDefault;
256 :
257 0 : nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
258 :
259 : // check channel's charset...
260 0 : const Encoding* encoding = nullptr;
261 0 : nsAutoCString charsetVal;
262 0 : if (NS_SUCCEEDED(channel->GetContentCharset(charsetVal))) {
263 0 : encoding = Encoding::ForLabel(charsetVal);
264 0 : if (encoding) {
265 0 : charsetSource = kCharsetFromChannel;
266 : }
267 : }
268 :
269 0 : if (!encoding) {
270 0 : encoding = UTF_8_ENCODING;
271 : }
272 :
273 0 : mParser->SetDocumentCharset(WrapNotNull(encoding), charsetSource);
274 :
275 0 : nsAutoCString contentType;
276 0 : channel->GetContentType(contentType);
277 :
278 : // Time to sniff! Note: this should go away once file channels do
279 : // sniffing themselves.
280 0 : nsCOMPtr<nsIURI> uri;
281 0 : channel->GetURI(getter_AddRefs(uri));
282 : bool sniff;
283 0 : if (NS_SUCCEEDED(uri->SchemeIs("file", &sniff)) && sniff &&
284 0 : contentType.Equals(UNKNOWN_CONTENT_TYPE)) {
285 : nsresult rv;
286 : nsCOMPtr<nsIStreamConverterService> serv =
287 0 : do_GetService("@mozilla.org/streamConverters;1", &rv);
288 0 : if (NS_SUCCEEDED(rv)) {
289 0 : nsCOMPtr<nsIStreamListener> converter;
290 0 : rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
291 : "*/*",
292 : mListener,
293 : mParser,
294 0 : getter_AddRefs(converter));
295 0 : if (NS_SUCCEEDED(rv)) {
296 0 : mListener = converter;
297 : }
298 : }
299 : }
300 :
301 0 : return mListener->OnStartRequest(aRequest, mParser);
302 : }
303 :
304 : NS_IMETHODIMP
305 0 : txStylesheetSink::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
306 : nsresult aStatusCode)
307 : {
308 0 : bool success = true;
309 :
310 0 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
311 0 : if (httpChannel) {
312 0 : Unused << httpChannel->GetRequestSucceeded(&success);
313 : }
314 :
315 0 : nsresult result = aStatusCode;
316 0 : if (!success) {
317 : // XXX We sometimes want to use aStatusCode here, but the parser resets
318 : // it to NS_ERROR_NOINTERFACE because we don't implement
319 : // nsIHTMLContentSink.
320 0 : result = NS_ERROR_XSLT_NETWORK_ERROR;
321 : }
322 0 : else if (!mCheckedForXML) {
323 0 : nsCOMPtr<nsIDTD> dtd;
324 0 : mParser->GetDTD(getter_AddRefs(dtd));
325 0 : if (dtd && !(dtd->GetType() & NS_IPARSER_FLAG_XML)) {
326 0 : result = NS_ERROR_XSLT_WRONG_MIME_TYPE;
327 : }
328 : }
329 :
330 0 : if (NS_FAILED(result)) {
331 0 : nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
332 0 : nsAutoString spec;
333 0 : getSpec(channel, spec);
334 0 : mCompiler->cancel(result, nullptr, spec.get());
335 : }
336 :
337 0 : nsresult rv = mListener->OnStopRequest(aRequest, mParser, aStatusCode);
338 0 : mListener = nullptr;
339 0 : mParser = nullptr;
340 0 : return rv;
341 : }
342 :
343 : NS_IMETHODIMP
344 0 : txStylesheetSink::GetInterface(const nsIID& aIID, void** aResult)
345 : {
346 0 : if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
347 0 : NS_ENSURE_ARG(aResult);
348 0 : *aResult = nullptr;
349 :
350 : nsresult rv;
351 : nsCOMPtr<nsIWindowWatcher> wwatcher =
352 0 : do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
353 0 : NS_ENSURE_SUCCESS(rv, rv);
354 :
355 0 : nsCOMPtr<nsIAuthPrompt> prompt;
356 0 : rv = wwatcher->GetNewAuthPrompter(nullptr, getter_AddRefs(prompt));
357 0 : NS_ENSURE_SUCCESS(rv, rv);
358 :
359 0 : prompt.forget(aResult);
360 :
361 0 : return NS_OK;
362 : }
363 :
364 0 : return NS_ERROR_NO_INTERFACE;
365 : }
366 :
367 : class txCompileObserver final : public txACompileObserver
368 : {
369 : public:
370 : txCompileObserver(txMozillaXSLTProcessor* aProcessor,
371 : nsIDocument* aLoaderDocument);
372 :
373 : TX_DECL_ACOMPILEOBSERVER
374 0 : NS_INLINE_DECL_REFCOUNTING(txCompileObserver)
375 :
376 : nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
377 : nsIPrincipal* aSourcePrincipal,
378 : ReferrerPolicy aReferrerPolicy);
379 :
380 : private:
381 : RefPtr<txMozillaXSLTProcessor> mProcessor;
382 : nsCOMPtr<nsIDocument> mLoaderDocument;
383 :
384 : // This exists solely to suppress a warning from nsDerivedSafe
385 : txCompileObserver();
386 :
387 : // Private destructor, to discourage deletion outside of Release():
388 0 : ~txCompileObserver()
389 0 : {
390 0 : }
391 : };
392 :
393 0 : txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor,
394 0 : nsIDocument* aLoaderDocument)
395 : : mProcessor(aProcessor),
396 0 : mLoaderDocument(aLoaderDocument)
397 : {
398 0 : }
399 :
400 : nsresult
401 0 : txCompileObserver::loadURI(const nsAString& aUri,
402 : const nsAString& aReferrerUri,
403 : ReferrerPolicy aReferrerPolicy,
404 : txStylesheetCompiler* aCompiler)
405 : {
406 0 : if (mProcessor->IsLoadDisabled()) {
407 0 : return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR;
408 : }
409 :
410 0 : nsCOMPtr<nsIURI> uri;
411 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
412 0 : NS_ENSURE_SUCCESS(rv, rv);
413 :
414 0 : nsCOMPtr<nsIURI> referrerUri;
415 0 : rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
416 0 : NS_ENSURE_SUCCESS(rv, rv);
417 :
418 0 : OriginAttributes attrs;
419 : nsCOMPtr<nsIPrincipal> referrerPrincipal =
420 0 : BasePrincipal::CreateCodebasePrincipal(referrerUri, attrs);
421 0 : NS_ENSURE_TRUE(referrerPrincipal, NS_ERROR_FAILURE);
422 :
423 0 : return startLoad(uri, aCompiler, referrerPrincipal, aReferrerPolicy);
424 : }
425 :
426 : void
427 0 : txCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
428 : nsresult aResult,
429 : const char16_t *aErrorText,
430 : const char16_t *aParam)
431 : {
432 0 : if (NS_SUCCEEDED(aResult)) {
433 0 : mProcessor->setStylesheet(aCompiler->getStylesheet());
434 : }
435 : else {
436 0 : mProcessor->reportError(aResult, aErrorText, aParam);
437 : }
438 0 : }
439 :
440 : nsresult
441 0 : txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
442 : nsIPrincipal* aReferrerPrincipal,
443 : ReferrerPolicy aReferrerPolicy)
444 : {
445 0 : nsCOMPtr<nsILoadGroup> loadGroup = mLoaderDocument->GetDocumentLoadGroup();
446 0 : if (!loadGroup) {
447 0 : return NS_ERROR_FAILURE;
448 : }
449 :
450 0 : nsCOMPtr<nsIChannel> channel;
451 0 : nsresult rv = NS_NewChannelWithTriggeringPrincipal(
452 0 : getter_AddRefs(channel),
453 : aUri,
454 : mLoaderDocument,
455 : aReferrerPrincipal, // triggeringPrincipal
456 : nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
457 : nsIContentPolicy::TYPE_XSLT,
458 0 : loadGroup);
459 :
460 0 : NS_ENSURE_SUCCESS(rv, rv);
461 :
462 0 : channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
463 :
464 0 : nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
465 0 : if (httpChannel) {
466 0 : DebugOnly<nsresult> rv;
467 0 : rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
468 0 : NS_LITERAL_CSTRING("*/*"),
469 0 : false);
470 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
471 :
472 0 : nsCOMPtr<nsIURI> referrerURI;
473 0 : aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI));
474 0 : if (referrerURI) {
475 0 : rv = httpChannel->SetReferrerWithPolicy(referrerURI, aReferrerPolicy);
476 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
477 : }
478 : }
479 :
480 0 : nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
481 0 : NS_ENSURE_SUCCESS(rv, rv);
482 :
483 0 : RefPtr<txStylesheetSink> sink = new txStylesheetSink(aCompiler, parser);
484 0 : NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY);
485 :
486 0 : channel->SetNotificationCallbacks(sink);
487 :
488 0 : parser->SetCommand(kLoadAsData);
489 0 : parser->SetContentSink(sink);
490 0 : parser->Parse(aUri);
491 :
492 0 : return channel->AsyncOpen2(sink);
493 : }
494 :
495 : nsresult
496 0 : TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
497 : nsIDocument* aLoaderDocument, ReferrerPolicy aReferrerPolicy)
498 : {
499 0 : nsIPrincipal* principal = aLoaderDocument->NodePrincipal();
500 :
501 0 : nsAutoCString spec;
502 0 : aUri->GetSpec(spec);
503 0 : MOZ_LOG(txLog::xslt, LogLevel::Info, ("TX_LoadSheet: %s\n", spec.get()));
504 :
505 : RefPtr<txCompileObserver> observer =
506 0 : new txCompileObserver(aProcessor, aLoaderDocument);
507 0 : NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY);
508 :
509 : RefPtr<txStylesheetCompiler> compiler =
510 0 : new txStylesheetCompiler(NS_ConvertUTF8toUTF16(spec), aReferrerPolicy,
511 0 : observer);
512 0 : NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
513 :
514 0 : return observer->startLoad(aUri, compiler, principal, aReferrerPolicy);
515 : }
516 :
517 : /**
518 : * handling DOM->txStylesheet
519 : * Observer needs to do synchronous loads.
520 : */
521 : static nsresult
522 0 : handleNode(nsINode* aNode, txStylesheetCompiler* aCompiler)
523 : {
524 0 : nsresult rv = NS_OK;
525 :
526 0 : if (aNode->IsElement()) {
527 0 : dom::Element* element = aNode->AsElement();
528 :
529 0 : uint32_t attsCount = element->GetAttrCount();
530 0 : UniquePtr<txStylesheetAttr[]> atts;
531 0 : if (attsCount > 0) {
532 0 : atts = MakeUnique<txStylesheetAttr[]>(attsCount);
533 : uint32_t counter;
534 0 : for (counter = 0; counter < attsCount; ++counter) {
535 0 : txStylesheetAttr& att = atts[counter];
536 0 : const nsAttrName* name = element->GetAttrNameAt(counter);
537 0 : att.mNamespaceID = name->NamespaceID();
538 0 : att.mLocalName = name->LocalName();
539 0 : att.mPrefix = name->GetPrefix();
540 0 : element->GetAttr(att.mNamespaceID, att.mLocalName, att.mValue);
541 : }
542 : }
543 :
544 0 : mozilla::dom::NodeInfo *ni = element->NodeInfo();
545 :
546 0 : rv = aCompiler->startElement(ni->NamespaceID(),
547 : ni->NameAtom(),
548 : ni->GetPrefixAtom(), atts.get(),
549 0 : attsCount);
550 0 : NS_ENSURE_SUCCESS(rv, rv);
551 :
552 : // explicitly destroy the attrs here since we no longer need it
553 0 : atts = nullptr;
554 :
555 0 : for (nsIContent* child = element->GetFirstChild();
556 0 : child;
557 0 : child = child->GetNextSibling()) {
558 :
559 0 : rv = handleNode(child, aCompiler);
560 0 : NS_ENSURE_SUCCESS(rv, rv);
561 : }
562 :
563 0 : rv = aCompiler->endElement();
564 0 : NS_ENSURE_SUCCESS(rv, rv);
565 : }
566 0 : else if (aNode->IsNodeOfType(nsINode::eTEXT)) {
567 0 : nsAutoString chars;
568 0 : static_cast<nsIContent*>(aNode)->AppendTextTo(chars);
569 0 : rv = aCompiler->characters(chars);
570 0 : NS_ENSURE_SUCCESS(rv, rv);
571 : }
572 0 : else if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
573 0 : for (nsIContent* child = aNode->GetFirstChild();
574 0 : child;
575 0 : child = child->GetNextSibling()) {
576 :
577 0 : rv = handleNode(child, aCompiler);
578 0 : NS_ENSURE_SUCCESS(rv, rv);
579 : }
580 : }
581 :
582 0 : return NS_OK;
583 : }
584 :
585 : class txSyncCompileObserver final : public txACompileObserver
586 : {
587 : public:
588 : explicit txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor);
589 :
590 : TX_DECL_ACOMPILEOBSERVER
591 0 : NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver)
592 :
593 : private:
594 : // Private destructor, to discourage deletion outside of Release():
595 0 : ~txSyncCompileObserver()
596 0 : {
597 0 : }
598 :
599 : RefPtr<txMozillaXSLTProcessor> mProcessor;
600 : };
601 :
602 0 : txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor)
603 0 : : mProcessor(aProcessor)
604 : {
605 0 : }
606 :
607 : nsresult
608 0 : txSyncCompileObserver::loadURI(const nsAString& aUri,
609 : const nsAString& aReferrerUri,
610 : ReferrerPolicy aReferrerPolicy,
611 : txStylesheetCompiler* aCompiler)
612 : {
613 0 : if (mProcessor->IsLoadDisabled()) {
614 0 : return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR;
615 : }
616 :
617 0 : nsCOMPtr<nsIURI> uri;
618 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
619 0 : NS_ENSURE_SUCCESS(rv, rv);
620 :
621 0 : nsCOMPtr<nsIURI> referrerUri;
622 0 : rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
623 0 : NS_ENSURE_SUCCESS(rv, rv);
624 :
625 : nsCOMPtr<nsIPrincipal> referrerPrincipal =
626 0 : BasePrincipal::CreateCodebasePrincipal(referrerUri, OriginAttributes());
627 0 : NS_ENSURE_TRUE(referrerPrincipal, NS_ERROR_FAILURE);
628 :
629 : // This is probably called by js, a loadGroup for the channel doesn't
630 : // make sense.
631 0 : nsCOMPtr<nsINode> source;
632 0 : if (mProcessor) {
633 : source =
634 0 : do_QueryInterface(mProcessor->GetSourceContentModel());
635 : }
636 0 : nsAutoSyncOperation sync(source ? source->OwnerDoc() : nullptr);
637 0 : nsCOMPtr<nsIDOMDocument> document;
638 :
639 0 : rv = nsSyncLoadService::LoadDocument(uri, nsIContentPolicy::TYPE_XSLT,
640 : referrerPrincipal,
641 : nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
642 : nullptr, false,
643 : aReferrerPolicy,
644 0 : getter_AddRefs(document));
645 0 : NS_ENSURE_SUCCESS(rv, rv);
646 :
647 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
648 0 : rv = handleNode(doc, aCompiler);
649 0 : if (NS_FAILED(rv)) {
650 0 : nsAutoCString spec;
651 0 : uri->GetSpec(spec);
652 0 : aCompiler->cancel(rv, nullptr, NS_ConvertUTF8toUTF16(spec).get());
653 0 : return rv;
654 : }
655 :
656 0 : rv = aCompiler->doneLoading();
657 0 : return rv;
658 : }
659 :
660 0 : void txSyncCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
661 : nsresult aResult,
662 : const char16_t *aErrorText,
663 : const char16_t *aParam)
664 : {
665 0 : }
666 :
667 : nsresult
668 0 : TX_CompileStylesheet(nsINode* aNode, txMozillaXSLTProcessor* aProcessor,
669 : txStylesheet** aStylesheet)
670 : {
671 : // If we move GetBaseURI to nsINode this can be simplified.
672 0 : nsCOMPtr<nsIDocument> doc = aNode->OwnerDoc();
673 :
674 0 : nsCOMPtr<nsIURI> uri;
675 0 : if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
676 0 : uri = static_cast<nsIContent*>(aNode)->GetBaseURI();
677 : }
678 : else {
679 0 : NS_ASSERTION(aNode->IsNodeOfType(nsINode::eDOCUMENT), "not a doc");
680 0 : uri = static_cast<nsIDocument*>(aNode)->GetBaseURI();
681 : }
682 0 : NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
683 :
684 0 : nsAutoCString spec;
685 0 : uri->GetSpec(spec);
686 0 : NS_ConvertUTF8toUTF16 baseURI(spec);
687 :
688 0 : nsIURI* docUri = doc->GetDocumentURI();
689 0 : NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE);
690 :
691 : // We need to remove the ref, a URI with a ref would mean that we have an
692 : // embedded stylesheet.
693 0 : docUri->CloneIgnoringRef(getter_AddRefs(uri));
694 0 : NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
695 :
696 0 : uri->GetSpec(spec);
697 0 : NS_ConvertUTF8toUTF16 stylesheetURI(spec);
698 :
699 : RefPtr<txSyncCompileObserver> obs =
700 0 : new txSyncCompileObserver(aProcessor);
701 0 : NS_ENSURE_TRUE(obs, NS_ERROR_OUT_OF_MEMORY);
702 :
703 : RefPtr<txStylesheetCompiler> compiler =
704 0 : new txStylesheetCompiler(stylesheetURI, doc->GetReferrerPolicy(), obs);
705 0 : NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
706 :
707 0 : compiler->setBaseURI(baseURI);
708 :
709 0 : nsresult rv = handleNode(aNode, compiler);
710 0 : if (NS_FAILED(rv)) {
711 0 : compiler->cancel(rv);
712 0 : return rv;
713 : }
714 :
715 0 : rv = compiler->doneLoading();
716 0 : NS_ENSURE_SUCCESS(rv, rv);
717 :
718 0 : *aStylesheet = compiler->getStylesheet();
719 0 : NS_ADDREF(*aStylesheet);
720 :
721 0 : return NS_OK;
722 : }
|