624 lines
19 KiB
C++
624 lines
19 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsIAuthPrompt.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "nsIExpatSink.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsILoadGroup.h"
|
|
#include "nsParser.h"
|
|
#include "nsCharsetSource.h"
|
|
#include "nsIRequestObserver.h"
|
|
#include "nsContentPolicyUtils.h"
|
|
#include "nsIStreamConverterService.h"
|
|
#include "nsSyncLoadService.h"
|
|
#include "nsIHttpChannel.h"
|
|
#include "nsIURI.h"
|
|
#include "nsIPrincipal.h"
|
|
#include "nsIWindowWatcher.h"
|
|
#include "nsIXMLContentSink.h"
|
|
#include "nsMimeTypes.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "txLog.h"
|
|
#include "txMozillaXSLTProcessor.h"
|
|
#include "txStylesheetCompiler.h"
|
|
#include "txXMLUtils.h"
|
|
#include "nsAttrName.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsIScriptError.h"
|
|
#include "nsError.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#include "mozilla/dom/Text.h"
|
|
#include "mozilla/Encoding.h"
|
|
#include "mozilla/UniquePtr.h"
|
|
#include "ReferrerInfo.h"
|
|
|
|
using namespace mozilla;
|
|
using mozilla::dom::Document;
|
|
using mozilla::dom::ReferrerPolicy;
|
|
|
|
static void getSpec(nsIChannel* aChannel, nsAString& aSpec) {
|
|
if (!aChannel) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
|
if (!uri) {
|
|
return;
|
|
}
|
|
|
|
nsAutoCString spec;
|
|
uri->GetSpec(spec);
|
|
AppendUTF8toUTF16(spec, aSpec);
|
|
}
|
|
|
|
class txStylesheetSink final : public nsIXMLContentSink,
|
|
public nsIExpatSink,
|
|
public nsIStreamListener,
|
|
public nsIInterfaceRequestor {
|
|
public:
|
|
txStylesheetSink(txStylesheetCompiler* aCompiler, nsParser* aParser);
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIEXPATSINK
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
NS_DECL_NSIINTERFACEREQUESTOR
|
|
|
|
// nsIContentSink
|
|
NS_IMETHOD WillParse(void) override { return NS_OK; }
|
|
NS_IMETHOD DidBuildModel(bool aTerminated) override;
|
|
NS_IMETHOD WillInterrupt(void) override { return NS_OK; }
|
|
void WillResume() override {}
|
|
NS_IMETHOD SetParser(nsParserBase* aParser) override { return NS_OK; }
|
|
virtual void FlushPendingNotifications(mozilla::FlushType aType) override {}
|
|
virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override {
|
|
}
|
|
virtual nsISupports* GetTarget() override { return nullptr; }
|
|
|
|
private:
|
|
RefPtr<txStylesheetCompiler> mCompiler;
|
|
nsCOMPtr<nsIStreamListener> mListener;
|
|
RefPtr<nsParser> mParser;
|
|
bool mCheckedForXML;
|
|
|
|
protected:
|
|
~txStylesheetSink() = default;
|
|
|
|
// This exists solely to suppress a warning from nsDerivedSafe
|
|
txStylesheetSink();
|
|
};
|
|
|
|
txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler,
|
|
nsParser* aParser)
|
|
: mCompiler(aCompiler),
|
|
mListener(aParser),
|
|
mParser(aParser),
|
|
mCheckedForXML(false) {}
|
|
|
|
NS_IMPL_ISUPPORTS(txStylesheetSink, nsIXMLContentSink, nsIContentSink,
|
|
nsIExpatSink, nsIStreamListener, nsIRequestObserver,
|
|
nsIInterfaceRequestor)
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleStartElement(const char16_t* aName,
|
|
const char16_t** aAtts,
|
|
uint32_t aAttsCount, uint32_t aLineNumber,
|
|
uint32_t aColumnNumber) {
|
|
MOZ_ASSERT(aAttsCount % 2 == 0, "incorrect aAttsCount");
|
|
|
|
nsresult rv = mCompiler->startElement(aName, aAtts, aAttsCount / 2);
|
|
if (NS_FAILED(rv)) {
|
|
mCompiler->cancel(rv);
|
|
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleEndElement(const char16_t* aName) {
|
|
nsresult rv = mCompiler->endElement();
|
|
if (NS_FAILED(rv)) {
|
|
mCompiler->cancel(rv);
|
|
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleComment(const char16_t* aName) { return NS_OK; }
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleCDataSection(const char16_t* aData, uint32_t aLength) {
|
|
return HandleCharacterData(aData, aLength);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleDoctypeDecl(const nsAString& aSubset,
|
|
const nsAString& aName,
|
|
const nsAString& aSystemId,
|
|
const nsAString& aPublicId,
|
|
nsISupports* aCatalogData) {
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleCharacterData(const char16_t* aData, uint32_t aLength) {
|
|
nsresult rv = mCompiler->characters(Substring(aData, aData + aLength));
|
|
if (NS_FAILED(rv)) {
|
|
mCompiler->cancel(rv);
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleProcessingInstruction(const char16_t* aTarget,
|
|
const char16_t* aData) {
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::HandleXMLDeclaration(const char16_t* aVersion,
|
|
const char16_t* aEncoding,
|
|
int32_t aStandalone) {
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::ReportError(const char16_t* aErrorText,
|
|
const char16_t* aSourceText,
|
|
nsIScriptError* aError, bool* _retval) {
|
|
MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
|
|
|
|
// The expat driver should report the error.
|
|
*_retval = true;
|
|
|
|
mCompiler->cancel(NS_ERROR_FAILURE, aErrorText, aSourceText);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::DidBuildModel(bool aTerminated) {
|
|
return mCompiler->doneLoading();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::OnDataAvailable(nsIRequest* aRequest,
|
|
nsIInputStream* aInputStream,
|
|
uint64_t aOffset, uint32_t aCount) {
|
|
if (!mCheckedForXML) {
|
|
Maybe<bool> isForXML = mParser->IsForParsingXML();
|
|
mCheckedForXML = isForXML.isSome();
|
|
if (mCheckedForXML && !isForXML.value()) {
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
|
nsAutoString spec;
|
|
getSpec(channel, spec);
|
|
mCompiler->cancel(NS_ERROR_XSLT_WRONG_MIME_TYPE, nullptr, spec.get());
|
|
|
|
return NS_ERROR_XSLT_WRONG_MIME_TYPE;
|
|
}
|
|
}
|
|
|
|
return mListener->OnDataAvailable(aRequest, aInputStream, aOffset, aCount);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::OnStartRequest(nsIRequest* aRequest) {
|
|
int32_t charsetSource = kCharsetFromDocTypeDefault;
|
|
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
|
|
|
// check channel's charset...
|
|
const Encoding* encoding = nullptr;
|
|
nsAutoCString charsetVal;
|
|
if (NS_SUCCEEDED(channel->GetContentCharset(charsetVal))) {
|
|
encoding = Encoding::ForLabel(charsetVal);
|
|
if (encoding) {
|
|
charsetSource = kCharsetFromChannel;
|
|
}
|
|
}
|
|
|
|
if (!encoding) {
|
|
encoding = UTF_8_ENCODING;
|
|
}
|
|
|
|
mParser->SetDocumentCharset(WrapNotNull(encoding), charsetSource, false);
|
|
|
|
nsAutoCString contentType;
|
|
channel->GetContentType(contentType);
|
|
|
|
// Time to sniff! Note: this should go away once file channels do
|
|
// sniffing themselves.
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsAutoCString spec;
|
|
uri->GetSpec(spec);
|
|
NS_ConvertUTF8toUTF16 baseURI(spec);
|
|
mCompiler->setBaseURI(
|
|
baseURI); // Redirections potentially impact the Base URI, always update
|
|
// the base URI with the final URL.
|
|
if (uri->SchemeIs("file") &&
|
|
contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
|
|
nsresult rv;
|
|
nsCOMPtr<nsIStreamConverterService> serv =
|
|
do_GetService("@mozilla.org/streamConverters;1", &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsIStreamListener> converter;
|
|
rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE, "*/*", mListener,
|
|
NS_ISUPPORTS_CAST(nsIParser*, mParser),
|
|
getter_AddRefs(converter));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mListener = converter;
|
|
}
|
|
}
|
|
}
|
|
|
|
return mListener->OnStartRequest(aRequest);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
|
|
bool success = true;
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
|
|
if (httpChannel) {
|
|
Unused << httpChannel->GetRequestSucceeded(&success);
|
|
}
|
|
|
|
nsresult result = aStatusCode;
|
|
if (!success) {
|
|
// XXX We sometimes want to use aStatusCode here, but the parser resets
|
|
// it to NS_ERROR_NOINTERFACE because we don't implement
|
|
// nsIHTMLContentSink.
|
|
result = NS_ERROR_XSLT_NETWORK_ERROR;
|
|
} else if (!mCheckedForXML) {
|
|
Maybe<bool> isForXML = mParser->IsForParsingXML();
|
|
if (isForXML.isSome() && !isForXML.value()) {
|
|
result = NS_ERROR_XSLT_WRONG_MIME_TYPE;
|
|
}
|
|
}
|
|
|
|
if (NS_FAILED(result)) {
|
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
|
nsAutoString spec;
|
|
getSpec(channel, spec);
|
|
mCompiler->cancel(result, nullptr, spec.get());
|
|
}
|
|
|
|
nsresult rv = mListener->OnStopRequest(aRequest, aStatusCode);
|
|
mListener = nullptr;
|
|
mParser = nullptr;
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
txStylesheetSink::GetInterface(const nsIID& aIID, void** aResult) {
|
|
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
|
|
NS_ENSURE_ARG(aResult);
|
|
*aResult = nullptr;
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsIWindowWatcher> wwatcher =
|
|
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIAuthPrompt> prompt;
|
|
rv = wwatcher->GetNewAuthPrompter(nullptr, getter_AddRefs(prompt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
prompt.forget(aResult);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
}
|
|
|
|
class txCompileObserver final : public txACompileObserver {
|
|
public:
|
|
txCompileObserver(txMozillaXSLTProcessor* aProcessor,
|
|
Document* aLoaderDocument);
|
|
|
|
TX_DECL_ACOMPILEOBSERVER
|
|
NS_INLINE_DECL_REFCOUNTING(txCompileObserver, override)
|
|
|
|
nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
|
nsIPrincipal* aSourcePrincipal,
|
|
ReferrerPolicy aReferrerPolicy);
|
|
|
|
private:
|
|
RefPtr<txMozillaXSLTProcessor> mProcessor;
|
|
nsCOMPtr<Document> mLoaderDocument;
|
|
|
|
// This exists solely to suppress a warning from nsDerivedSafe
|
|
txCompileObserver();
|
|
|
|
// Private destructor, to discourage deletion outside of Release():
|
|
~txCompileObserver() = default;
|
|
};
|
|
|
|
txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor,
|
|
Document* aLoaderDocument)
|
|
: mProcessor(aProcessor), mLoaderDocument(aLoaderDocument) {}
|
|
|
|
nsresult txCompileObserver::loadURI(const nsAString& aUri,
|
|
const nsAString& aReferrerUri,
|
|
ReferrerPolicy aReferrerPolicy,
|
|
txStylesheetCompiler* aCompiler) {
|
|
if (mProcessor->IsLoadDisabled()) {
|
|
return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIURI> referrerUri;
|
|
rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
OriginAttributes attrs;
|
|
nsCOMPtr<nsIPrincipal> referrerPrincipal =
|
|
BasePrincipal::CreateContentPrincipal(referrerUri, attrs);
|
|
NS_ENSURE_TRUE(referrerPrincipal, NS_ERROR_FAILURE);
|
|
|
|
return startLoad(uri, aCompiler, referrerPrincipal, aReferrerPolicy);
|
|
}
|
|
|
|
void txCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
|
|
nsresult aResult,
|
|
const char16_t* aErrorText,
|
|
const char16_t* aParam) {
|
|
if (NS_SUCCEEDED(aResult)) {
|
|
mProcessor->setStylesheet(aCompiler->getStylesheet());
|
|
} else {
|
|
mProcessor->reportError(aResult, aErrorText, aParam);
|
|
}
|
|
}
|
|
|
|
nsresult txCompileObserver::startLoad(nsIURI* aUri,
|
|
txStylesheetCompiler* aCompiler,
|
|
nsIPrincipal* aReferrerPrincipal,
|
|
ReferrerPolicy aReferrerPolicy) {
|
|
nsCOMPtr<nsILoadGroup> loadGroup = mLoaderDocument->GetDocumentLoadGroup();
|
|
if (!loadGroup) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
nsresult rv = NS_NewChannelWithTriggeringPrincipal(
|
|
getter_AddRefs(channel), aUri, mLoaderDocument,
|
|
aReferrerPrincipal, // triggeringPrincipal
|
|
nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT,
|
|
nsIContentPolicy::TYPE_XSLT,
|
|
nullptr, // aPerformanceStorage
|
|
loadGroup);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
channel->SetContentType("text/xml"_ns);
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
|
if (httpChannel) {
|
|
nsCOMPtr<nsIReferrerInfo> referrerInfo;
|
|
nsresult rv = aReferrerPrincipal->CreateReferrerInfo(
|
|
aReferrerPolicy, getter_AddRefs(referrerInfo));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
}
|
|
}
|
|
|
|
RefPtr<nsParser> parser = new nsParser();
|
|
RefPtr<txStylesheetSink> sink = new txStylesheetSink(aCompiler, parser);
|
|
|
|
channel->SetNotificationCallbacks(sink);
|
|
|
|
parser->SetCommand(kLoadAsData);
|
|
parser->SetContentSink(sink);
|
|
parser->Parse(aUri);
|
|
|
|
return channel->AsyncOpen(sink);
|
|
}
|
|
|
|
nsresult TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
|
|
Document* aLoaderDocument,
|
|
ReferrerPolicy aReferrerPolicy) {
|
|
nsIPrincipal* principal = aLoaderDocument->NodePrincipal();
|
|
|
|
nsAutoCString spec;
|
|
aUri->GetSpec(spec);
|
|
MOZ_LOG(txLog::xslt, LogLevel::Info, ("TX_LoadSheet: %s\n", spec.get()));
|
|
|
|
RefPtr<txCompileObserver> observer =
|
|
new txCompileObserver(aProcessor, aLoaderDocument);
|
|
|
|
RefPtr<txStylesheetCompiler> compiler = new txStylesheetCompiler(
|
|
NS_ConvertUTF8toUTF16(spec), aReferrerPolicy, observer);
|
|
|
|
return observer->startLoad(aUri, compiler, principal, aReferrerPolicy);
|
|
}
|
|
|
|
/**
|
|
* handling DOM->txStylesheet
|
|
* Observer needs to do synchronous loads.
|
|
*/
|
|
static nsresult handleNode(nsINode* aNode, txStylesheetCompiler* aCompiler) {
|
|
nsresult rv = NS_OK;
|
|
|
|
if (aNode->IsElement()) {
|
|
dom::Element* element = aNode->AsElement();
|
|
|
|
uint32_t attsCount = element->GetAttrCount();
|
|
UniquePtr<txStylesheetAttr[]> atts;
|
|
if (attsCount > 0) {
|
|
atts = MakeUnique<txStylesheetAttr[]>(attsCount);
|
|
uint32_t counter;
|
|
for (counter = 0; counter < attsCount; ++counter) {
|
|
txStylesheetAttr& att = atts[counter];
|
|
const nsAttrName* name = element->GetAttrNameAt(counter);
|
|
att.mNamespaceID = name->NamespaceID();
|
|
att.mLocalName = name->LocalName();
|
|
att.mPrefix = name->GetPrefix();
|
|
element->GetAttr(att.mNamespaceID, att.mLocalName, att.mValue);
|
|
}
|
|
}
|
|
|
|
mozilla::dom::NodeInfo* ni = element->NodeInfo();
|
|
|
|
rv = aCompiler->startElement(ni->NamespaceID(), ni->NameAtom(),
|
|
ni->GetPrefixAtom(), atts.get(), attsCount);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// explicitly destroy the attrs here since we no longer need it
|
|
atts = nullptr;
|
|
|
|
for (nsCOMPtr<nsIContent> child = element->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
rv = handleNode(child, aCompiler);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
rv = aCompiler->endElement();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
} else if (dom::Text* text = aNode->GetAsText()) {
|
|
nsAutoString chars;
|
|
text->AppendTextTo(chars);
|
|
rv = aCompiler->characters(chars);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
} else if (aNode->IsDocument()) {
|
|
for (nsCOMPtr<nsIContent> child = aNode->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
rv = handleNode(child, aCompiler);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
class txSyncCompileObserver final : public txACompileObserver {
|
|
public:
|
|
explicit txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor);
|
|
|
|
TX_DECL_ACOMPILEOBSERVER
|
|
NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver, override)
|
|
|
|
private:
|
|
// Private destructor, to discourage deletion outside of Release():
|
|
~txSyncCompileObserver() = default;
|
|
|
|
RefPtr<txMozillaXSLTProcessor> mProcessor;
|
|
};
|
|
|
|
txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor)
|
|
: mProcessor(aProcessor) {}
|
|
|
|
nsresult txSyncCompileObserver::loadURI(const nsAString& aUri,
|
|
const nsAString& aReferrerUri,
|
|
ReferrerPolicy aReferrerPolicy,
|
|
txStylesheetCompiler* aCompiler) {
|
|
if (mProcessor->IsLoadDisabled()) {
|
|
return NS_ERROR_XSLT_LOAD_BLOCKED_ERROR;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
do_QueryInterface(mProcessor->GetParentObject());
|
|
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
|
nsCOMPtr<Document> loaderDoc = window->GetExtantDoc();
|
|
NS_ENSURE_TRUE(loaderDoc, NS_ERROR_FAILURE);
|
|
|
|
// This is probably called by js, a loadGroup for the channel doesn't
|
|
// make sense.
|
|
nsCOMPtr<nsINode> source = mProcessor->GetSourceContentModel();
|
|
dom::nsAutoSyncOperation sync(source ? source->OwnerDoc() : nullptr,
|
|
dom::SyncOperationBehavior::eSuspendInput);
|
|
nsCOMPtr<Document> document;
|
|
|
|
rv = nsSyncLoadService::LoadDocument(
|
|
uri, nsIContentPolicy::TYPE_XSLT, loaderDoc,
|
|
/* aLoaderPrincipal */ nullptr,
|
|
nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT, nullptr, nullptr,
|
|
false, aReferrerPolicy, getter_AddRefs(document));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = handleNode(document, aCompiler);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoCString spec;
|
|
uri->GetSpec(spec);
|
|
aCompiler->cancel(rv, nullptr, NS_ConvertUTF8toUTF16(spec).get());
|
|
return rv;
|
|
}
|
|
|
|
rv = aCompiler->doneLoading();
|
|
return rv;
|
|
}
|
|
|
|
void txSyncCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
|
|
nsresult aResult,
|
|
const char16_t* aErrorText,
|
|
const char16_t* aParam) {}
|
|
|
|
nsresult TX_CompileStylesheet(nsINode* aNode,
|
|
txMozillaXSLTProcessor* aProcessor,
|
|
txStylesheet** aStylesheet) {
|
|
// If we move GetBaseURI to nsINode this can be simplified.
|
|
nsCOMPtr<Document> doc = aNode->OwnerDoc();
|
|
|
|
nsIURI* nodeBaseURI = aNode->GetBaseURI();
|
|
NS_ENSURE_TRUE(nodeBaseURI, NS_ERROR_FAILURE);
|
|
|
|
nsAutoCString spec;
|
|
nodeBaseURI->GetSpec(spec);
|
|
NS_ConvertUTF8toUTF16 baseURI(spec);
|
|
|
|
nsIURI* docUri = doc->GetDocumentURI();
|
|
NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE);
|
|
|
|
// We need to remove the ref, a URI with a ref would mean that we have an
|
|
// embedded stylesheet.
|
|
nsCOMPtr<nsIURI> uri;
|
|
NS_GetURIWithoutRef(docUri, getter_AddRefs(uri));
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
|
|
|
uri->GetSpec(spec);
|
|
NS_ConvertUTF8toUTF16 stylesheetURI(spec);
|
|
|
|
RefPtr<txSyncCompileObserver> obs = new txSyncCompileObserver(aProcessor);
|
|
|
|
RefPtr<txStylesheetCompiler> compiler =
|
|
new txStylesheetCompiler(stylesheetURI, doc->GetReferrerPolicy(), obs);
|
|
|
|
compiler->setBaseURI(baseURI);
|
|
|
|
nsresult rv = handleNode(aNode, compiler);
|
|
if (NS_FAILED(rv)) {
|
|
compiler->cancel(rv);
|
|
return rv;
|
|
}
|
|
|
|
rv = compiler->doneLoading();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
*aStylesheet = compiler->getStylesheet();
|
|
NS_ADDREF(*aStylesheet);
|
|
|
|
return NS_OK;
|
|
}
|