diff --git a/content/base/public/nsIDocumentObserver.h b/content/base/public/nsIDocumentObserver.h index 79f98bdf0532..74c69c4bca52 100644 --- a/content/base/public/nsIDocumentObserver.h +++ b/content/base/public/nsIDocumentObserver.h @@ -331,4 +331,62 @@ public: NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) = 0; }; +#define NS_DECL_NSIDOCUMENTOBSERVER \ + NS_IMETHOD BeginUpdate(nsIDocument* aDocument); \ + NS_IMETHOD EndUpdate(nsIDocument* aDocument); \ + NS_IMETHOD BeginLoad(nsIDocument* aDocument); \ + NS_IMETHOD EndLoad(nsIDocument* aDocument); \ + NS_IMETHOD BeginReflow(nsIDocument* aDocument, \ + nsIPresShell* aShell); \ + NS_IMETHOD EndReflow(nsIDocument* aDocument, \ + nsIPresShell* aShell); \ + NS_IMETHOD ContentChanged(nsIDocument* aDocument, \ + nsIContent* aContent, \ + nsISupports* aSubContent); \ + NS_IMETHOD ContentStatesChanged(nsIDocument* aDocument, \ + nsIContent* aContent1, \ + nsIContent* aContent2, \ + PRInt32 aStateMask); \ + NS_IMETHOD AttributeChanged(nsIDocument* aDocument, \ + nsIContent* aContent, \ + PRInt32 aNameSpaceID, \ + nsIAtom* aAttribute, \ + PRInt32 aModType, \ + nsChangeHint aHint); \ + NS_IMETHOD ContentAppended(nsIDocument* aDocument, \ + nsIContent* aContainer, \ + PRInt32 aNewIndexInContainer); \ + NS_IMETHOD ContentInserted(nsIDocument* aDocument, \ + nsIContent* aContainer, \ + nsIContent* aChild, \ + PRInt32 aIndexInContainer); \ + NS_IMETHOD ContentReplaced(nsIDocument* aDocument, \ + nsIContent* aContainer, \ + nsIContent* aOldChild, \ + nsIContent* aNewChild, \ + PRInt32 aIndexInContainer); \ + NS_IMETHOD ContentRemoved(nsIDocument* aDocument, \ + nsIContent* aContainer, \ + nsIContent* aChild, \ + PRInt32 aIndexInContainer); \ + NS_IMETHOD StyleSheetAdded(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet); \ + NS_IMETHOD StyleSheetRemoved(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet); \ + NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet, \ + PRBool aDisabled); \ + NS_IMETHOD StyleRuleChanged(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet, \ + nsIStyleRule* aStyleRule, \ + nsChangeHint aHint); \ + NS_IMETHOD StyleRuleAdded(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet, \ + nsIStyleRule* aStyleRule); \ + NS_IMETHOD StyleRuleRemoved(nsIDocument* aDocument, \ + nsIStyleSheet* aStyleSheet, \ + nsIStyleRule* aStyleRule); \ + NS_IMETHOD DocumentWillBeDestroyed(nsIDocument* aDocument); \ + + #endif /* nsIDocumentObserver_h___ */ diff --git a/content/macbuild/content.xml b/content/macbuild/content.xml index d0207035fb10..82444d78e3aa 100644 --- a/content/macbuild/content.xml +++ b/content/macbuild/content.xml @@ -1435,6 +1435,13 @@ Text Debug + + Name + nsXMLPrettyPrinter.cpp + MacOS + Text + Debug + Name nsXMLDocument.cpp @@ -2879,6 +2886,11 @@ nsXMLContentSink.cpp MacOS + + Name + nsXMLPrettyPrinter.cpp + MacOS + Name nsXMLDocument.cpp @@ -5008,6 +5020,13 @@ Text Debug + + Name + nsXMLPrettyPrinter.cpp + MacOS + Text + Debug + Name nsXMLDocument.cpp @@ -6497,6 +6516,11 @@ nsXMLContentSink.cpp MacOS + + Name + nsXMLPrettyPrinter.cpp + MacOS + Name nsXMLDocument.cpp @@ -8280,6 +8304,12 @@ nsXMLContentSink.cpp MacOS + + content.shlb + Name + nsXMLPrettyPrinter.cpp + MacOS + content.shlb Name diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index 8a8e708be7cd..f288c1bb2d10 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -794,38 +794,65 @@ nsBindingManager::AddLayeredBinding(nsIContent* aContent, const nsAString& aURL) NS_IMETHODIMP nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, const nsAString& aURL) { - /* nsCOMPtr binding; - GetBinding(aParent, getter_AddRefs(binding)); + GetBinding(aContent, getter_AddRefs(binding)); - nsCOMPtr prevBinding; - - while (binding) { - nsCOMPtr nextBinding; - binding->GetBaseBinding(getter_AddRefs(nextBinding)); - - PRBool style; - binding->IsStyleBinding(&style); - if (!style) { - // Remove only our binding. - if (prevBinding) { - prevBinding->SetBaseBinding(nextBinding); - - // XXX Unhooking the binding should kill event handlers and - // fix up the prototype chain. - // e.g., binding->UnhookEventHandlers(); - // binding->FixupPrototypeChain(); - // or maybe just binding->Unhook(); - - } - else SetBinding(aContent, nextBinding); - } - - prevBinding = binding; - binding = nextBinding; + if (!binding) { + return NS_OK; } -*/ - return NS_OK; + + // For now we can only handle removing a binding if it's the only one + nsCOMPtr nextBinding; + binding->GetBaseBinding(getter_AddRefs(nextBinding)); + NS_ENSURE_FALSE(nextBinding, NS_ERROR_FAILURE); + + // Make sure that the binding has the URI that is requested to be removed + nsCAutoString bindingUriStr; + binding->GetBindingURI(bindingUriStr); + nsCOMPtr bindingUri; + nsresult rv = NS_NewURI(getter_AddRefs(bindingUri), bindingUriStr); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr uri; + rv = NS_NewURI(getter_AddRefs(uri), aURL); + NS_ENSURE_SUCCESS(rv, rv); + PRBool equalUri; + rv = uri->Equals(bindingUri, &equalUri); + NS_ENSURE_SUCCESS(rv, rv); + if (!equalUri) { + return NS_OK; + } + + // Make sure it isn't a style binding + PRBool style; + binding->IsStyleBinding(&style); + if (style) { + return NS_OK; + } + + // Get to the document, this way is safer then using nsIContent::GetDocument + nsCOMPtr node = do_QueryInterface(aContent); + NS_ASSERTION(node, "uh? RemoveLayeredBinding called on non-node"); + nsCOMPtr domDoc; + node->GetOwnerDocument(getter_AddRefs(domDoc)); + NS_ENSURE_TRUE(domDoc, NS_ERROR_UNEXPECTED); + nsCOMPtr doc = do_QueryInterface(domDoc); + NS_ASSERTION(doc, "document doesn't implement nsIDocument"); + + // Finally remove the binding... + binding->UnhookEventHandlers(); + binding->ChangeDocument(doc, nsnull); + SetBinding(aContent, nsnull); + binding->MarkForDeath(); + + // ...and recreate it's frames. We need to do this since the frames may have + // been removed and style may have changed due to the removal of the + // anonymous children. + nsCOMPtr presShell; + rv = doc->GetShellAt(0, getter_AddRefs(presShell)); + NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + + return presShell->RecreateFramesFor(aContent);; } NS_IMETHODIMP diff --git a/content/xml/document/resources/XMLPrettyPrint.css b/content/xml/document/resources/XMLPrettyPrint.css index c1cde22ef492..6847033eb740 100644 --- a/content/xml/document/resources/XMLPrettyPrint.css +++ b/content/xml/document/resources/XMLPrettyPrint.css @@ -79,3 +79,8 @@ td { .expander-closed > * > .expander-content { display: none; } + +.comment { + font-family: monospace; + white-space: pre; +} diff --git a/content/xml/document/resources/XMLPrettyPrint.xml b/content/xml/document/resources/XMLPrettyPrint.xml index 7402e6bc3933..4fb59ce421e7 100644 --- a/content/xml/document/resources/XMLPrettyPrint.xml +++ b/content/xml/document/resources/XMLPrettyPrint.xml @@ -65,11 +65,11 @@ if (par.nodeName == 'td' && par.className == 'expander') { if (par.parentNode.className == 'expander-closed') { par.parentNode.className = ''; - event.originalTarget.src = 'chrome://global/skin/tree/twisty-open.gif'; + event.originalTarget.data = '-'; } else { par.parentNode.className = 'expander-closed'; - event.originalTarget.src = 'chrome://global/skin/tree/twisty-clsd.gif'; + event.originalTarget.data = '+'; } } } catch (e) { diff --git a/content/xml/document/resources/XMLPrettyPrint.xsl b/content/xml/document/resources/XMLPrettyPrint.xsl index 99bddf54dfab..fe8f8cb9859a 100644 --- a/content/xml/document/resources/XMLPrettyPrint.xsl +++ b/content/xml/document/resources/XMLPrettyPrint.xsl @@ -155,7 +155,7 @@ -
+ -
diff --git a/content/xml/document/src/Makefile.in b/content/xml/document/src/Makefile.in index f5b73c52d28d..674b318a2675 100644 --- a/content/xml/document/src/Makefile.in +++ b/content/xml/document/src/Makefile.in @@ -56,6 +56,7 @@ REQUIRES = xpcom \ CPPSRCS = \ nsXMLContentSink.cpp \ nsXMLDocument.cpp \ + nsXMLPrettyPrinter.cpp \ nsFIXptr.cpp \ $(NULL) diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index fab6f87c5f81..356ef78db39b 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -107,18 +107,8 @@ #include "nsIPrincipal.h" #include "nsIAggregatePrincipal.h" #include "nsICodebasePrincipal.h" -#include "nsIDOMDocumentView.h" -#include "nsIDOMAbstractView.h" -#include "nsIDOMCSSStyleDeclaration.h" -#include "nsIDOMViewCSS.h" #include "nsXBLAtoms.h" -#include "nsIPref.h" -#include "nsIDOMDocumentXBL.h" -#include "nsIBindingManager.h" -#include "nsIObserver.h" -#include "nsIDocumentTransformer.h" -#include "nsISyncLoadDOMService.h" -#include "nsIXSLTProcessor.h" +#include "nsXMLPrettyPrinter.h" // XXX misnamed header file, but oh well #include "nsHTMLTokens.h" @@ -364,121 +354,20 @@ nsXMLContentSink::MaybePrettyPrint() return NS_OK; } - // Check for correct load-command or if we're in a display:none iframe + // Check for correct load-command nsAutoString command; mParser->GetCommand(command); - if (!command.Equals(NS_LITERAL_STRING("view")) || - !mDocument->GetNumberOfShells()) { + if (!command.Equals(NS_LITERAL_STRING("view"))) { mPrettyPrintXML = PR_FALSE; return NS_OK; } - // check if we're in an invisible iframe - nsCOMPtr sgo; - mDocument->GetScriptGlobalObject(getter_AddRefs(sgo)); - nsCOMPtr internalWin = do_QueryInterface(sgo); - nsCOMPtr frameElem; - if (internalWin) { - internalWin->GetFrameElement(getter_AddRefs(frameElem)); - } - - if (frameElem) { - nsCOMPtr computedStyle; - nsCOMPtr frameOwnerDoc; - frameElem->GetOwnerDocument(getter_AddRefs(frameOwnerDoc)); - nsCOMPtr docView = do_QueryInterface(frameOwnerDoc); - if (docView) { - nsCOMPtr defaultView; - docView->GetDefaultView(getter_AddRefs(defaultView)); - nsCOMPtr defaultCSSView = do_QueryInterface(defaultView); - if (defaultCSSView) { - defaultCSSView->GetComputedStyle(frameElem, NS_LITERAL_STRING(""), - getter_AddRefs(computedStyle)); - } - } - - if (computedStyle) { - nsAutoString visibility; - computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"), visibility); - if (!visibility.Equals(NS_LITERAL_STRING("visible"))) { - mPrettyPrintXML = PR_FALSE; - - return NS_OK; - } - } - } - - // check the pref - nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID); - if (prefs) { - PRBool pref = PR_FALSE; - prefs->GetBoolPref("layout.xml.prettyprint", &pref); - if (!pref) { - mPrettyPrintXML = PR_FALSE; - - return NS_OK; - } - } - - - // Ok, we should prettyprint. Let's do it! - nsresult rv = NS_OK; - - // Load the XSLT - nsCOMPtr xslUri; - rv = NS_NewURI(getter_AddRefs(xslUri), - NS_LITERAL_CSTRING("chrome://communicator/content/xml/XMLPrettyPrint.xsl")); + nsCOMPtr printer; + nsresult rv = NS_NewXMLPrettyPrinter(getter_AddRefs(printer)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr channel; - rv = NS_NewChannel(getter_AddRefs(channel), xslUri, nsnull, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr xslDocument; - nsCOMPtr loader = - do_GetService("@mozilla.org/content/syncload-dom-service;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - rv = loader->LoadLocalDocument(channel, nsnull, getter_AddRefs(xslDocument)); - NS_ENSURE_SUCCESS(rv, rv); - - // Transform the document - nsCOMPtr transformer = - do_CreateInstance("@mozilla.org/document-transformer;1?type=text/xsl", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = transformer->ImportStylesheet(xslDocument); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr resultFragment; - nsCOMPtr sourceDocument = do_QueryInterface(mDocument); - rv = transformer->TransformToFragment(sourceDocument, xslDocument, - getter_AddRefs(resultFragment)); - NS_ENSURE_SUCCESS(rv, rv); - - // Add the binding - nsCOMPtr xblDoc = do_QueryInterface(mDocument); - NS_ASSERTION(xblDoc, "xml document doesn't implement nsIDOMDocumentXBL"); - NS_ENSURE_TRUE(xblDoc, NS_ERROR_FAILURE); - - nsCOMPtr dummy; - xblDoc->LoadBindingDocument(NS_LITERAL_STRING("chrome://communicator/content/xml/XMLPrettyPrint.xml"), getter_AddRefs(dummy)); - - nsCOMPtr rootElem = do_QueryInterface(mDocElement); - NS_ASSERTION(rootElem, "No root element"); - - rv = xblDoc->AddBinding(rootElem, NS_LITERAL_STRING("chrome://communicator/content/xml/XMLPrettyPrint.xml#prettyprint")); - NS_ENSURE_SUCCESS(rv, rv); - - // Hand the result document to the binding - nsCOMPtr manager; - mDocument->GetBindingManager(getter_AddRefs(manager)); - nsCOMPtr binding; - manager->GetBindingImplementation(mDocElement, NS_GET_IID(nsIObserver), (void**)getter_AddRefs(binding)); - NS_ASSERTION(binding, "Prettyprint binding doesn't implement nsIObserver"); - NS_ENSURE_TRUE(binding, NS_ERROR_UNEXPECTED); - - return binding->Observe(resultFragment, "prettyprint-dom-created", NS_LITERAL_STRING("").get()); + return printer->PrettyPrint(mDocument); } @@ -2186,6 +2075,8 @@ nsXMLContentSink::ReportError(const PRUnichar* aErrorText, const PRUnichar* aSourceText) { nsresult rv = NS_OK; + + mPrettyPrintXML = PR_FALSE; mState = eXMLContentSinkState_InProlog; diff --git a/content/xml/document/src/nsXMLPrettyPrinter.cpp b/content/xml/document/src/nsXMLPrettyPrinter.cpp new file mode 100644 index 000000000000..5050c782d121 --- /dev/null +++ b/content/xml/document/src/nsXMLPrettyPrinter.cpp @@ -0,0 +1,408 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXMLPrettyPrinter.h" +#include "nsIDOMDocumentView.h" +#include "nsIDOMAbstractView.h" +#include "nsIDOMCSSStyleDeclaration.h" +#include "nsIDOMViewCSS.h" +#include "nsIPrefService.h" +#include "nsIDOMDocumentXBL.h" +#include "nsIBindingManager.h" +#include "nsIObserver.h" +#include "nsIXSLTProcessor.h" +#include "nsISyncLoadDOMService.h" +#include "nsIScriptGlobalObject.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDOMElement.h" +#include "nsIDOMDocument.h" +#include "nsIServiceManager.h" +#include "nsNetUtil.h" +#include "nsIContent.h" +#include "nsIDOMDocumentFragment.h" + +NS_IMPL_ISUPPORTS1(nsXMLPrettyPrinter, + nsIDocumentObserver) + +nsXMLPrettyPrinter::nsXMLPrettyPrinter() : mUnhookPending(PR_FALSE), + mDocument(nsnull), + mUpdateDepth(0) +{ + NS_INIT_ISUPPORTS(); +} + +nsXMLPrettyPrinter::~nsXMLPrettyPrinter() +{ + NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still"); +} + +nsresult +nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument) +{ + // Check for iframe with display:none. Such iframes don't have presshells + if (!aDocument->GetNumberOfShells()) { + return NS_OK; + } + + // check if we're in an invisible iframe + nsCOMPtr sgo; + aDocument->GetScriptGlobalObject(getter_AddRefs(sgo)); + nsCOMPtr internalWin = do_QueryInterface(sgo); + nsCOMPtr frameElem; + if (internalWin) { + internalWin->GetFrameElement(getter_AddRefs(frameElem)); + } + + if (frameElem) { + nsCOMPtr computedStyle; + nsCOMPtr frameOwnerDoc; + frameElem->GetOwnerDocument(getter_AddRefs(frameOwnerDoc)); + nsCOMPtr docView = do_QueryInterface(frameOwnerDoc); + if (docView) { + nsCOMPtr defaultView; + docView->GetDefaultView(getter_AddRefs(defaultView)); + nsCOMPtr defaultCSSView = + do_QueryInterface(defaultView); + if (defaultCSSView) { + defaultCSSView->GetComputedStyle(frameElem, + NS_LITERAL_STRING(""), + getter_AddRefs(computedStyle)); + } + } + + if (computedStyle) { + nsAutoString visibility; + computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"), + visibility); + if (!visibility.Equals(NS_LITERAL_STRING("visible"))) { + + return NS_OK; + } + } + } + + // check the pref + nsCOMPtr prefBranch = + do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefBranch) { + PRBool pref = PR_TRUE; + prefBranch->GetBoolPref("layout.xml.prettyprint", &pref); + if (!pref) { + return NS_OK; + } + } + + + // Ok, we should prettyprint. Let's do it! + nsresult rv = NS_OK; + + // Load the XSLT + nsCOMPtr xslUri; + rv = NS_NewURI(getter_AddRefs(xslUri), + NS_LITERAL_CSTRING("chrome://communicator/content/xml/XMLPrettyPrint.xsl")); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr channel; + rv = NS_NewChannel(getter_AddRefs(channel), xslUri, nsnull, nsnull); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr xslDocument; + nsCOMPtr loader = + do_GetService("@mozilla.org/content/syncload-dom-service;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = loader->LoadLocalDocument(channel, nsnull, getter_AddRefs(xslDocument)); + NS_ENSURE_SUCCESS(rv, rv); + + // Transform the document + nsCOMPtr transformer = + do_CreateInstance("@mozilla.org/document-transformer;1?type=text/xsl", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = transformer->ImportStylesheet(xslDocument); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resultFragment; + nsCOMPtr sourceDocument = do_QueryInterface(aDocument); + rv = transformer->TransformToFragment(sourceDocument, xslDocument, + getter_AddRefs(resultFragment)); + NS_ENSURE_SUCCESS(rv, rv); + + // Add the binding + nsCOMPtr xblDoc = do_QueryInterface(aDocument); + NS_ASSERTION(xblDoc, "xml document doesn't implement nsIDOMDocumentXBL"); + NS_ENSURE_TRUE(xblDoc, NS_ERROR_FAILURE); + + nsCOMPtr dummy; + xblDoc->LoadBindingDocument(NS_LITERAL_STRING("chrome://communicator/content/xml/XMLPrettyPrint.xml"), + getter_AddRefs(dummy)); + + nsCOMPtr rootElem; + sourceDocument->GetDocumentElement(getter_AddRefs(rootElem)); + NS_ENSURE_TRUE(rootElem, NS_ERROR_UNEXPECTED); + + rv = xblDoc->AddBinding(rootElem, + NS_LITERAL_STRING("chrome://communicator/content/xml/XMLPrettyPrint.xml#prettyprint")); + NS_ENSURE_SUCCESS(rv, rv); + + // Hand the result document to the binding + nsCOMPtr manager; + aDocument->GetBindingManager(getter_AddRefs(manager)); + nsCOMPtr binding; + nsCOMPtr rootCont = do_QueryInterface(rootElem); + NS_ASSERTION(rootCont, "Element doesn't implement nsIContent"); + manager->GetBindingImplementation(rootCont, NS_GET_IID(nsIObserver), + (void**)getter_AddRefs(binding)); + NS_ASSERTION(binding, "Prettyprint binding doesn't implement nsIObserver"); + NS_ENSURE_TRUE(binding, NS_ERROR_UNEXPECTED); + + rv = binding->Observe(resultFragment, "prettyprint-dom-created", NS_LITERAL_STRING("").get()); + NS_ENSURE_SUCCESS(rv, rv); + + // 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) +{ + nsCOMPtr bindingParent; + if (aContent) { + aContent->GetBindingParent(getter_AddRefs(bindingParent)); + } + // If there either aContent is null (the document-node was modified) or + // there isn't a binding parent we know it's non-anonymous content. + if (!bindingParent) { + mUnhookPending = PR_TRUE; + } +} + +// nsIDocumentObserver implementation +NS_IMETHODIMP +nsXMLPrettyPrinter::BeginUpdate(nsIDocument* aDocument) +{ + mUpdateDepth++; + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::EndUpdate(nsIDocument* aDocument) +{ + mUpdateDepth--; + + // Only remove the binding once we're outside all updates. This protects us + // from nasty surprices of elements being removed from the document in the + // midst of setting attributes etc. + if (mUnhookPending && mUpdateDepth == 0) { + mDocument->RemoveObserver(this); + nsCOMPtr document = do_QueryInterface(mDocument); + nsCOMPtr rootElem; + document->GetDocumentElement(getter_AddRefs(rootElem)); + nsCOMPtr xblDoc = do_QueryInterface(mDocument); + xblDoc->RemoveBinding(rootElem, + NS_LITERAL_STRING("chrome://communicator/content/xml/XMLPrettyPrint.xml#prettyprint")); + + mDocument = nsnull; + + NS_RELEASE_THIS(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::BeginLoad(nsIDocument* aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::EndLoad(nsIDocument* aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::BeginReflow(nsIDocument* aDocument, + nsIPresShell* aShell) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::EndReflow(nsIDocument* aDocument, + nsIPresShell* aShell) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentChanged(nsIDocument* aDocument, + nsIContent *aContent, + nsISupports *aSubContent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentStatesChanged(nsIDocument* aDocument, + nsIContent* aContent1, + nsIContent* aContent2, + PRInt32 aStateMask) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::AttributeChanged(nsIDocument* aDocument, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + nsChangeHint aHint) +{ + MaybeUnhook(aContent); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentAppended(nsIDocument* aDocument, + nsIContent* aContainer, + PRInt32 aNewIndexInContainer) +{ + MaybeUnhook(aContainer); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + MaybeUnhook(aContainer); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentReplaced(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aOldChild, + nsIContent* aNewChild, + PRInt32 aIndexInContainer) +{ + MaybeUnhook(aContainer); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + MaybeUnhook(aContainer); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleSheetAdded(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleSheetRemoved(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleSheetDisabledStateChanged(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet, + PRBool aDisabled) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleRuleChanged(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule, + nsChangeHint aHint) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleRuleAdded(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::StyleRuleRemoved(nsIDocument* aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXMLPrettyPrinter::DocumentWillBeDestroyed(nsIDocument* aDocument) +{ + mDocument = nsnull; + NS_RELEASE_THIS(); + + return NS_OK; +} + + +nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter) +{ + *aPrinter = new nsXMLPrettyPrinter; + NS_ENSURE_TRUE(*aPrinter, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(*aPrinter); + return NS_OK; +} diff --git a/content/xml/document/src/nsXMLPrettyPrinter.h b/content/xml/document/src/nsXMLPrettyPrinter.h new file mode 100644 index 000000000000..0ba17a729e09 --- /dev/null +++ b/content/xml/document/src/nsXMLPrettyPrinter.h @@ -0,0 +1,78 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jonas Sicking (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsXMLPrettyPrinter_h__ +#define nsXMLPrettyPrinter_h__ + +#include "nsIDocumentObserver.h" +#include "nsIDocument.h" +#include "nsCOMPtr.h" + +class nsXMLPrettyPrinter : public nsIDocumentObserver +{ +public: + nsXMLPrettyPrinter(); + ~nsXMLPrettyPrinter(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIDOCUMENTOBSERVER + + /** + * This will prettyprint the document if the document is loaded in a + * displayed window. + * + * @param aDocument document to prettyprint + */ + nsresult PrettyPrint(nsIDocument* aDocument); + +private: + /** + * Signals for unhooking by setting mUnhookPending if the node changed is + * non-anonymous content. + * + * @param aContent content that has changed + */ + void MaybeUnhook(nsIContent* aContent); + + nsIDocument* mDocument; //weak. Set as long as we're observing the document + PRUint32 mUpdateDepth; + PRPackedBool mUnhookPending; +}; + +nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter); + +#endif //nsXMLPrettyPrinter_h__