Bumping manifests a=b2g-bump
[gecko.git] / layout / build / nsContentDLF.cpp
blobc311b45481630fc541ab565918a88d6f2cebffd8
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 "nsNodeInfoManager.h"
19 #include "nsIScriptSecurityManager.h"
20 #include "nsString.h"
21 #include "nsContentCID.h"
22 #include "prprf.h"
23 #include "nsNetUtil.h"
24 #include "nsCRT.h"
25 #include "nsIViewSourceChannel.h"
26 #include "nsContentUtils.h"
27 #include "imgLoader.h"
28 #include "nsCharsetSource.h"
29 #include "nsMimeTypes.h"
30 #include "DecoderTraits.h"
33 // plugins
34 #include "nsIPluginHost.h"
35 #include "nsPluginHost.h"
36 static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
38 // Factory code for creating variations on html documents
40 #undef NOISY_REGISTRY
42 static NS_DEFINE_IID(kHTMLDocumentCID, NS_HTMLDOCUMENT_CID);
43 static NS_DEFINE_IID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
44 static NS_DEFINE_IID(kSVGDocumentCID, NS_SVGDOCUMENT_CID);
45 static NS_DEFINE_IID(kVideoDocumentCID, NS_VIDEODOCUMENT_CID);
46 static NS_DEFINE_IID(kImageDocumentCID, NS_IMAGEDOCUMENT_CID);
47 static NS_DEFINE_IID(kXULDocumentCID, NS_XULDOCUMENT_CID);
49 already_AddRefed<nsIContentViewer> NS_NewContentViewer();
51 // XXXbz if you change the MIME types here, be sure to update
52 // nsIParser.h and DetermineParseMode in nsParser.cpp and
53 // nsHTMLDocument::StartDocumentLoad accordingly.
54 static const char* const gHTMLTypes[] = {
55 TEXT_HTML,
56 TEXT_PLAIN,
57 TEXT_CACHE_MANIFEST,
58 TEXT_CSS,
59 TEXT_JAVASCRIPT,
60 TEXT_ECMASCRIPT,
61 APPLICATION_JAVASCRIPT,
62 APPLICATION_ECMASCRIPT,
63 APPLICATION_XJAVASCRIPT,
64 APPLICATION_JSON,
65 VIEWSOURCE_CONTENT_TYPE,
66 APPLICATION_XHTML_XML,
70 static const char* const gXMLTypes[] = {
71 TEXT_XML,
72 APPLICATION_XML,
73 APPLICATION_MATHML_XML,
74 APPLICATION_RDF_XML,
75 TEXT_RDF,
79 static const char* const gSVGTypes[] = {
80 IMAGE_SVG_XML,
84 static const char* const gXULTypes[] = {
85 TEXT_XUL,
86 APPLICATION_CACHED_XUL,
90 nsresult
91 NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult)
93 NS_PRECONDITION(aResult, "null OUT ptr");
94 if (!aResult) {
95 return NS_ERROR_NULL_POINTER;
97 nsContentDLF* it = new nsContentDLF();
98 if (!it) {
99 return NS_ERROR_OUT_OF_MEMORY;
102 return CallQueryInterface(it, aResult);
105 nsContentDLF::nsContentDLF()
109 nsContentDLF::~nsContentDLF()
113 NS_IMPL_ISUPPORTS(nsContentDLF,
114 nsIDocumentLoaderFactory)
116 bool
117 MayUseXULXBL(nsIChannel* aChannel)
119 nsIScriptSecurityManager *securityManager =
120 nsContentUtils::GetSecurityManager();
121 if (!securityManager) {
122 return false;
125 nsCOMPtr<nsIPrincipal> principal;
126 securityManager->GetChannelPrincipal(aChannel, getter_AddRefs(principal));
127 NS_ENSURE_TRUE(principal, false);
129 return nsContentUtils::AllowXULXBLForPrincipal(principal);
132 NS_IMETHODIMP
133 nsContentDLF::CreateInstance(const char* aCommand,
134 nsIChannel* aChannel,
135 nsILoadGroup* aLoadGroup,
136 const char* aContentType,
137 nsIDocShell* aContainer,
138 nsISupports* aExtraInfo,
139 nsIStreamListener** aDocListener,
140 nsIContentViewer** aDocViewer)
142 // Declare "type" here. This is because although the variable itself only
143 // needs limited scope, we need to use the raw string memory -- as returned
144 // by "type.get()" farther down in the function.
145 nsAutoCString type;
147 // Are we viewing source?
148 nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel);
149 if (viewSourceChannel)
151 aCommand = "view-source";
153 // The parser freaks out when it sees the content-type that a
154 // view-source channel normally returns. Get the actual content
155 // type of the data. If it's known, use it; otherwise use
156 // text/plain.
157 viewSourceChannel->GetOriginalContentType(type);
158 bool knownType = false;
159 int32_t typeIndex;
160 for (typeIndex = 0; gHTMLTypes[typeIndex] && !knownType; ++typeIndex) {
161 if (type.Equals(gHTMLTypes[typeIndex]) &&
162 !type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
163 knownType = true;
167 for (typeIndex = 0; gXMLTypes[typeIndex] && !knownType; ++typeIndex) {
168 if (type.Equals(gXMLTypes[typeIndex])) {
169 knownType = true;
173 for (typeIndex = 0; gSVGTypes[typeIndex] && !knownType; ++typeIndex) {
174 if (type.Equals(gSVGTypes[typeIndex])) {
175 knownType = true;
179 for (typeIndex = 0; gXULTypes[typeIndex] && !knownType; ++typeIndex) {
180 if (type.Equals(gXULTypes[typeIndex])) {
181 knownType = true;
185 if (knownType) {
186 viewSourceChannel->SetContentType(type);
187 } else if (IsImageContentType(type.get())) {
188 // If it's an image, we want to display it the same way we normally would.
189 // Also note the lifetime of "type" allows us to safely use "get()" here.
190 aContentType = type.get();
191 } else {
192 viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
194 } else if (0 == PL_strcmp(VIEWSOURCE_CONTENT_TYPE, aContentType)) {
195 aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
196 aContentType = TEXT_PLAIN;
198 // Try html
199 int typeIndex=0;
200 while(gHTMLTypes[typeIndex]) {
201 if (0 == PL_strcmp(gHTMLTypes[typeIndex++], aContentType)) {
202 return CreateDocument(aCommand,
203 aChannel, aLoadGroup,
204 aContainer, kHTMLDocumentCID,
205 aDocListener, aDocViewer);
209 // Try XML
210 typeIndex = 0;
211 while(gXMLTypes[typeIndex]) {
212 if (0== PL_strcmp(gXMLTypes[typeIndex++], aContentType)) {
213 return CreateDocument(aCommand,
214 aChannel, aLoadGroup,
215 aContainer, kXMLDocumentCID,
216 aDocListener, aDocViewer);
220 // Try SVG
221 typeIndex = 0;
222 while(gSVGTypes[typeIndex]) {
223 if (!PL_strcmp(gSVGTypes[typeIndex++], aContentType)) {
224 return CreateDocument(aCommand,
225 aChannel, aLoadGroup,
226 aContainer, kSVGDocumentCID,
227 aDocListener, aDocViewer);
231 // Try XUL
232 typeIndex = 0;
233 while (gXULTypes[typeIndex]) {
234 if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType)) {
235 if (!MayUseXULXBL(aChannel)) {
236 return NS_ERROR_REMOTE_XUL;
239 return CreateXULDocument(aCommand,
240 aChannel, aLoadGroup,
241 aContentType, aContainer,
242 aExtraInfo, aDocListener, aDocViewer);
246 if (mozilla::DecoderTraits::ShouldHandleMediaType(aContentType)) {
247 return CreateDocument(aCommand,
248 aChannel, aLoadGroup,
249 aContainer, kVideoDocumentCID,
250 aDocListener, aDocViewer);
253 // Try image types
254 if (IsImageContentType(aContentType)) {
255 return CreateDocument(aCommand,
256 aChannel, aLoadGroup,
257 aContainer, kImageDocumentCID,
258 aDocListener, aDocViewer);
261 nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
262 nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
263 if(pluginHost &&
264 pluginHost->PluginExistsForType(aContentType)) {
265 return CreateDocument(aCommand,
266 aChannel, aLoadGroup,
267 aContainer, kPluginDocumentCID,
268 aDocListener, aDocViewer);
271 // If we get here, then we weren't able to create anything. Sorry!
272 return NS_ERROR_FAILURE;
276 NS_IMETHODIMP
277 nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
278 nsIDocument* aDocument,
279 const char *aCommand,
280 nsIContentViewer** aContentViewer)
282 MOZ_ASSERT(aDocument);
284 nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
286 // Bind the document to the Content Viewer
287 contentViewer->LoadStart(aDocument);
288 contentViewer.forget(aContentViewer);
289 return NS_OK;
292 NS_IMETHODIMP
293 nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup,
294 nsIPrincipal* aPrincipal,
295 nsIDocument **aDocument)
297 *aDocument = nullptr;
299 nsresult rv = NS_ERROR_FAILURE;
301 // create a new blank HTML document
302 nsCOMPtr<nsIDocument> blankDoc(do_CreateInstance(kHTMLDocumentCID));
304 if (blankDoc) {
305 // initialize
306 nsCOMPtr<nsIURI> uri;
307 NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
308 if (uri) {
309 blankDoc->ResetToURI(uri, aLoadGroup, aPrincipal);
310 rv = NS_OK;
314 // add some simple content structure
315 if (NS_SUCCEEDED(rv)) {
316 rv = NS_ERROR_FAILURE;
318 nsNodeInfoManager *nim = blankDoc->NodeInfoManager();
320 nsRefPtr<mozilla::dom::NodeInfo> htmlNodeInfo;
322 // generate an html html element
323 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::html, 0, kNameSpaceID_XHTML,
324 nsIDOMNode::ELEMENT_NODE);
325 nsCOMPtr<nsIContent> htmlElement =
326 NS_NewHTMLHtmlElement(htmlNodeInfo.forget());
328 // generate an html head element
329 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::head, 0, kNameSpaceID_XHTML,
330 nsIDOMNode::ELEMENT_NODE);
331 nsCOMPtr<nsIContent> headElement =
332 NS_NewHTMLHeadElement(htmlNodeInfo.forget());
334 // generate an html body elemment
335 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::body, 0, kNameSpaceID_XHTML,
336 nsIDOMNode::ELEMENT_NODE);
337 nsCOMPtr<nsIContent> bodyElement =
338 NS_NewHTMLBodyElement(htmlNodeInfo.forget());
340 // blat in the structure
341 if (htmlElement && headElement && bodyElement) {
342 NS_ASSERTION(blankDoc->GetChildCount() == 0,
343 "Shouldn't have children");
344 rv = blankDoc->AppendChildTo(htmlElement, false);
345 if (NS_SUCCEEDED(rv)) {
346 rv = htmlElement->AppendChildTo(headElement, false);
348 if (NS_SUCCEEDED(rv)) {
349 // XXXbz Why not notifying here?
350 htmlElement->AppendChildTo(bodyElement, false);
356 // add a nice bow
357 if (NS_SUCCEEDED(rv)) {
358 blankDoc->SetDocumentCharacterSetSource(kCharsetFromDocTypeDefault);
359 blankDoc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8"));
361 *aDocument = blankDoc;
362 NS_ADDREF(*aDocument);
364 return rv;
368 nsresult
369 nsContentDLF::CreateDocument(const char* aCommand,
370 nsIChannel* aChannel,
371 nsILoadGroup* aLoadGroup,
372 nsIDocShell* aContainer,
373 const nsCID& aDocumentCID,
374 nsIStreamListener** aDocListener,
375 nsIContentViewer** aContentViewer)
377 nsresult rv = NS_ERROR_FAILURE;
379 nsCOMPtr<nsIURI> aURL;
380 rv = aChannel->GetURI(getter_AddRefs(aURL));
381 if (NS_FAILED(rv)) return rv;
383 #ifdef NOISY_CREATE_DOC
384 if (nullptr != aURL) {
385 nsAutoString tmp;
386 aURL->ToString(tmp);
387 fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
388 printf(": creating document\n");
390 #endif
392 // Create the document
393 nsCOMPtr<nsIDocument> doc = do_CreateInstance(aDocumentCID, &rv);
394 NS_ENSURE_SUCCESS(rv, rv);
396 // Create the content viewer XXX: could reuse content viewer here!
397 nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
399 doc->SetContainer(static_cast<nsDocShell*>(aContainer));
401 // Initialize the document to begin loading the data. An
402 // nsIStreamListener connected to the parser is returned in
403 // aDocListener.
404 rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
405 NS_ENSURE_SUCCESS(rv, rv);
407 // Bind the document to the Content Viewer
408 contentViewer->LoadStart(doc);
409 contentViewer.forget(aContentViewer);
410 return NS_OK;
413 nsresult
414 nsContentDLF::CreateXULDocument(const char* aCommand,
415 nsIChannel* aChannel,
416 nsILoadGroup* aLoadGroup,
417 const char* aContentType,
418 nsIDocShell* aContainer,
419 nsISupports* aExtraInfo,
420 nsIStreamListener** aDocListener,
421 nsIContentViewer** aContentViewer)
423 nsresult rv;
424 nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv);
425 if (NS_FAILED(rv)) return rv;
427 nsCOMPtr<nsIContentViewer> contentViewer = NS_NewContentViewer();
429 nsCOMPtr<nsIURI> aURL;
430 rv = aChannel->GetURI(getter_AddRefs(aURL));
431 if (NS_FAILED(rv)) return rv;
434 * Initialize the document to begin loading the data...
436 * An nsIStreamListener connected to the parser is returned in
437 * aDocListener.
440 doc->SetContainer(static_cast<nsDocShell*>(aContainer));
442 rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
443 if (NS_FAILED(rv)) return rv;
446 * Bind the document to the Content Viewer...
448 contentViewer->LoadStart(doc);
449 contentViewer.forget(aContentViewer);
450 return NS_OK;
453 bool nsContentDLF::IsImageContentType(const char* aContentType) {
454 return imgLoader::SupportImageWithMimeType(aContentType);