content/xml/document/src/nsXMLPrettyPrinter.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #include "nsXMLPrettyPrinter.h"
     7 #include "nsContentUtils.h"
     8 #include "nsIDOMCSSStyleDeclaration.h"
     9 #include "nsIDOMDocumentXBL.h"
    10 #include "nsIObserver.h"
    11 #include "nsIXSLTProcessor.h"
    12 #include "nsSyncLoadService.h"
    13 #include "nsPIDOMWindow.h"
    14 #include "nsIDOMElement.h"
    15 #include "nsIDOMDocument.h"
    16 #include "nsIServiceManager.h"
    17 #include "nsNetUtil.h"
    18 #include "mozilla/dom/Element.h"
    19 #include "nsIDOMDocumentFragment.h"
    20 #include "nsBindingManager.h"
    21 #include "nsXBLService.h"
    22 #include "nsIScriptSecurityManager.h"
    23 #include "mozilla/Preferences.h"
    24 #include "nsIDocument.h"
    25 #include "nsVariant.h"
    26 #include "nsIDOMCustomEvent.h"
    27 #include "GeneratedEvents.h"
    29 using namespace mozilla;
    30 using namespace mozilla::dom;
    32 NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter,
    33                   nsIDocumentObserver,
    34                   nsIMutationObserver)
    36 nsXMLPrettyPrinter::nsXMLPrettyPrinter() : mDocument(nullptr),
    37                                            mUnhookPending(false)
    38 {
    39 }
    41 nsXMLPrettyPrinter::~nsXMLPrettyPrinter()
    42 {
    43     NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still");
    44 }
    46 nsresult
    47 nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
    48                                 bool* aDidPrettyPrint)
    49 {
    50     *aDidPrettyPrint = false;
    52     // Check for iframe with display:none. Such iframes don't have presshells
    53     if (!aDocument->GetShell()) {
    54         return NS_OK;
    55     }
    57     // check if we're in an invisible iframe
    58     nsPIDOMWindow *internalWin = aDocument->GetWindow();
    59     nsCOMPtr<nsIDOMElement> frameElem;
    60     if (internalWin) {
    61         internalWin->GetFrameElement(getter_AddRefs(frameElem));
    62     }
    64     if (frameElem) {
    65         nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
    66         nsCOMPtr<nsIDOMDocument> frameOwnerDoc;
    67         frameElem->GetOwnerDocument(getter_AddRefs(frameOwnerDoc));
    68         if (frameOwnerDoc) {
    69             nsCOMPtr<nsIDOMWindow> window;
    70             frameOwnerDoc->GetDefaultView(getter_AddRefs(window));
    71             if (window) {
    72                 window->GetComputedStyle(frameElem,
    73                                          EmptyString(),
    74                                          getter_AddRefs(computedStyle));
    75             }
    76         }
    78         if (computedStyle) {
    79             nsAutoString visibility;
    80             computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"),
    81                                             visibility);
    82             if (!visibility.EqualsLiteral("visible")) {
    84                 return NS_OK;
    85             }
    86         }
    87     }
    89     // check the pref
    90     if (!Preferences::GetBool("layout.xml.prettyprint", true)) {
    91         return NS_OK;
    92     }
    94     // Ok, we should prettyprint. Let's do it!
    95     *aDidPrettyPrint = true;
    96     nsresult rv = NS_OK;
    98     // Load the XSLT
    99     nsCOMPtr<nsIURI> xslUri;
   100     rv = NS_NewURI(getter_AddRefs(xslUri),
   101                    NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
   102     NS_ENSURE_SUCCESS(rv, rv);
   104     nsCOMPtr<nsIDOMDocument> xslDocument;
   105     rv = nsSyncLoadService::LoadDocument(xslUri, nullptr, nullptr, true,
   106                                          getter_AddRefs(xslDocument));
   107     NS_ENSURE_SUCCESS(rv, rv);
   109     // Transform the document
   110     nsCOMPtr<nsIXSLTProcessor> transformer =
   111         do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt", &rv);
   112     NS_ENSURE_SUCCESS(rv, rv);
   114     rv = transformer->ImportStylesheet(xslDocument);
   115     NS_ENSURE_SUCCESS(rv, rv);
   117     nsCOMPtr<nsIDOMDocumentFragment> resultFragment;
   118     nsCOMPtr<nsIDOMDocument> sourceDocument = do_QueryInterface(aDocument);
   119     rv = transformer->TransformToFragment(sourceDocument, sourceDocument,
   120                                           getter_AddRefs(resultFragment));
   121     NS_ENSURE_SUCCESS(rv, rv);
   123     //
   124     // Apply the prettprint XBL binding.
   125     //
   126     // We take some shortcuts here. In particular, we don't bother invoking the
   127     // contstructor (since the binding has no constructor), and we don't bother
   128     // calling LoadBindingDocument because it's a chrome:// URI and thus will get
   129     // sync loaded no matter what.
   130     //
   132     // Grab the XBL service.
   133     nsXBLService* xblService = nsXBLService::GetInstance();
   134     NS_ENSURE_TRUE(xblService, NS_ERROR_NOT_AVAILABLE);
   136     // Compute the binding URI.
   137     nsCOMPtr<nsIURI> bindingUri;
   138     rv = NS_NewURI(getter_AddRefs(bindingUri),
   139         NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint"));
   140     NS_ENSURE_SUCCESS(rv, rv);
   142     // Compute the bound element.
   143     nsCOMPtr<nsIContent> rootCont = aDocument->GetRootElement();
   144     NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED);
   146     // Grab the system principal.
   147     nsCOMPtr<nsIPrincipal> sysPrincipal;
   148     nsContentUtils::GetSecurityManager()->
   149         GetSystemPrincipal(getter_AddRefs(sysPrincipal));
   151     // Load the bindings.
   152     nsRefPtr<nsXBLBinding> unused;
   153     bool ignored;
   154     rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal,
   155                                   getter_AddRefs(unused), &ignored);
   156     NS_ENSURE_SUCCESS(rv, rv);
   158     // Fire an event at the bound element to pass it |resultFragment|.
   159     nsCOMPtr<nsIDOMEvent> domEvent;
   160     rv = NS_NewDOMCustomEvent(getter_AddRefs(domEvent), rootCont,
   161                               nullptr, nullptr);
   162     NS_ENSURE_SUCCESS(rv, rv);
   163     nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
   164     MOZ_ASSERT(customEvent);
   165     nsCOMPtr<nsIWritableVariant> resultFragmentVariant = new nsVariant();
   166     rv = resultFragmentVariant->SetAsISupports(resultFragment);
   167     MOZ_ASSERT(NS_SUCCEEDED(rv));
   168     rv = customEvent->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"),
   169                                       /* bubbles = */ false, /* cancelable = */ false,
   170                                       /* detail = */ resultFragmentVariant);
   171     NS_ENSURE_SUCCESS(rv, rv);
   172     customEvent->SetTrusted(true);
   173     bool dummy;
   174     rv = rootCont->DispatchEvent(domEvent, &dummy);
   175     NS_ENSURE_SUCCESS(rv, rv);
   177     // Observe the document so we know when to switch to "normal" view
   178     aDocument->AddObserver(this);
   179     mDocument = aDocument;
   181     NS_ADDREF_THIS();
   183     return NS_OK;
   184 }
   186 void
   187 nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent)
   188 {
   189     // If there either aContent is null (the document-node was modified) or
   190     // there isn't a binding parent we know it's non-anonymous content.
   191     if ((!aContent || !aContent->GetBindingParent()) && !mUnhookPending) {
   192         // Can't blindly to mUnhookPending after AddScriptRunner,
   193         // since AddScriptRunner _could_ in theory run us
   194         // synchronously
   195         mUnhookPending = true;
   196         nsContentUtils::AddScriptRunner(
   197           NS_NewRunnableMethod(this, &nsXMLPrettyPrinter::Unhook));
   198     }
   199 }
   201 void
   202 nsXMLPrettyPrinter::Unhook()
   203 {
   204     mDocument->RemoveObserver(this);
   205     nsCOMPtr<Element> element = mDocument->GetDocumentElement();
   207     if (element) {
   208         mDocument->BindingManager()->ClearBinding(element);
   209     }
   211     mDocument = nullptr;
   213     NS_RELEASE_THIS();
   214 }
   216 void
   217 nsXMLPrettyPrinter::AttributeChanged(nsIDocument* aDocument,
   218                                      Element* aElement,
   219                                      int32_t aNameSpaceID,
   220                                      nsIAtom* aAttribute,
   221                                      int32_t aModType)
   222 {
   223     MaybeUnhook(aElement);
   224 }
   226 void
   227 nsXMLPrettyPrinter::ContentAppended(nsIDocument* aDocument,
   228                                     nsIContent* aContainer,
   229                                     nsIContent* aFirstNewContent,
   230                                     int32_t aNewIndexInContainer)
   231 {
   232     MaybeUnhook(aContainer);
   233 }
   235 void
   236 nsXMLPrettyPrinter::ContentInserted(nsIDocument* aDocument,
   237                                     nsIContent* aContainer,
   238                                     nsIContent* aChild,
   239                                     int32_t aIndexInContainer)
   240 {
   241     MaybeUnhook(aContainer);
   242 }
   244 void
   245 nsXMLPrettyPrinter::ContentRemoved(nsIDocument* aDocument,
   246                                    nsIContent* aContainer,
   247                                    nsIContent* aChild,
   248                                    int32_t aIndexInContainer,
   249                                    nsIContent* aPreviousSibling)
   250 {
   251     MaybeUnhook(aContainer);
   252 }
   254 void
   255 nsXMLPrettyPrinter::NodeWillBeDestroyed(const nsINode* aNode)
   256 {
   257     mDocument = nullptr;
   258     NS_RELEASE_THIS();
   259 }
   262 nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter)
   263 {
   264     *aPrinter = new nsXMLPrettyPrinter;
   265     NS_ADDREF(*aPrinter);
   266     return NS_OK;
   267 }

mercurial