layout/build/nsContentDLF.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial