2018-11-30 19:52:05 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2017-07-06 12:00:35 +00:00
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
#include "nsXMLPrettyPrinter.h"
|
2004-04-29 23:34:19 +00:00
|
|
|
#include "nsContentUtils.h"
|
2015-10-26 21:37:32 +00:00
|
|
|
#include "nsICSSDeclaration.h"
|
2002-10-22 05:28:36 +00:00
|
|
|
#include "nsIObserver.h"
|
2006-06-15 20:30:44 +00:00
|
|
|
#include "nsSyncLoadService.h"
|
2005-11-28 23:56:44 +00:00
|
|
|
#include "nsPIDOMWindow.h"
|
2002-10-22 05:28:36 +00:00
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsNetUtil.h"
|
2010-08-24 07:05:56 +00:00
|
|
|
#include "mozilla/dom/Element.h"
|
2010-08-28 05:54:28 +00:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
2011-05-25 06:31:59 +00:00
|
|
|
#include "mozilla/Preferences.h"
|
2019-01-02 13:05:23 +00:00
|
|
|
#include "mozilla/dom/Document.h"
|
2013-10-03 14:02:36 +00:00
|
|
|
#include "nsVariant.h"
|
2015-08-12 11:39:31 +00:00
|
|
|
#include "mozilla/dom/CustomEvent.h"
|
2018-02-05 21:00:04 +00:00
|
|
|
#include "mozilla/dom/DocumentFragment.h"
|
2018-03-26 18:53:51 +00:00
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
|
|
#include "mozilla/dom/ToJSValue.h"
|
2018-02-05 21:00:04 +00:00
|
|
|
#include "mozilla/dom/txMozillaXSLTProcessor.h"
|
2002-10-22 05:28:36 +00:00
|
|
|
|
2011-05-25 06:31:59 +00:00
|
|
|
using namespace mozilla;
|
2010-08-24 07:05:56 +00:00
|
|
|
using namespace mozilla::dom;
|
|
|
|
|
2014-04-27 07:06:00 +00:00
|
|
|
NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter, nsIDocumentObserver, nsIMutationObserver)
|
2002-10-22 05:28:36 +00:00
|
|
|
|
2012-07-30 14:20:58 +00:00
|
|
|
nsXMLPrettyPrinter::nsXMLPrettyPrinter()
|
2011-10-17 14:59:28 +00:00
|
|
|
: mDocument(nullptr), mUnhookPending(false) {}
|
2002-10-22 05:28:36 +00:00
|
|
|
|
|
|
|
nsXMLPrettyPrinter::~nsXMLPrettyPrinter() {
|
|
|
|
NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still");
|
|
|
|
}
|
|
|
|
|
2019-01-02 13:05:23 +00:00
|
|
|
nsresult nsXMLPrettyPrinter::PrettyPrint(Document* aDocument,
|
2006-06-15 20:30:44 +00:00
|
|
|
bool* aDidPrettyPrint) {
|
2017-12-05 17:05:51 +00:00
|
|
|
*aDidPrettyPrint = false;
|
2002-10-22 05:28:36 +00:00
|
|
|
|
|
|
|
// check the pref
|
2011-09-29 06:19:26 +00:00
|
|
|
if (!Preferences::GetBool("layout.xml.prettyprint", true)) {
|
2002-10-22 05:28:36 +00:00
|
|
|
return NS_OK;
|
2018-11-30 10:46:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-31 18:33:30 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
// Ok, we should prettyprint. Let's do it!
|
2011-10-17 14:59:28 +00:00
|
|
|
*aDidPrettyPrint = true;
|
2002-10-22 05:28:36 +00:00
|
|
|
nsresult rv = NS_OK;
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
// Load the XSLT
|
|
|
|
nsCOMPtr<nsIURI> xslUri;
|
|
|
|
rv = NS_NewURI(
|
|
|
|
getter_AddRefs(xslUri),
|
2005-05-20 16:42:15 +00:00
|
|
|
NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
|
2002-10-22 05:28:36 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2019-01-02 13:05:23 +00:00
|
|
|
nsCOMPtr<Document> xslDocument;
|
2015-10-26 21:22:59 +00:00
|
|
|
rv = nsSyncLoadService::LoadDocument(
|
|
|
|
xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(),
|
|
|
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nullptr, true,
|
2017-01-05 03:29:56 +00:00
|
|
|
mozilla::net::RP_Unset, getter_AddRefs(xslDocument));
|
2002-10-22 05:28:36 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
// Transform the document
|
2018-02-05 21:00:04 +00:00
|
|
|
RefPtr<txMozillaXSLTProcessor> transformer = new txMozillaXSLTProcessor();
|
2018-02-05 21:00:04 +00:00
|
|
|
ErrorResult err;
|
2018-05-11 17:46:15 +00:00
|
|
|
transformer->ImportStylesheet(*xslDocument, err);
|
2018-02-05 21:00:04 +00:00
|
|
|
if (NS_WARN_IF(err.Failed())) {
|
|
|
|
return err.StealNSResult();
|
2018-11-30 10:46:48 +00:00
|
|
|
}
|
|
|
|
|
2018-02-05 21:00:04 +00:00
|
|
|
RefPtr<DocumentFragment> resultFragment =
|
|
|
|
transformer->TransformToFragment(*aDocument, *aDocument, err);
|
2018-02-05 21:00:04 +00:00
|
|
|
if (NS_WARN_IF(err.Failed())) {
|
|
|
|
return err.StealNSResult();
|
2018-11-30 10:46:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 18:38:57 +00:00
|
|
|
// 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.");
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2018-11-15 06:51:07 +00:00
|
|
|
// Append the document fragment to the shadow dom.
|
|
|
|
shadowRoot->AppendChild(*resultFragment, err);
|
|
|
|
if (NS_WARN_IF(err.Failed())) {
|
|
|
|
return err.StealNSResult();
|
2018-11-30 10:46:48 +00:00
|
|
|
}
|
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
// Observe the document so we know when to switch to "normal" view
|
|
|
|
aDocument->AddObserver(this);
|
|
|
|
mDocument = aDocument;
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
NS_ADDREF_THIS();
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2002-10-22 05:28:36 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent) {
|
2018-06-01 09:45:11 +00:00
|
|
|
// If aContent is null, the document-node was modified.
|
2018-11-15 06:51:07 +00:00
|
|
|
// 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.
|
2018-06-01 09:45:11 +00:00
|
|
|
bool isGeneratedContent =
|
|
|
|
!aContent ? false
|
|
|
|
: aContent->GetBindingParent() || aContent->IsInShadowTree();
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2018-06-01 09:45:11 +00:00
|
|
|
if (!isGeneratedContent && !mUnhookPending) {
|
2011-05-31 21:26:13 +00:00
|
|
|
// Can't blindly to mUnhookPending after AddScriptRunner,
|
|
|
|
// since AddScriptRunner _could_ in theory run us
|
|
|
|
// synchronously
|
2011-10-17 14:59:28 +00:00
|
|
|
mUnhookPending = true;
|
2017-06-12 19:34:10 +00:00
|
|
|
nsContentUtils::AddScriptRunner(NewRunnableMethod(
|
|
|
|
"nsXMLPrettyPrinter::Unhook", this, &nsXMLPrettyPrinter::Unhook));
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-31 21:26:13 +00:00
|
|
|
void nsXMLPrettyPrinter::Unhook() {
|
|
|
|
mDocument->RemoveObserver(this);
|
2013-01-24 17:45:50 +00:00
|
|
|
nsCOMPtr<Element> element = mDocument->GetDocumentElement();
|
|
|
|
|
|
|
|
if (element) {
|
2018-06-01 09:45:11 +00:00
|
|
|
// Remove the shadow root
|
|
|
|
element->UnattachShadow();
|
2011-05-31 21:26:13 +00:00
|
|
|
}
|
2002-10-22 05:28:36 +00:00
|
|
|
|
2012-07-30 14:20:58 +00:00
|
|
|
mDocument = nullptr;
|
2002-10-22 05:28:36 +00:00
|
|
|
|
2011-05-31 21:26:13 +00:00
|
|
|
NS_RELEASE_THIS();
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 11:36:58 +00:00
|
|
|
void nsXMLPrettyPrinter::AttributeChanged(Element* aElement,
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t aNameSpaceID,
|
2017-10-02 22:05:19 +00:00
|
|
|
nsAtom* aAttribute, int32_t aModType,
|
2015-07-25 06:01:19 +00:00
|
|
|
const nsAttrValue* aOldValue) {
|
2010-08-24 07:05:56 +00:00
|
|
|
MaybeUnhook(aElement);
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 11:36:58 +00:00
|
|
|
void nsXMLPrettyPrinter::ContentAppended(nsIContent* aFirstNewContent) {
|
|
|
|
MaybeUnhook(aFirstNewContent->GetParent());
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 11:36:58 +00:00
|
|
|
void nsXMLPrettyPrinter::ContentInserted(nsIContent* aChild) {
|
|
|
|
MaybeUnhook(aChild->GetParent());
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 11:36:58 +00:00
|
|
|
void nsXMLPrettyPrinter::ContentRemoved(nsIContent* aChild,
|
2010-07-21 22:05:17 +00:00
|
|
|
nsIContent* aPreviousSibling) {
|
2018-03-01 11:36:58 +00:00
|
|
|
MaybeUnhook(aChild->GetParent());
|
2002-10-22 05:28:36 +00:00
|
|
|
}
|
|
|
|
|
2006-07-02 07:23:10 +00:00
|
|
|
void nsXMLPrettyPrinter::NodeWillBeDestroyed(const nsINode* aNode) {
|
2012-07-30 14:20:58 +00:00
|
|
|
mDocument = nullptr;
|
2002-10-22 05:28:36 +00:00
|
|
|
NS_RELEASE_THIS();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter) {
|
|
|
|
*aPrinter = new nsXMLPrettyPrinter;
|
|
|
|
NS_ADDREF(*aPrinter);
|
|
|
|
return NS_OK;
|
|
|
|
}
|