tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsDOMSerializer.cpp (3032B)


      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 
      7 #include "nsDOMSerializer.h"
      8 
      9 #include "mozilla/Encoding.h"
     10 #include "mozilla/dom/Document.h"
     11 #include "nsComponentManagerUtils.h"
     12 #include "nsContentUtils.h"
     13 #include "nsError.h"
     14 #include "nsIDocumentEncoder.h"
     15 #include "nsINode.h"
     16 
     17 using namespace mozilla;
     18 
     19 nsDOMSerializer::nsDOMSerializer() = default;
     20 
     21 static already_AddRefed<nsIDocumentEncoder> SetUpEncoder(
     22    nsINode& aRoot, const nsAString& aCharset, ErrorResult& aRv) {
     23  nsCOMPtr<nsIDocumentEncoder> encoder =
     24      do_createDocumentEncoder("application/xhtml+xml");
     25  if (!encoder) {
     26    aRv.Throw(NS_ERROR_FAILURE);
     27    return nullptr;
     28  }
     29 
     30  dom::Document* doc = aRoot.OwnerDoc();
     31  bool entireDocument = (doc == &aRoot);
     32 
     33  // This method will fail if no document
     34  nsresult rv = encoder->Init(
     35      doc, u"application/xhtml+xml"_ns,
     36      nsIDocumentEncoder::OutputRaw |
     37          nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration);
     38 
     39  if (NS_FAILED(rv)) {
     40    aRv.Throw(rv);
     41    return nullptr;
     42  }
     43 
     44  NS_ConvertUTF16toUTF8 charset(aCharset);
     45  if (charset.IsEmpty()) {
     46    doc->GetDocumentCharacterSet()->Name(charset);
     47  }
     48  rv = encoder->SetCharset(charset);
     49  if (NS_FAILED(rv)) {
     50    aRv.Throw(rv);
     51    return nullptr;
     52  }
     53 
     54  // If we are working on the entire document we do not need to
     55  // specify which part to serialize
     56  if (!entireDocument) {
     57    rv = encoder->SetNode(&aRoot);
     58  }
     59 
     60  if (NS_FAILED(rv)) {
     61    aRv.Throw(rv);
     62    return nullptr;
     63  }
     64 
     65  return encoder.forget();
     66 }
     67 
     68 void nsDOMSerializer::SerializeToString(nsINode& aRoot, nsAString& aStr,
     69                                        ErrorResult& aRv) {
     70  aStr.Truncate();
     71 
     72  if (!nsContentUtils::CanCallerAccess(&aRoot)) {
     73    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     74    return;
     75  }
     76 
     77  nsCOMPtr<nsIDocumentEncoder> encoder = SetUpEncoder(aRoot, u""_ns, aRv);
     78  if (aRv.Failed()) {
     79    return;
     80  }
     81 
     82  nsresult rv = encoder->EncodeToString(aStr);
     83  if (NS_FAILED(rv)) {
     84    aRv.Throw(rv);
     85  }
     86 }
     87 
     88 void nsDOMSerializer::SerializeToStream(nsINode& aRoot,
     89                                        nsIOutputStream* aStream,
     90                                        const nsAString& aCharset,
     91                                        ErrorResult& aRv) {
     92  if (NS_WARN_IF(!aStream)) {
     93    aRv.Throw(NS_ERROR_INVALID_ARG);
     94    return;
     95  }
     96 
     97  // The charset arg can be empty, in which case we get the document's
     98  // charset and use that when serializing.
     99 
    100  // No point doing a CanCallerAccess check, because we can only be
    101  // called by system JS or C++.
    102  nsCOMPtr<nsIDocumentEncoder> encoder = SetUpEncoder(aRoot, aCharset, aRv);
    103  if (aRv.Failed()) {
    104    return;
    105  }
    106 
    107  nsresult rv = encoder->EncodeToStream(aStream);
    108  if (NS_FAILED(rv)) {
    109    aRv.Throw(rv);
    110  }
    111 }