layout/build/nsContentDLF.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 "nsCOMPtr.h"
     7 #include "nsContentDLF.h"
     8 #include "nsDocShell.h"
     9 #include "nsGenericHTMLElement.h"
    10 #include "nsGkAtoms.h"
    11 #include "nsIComponentManager.h"
    12 #include "nsIComponentRegistrar.h"
    13 #include "nsIContentViewer.h"
    14 #include "nsICategoryManager.h"
    15 #include "nsIDocumentLoaderFactory.h"
    16 #include "nsIDocument.h"
    17 #include "nsIURL.h"
    18 #include "nsNodeInfo.h"
    19 #include "nsNodeInfoManager.h"
    20 #include "nsIScriptSecurityManager.h"
    21 #include "nsString.h"
    22 #include "nsContentCID.h"
    23 #include "prprf.h"
    24 #include "nsNetUtil.h"
    25 #include "nsCRT.h"
    26 #include "nsIViewSourceChannel.h"
    27 #include "nsContentUtils.h"
    28 #include "imgLoader.h"
    29 #include "nsCharsetSource.h"
    30 #include "nsMimeTypes.h"
    31 #include "DecoderTraits.h"
    34 // plugins
    35 #include "nsIPluginHost.h"
    36 #include "nsPluginHost.h"
    37 static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
    39 // Factory code for creating variations on html documents
    41 #undef NOISY_REGISTRY
    43 static NS_DEFINE_IID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID);
    44 static NS_DEFINE_IID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
    45 static NS_DEFINE_IID(kSVGDocumentCID, NS_SVGDOCUMENT_CID);
    46 static NS_DEFINE_IID(kVideoDocumentCID, NS_VIDEODOCUMENT_CID);
    47 static NS_DEFINE_IID(kImageDocumentCID, NS_IMAGEDOCUMENT_CID);
    48 static NS_DEFINE_IID(kXULDocumentCID, NS_XULDOCUMENT_CID);
    50 already_AddRefed<nsIContentViewer> NS_NewContentViewer();
    52 // XXXbz if you change the MIME types here, be sure to update
    53 // nsIParser.h and DetermineParseMode in nsParser.cpp and
    54 // nsHTMLDocument::StartDocumentLoad accordingly.
    55 static const char* const gHTMLTypes[] = {
    56   TEXT_HTML,
    57   TEXT_PLAIN,
    58   TEXT_CACHE_MANIFEST,
    59   TEXT_CSS,
    60   TEXT_JAVASCRIPT,
    61   TEXT_ECMASCRIPT,
    62   APPLICATION_JAVASCRIPT,
    63   APPLICATION_ECMASCRIPT,
    64   APPLICATION_XJAVASCRIPT,
    65   APPLICATION_JSON,
    66   VIEWSOURCE_CONTENT_TYPE,
    67   APPLICATION_XHTML_XML,
    68   0
    69 };
    71 static const char* const gXMLTypes[] = {
    72   TEXT_XML,
    73   APPLICATION_XML,
    74   APPLICATION_MATHML_XML,
    75   APPLICATION_RDF_XML,
    76   TEXT_RDF,
    77   0
    78 };
    80 static const char* const gSVGTypes[] = {
    81   IMAGE_SVG_XML,
    82   0
    83 };
    85 static const char* const gXULTypes[] = {
    86   TEXT_XUL,
    87   APPLICATION_CACHED_XUL,
    88   0
    89 };
    91 nsresult
    92 NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult)
    93 {
    94   NS_PRECONDITION(aResult, "null OUT ptr");
    95   if (!aResult) {
    96     return NS_ERROR_NULL_POINTER;
    97   }
    98   nsContentDLF* it = new nsContentDLF();
    99   if (!it) {
   100     return NS_ERROR_OUT_OF_MEMORY;
   101   }
   103   return CallQueryInterface(it, aResult);
   104 }
   106 nsContentDLF::nsContentDLF()
   107 {
   108 }
   110 nsContentDLF::~nsContentDLF()
   111 {
   112 }
   114 NS_IMPL_ISUPPORTS(nsContentDLF,
   115                   nsIDocumentLoaderFactory)
   117 bool
   118 MayUseXULXBL(nsIChannel* aChannel)
   119 {
   120   nsIScriptSecurityManager *securityManager =
   121     nsContentUtils::GetSecurityManager();
   122   if (!securityManager) {
   123     return false;
   124   }
   126   nsCOMPtr<nsIPrincipal> principal;
   127   securityManager->GetChannelPrincipal(aChannel, getter_AddRefs(principal));
   128   NS_ENSURE_TRUE(principal, false);
   130   return nsContentUtils::AllowXULXBLForPrincipal(principal);
   131 }
   133 NS_IMETHODIMP
   134 nsContentDLF::CreateInstance(const char* aCommand,
   135                              nsIChannel* aChannel,
   136                              nsILoadGroup* aLoadGroup,
   137                              const char* aContentType, 
   138                              nsIDocShell* aContainer,
   139                              nsISupports* aExtraInfo,
   140                              nsIStreamListener** aDocListener,
   141                              nsIContentViewer** aDocViewer)
   142 {
   143   // Declare "type" here.  This is because although the variable itself only
   144   // needs limited scope, we need to use the raw string memory -- as returned
   145   // by "type.get()" farther down in the function.
   146   nsAutoCString type;
   148   // Are we viewing source?
   149   nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel);
   150   if (viewSourceChannel)
   151   {
   152     aCommand = "view-source";
   154     // The parser freaks out when it sees the content-type that a
   155     // view-source channel normally returns.  Get the actual content
   156     // type of the data.  If it's known, use it; otherwise use
   157     // text/plain.
   158     viewSourceChannel->GetOriginalContentType(type);
   159     bool knownType = false;
   160     int32_t typeIndex;
   161     for (typeIndex = 0; gHTMLTypes[typeIndex] && !knownType; ++typeIndex) {
   162       if (type.Equals(gHTMLTypes[typeIndex]) &&
   163           !type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
   164         knownType = true;
   165       }
   166     }
   168     for (typeIndex = 0; gXMLTypes[typeIndex] && !knownType; ++typeIndex) {
   169       if (type.Equals(gXMLTypes[typeIndex])) {
   170         knownType = true;
   171       }
   172     }
   174     for (typeIndex = 0; gSVGTypes[typeIndex] && !knownType; ++typeIndex) {
   175       if (type.Equals(gSVGTypes[typeIndex])) {
   176         knownType = true;
   177       }
   178     }
   180     for (typeIndex = 0; gXULTypes[typeIndex] && !knownType; ++typeIndex) {
   181       if (type.Equals(gXULTypes[typeIndex])) {
   182         knownType = true;
   183       }
   184     }
   186     if (knownType) {
   187       viewSourceChannel->SetContentType(type);
   188     } else if (IsImageContentType(type.get())) {
   189       // If it's an image, we want to display it the same way we normally would.
   190       // Also note the lifetime of "type" allows us to safely use "get()" here.
   191       aContentType = type.get();
   192     } else {
   193       viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
   194     }
   195   } else if (0 == PL_strcmp(VIEWSOURCE_CONTENT_TYPE, aContentType)) {
   196     aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
   197     aContentType = TEXT_PLAIN;
   198   }
   199   // Try html
   200   int typeIndex=0;
   201   while(gHTMLTypes[typeIndex]) {
   202     if (0 == PL_strcmp(gHTMLTypes[typeIndex++], aContentType)) {
   203       return CreateDocument(aCommand, 
   204                             aChannel, aLoadGroup,
   205                             aContainer, kHTMLDocumentCID,
   206                             aDocListener, aDocViewer);
   207     }
   208   }
   210   // Try XML
   211   typeIndex = 0;
   212   while(gXMLTypes[typeIndex]) {
   213     if (0== PL_strcmp(gXMLTypes[typeIndex++], aContentType)) {
   214       return CreateDocument(aCommand, 
   215                             aChannel, aLoadGroup,
   216                             aContainer, kXMLDocumentCID,
   217                             aDocListener, aDocViewer);
   218     }
   219   }
   221   // Try SVG
   222   typeIndex = 0;
   223   while(gSVGTypes[typeIndex]) {
   224     if (!PL_strcmp(gSVGTypes[typeIndex++], aContentType)) {
   225       return CreateDocument(aCommand,
   226                             aChannel, aLoadGroup,
   227                             aContainer, kSVGDocumentCID,
   228                             aDocListener, aDocViewer);
   229     }
   230   }
   232   // Try XUL
   233   typeIndex = 0;
   234   while (gXULTypes[typeIndex]) {
   235     if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType)) {
   236       if (!MayUseXULXBL(aChannel)) {
   237         return NS_ERROR_REMOTE_XUL;
   238       }
   240       return CreateXULDocument(aCommand,
   241                                aChannel, aLoadGroup,
   242                                aContentType, aContainer,
   243                                aExtraInfo, aDocListener, aDocViewer);
   244     }
   245   }
   247   if (mozilla::DecoderTraits::ShouldHandleMediaType(aContentType)) {
   248     return CreateDocument(aCommand, 
   249                           aChannel, aLoadGroup,
   250                           aContainer, kVideoDocumentCID,
   251                           aDocListener, aDocViewer);
   252   }  
   254   // Try image types
   255   if (IsImageContentType(aContentType)) {
   256     return CreateDocument(aCommand, 
   257                           aChannel, aLoadGroup,
   258                           aContainer, kImageDocumentCID,
   259                           aDocListener, aDocViewer);
   260   }
   262   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
   263   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
   264   if(pluginHost &&
   265      pluginHost->PluginExistsForType(aContentType)) {
   266     return CreateDocument(aCommand,
   267                           aChannel, aLoadGroup,
   268                           aContainer, kPluginDocumentCID,
   269                           aDocListener, aDocViewer);
   270   }
   272   // If we get here, then we weren't able to create anything. Sorry!
   273   return NS_ERROR_FAILURE;
   274 }
   277 NS_IMETHODIMP
   278 nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
   279                                         nsIDocument* aDocument,
   280                                         const char *aCommand,
   281                                         nsIContentViewer** aContentViewer)
   282 {
   283   MOZ_ASSERT(aDocument);
   285   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
   287   // Bind the document to the Content Viewer
   288   contentViewer->LoadStart(aDocument);
   289   contentViewer.forget(aContentViewer);
   290   return NS_OK;
   291 }
   293 NS_IMETHODIMP
   294 nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup,
   295                                   nsIPrincipal* aPrincipal,
   296                                   nsIDocument **aDocument)
   297 {
   298   *aDocument = nullptr;
   300   nsresult rv = NS_ERROR_FAILURE;
   302   // create a new blank HTML document
   303   nsCOMPtr<nsIDocument> blankDoc(do_CreateInstance(kHTMLDocumentCID));
   305   if (blankDoc) {
   306     // initialize
   307     nsCOMPtr<nsIURI> uri;
   308     NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
   309     if (uri) {
   310       blankDoc->ResetToURI(uri, aLoadGroup, aPrincipal);
   311       rv = NS_OK;
   312     }
   313   }
   315   // add some simple content structure
   316   if (NS_SUCCEEDED(rv)) {
   317     rv = NS_ERROR_FAILURE;
   319     nsNodeInfoManager *nim = blankDoc->NodeInfoManager();
   321     nsCOMPtr<nsINodeInfo> htmlNodeInfo;
   323     // generate an html html element
   324     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::html, 0, kNameSpaceID_XHTML,
   325                                     nsIDOMNode::ELEMENT_NODE);
   326     nsCOMPtr<nsIContent> htmlElement =
   327       NS_NewHTMLHtmlElement(htmlNodeInfo.forget());
   329     // generate an html head element
   330     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::head, 0, kNameSpaceID_XHTML,
   331                                     nsIDOMNode::ELEMENT_NODE);
   332     nsCOMPtr<nsIContent> headElement =
   333       NS_NewHTMLHeadElement(htmlNodeInfo.forget());
   335     // generate an html body elemment
   336     htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::body, 0, kNameSpaceID_XHTML,
   337                                     nsIDOMNode::ELEMENT_NODE);
   338     nsCOMPtr<nsIContent> bodyElement =
   339       NS_NewHTMLBodyElement(htmlNodeInfo.forget());
   341     // blat in the structure
   342     if (htmlElement && headElement && bodyElement) {
   343       NS_ASSERTION(blankDoc->GetChildCount() == 0,
   344                    "Shouldn't have children");
   345       rv = blankDoc->AppendChildTo(htmlElement, false);
   346       if (NS_SUCCEEDED(rv)) {
   347         rv = htmlElement->AppendChildTo(headElement, false);
   349         if (NS_SUCCEEDED(rv)) {
   350           // XXXbz Why not notifying here?
   351           htmlElement->AppendChildTo(bodyElement, false);
   352         }
   353       }
   354     }
   355   }
   357   // add a nice bow
   358   if (NS_SUCCEEDED(rv)) {
   359     blankDoc->SetDocumentCharacterSetSource(kCharsetFromDocTypeDefault);
   360     blankDoc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8"));
   362     *aDocument = blankDoc;
   363     NS_ADDREF(*aDocument);
   364   }
   365   return rv;
   366 }
   369 nsresult
   370 nsContentDLF::CreateDocument(const char* aCommand,
   371                              nsIChannel* aChannel,
   372                              nsILoadGroup* aLoadGroup,
   373                              nsIDocShell* aContainer,
   374                              const nsCID& aDocumentCID,
   375                              nsIStreamListener** aDocListener,
   376                              nsIContentViewer** aContentViewer)
   377 {
   378   nsresult rv = NS_ERROR_FAILURE;
   380   nsCOMPtr<nsIURI> aURL;
   381   rv = aChannel->GetURI(getter_AddRefs(aURL));
   382   if (NS_FAILED(rv)) return rv;
   384 #ifdef NOISY_CREATE_DOC
   385   if (nullptr != aURL) {
   386     nsAutoString tmp;
   387     aURL->ToString(tmp);
   388     fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
   389     printf(": creating document\n");
   390   }
   391 #endif
   393   // Create the document
   394   nsCOMPtr<nsIDocument> doc = do_CreateInstance(aDocumentCID, &rv);
   395   NS_ENSURE_SUCCESS(rv, rv);
   397   // Create the content viewer  XXX: could reuse content viewer here!
   398   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
   400   doc->SetContainer(static_cast<nsDocShell*>(aContainer));
   402   // Initialize the document to begin loading the data.  An
   403   // nsIStreamListener connected to the parser is returned in
   404   // aDocListener.
   405   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
   406   NS_ENSURE_SUCCESS(rv, rv);
   408   // Bind the document to the Content Viewer
   409   contentViewer->LoadStart(doc);
   410   contentViewer.forget(aContentViewer);
   411   return NS_OK;
   412 }
   414 nsresult
   415 nsContentDLF::CreateXULDocument(const char* aCommand,
   416                                 nsIChannel* aChannel,
   417                                 nsILoadGroup* aLoadGroup,
   418                                 const char* aContentType,
   419                                 nsIDocShell* aContainer,
   420                                 nsISupports* aExtraInfo,
   421                                 nsIStreamListener** aDocListener,
   422                                 nsIContentViewer** aContentViewer)
   423 {
   424   nsresult rv;
   425   nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv);
   426   if (NS_FAILED(rv)) return rv;
   428   nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
   430   nsCOMPtr<nsIURI> aURL;
   431   rv = aChannel->GetURI(getter_AddRefs(aURL));
   432   if (NS_FAILED(rv)) return rv;
   434   /* 
   435    * Initialize the document to begin loading the data...
   436    *
   437    * An nsIStreamListener connected to the parser is returned in
   438    * aDocListener.
   439    */
   441   doc->SetContainer(static_cast<nsDocShell*>(aContainer));
   443   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
   444   if (NS_FAILED(rv)) return rv;
   446   /*
   447    * Bind the document to the Content Viewer...
   448    */
   449   contentViewer->LoadStart(doc);
   450   contentViewer.forget(aContentViewer);
   451   return NS_OK;
   452 }
   454 bool nsContentDLF::IsImageContentType(const char* aContentType) {
   455   return imgLoader::SupportImageWithMimeType(aContentType);
   456 }

mercurial