Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 }