gecko-dev/dom/xml/nsXMLPrettyPrinter.cpp
Dorel Luca ac34e1d973 Backed out 16 changesets (bug 1525245) for Android failures. CLOSED TREE
Backed out changeset 9f8a1b410320 (bug 1525245)
Backed out changeset 0ef284a9a1d5 (bug 1525245)
Backed out changeset 835e5f642a03 (bug 1525245)
Backed out changeset 362f5a8d033c (bug 1525245)
Backed out changeset 9da3ab33cf67 (bug 1525245)
Backed out changeset 6aacd2d6e835 (bug 1525245)
Backed out changeset 8ff9e8f45e02 (bug 1525245)
Backed out changeset 2020227181cc (bug 1525245)
Backed out changeset fc3c64c330b9 (bug 1525245)
Backed out changeset 2762bf88e050 (bug 1525245)
Backed out changeset ffc10fdc50a6 (bug 1525245)
Backed out changeset bb6ade1207d7 (bug 1525245)
Backed out changeset 1875eb5085e4 (bug 1525245)
Backed out changeset 7e4f67a6d6f1 (bug 1525245)
Backed out changeset e671fc9581eb (bug 1525245)
Backed out changeset b89f5def8d0d (bug 1525245)
2019-03-06 21:07:49 +02:00

171 lines
5.4 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 "nsXMLPrettyPrinter.h"
#include "nsContentUtils.h"
#include "nsICSSDeclaration.h"
#include "nsIObserver.h"
#include "nsSyncLoadService.h"
#include "nsPIDOMWindow.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "mozilla/dom/Element.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Document.h"
#include "nsVariant.h"
#include "mozilla/dom/CustomEvent.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/txMozillaXSLTProcessor.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter, nsIDocumentObserver, nsIMutationObserver)
nsXMLPrettyPrinter::nsXMLPrettyPrinter()
: mDocument(nullptr), mUnhookPending(false) {}
nsXMLPrettyPrinter::~nsXMLPrettyPrinter() {
NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still");
}
nsresult nsXMLPrettyPrinter::PrettyPrint(Document* aDocument,
bool* aDidPrettyPrint) {
*aDidPrettyPrint = false;
// check the pref
if (!Preferences::GetBool("layout.xml.prettyprint", true)) {
return NS_OK;
}
// Find the root element
RefPtr<Element> rootElement = aDocument->GetRootElement();
NS_ENSURE_TRUE(rootElement, NS_ERROR_UNEXPECTED);
// nsXMLContentSink should not ask us to pretty print an XML doc that comes
// with a CanAttachShadowDOM() == true root element, but just in case:
if (rootElement->CanAttachShadowDOM()) {
MOZ_DIAGNOSTIC_ASSERT(false, "We shouldn't be getting this root element");
return NS_ERROR_UNEXPECTED;
}
// Ok, we should prettyprint. Let's do it!
*aDidPrettyPrint = true;
nsresult rv = NS_OK;
// Load the XSLT
nsCOMPtr<nsIURI> xslUri;
rv = NS_NewURI(
getter_AddRefs(xslUri),
NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Document> xslDocument;
rv = nsSyncLoadService::LoadDocument(
xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nullptr, true,
mozilla::net::RP_Unset, getter_AddRefs(xslDocument));
NS_ENSURE_SUCCESS(rv, rv);
// Transform the document
RefPtr<txMozillaXSLTProcessor> transformer = new txMozillaXSLTProcessor();
ErrorResult err;
transformer->ImportStylesheet(*xslDocument, err);
if (NS_WARN_IF(err.Failed())) {
return err.StealNSResult();
}
RefPtr<DocumentFragment> resultFragment =
transformer->TransformToFragment(*aDocument, *aDocument, err);
if (NS_WARN_IF(err.Failed())) {
return err.StealNSResult();
}
// Attach an UA Widget Shadow Root on it.
rootElement->AttachAndSetUAShadowRoot();
RefPtr<ShadowRoot> shadowRoot = rootElement->GetShadowRoot();
MOZ_RELEASE_ASSERT(shadowRoot && shadowRoot->IsUAWidget(),
"There should be a UA Shadow Root here.");
// Append the document fragment to the shadow dom.
shadowRoot->AppendChild(*resultFragment, err);
if (NS_WARN_IF(err.Failed())) {
return err.StealNSResult();
}
// Observe the document so we know when to switch to "normal" view
aDocument->AddObserver(this);
mDocument = aDocument;
NS_ADDREF_THIS();
return NS_OK;
}
void nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent) {
// If aContent is null, the document-node was modified.
// If it is not null but in the shadow tree or the <scrollbar> NACs,
// the change was in the generated content, and it should be ignored.
bool isGeneratedContent =
!aContent ? false
: aContent->GetBindingParent() || aContent->IsInShadowTree();
if (!isGeneratedContent && !mUnhookPending) {
// Can't blindly to mUnhookPending after AddScriptRunner,
// since AddScriptRunner _could_ in theory run us
// synchronously
mUnhookPending = true;
nsContentUtils::AddScriptRunner(NewRunnableMethod(
"nsXMLPrettyPrinter::Unhook", this, &nsXMLPrettyPrinter::Unhook));
}
}
void nsXMLPrettyPrinter::Unhook() {
mDocument->RemoveObserver(this);
nsCOMPtr<Element> element = mDocument->GetDocumentElement();
if (element) {
// Remove the shadow root
element->UnattachShadow();
}
mDocument = nullptr;
NS_RELEASE_THIS();
}
void nsXMLPrettyPrinter::AttributeChanged(Element* aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue) {
MaybeUnhook(aElement);
}
void nsXMLPrettyPrinter::ContentAppended(nsIContent* aFirstNewContent) {
MaybeUnhook(aFirstNewContent->GetParent());
}
void nsXMLPrettyPrinter::ContentInserted(nsIContent* aChild) {
MaybeUnhook(aChild->GetParent());
}
void nsXMLPrettyPrinter::ContentRemoved(nsIContent* aChild,
nsIContent* aPreviousSibling) {
MaybeUnhook(aChild->GetParent());
}
void nsXMLPrettyPrinter::NodeWillBeDestroyed(const nsINode* aNode) {
mDocument = nullptr;
NS_RELEASE_THIS();
}
nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter) {
*aPrinter = new nsXMLPrettyPrinter;
NS_ADDREF(*aPrinter);
return NS_OK;
}