LCOV - code coverage report
Current view: top level - layout/build - nsContentDLF.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 103 137 75.2 %
Date: 2017-07-14 16:53:18 Functions: 12 15 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 sw=2 et tw=78: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "nsContentDLF.h"
       7             : 
       8             : #include "mozilla/Encoding.h"
       9             : 
      10             : #include "nsCOMPtr.h"
      11             : #include "nsDocShell.h"
      12             : #include "nsGenericHTMLElement.h"
      13             : #include "nsGkAtoms.h"
      14             : #include "nsIComponentManager.h"
      15             : #include "nsIComponentRegistrar.h"
      16             : #include "nsIContentViewer.h"
      17             : #include "nsICategoryManager.h"
      18             : #include "nsIDocumentLoaderFactory.h"
      19             : #include "nsIDocument.h"
      20             : #include "nsIURL.h"
      21             : #include "nsNodeInfoManager.h"
      22             : #include "nsIScriptSecurityManager.h"
      23             : #include "nsString.h"
      24             : #include "nsContentCID.h"
      25             : #include "nsNetUtil.h"
      26             : #include "nsCRT.h"
      27             : #include "nsIViewSourceChannel.h"
      28             : #include "nsContentUtils.h"
      29             : #include "imgLoader.h"
      30             : #include "nsCharsetSource.h"
      31             : #include "nsMimeTypes.h"
      32             : #include "DecoderTraits.h"
      33             : 
      34             : 
      35             : // plugins
      36             : #include "nsIPluginHost.h"
      37             : #include "nsPluginHost.h"
      38             : static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
      39             : 
      40             : // Factory code for creating variations on html documents
      41             : 
      42             : #undef NOISY_REGISTRY
      43             : 
      44             : static NS_DEFINE_IID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID);
      45             : static NS_DEFINE_IID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
      46             : static NS_DEFINE_IID(kSVGDocumentCID, NS_SVGDOCUMENT_CID);
      47             : static NS_DEFINE_IID(kVideoDocumentCID, NS_VIDEODOCUMENT_CID);
      48             : static NS_DEFINE_IID(kImageDocumentCID, NS_IMAGEDOCUMENT_CID);
      49             : static NS_DEFINE_IID(kXULDocumentCID, NS_XULDOCUMENT_CID);
      50             : 
      51             : already_AddRefed<nsIContentViewer> NS_NewContentViewer();
      52             : 
      53             : static const char* const gHTMLTypes[] = {
      54             :   TEXT_HTML,
      55             :   VIEWSOURCE_CONTENT_TYPE,
      56             :   APPLICATION_XHTML_XML,
      57             :   APPLICATION_WAPXHTML_XML,
      58             :   0
      59             : };
      60             : 
      61             : static const char* const gXMLTypes[] = {
      62             :   TEXT_XML,
      63             :   APPLICATION_XML,
      64             :   APPLICATION_MATHML_XML,
      65             :   APPLICATION_RDF_XML,
      66             :   TEXT_RDF,
      67             :   0
      68             : };
      69             : 
      70             : static const char* const gSVGTypes[] = {
      71             :   IMAGE_SVG_XML,
      72             :   0
      73             : };
      74             : 
      75             : static const char* const gXULTypes[] = {
      76             :   TEXT_XUL,
      77             :   APPLICATION_CACHED_XUL,
      78             :   0
      79             : };
      80             : 
      81             : static bool
      82          70 : IsTypeInList(const nsACString& aType, const char* const aList[])
      83             : {
      84             :   int32_t typeIndex;
      85         269 :   for (typeIndex = 0; aList[typeIndex]; ++typeIndex) {
      86         224 :     if (aType.Equals(aList[typeIndex])) {
      87          25 :       return true;
      88             :     }
      89             :   }
      90             : 
      91          45 :   return false;
      92             : }
      93             : 
      94             : nsresult
      95           2 : NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult)
      96             : {
      97           2 :   NS_PRECONDITION(aResult, "null OUT ptr");
      98           2 :   if (!aResult) {
      99           0 :     return NS_ERROR_NULL_POINTER;
     100             :   }
     101           2 :   nsContentDLF* it = new nsContentDLF();
     102           2 :   if (!it) {
     103           0 :     return NS_ERROR_OUT_OF_MEMORY;
     104             :   }
     105             : 
     106           2 :   return CallQueryInterface(it, aResult);
     107             : }
     108             : 
     109           2 : nsContentDLF::nsContentDLF()
     110             : {
     111           2 : }
     112             : 
     113           0 : nsContentDLF::~nsContentDLF()
     114             : {
     115           0 : }
     116             : 
     117         149 : NS_IMPL_ISUPPORTS(nsContentDLF,
     118             :                   nsIDocumentLoaderFactory)
     119             : 
     120             : bool
     121           1 : MayUseXULXBL(nsIChannel* aChannel)
     122             : {
     123             :   nsIScriptSecurityManager *securityManager =
     124           1 :     nsContentUtils::GetSecurityManager();
     125           1 :   if (!securityManager) {
     126           0 :     return false;
     127             :   }
     128             : 
     129           2 :   nsCOMPtr<nsIPrincipal> principal;
     130           1 :   securityManager->GetChannelResultPrincipal(aChannel, getter_AddRefs(principal));
     131           1 :   NS_ENSURE_TRUE(principal, false);
     132             : 
     133           1 :   return nsContentUtils::AllowXULXBLForPrincipal(principal);
     134             : }
     135             : 
     136             : NS_IMETHODIMP
     137          25 : nsContentDLF::CreateInstance(const char* aCommand,
     138             :                              nsIChannel* aChannel,
     139             :                              nsILoadGroup* aLoadGroup,
     140             :                              const nsACString& aContentType,
     141             :                              nsIDocShell* aContainer,
     142             :                              nsISupports* aExtraInfo,
     143             :                              nsIStreamListener** aDocListener,
     144             :                              nsIContentViewer** aDocViewer)
     145             : {
     146             :   // Make a copy of aContentType, because we're possibly going to change it.
     147          50 :   nsAutoCString contentType(aContentType);
     148             : 
     149             :   // Are we viewing source?
     150          50 :   nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel);
     151          25 :   if (viewSourceChannel)
     152             :   {
     153           0 :     aCommand = "view-source";
     154             : 
     155             :     // The parser freaks out when it sees the content-type that a
     156             :     // view-source channel normally returns.  Get the actual content
     157             :     // type of the data.  If it's known, use it; otherwise use
     158             :     // text/plain.
     159           0 :     nsAutoCString type;
     160           0 :     mozilla::Unused << viewSourceChannel->GetOriginalContentType(type);
     161             :     bool knownType =
     162           0 :       (!type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE) &&
     163           0 :         IsTypeInList(type, gHTMLTypes)) ||
     164           0 :       nsContentUtils::IsPlainTextType(type) ||
     165           0 :       IsTypeInList(type, gXMLTypes) ||
     166           0 :       IsTypeInList(type, gSVGTypes) ||
     167           0 :       IsTypeInList(type, gXMLTypes);
     168             : 
     169           0 :     if (knownType) {
     170           0 :       viewSourceChannel->SetContentType(type);
     171           0 :     } else if (IsImageContentType(type.get())) {
     172             :       // If it's an image, we want to display it the same way we normally would.
     173             :       // Also note the lifetime of "type" allows us to safely use "get()" here.
     174           0 :       contentType = type;
     175             :     } else {
     176           0 :       viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
     177             :     }
     178          25 :   } else if (aContentType.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
     179           0 :     aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
     180           0 :     contentType = TEXT_PLAIN;
     181             :   }
     182             : 
     183             :   // Try html or plaintext; both use the same document CID
     184          47 :   if (IsTypeInList(contentType, gHTMLTypes) ||
     185          22 :       nsContentUtils::IsPlainTextType(contentType)) {
     186             :     return CreateDocument(aCommand,
     187             :                           aChannel, aLoadGroup,
     188             :                           aContainer, kHTMLDocumentCID,
     189           3 :                           aDocListener, aDocViewer);
     190             :   }
     191             : 
     192             :   // Try XML
     193          22 :   if (IsTypeInList(contentType, gXMLTypes)) {
     194             :     return CreateDocument(aCommand,
     195             :                           aChannel, aLoadGroup,
     196             :                           aContainer, kXMLDocumentCID,
     197           0 :                           aDocListener, aDocViewer);
     198             :   }
     199             : 
     200             :   // Try SVG
     201          22 :   if (IsTypeInList(contentType, gSVGTypes)) {
     202             :     return CreateDocument(aCommand,
     203             :                           aChannel, aLoadGroup,
     204             :                           aContainer, kSVGDocumentCID,
     205          21 :                           aDocListener, aDocViewer);
     206             :   }
     207             : 
     208             :   // Try XUL
     209           1 :   if (IsTypeInList(contentType, gXULTypes)) {
     210           1 :     if (!MayUseXULXBL(aChannel)) {
     211           0 :       return NS_ERROR_REMOTE_XUL;
     212             :     }
     213             : 
     214             :     return CreateXULDocument(aCommand, aChannel, aLoadGroup, aContainer,
     215           1 :                              aExtraInfo, aDocListener, aDocViewer);
     216             :   }
     217             : 
     218           0 :   if (mozilla::DecoderTraits::ShouldHandleMediaType(contentType.get(),
     219             :                     /* DecoderDoctorDiagnostics* */ nullptr)) {
     220             :     return CreateDocument(aCommand,
     221             :                           aChannel, aLoadGroup,
     222             :                           aContainer, kVideoDocumentCID,
     223           0 :                           aDocListener, aDocViewer);
     224             :   }
     225             : 
     226             :   // Try image types
     227           0 :   if (IsImageContentType(contentType.get())) {
     228             :     return CreateDocument(aCommand,
     229             :                           aChannel, aLoadGroup,
     230             :                           aContainer, kImageDocumentCID,
     231           0 :                           aDocListener, aDocViewer);
     232             :   }
     233             : 
     234           0 :   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
     235             :   // Don't exclude disabled plugins, which will still trigger the "this plugin
     236             :   // is disabled" placeholder.
     237           0 :   if (pluginHost && pluginHost->HavePluginForType(contentType,
     238           0 :                                                   nsPluginHost::eExcludeNone)) {
     239             :     return CreateDocument(aCommand,
     240             :                           aChannel, aLoadGroup,
     241             :                           aContainer, kPluginDocumentCID,
     242           0 :                           aDocListener, aDocViewer);
     243             :   }
     244             : 
     245             :   // If we get here, then we weren't able to create anything. Sorry!
     246           0 :   return NS_ERROR_FAILURE;
     247             : }
     248             : 
     249             : 
     250             : NS_IMETHODIMP
     251           4 : nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
     252             :                                         nsIDocument* aDocument,
     253             :                                         const char *aCommand,
     254             :                                         nsIContentViewer** aContentViewer)
     255             : {
     256           4 :   MOZ_ASSERT(aDocument);
     257             : 
     258           8 :   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
     259             : 
     260             :   // Bind the document to the Content Viewer
     261           4 :   contentViewer->LoadStart(aDocument);
     262           4 :   contentViewer.forget(aContentViewer);
     263           8 :   return NS_OK;
     264             : }
     265             : 
     266             : NS_IMETHODIMP
     267           4 : nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup,
     268             :                                   nsIPrincipal* aPrincipal,
     269             :                                   nsIDocument **aDocument)
     270             : {
     271           4 :   *aDocument = nullptr;
     272             : 
     273           4 :   nsresult rv = NS_ERROR_FAILURE;
     274             : 
     275             :   // create a new blank HTML document
     276           8 :   nsCOMPtr<nsIDocument> blankDoc(do_CreateInstance(kHTMLDocumentCID));
     277             : 
     278           4 :   if (blankDoc) {
     279             :     // initialize
     280           8 :     nsCOMPtr<nsIURI> uri;
     281           4 :     NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
     282           4 :     if (uri) {
     283           4 :       blankDoc->ResetToURI(uri, aLoadGroup, aPrincipal);
     284           4 :       rv = NS_OK;
     285             :     }
     286             :   }
     287             : 
     288             :   // add some simple content structure
     289           4 :   if (NS_SUCCEEDED(rv)) {
     290           4 :     rv = NS_ERROR_FAILURE;
     291             : 
     292           4 :     nsNodeInfoManager *nim = blankDoc->NodeInfoManager();
     293             : 
     294           8 :     RefPtr<mozilla::dom::NodeInfo> htmlNodeInfo;
     295             : 
     296             :     // generate an html html element
     297           8 :     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::html, 0, kNameSpaceID_XHTML,
     298           4 :                                     nsIDOMNode::ELEMENT_NODE);
     299             :     nsCOMPtr<nsIContent> htmlElement =
     300           8 :       NS_NewHTMLHtmlElement(htmlNodeInfo.forget());
     301             : 
     302             :     // generate an html head element
     303           8 :     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::head, 0, kNameSpaceID_XHTML,
     304           4 :                                     nsIDOMNode::ELEMENT_NODE);
     305             :     nsCOMPtr<nsIContent> headElement =
     306           8 :       NS_NewHTMLHeadElement(htmlNodeInfo.forget());
     307             : 
     308             :     // generate an html body elemment
     309           8 :     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::body, 0, kNameSpaceID_XHTML,
     310           4 :                                     nsIDOMNode::ELEMENT_NODE);
     311             :     nsCOMPtr<nsIContent> bodyElement =
     312           8 :       NS_NewHTMLBodyElement(htmlNodeInfo.forget());
     313             : 
     314             :     // blat in the structure
     315           4 :     if (htmlElement && headElement && bodyElement) {
     316           4 :       NS_ASSERTION(blankDoc->GetChildCount() == 0,
     317             :                    "Shouldn't have children");
     318           4 :       rv = blankDoc->AppendChildTo(htmlElement, false);
     319           4 :       if (NS_SUCCEEDED(rv)) {
     320           4 :         rv = htmlElement->AppendChildTo(headElement, false);
     321             : 
     322           4 :         if (NS_SUCCEEDED(rv)) {
     323             :           // XXXbz Why not notifying here?
     324           4 :           htmlElement->AppendChildTo(bodyElement, false);
     325             :         }
     326             :       }
     327             :     }
     328             :   }
     329             : 
     330             :   // add a nice bow
     331           4 :   if (NS_SUCCEEDED(rv)) {
     332           4 :     blankDoc->SetDocumentCharacterSetSource(kCharsetFromDocTypeDefault);
     333           4 :     blankDoc->SetDocumentCharacterSet(UTF_8_ENCODING);
     334             : 
     335           4 :     blankDoc.forget(aDocument);
     336             :   }
     337           8 :   return rv;
     338             : }
     339             : 
     340             : 
     341             : nsresult
     342          24 : nsContentDLF::CreateDocument(const char* aCommand,
     343             :                              nsIChannel* aChannel,
     344             :                              nsILoadGroup* aLoadGroup,
     345             :                              nsIDocShell* aContainer,
     346             :                              const nsCID& aDocumentCID,
     347             :                              nsIStreamListener** aDocListener,
     348             :                              nsIContentViewer** aContentViewer)
     349             : {
     350          24 :   nsresult rv = NS_ERROR_FAILURE;
     351             : 
     352          48 :   nsCOMPtr<nsIURI> aURL;
     353          24 :   rv = aChannel->GetURI(getter_AddRefs(aURL));
     354          24 :   if (NS_FAILED(rv)) return rv;
     355             : 
     356             : #ifdef NOISY_CREATE_DOC
     357             :   if (nullptr != aURL) {
     358             :     nsAutoString tmp;
     359             :     aURL->ToString(tmp);
     360             :     fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
     361             :     printf(": creating document\n");
     362             :   }
     363             : #endif
     364             : 
     365             :   // Create the document
     366          48 :   nsCOMPtr<nsIDocument> doc = do_CreateInstance(aDocumentCID, &rv);
     367          24 :   NS_ENSURE_SUCCESS(rv, rv);
     368             : 
     369             :   // Create the content viewer  XXX: could reuse content viewer here!
     370          48 :   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
     371             : 
     372          24 :   doc->SetContainer(static_cast<nsDocShell*>(aContainer));
     373             : 
     374             :   // Initialize the document to begin loading the data.  An
     375             :   // nsIStreamListener connected to the parser is returned in
     376             :   // aDocListener.
     377          24 :   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
     378          24 :   NS_ENSURE_SUCCESS(rv, rv);
     379             : 
     380             :   // Bind the document to the Content Viewer
     381          24 :   contentViewer->LoadStart(doc);
     382          24 :   contentViewer.forget(aContentViewer);
     383          24 :   return NS_OK;
     384             : }
     385             : 
     386             : nsresult
     387           1 : nsContentDLF::CreateXULDocument(const char* aCommand,
     388             :                                 nsIChannel* aChannel,
     389             :                                 nsILoadGroup* aLoadGroup,
     390             :                                 nsIDocShell* aContainer,
     391             :                                 nsISupports* aExtraInfo,
     392             :                                 nsIStreamListener** aDocListener,
     393             :                                 nsIContentViewer** aContentViewer)
     394             : {
     395             :   nsresult rv;
     396           2 :   nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv);
     397           1 :   if (NS_FAILED(rv)) return rv;
     398             : 
     399           2 :   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
     400             : 
     401           2 :   nsCOMPtr<nsIURI> aURL;
     402           1 :   rv = aChannel->GetURI(getter_AddRefs(aURL));
     403           1 :   if (NS_FAILED(rv)) return rv;
     404             : 
     405             :   /*
     406             :    * Initialize the document to begin loading the data...
     407             :    *
     408             :    * An nsIStreamListener connected to the parser is returned in
     409             :    * aDocListener.
     410             :    */
     411             : 
     412           1 :   doc->SetContainer(static_cast<nsDocShell*>(aContainer));
     413             : 
     414           1 :   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
     415           1 :   if (NS_FAILED(rv)) return rv;
     416             : 
     417             :   /*
     418             :    * Bind the document to the Content Viewer...
     419             :    */
     420           1 :   contentViewer->LoadStart(doc);
     421           1 :   contentViewer.forget(aContentViewer);
     422           1 :   return NS_OK;
     423             : }
     424             : 
     425           0 : bool nsContentDLF::IsImageContentType(const char* aContentType) {
     426           0 :   return imgLoader::SupportImageWithMimeType(aContentType);
     427             : }

Generated by: LCOV version 1.13