1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/build/nsContentDLF.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,456 @@ 1.4 +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +#include "nsCOMPtr.h" 1.10 +#include "nsContentDLF.h" 1.11 +#include "nsDocShell.h" 1.12 +#include "nsGenericHTMLElement.h" 1.13 +#include "nsGkAtoms.h" 1.14 +#include "nsIComponentManager.h" 1.15 +#include "nsIComponentRegistrar.h" 1.16 +#include "nsIContentViewer.h" 1.17 +#include "nsICategoryManager.h" 1.18 +#include "nsIDocumentLoaderFactory.h" 1.19 +#include "nsIDocument.h" 1.20 +#include "nsIURL.h" 1.21 +#include "nsNodeInfo.h" 1.22 +#include "nsNodeInfoManager.h" 1.23 +#include "nsIScriptSecurityManager.h" 1.24 +#include "nsString.h" 1.25 +#include "nsContentCID.h" 1.26 +#include "prprf.h" 1.27 +#include "nsNetUtil.h" 1.28 +#include "nsCRT.h" 1.29 +#include "nsIViewSourceChannel.h" 1.30 +#include "nsContentUtils.h" 1.31 +#include "imgLoader.h" 1.32 +#include "nsCharsetSource.h" 1.33 +#include "nsMimeTypes.h" 1.34 +#include "DecoderTraits.h" 1.35 + 1.36 + 1.37 +// plugins 1.38 +#include "nsIPluginHost.h" 1.39 +#include "nsPluginHost.h" 1.40 +static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID); 1.41 + 1.42 +// Factory code for creating variations on html documents 1.43 + 1.44 +#undef NOISY_REGISTRY 1.45 + 1.46 +static NS_DEFINE_IID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID); 1.47 +static NS_DEFINE_IID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); 1.48 +static NS_DEFINE_IID(kSVGDocumentCID, NS_SVGDOCUMENT_CID); 1.49 +static NS_DEFINE_IID(kVideoDocumentCID, NS_VIDEODOCUMENT_CID); 1.50 +static NS_DEFINE_IID(kImageDocumentCID, NS_IMAGEDOCUMENT_CID); 1.51 +static NS_DEFINE_IID(kXULDocumentCID, NS_XULDOCUMENT_CID); 1.52 + 1.53 +already_AddRefed<nsIContentViewer> NS_NewContentViewer(); 1.54 + 1.55 +// XXXbz if you change the MIME types here, be sure to update 1.56 +// nsIParser.h and DetermineParseMode in nsParser.cpp and 1.57 +// nsHTMLDocument::StartDocumentLoad accordingly. 1.58 +static const char* const gHTMLTypes[] = { 1.59 + TEXT_HTML, 1.60 + TEXT_PLAIN, 1.61 + TEXT_CACHE_MANIFEST, 1.62 + TEXT_CSS, 1.63 + TEXT_JAVASCRIPT, 1.64 + TEXT_ECMASCRIPT, 1.65 + APPLICATION_JAVASCRIPT, 1.66 + APPLICATION_ECMASCRIPT, 1.67 + APPLICATION_XJAVASCRIPT, 1.68 + APPLICATION_JSON, 1.69 + VIEWSOURCE_CONTENT_TYPE, 1.70 + APPLICATION_XHTML_XML, 1.71 + 0 1.72 +}; 1.73 + 1.74 +static const char* const gXMLTypes[] = { 1.75 + TEXT_XML, 1.76 + APPLICATION_XML, 1.77 + APPLICATION_MATHML_XML, 1.78 + APPLICATION_RDF_XML, 1.79 + TEXT_RDF, 1.80 + 0 1.81 +}; 1.82 + 1.83 +static const char* const gSVGTypes[] = { 1.84 + IMAGE_SVG_XML, 1.85 + 0 1.86 +}; 1.87 + 1.88 +static const char* const gXULTypes[] = { 1.89 + TEXT_XUL, 1.90 + APPLICATION_CACHED_XUL, 1.91 + 0 1.92 +}; 1.93 + 1.94 +nsresult 1.95 +NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult) 1.96 +{ 1.97 + NS_PRECONDITION(aResult, "null OUT ptr"); 1.98 + if (!aResult) { 1.99 + return NS_ERROR_NULL_POINTER; 1.100 + } 1.101 + nsContentDLF* it = new nsContentDLF(); 1.102 + if (!it) { 1.103 + return NS_ERROR_OUT_OF_MEMORY; 1.104 + } 1.105 + 1.106 + return CallQueryInterface(it, aResult); 1.107 +} 1.108 + 1.109 +nsContentDLF::nsContentDLF() 1.110 +{ 1.111 +} 1.112 + 1.113 +nsContentDLF::~nsContentDLF() 1.114 +{ 1.115 +} 1.116 + 1.117 +NS_IMPL_ISUPPORTS(nsContentDLF, 1.118 + nsIDocumentLoaderFactory) 1.119 + 1.120 +bool 1.121 +MayUseXULXBL(nsIChannel* aChannel) 1.122 +{ 1.123 + nsIScriptSecurityManager *securityManager = 1.124 + nsContentUtils::GetSecurityManager(); 1.125 + if (!securityManager) { 1.126 + return false; 1.127 + } 1.128 + 1.129 + nsCOMPtr<nsIPrincipal> principal; 1.130 + securityManager->GetChannelPrincipal(aChannel, getter_AddRefs(principal)); 1.131 + NS_ENSURE_TRUE(principal, false); 1.132 + 1.133 + return nsContentUtils::AllowXULXBLForPrincipal(principal); 1.134 +} 1.135 + 1.136 +NS_IMETHODIMP 1.137 +nsContentDLF::CreateInstance(const char* aCommand, 1.138 + nsIChannel* aChannel, 1.139 + nsILoadGroup* aLoadGroup, 1.140 + const char* aContentType, 1.141 + nsIDocShell* aContainer, 1.142 + nsISupports* aExtraInfo, 1.143 + nsIStreamListener** aDocListener, 1.144 + nsIContentViewer** aDocViewer) 1.145 +{ 1.146 + // Declare "type" here. This is because although the variable itself only 1.147 + // needs limited scope, we need to use the raw string memory -- as returned 1.148 + // by "type.get()" farther down in the function. 1.149 + nsAutoCString type; 1.150 + 1.151 + // Are we viewing source? 1.152 + nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel); 1.153 + if (viewSourceChannel) 1.154 + { 1.155 + aCommand = "view-source"; 1.156 + 1.157 + // The parser freaks out when it sees the content-type that a 1.158 + // view-source channel normally returns. Get the actual content 1.159 + // type of the data. If it's known, use it; otherwise use 1.160 + // text/plain. 1.161 + viewSourceChannel->GetOriginalContentType(type); 1.162 + bool knownType = false; 1.163 + int32_t typeIndex; 1.164 + for (typeIndex = 0; gHTMLTypes[typeIndex] && !knownType; ++typeIndex) { 1.165 + if (type.Equals(gHTMLTypes[typeIndex]) && 1.166 + !type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) { 1.167 + knownType = true; 1.168 + } 1.169 + } 1.170 + 1.171 + for (typeIndex = 0; gXMLTypes[typeIndex] && !knownType; ++typeIndex) { 1.172 + if (type.Equals(gXMLTypes[typeIndex])) { 1.173 + knownType = true; 1.174 + } 1.175 + } 1.176 + 1.177 + for (typeIndex = 0; gSVGTypes[typeIndex] && !knownType; ++typeIndex) { 1.178 + if (type.Equals(gSVGTypes[typeIndex])) { 1.179 + knownType = true; 1.180 + } 1.181 + } 1.182 + 1.183 + for (typeIndex = 0; gXULTypes[typeIndex] && !knownType; ++typeIndex) { 1.184 + if (type.Equals(gXULTypes[typeIndex])) { 1.185 + knownType = true; 1.186 + } 1.187 + } 1.188 + 1.189 + if (knownType) { 1.190 + viewSourceChannel->SetContentType(type); 1.191 + } else if (IsImageContentType(type.get())) { 1.192 + // If it's an image, we want to display it the same way we normally would. 1.193 + // Also note the lifetime of "type" allows us to safely use "get()" here. 1.194 + aContentType = type.get(); 1.195 + } else { 1.196 + viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN)); 1.197 + } 1.198 + } else if (0 == PL_strcmp(VIEWSOURCE_CONTENT_TYPE, aContentType)) { 1.199 + aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN)); 1.200 + aContentType = TEXT_PLAIN; 1.201 + } 1.202 + // Try html 1.203 + int typeIndex=0; 1.204 + while(gHTMLTypes[typeIndex]) { 1.205 + if (0 == PL_strcmp(gHTMLTypes[typeIndex++], aContentType)) { 1.206 + return CreateDocument(aCommand, 1.207 + aChannel, aLoadGroup, 1.208 + aContainer, kHTMLDocumentCID, 1.209 + aDocListener, aDocViewer); 1.210 + } 1.211 + } 1.212 + 1.213 + // Try XML 1.214 + typeIndex = 0; 1.215 + while(gXMLTypes[typeIndex]) { 1.216 + if (0== PL_strcmp(gXMLTypes[typeIndex++], aContentType)) { 1.217 + return CreateDocument(aCommand, 1.218 + aChannel, aLoadGroup, 1.219 + aContainer, kXMLDocumentCID, 1.220 + aDocListener, aDocViewer); 1.221 + } 1.222 + } 1.223 + 1.224 + // Try SVG 1.225 + typeIndex = 0; 1.226 + while(gSVGTypes[typeIndex]) { 1.227 + if (!PL_strcmp(gSVGTypes[typeIndex++], aContentType)) { 1.228 + return CreateDocument(aCommand, 1.229 + aChannel, aLoadGroup, 1.230 + aContainer, kSVGDocumentCID, 1.231 + aDocListener, aDocViewer); 1.232 + } 1.233 + } 1.234 + 1.235 + // Try XUL 1.236 + typeIndex = 0; 1.237 + while (gXULTypes[typeIndex]) { 1.238 + if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType)) { 1.239 + if (!MayUseXULXBL(aChannel)) { 1.240 + return NS_ERROR_REMOTE_XUL; 1.241 + } 1.242 + 1.243 + return CreateXULDocument(aCommand, 1.244 + aChannel, aLoadGroup, 1.245 + aContentType, aContainer, 1.246 + aExtraInfo, aDocListener, aDocViewer); 1.247 + } 1.248 + } 1.249 + 1.250 + if (mozilla::DecoderTraits::ShouldHandleMediaType(aContentType)) { 1.251 + return CreateDocument(aCommand, 1.252 + aChannel, aLoadGroup, 1.253 + aContainer, kVideoDocumentCID, 1.254 + aDocListener, aDocViewer); 1.255 + } 1.256 + 1.257 + // Try image types 1.258 + if (IsImageContentType(aContentType)) { 1.259 + return CreateDocument(aCommand, 1.260 + aChannel, aLoadGroup, 1.261 + aContainer, kImageDocumentCID, 1.262 + aDocListener, aDocViewer); 1.263 + } 1.264 + 1.265 + nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); 1.266 + nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get()); 1.267 + if(pluginHost && 1.268 + pluginHost->PluginExistsForType(aContentType)) { 1.269 + return CreateDocument(aCommand, 1.270 + aChannel, aLoadGroup, 1.271 + aContainer, kPluginDocumentCID, 1.272 + aDocListener, aDocViewer); 1.273 + } 1.274 + 1.275 + // If we get here, then we weren't able to create anything. Sorry! 1.276 + return NS_ERROR_FAILURE; 1.277 +} 1.278 + 1.279 + 1.280 +NS_IMETHODIMP 1.281 +nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer, 1.282 + nsIDocument* aDocument, 1.283 + const char *aCommand, 1.284 + nsIContentViewer** aContentViewer) 1.285 +{ 1.286 + MOZ_ASSERT(aDocument); 1.287 + 1.288 + nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer(); 1.289 + 1.290 + // Bind the document to the Content Viewer 1.291 + contentViewer->LoadStart(aDocument); 1.292 + contentViewer.forget(aContentViewer); 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 +NS_IMETHODIMP 1.297 +nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup, 1.298 + nsIPrincipal* aPrincipal, 1.299 + nsIDocument **aDocument) 1.300 +{ 1.301 + *aDocument = nullptr; 1.302 + 1.303 + nsresult rv = NS_ERROR_FAILURE; 1.304 + 1.305 + // create a new blank HTML document 1.306 + nsCOMPtr<nsIDocument> blankDoc(do_CreateInstance(kHTMLDocumentCID)); 1.307 + 1.308 + if (blankDoc) { 1.309 + // initialize 1.310 + nsCOMPtr<nsIURI> uri; 1.311 + NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")); 1.312 + if (uri) { 1.313 + blankDoc->ResetToURI(uri, aLoadGroup, aPrincipal); 1.314 + rv = NS_OK; 1.315 + } 1.316 + } 1.317 + 1.318 + // add some simple content structure 1.319 + if (NS_SUCCEEDED(rv)) { 1.320 + rv = NS_ERROR_FAILURE; 1.321 + 1.322 + nsNodeInfoManager *nim = blankDoc->NodeInfoManager(); 1.323 + 1.324 + nsCOMPtr<nsINodeInfo> htmlNodeInfo; 1.325 + 1.326 + // generate an html html element 1.327 + htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::html, 0, kNameSpaceID_XHTML, 1.328 + nsIDOMNode::ELEMENT_NODE); 1.329 + nsCOMPtr<nsIContent> htmlElement = 1.330 + NS_NewHTMLHtmlElement(htmlNodeInfo.forget()); 1.331 + 1.332 + // generate an html head element 1.333 + htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::head, 0, kNameSpaceID_XHTML, 1.334 + nsIDOMNode::ELEMENT_NODE); 1.335 + nsCOMPtr<nsIContent> headElement = 1.336 + NS_NewHTMLHeadElement(htmlNodeInfo.forget()); 1.337 + 1.338 + // generate an html body elemment 1.339 + htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::body, 0, kNameSpaceID_XHTML, 1.340 + nsIDOMNode::ELEMENT_NODE); 1.341 + nsCOMPtr<nsIContent> bodyElement = 1.342 + NS_NewHTMLBodyElement(htmlNodeInfo.forget()); 1.343 + 1.344 + // blat in the structure 1.345 + if (htmlElement && headElement && bodyElement) { 1.346 + NS_ASSERTION(blankDoc->GetChildCount() == 0, 1.347 + "Shouldn't have children"); 1.348 + rv = blankDoc->AppendChildTo(htmlElement, false); 1.349 + if (NS_SUCCEEDED(rv)) { 1.350 + rv = htmlElement->AppendChildTo(headElement, false); 1.351 + 1.352 + if (NS_SUCCEEDED(rv)) { 1.353 + // XXXbz Why not notifying here? 1.354 + htmlElement->AppendChildTo(bodyElement, false); 1.355 + } 1.356 + } 1.357 + } 1.358 + } 1.359 + 1.360 + // add a nice bow 1.361 + if (NS_SUCCEEDED(rv)) { 1.362 + blankDoc->SetDocumentCharacterSetSource(kCharsetFromDocTypeDefault); 1.363 + blankDoc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8")); 1.364 + 1.365 + *aDocument = blankDoc; 1.366 + NS_ADDREF(*aDocument); 1.367 + } 1.368 + return rv; 1.369 +} 1.370 + 1.371 + 1.372 +nsresult 1.373 +nsContentDLF::CreateDocument(const char* aCommand, 1.374 + nsIChannel* aChannel, 1.375 + nsILoadGroup* aLoadGroup, 1.376 + nsIDocShell* aContainer, 1.377 + const nsCID& aDocumentCID, 1.378 + nsIStreamListener** aDocListener, 1.379 + nsIContentViewer** aContentViewer) 1.380 +{ 1.381 + nsresult rv = NS_ERROR_FAILURE; 1.382 + 1.383 + nsCOMPtr<nsIURI> aURL; 1.384 + rv = aChannel->GetURI(getter_AddRefs(aURL)); 1.385 + if (NS_FAILED(rv)) return rv; 1.386 + 1.387 +#ifdef NOISY_CREATE_DOC 1.388 + if (nullptr != aURL) { 1.389 + nsAutoString tmp; 1.390 + aURL->ToString(tmp); 1.391 + fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout); 1.392 + printf(": creating document\n"); 1.393 + } 1.394 +#endif 1.395 + 1.396 + // Create the document 1.397 + nsCOMPtr<nsIDocument> doc = do_CreateInstance(aDocumentCID, &rv); 1.398 + NS_ENSURE_SUCCESS(rv, rv); 1.399 + 1.400 + // Create the content viewer XXX: could reuse content viewer here! 1.401 + nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer(); 1.402 + 1.403 + doc->SetContainer(static_cast<nsDocShell*>(aContainer)); 1.404 + 1.405 + // Initialize the document to begin loading the data. An 1.406 + // nsIStreamListener connected to the parser is returned in 1.407 + // aDocListener. 1.408 + rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true); 1.409 + NS_ENSURE_SUCCESS(rv, rv); 1.410 + 1.411 + // Bind the document to the Content Viewer 1.412 + contentViewer->LoadStart(doc); 1.413 + contentViewer.forget(aContentViewer); 1.414 + return NS_OK; 1.415 +} 1.416 + 1.417 +nsresult 1.418 +nsContentDLF::CreateXULDocument(const char* aCommand, 1.419 + nsIChannel* aChannel, 1.420 + nsILoadGroup* aLoadGroup, 1.421 + const char* aContentType, 1.422 + nsIDocShell* aContainer, 1.423 + nsISupports* aExtraInfo, 1.424 + nsIStreamListener** aDocListener, 1.425 + nsIContentViewer** aContentViewer) 1.426 +{ 1.427 + nsresult rv; 1.428 + nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv); 1.429 + if (NS_FAILED(rv)) return rv; 1.430 + 1.431 + nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer(); 1.432 + 1.433 + nsCOMPtr<nsIURI> aURL; 1.434 + rv = aChannel->GetURI(getter_AddRefs(aURL)); 1.435 + if (NS_FAILED(rv)) return rv; 1.436 + 1.437 + /* 1.438 + * Initialize the document to begin loading the data... 1.439 + * 1.440 + * An nsIStreamListener connected to the parser is returned in 1.441 + * aDocListener. 1.442 + */ 1.443 + 1.444 + doc->SetContainer(static_cast<nsDocShell*>(aContainer)); 1.445 + 1.446 + rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true); 1.447 + if (NS_FAILED(rv)) return rv; 1.448 + 1.449 + /* 1.450 + * Bind the document to the Content Viewer... 1.451 + */ 1.452 + contentViewer->LoadStart(doc); 1.453 + contentViewer.forget(aContentViewer); 1.454 + return NS_OK; 1.455 +} 1.456 + 1.457 +bool nsContentDLF::IsImageContentType(const char* aContentType) { 1.458 + return imgLoader::SupportImageWithMimeType(aContentType); 1.459 +}