LCOV - code coverage report
Current view: top level - dom/xml - nsXMLPrettyPrinter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 117 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13