Backed out 6 changesets (bug 1712140) for causing Linux related wpt failures in nsHtm...
[gecko.git] / layout / build / nsContentDLF.cpp
blob60375d8e5657d3854f652b2440d43f41769da36c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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"
8 #include "mozilla/Encoding.h"
10 #include "nsCOMPtr.h"
11 #include "nsDocShell.h"
12 #include "nsGenericHTMLElement.h"
13 #include "nsGkAtoms.h"
14 #include "nsIDocumentViewer.h"
15 #include "nsIDocumentLoaderFactory.h"
16 #include "mozilla/dom/Document.h"
17 #include "nsNodeInfoManager.h"
18 #include "nsString.h"
19 #include "nsContentCID.h"
20 #include "nsNetUtil.h"
21 #include "nsCRT.h"
22 #include "nsIViewSourceChannel.h"
23 #include "nsContentUtils.h"
24 #include "imgLoader.h"
25 #include "nsCharsetSource.h"
26 #include "nsMimeTypes.h"
27 #include "DecoderTraits.h"
29 // Factory code for creating variations on html documents
31 #undef NOISY_REGISTRY
33 using mozilla::dom::Document;
35 already_AddRefed<nsIDocumentViewer> NS_NewDocumentViewer();
37 static const char* const gHTMLTypes[] = {TEXT_HTML, VIEWSOURCE_CONTENT_TYPE,
38 APPLICATION_XHTML_XML,
39 APPLICATION_WAPXHTML_XML, 0};
41 static const char* const gXMLTypes[] = {TEXT_XML,
42 APPLICATION_XML,
43 APPLICATION_MATHML_XML,
44 APPLICATION_RDF_XML,
45 TEXT_RDF,
46 0};
48 static const char* const gSVGTypes[] = {IMAGE_SVG_XML, 0};
50 static bool IsTypeInList(const nsACString& aType, const char* const aList[]) {
51 int32_t typeIndex;
52 for (typeIndex = 0; aList[typeIndex]; ++typeIndex) {
53 if (aType.Equals(aList[typeIndex])) {
54 return true;
58 return false;
61 nsresult NS_NewContentDocumentLoaderFactory(
62 nsIDocumentLoaderFactory** aResult) {
63 MOZ_ASSERT(aResult, "null OUT ptr");
64 if (!aResult) {
65 return NS_ERROR_NULL_POINTER;
67 RefPtr<nsContentDLF> it = new nsContentDLF();
68 it.forget(aResult);
69 return NS_OK;
72 nsContentDLF::nsContentDLF() = default;
74 nsContentDLF::~nsContentDLF() = default;
76 NS_IMPL_ISUPPORTS(nsContentDLF, nsIDocumentLoaderFactory)
78 NS_IMETHODIMP
79 nsContentDLF::CreateInstance(const char* aCommand, nsIChannel* aChannel,
80 nsILoadGroup* aLoadGroup,
81 const nsACString& aContentType,
82 nsIDocShell* aContainer, nsISupports* aExtraInfo,
83 nsIStreamListener** aDocListener,
84 nsIDocumentViewer** aDocViewer) {
85 // Make a copy of aContentType, because we're possibly going to change it.
86 nsAutoCString contentType(aContentType);
88 // Are we viewing source?
89 nsCOMPtr<nsIViewSourceChannel> viewSourceChannel =
90 do_QueryInterface(aChannel);
91 if (viewSourceChannel) {
92 aCommand = "view-source";
94 // The parser freaks out when it sees the content-type that a
95 // view-source channel normally returns. Get the actual content
96 // type of the data. If it's known, use it; otherwise use
97 // text/plain.
98 nsAutoCString type;
99 mozilla::Unused << viewSourceChannel->GetOriginalContentType(type);
100 bool knownType = (!type.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE) &&
101 IsTypeInList(type, gHTMLTypes)) ||
102 nsContentUtils::IsPlainTextType(type) ||
103 IsTypeInList(type, gXMLTypes) ||
104 IsTypeInList(type, gSVGTypes) ||
105 IsTypeInList(type, gXMLTypes);
107 if (knownType) {
108 viewSourceChannel->SetContentType(type);
109 } else if (IsImageContentType(type)) {
110 // If it's an image, we want to display it the same way we normally would.
111 contentType = type;
112 } else {
113 viewSourceChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
115 } else if (aContentType.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
116 aChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
117 contentType = TEXT_PLAIN;
120 nsresult rv;
121 bool imageDocument = false;
122 // Try html or plaintext; both use the same document CID
123 if (IsTypeInList(contentType, gHTMLTypes) ||
124 nsContentUtils::IsPlainTextType(contentType)) {
125 rv = CreateDocument(
126 aCommand, aChannel, aLoadGroup, aContainer,
127 []() -> already_AddRefed<Document> {
128 RefPtr<Document> doc;
129 nsresult rv =
130 NS_NewHTMLDocument(getter_AddRefs(doc), nullptr, nullptr);
131 NS_ENSURE_SUCCESS(rv, nullptr);
132 return doc.forget();
134 aDocListener, aDocViewer);
135 } // Try XML
136 else if (IsTypeInList(contentType, gXMLTypes)) {
137 rv = CreateDocument(
138 aCommand, aChannel, aLoadGroup, aContainer,
139 []() -> already_AddRefed<Document> {
140 RefPtr<Document> doc;
141 nsresult rv =
142 NS_NewXMLDocument(getter_AddRefs(doc), nullptr, nullptr);
143 NS_ENSURE_SUCCESS(rv, nullptr);
144 return doc.forget();
146 aDocListener, aDocViewer);
147 } // Try SVG
148 else if (IsTypeInList(contentType, gSVGTypes)) {
149 rv = CreateDocument(
150 aCommand, aChannel, aLoadGroup, aContainer,
151 []() -> already_AddRefed<Document> {
152 RefPtr<Document> doc;
153 nsresult rv =
154 NS_NewSVGDocument(getter_AddRefs(doc), nullptr, nullptr);
155 NS_ENSURE_SUCCESS(rv, nullptr);
156 return doc.forget();
158 aDocListener, aDocViewer);
159 } else if (mozilla::DecoderTraits::ShouldHandleMediaType(
160 contentType.get(),
161 /* DecoderDoctorDiagnostics* */ nullptr)) {
162 rv = CreateDocument(
163 aCommand, aChannel, aLoadGroup, aContainer,
164 []() -> already_AddRefed<Document> {
165 RefPtr<Document> doc;
166 nsresult rv =
167 NS_NewVideoDocument(getter_AddRefs(doc), nullptr, nullptr);
168 NS_ENSURE_SUCCESS(rv, nullptr);
169 return doc.forget();
171 aDocListener, aDocViewer);
172 } // Try image types
173 else if (IsImageContentType(contentType)) {
174 imageDocument = true;
175 rv = CreateDocument(
176 aCommand, aChannel, aLoadGroup, aContainer,
177 []() -> already_AddRefed<Document> {
178 RefPtr<Document> doc;
179 nsresult rv =
180 NS_NewImageDocument(getter_AddRefs(doc), nullptr, nullptr);
181 NS_ENSURE_SUCCESS(rv, nullptr);
182 return doc.forget();
184 aDocListener, aDocViewer);
185 } else {
186 // If we get here, then we weren't able to create anything. Sorry!
187 return NS_ERROR_FAILURE;
190 if (NS_SUCCEEDED(rv) && !imageDocument) {
191 Document* doc = (*aDocViewer)->GetDocument();
192 MOZ_ASSERT(doc);
193 doc->MakeBrowsingContextNonSynthetic();
196 return rv;
199 NS_IMETHODIMP
200 nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
201 Document* aDocument,
202 const char* aCommand,
203 nsIDocumentViewer** aDocumentViewer) {
204 MOZ_ASSERT(aDocument);
206 nsCOMPtr<nsIDocumentViewer> viewer = NS_NewDocumentViewer();
208 // Bind the document to the Content Viewer
209 viewer->LoadStart(aDocument);
210 viewer.forget(aDocumentViewer);
211 return NS_OK;
214 /* static */
215 already_AddRefed<Document> nsContentDLF::CreateBlankDocument(
216 nsILoadGroup* aLoadGroup, nsIPrincipal* aPrincipal,
217 nsIPrincipal* aPartitionedPrincipal, nsDocShell* aContainer) {
218 // create a new blank HTML document
219 RefPtr<Document> blankDoc;
220 mozilla::Unused << NS_NewHTMLDocument(getter_AddRefs(blankDoc), nullptr,
221 nullptr);
223 if (!blankDoc) {
224 return nullptr;
227 // initialize
228 nsCOMPtr<nsIURI> uri;
229 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
230 if (!uri) {
231 return nullptr;
233 blankDoc->ResetToURI(uri, aLoadGroup, aPrincipal, aPartitionedPrincipal);
234 blankDoc->SetContainer(aContainer);
236 // add some simple content structure
237 nsNodeInfoManager* nim = blankDoc->NodeInfoManager();
239 RefPtr<mozilla::dom::NodeInfo> htmlNodeInfo;
241 // generate an html html element
242 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::html, 0, kNameSpaceID_XHTML,
243 nsINode::ELEMENT_NODE);
244 nsCOMPtr<nsIContent> htmlElement =
245 NS_NewHTMLHtmlElement(htmlNodeInfo.forget());
247 // generate an html head element
248 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::head, 0, kNameSpaceID_XHTML,
249 nsINode::ELEMENT_NODE);
250 nsCOMPtr<nsIContent> headElement =
251 NS_NewHTMLHeadElement(htmlNodeInfo.forget());
253 // generate an html body elemment
254 htmlNodeInfo = nim->GetNodeInfo(nsGkAtoms::body, 0, kNameSpaceID_XHTML,
255 nsINode::ELEMENT_NODE);
256 nsCOMPtr<nsIContent> bodyElement =
257 NS_NewHTMLBodyElement(htmlNodeInfo.forget());
259 // blat in the structure
260 NS_ASSERTION(blankDoc->GetChildCount() == 0, "Shouldn't have children");
261 if (!htmlElement || !headElement || !bodyElement) {
262 return nullptr;
265 mozilla::IgnoredErrorResult rv;
266 blankDoc->AppendChildTo(htmlElement, false, rv);
267 if (rv.Failed()) {
268 return nullptr;
271 htmlElement->AppendChildTo(headElement, false, rv);
272 if (rv.Failed()) {
273 return nullptr;
276 // XXXbz Why not notifying here?
277 htmlElement->AppendChildTo(bodyElement, false, rv);
278 if (rv.Failed()) {
279 return nullptr;
282 // add a nice bow
283 blankDoc->SetDocumentCharacterSetSource(kCharsetFromDocTypeDefault);
284 blankDoc->SetDocumentCharacterSet(UTF_8_ENCODING);
285 return blankDoc.forget();
288 nsresult nsContentDLF::CreateDocument(
289 const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup,
290 nsIDocShell* aContainer, nsContentDLF::DocumentCreator aDocumentCreator,
291 nsIStreamListener** aDocListener, nsIDocumentViewer** aDocumentViewer) {
292 MOZ_ASSERT(aDocumentCreator);
294 nsresult rv = NS_ERROR_FAILURE;
296 nsCOMPtr<nsIURI> aURL;
297 rv = aChannel->GetURI(getter_AddRefs(aURL));
298 if (NS_FAILED(rv)) return rv;
300 #ifdef NOISY_CREATE_DOC
301 if (nullptr != aURL) {
302 nsAutoString tmp;
303 aURL->ToString(tmp);
304 fputs(NS_LossyConvertUTF16toASCII(tmp).get(), stdout);
305 printf(": creating document\n");
307 #endif
309 // Create the document
310 RefPtr<Document> doc = aDocumentCreator();
311 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
313 // Create the content viewer XXX: could reuse content viewer here!
314 nsCOMPtr<nsIDocumentViewer> viewer = NS_NewDocumentViewer();
316 doc->SetContainer(static_cast<nsDocShell*>(aContainer));
318 // Initialize the document to begin loading the data. An
319 // nsIStreamListener connected to the parser is returned in
320 // aDocListener.
321 rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
322 aDocListener, true);
323 NS_ENSURE_SUCCESS(rv, rv);
325 // Bind the document to the Content Viewer
326 viewer->LoadStart(doc);
327 viewer.forget(aDocumentViewer);
328 return NS_OK;
331 bool nsContentDLF::IsImageContentType(const nsACString& aContentType) {
332 return imgLoader::SupportImageWithMimeType(aContentType);