tor-browser

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

nsXMLFragmentContentSink.cpp (12610B)


      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 "mozilla/css/Loader.h"
      8 #include "mozilla/dom/Document.h"
      9 #include "mozilla/dom/DocumentFragment.h"
     10 #include "mozilla/dom/NodeInfo.h"
     11 #include "mozilla/dom/ProcessingInstruction.h"
     12 #include "mozilla/dom/ScriptLoader.h"
     13 #include "nsCOMPtr.h"
     14 #include "nsContentCreatorFunctions.h"
     15 #include "nsContentSink.h"
     16 #include "nsCycleCollectionParticipant.h"
     17 #include "nsError.h"
     18 #include "nsGkAtoms.h"
     19 #include "nsHashKeys.h"
     20 #include "nsIContent.h"
     21 #include "nsIDocShell.h"
     22 #include "nsIExpatSink.h"
     23 #include "nsIFragmentContentSink.h"
     24 #include "nsIScriptError.h"
     25 #include "nsIXMLContentSink.h"
     26 #include "nsTArray.h"
     27 #include "nsTHashtable.h"
     28 #include "nsXMLContentSink.h"
     29 
     30 using namespace mozilla::dom;
     31 
     32 class nsXMLFragmentContentSink : public nsXMLContentSink,
     33                                 public nsIFragmentContentSink {
     34 public:
     35  nsXMLFragmentContentSink();
     36 
     37  // nsISupports
     38  NS_DECL_ISUPPORTS_INHERITED
     39  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLFragmentContentSink,
     40                                           nsXMLContentSink)
     41 
     42  // nsIExpatSink
     43  NS_IMETHOD HandleDoctypeDecl(const nsAString& aSubset, const nsAString& aName,
     44                               const nsAString& aSystemId,
     45                               const nsAString& aPublicId,
     46                               nsISupports* aCatalogData) override;
     47  NS_IMETHOD HandleProcessingInstruction(const char16_t* aTarget,
     48                                         const char16_t* aData) override;
     49  NS_IMETHOD HandleXMLDeclaration(const char16_t* aVersion,
     50                                  const char16_t* aEncoding,
     51                                  int32_t aStandalone) override;
     52  NS_IMETHOD ReportError(const char16_t* aErrorText,
     53                         const char16_t* aSourceText, nsIScriptError* aError,
     54                         bool* aRetval) override;
     55 
     56  // nsIContentSink
     57  NS_IMETHOD WillBuildModel() override;
     58  NS_IMETHOD DidBuildModel(bool aTerminated) override;
     59  virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
     60  virtual nsISupports* GetTarget() override;
     61  NS_IMETHOD DidProcessATokenImpl();
     62 
     63  // nsIXMLContentSink
     64 
     65  // nsIFragmentContentSink
     66  NS_IMETHOD FinishFragmentParsing(DocumentFragment** aFragment) override;
     67  NS_IMETHOD SetTargetDocument(Document* aDocument) override;
     68  NS_IMETHOD WillBuildContent() override;
     69  NS_IMETHOD DidBuildContent() override;
     70  NS_IMETHOD IgnoreFirstContainer() override;
     71  NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) override;
     72 
     73 protected:
     74  virtual ~nsXMLFragmentContentSink();
     75 
     76  virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName,
     77                             nsIContent* aContent) override;
     78  virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
     79                                 mozilla::dom::NodeInfo* aNodeInfo,
     80                                 uint32_t aLineNumber, uint32_t aColumnNumber,
     81                                 nsIContent** aResult, bool* aAppendContent,
     82                                 mozilla::dom::FromParser aFromParser) override;
     83  virtual nsresult CloseElement(nsIContent* aContent) override;
     84 
     85  virtual void MaybeStartLayout(bool aIgnorePendingSheets) override;
     86 
     87  // nsContentSink overrides
     88  virtual nsresult ProcessStyleLinkFromHeader(
     89      const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
     90      const nsAString& aIntegrity, const nsAString& aType,
     91      const nsAString& aMedia, const nsAString& aReferrerPolicy,
     92      const nsAString& aFetchPriority) override;
     93 
     94  // nsXMLContentSink overrides
     95  virtual nsresult MaybeProcessXSLTLink(
     96      ProcessingInstruction* aProcessingInstruction, const nsAString& aHref,
     97      bool aAlternate, const nsAString& aTitle, const nsAString& aType,
     98      const nsAString& aMedia, const nsAString& aReferrerPolicy,
     99      bool* aWasXSLT = nullptr) override;
    100 
    101  nsCOMPtr<Document> mTargetDocument;
    102  // the fragment
    103  RefPtr<DocumentFragment> mRoot;
    104  bool mParseError;
    105 };
    106 
    107 static nsresult NewXMLFragmentContentSinkHelper(
    108    nsIFragmentContentSink** aResult) {
    109  nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink();
    110 
    111  NS_ADDREF(*aResult = it);
    112 
    113  return NS_OK;
    114 }
    115 
    116 nsresult NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult) {
    117  return NewXMLFragmentContentSinkHelper(aResult);
    118 }
    119 
    120 nsXMLFragmentContentSink::nsXMLFragmentContentSink() : mParseError(false) {
    121  mRunsToCompletion = true;
    122 }
    123 
    124 nsXMLFragmentContentSink::~nsXMLFragmentContentSink() = default;
    125 
    126 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLFragmentContentSink)
    127  NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
    128 NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
    129 
    130 NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
    131 NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
    132 
    133 NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink,
    134                                   mTargetDocument, mRoot)
    135 
    136 NS_IMETHODIMP
    137 nsXMLFragmentContentSink::WillBuildModel() {
    138  if (mRoot) {
    139    return NS_OK;
    140  }
    141 
    142  mState = eXMLContentSinkState_InDocumentElement;
    143 
    144  NS_ASSERTION(mTargetDocument, "Need a document!");
    145 
    146  mRoot = new (mNodeInfoManager) DocumentFragment(mNodeInfoManager);
    147 
    148  return NS_OK;
    149 }
    150 
    151 NS_IMETHODIMP
    152 nsXMLFragmentContentSink::DidBuildModel(bool aTerminated) {
    153  // Drop our reference to the parser to get rid of a circular
    154  // reference.
    155  mParser = nullptr;
    156 
    157  return NS_OK;
    158 }
    159 
    160 void nsXMLFragmentContentSink::SetDocumentCharset(
    161    NotNull<const Encoding*> aEncoding) {
    162  MOZ_ASSERT_UNREACHABLE("fragments shouldn't set charset");
    163 }
    164 
    165 nsISupports* nsXMLFragmentContentSink::GetTarget() {
    166  return ToSupports(mTargetDocument);
    167 }
    168 
    169 ////////////////////////////////////////////////////////////////////////
    170 
    171 bool nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
    172                                             nsAtom* aTagName,
    173                                             nsIContent* aContent) {
    174  // this is a fragment, not a document
    175  return false;
    176 }
    177 
    178 nsresult nsXMLFragmentContentSink::CreateElement(
    179    const char16_t** aAtts, uint32_t aAttsCount,
    180    mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
    181    uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent,
    182    FromParser /*aFromParser*/) {
    183  // Claim to not be coming from parser, since we don't do any of the
    184  // fancy CloseElement stuff.
    185  nsresult rv = nsXMLContentSink::CreateElement(
    186      aAtts, aAttsCount, aNodeInfo, aLineNumber, aColumnNumber, aResult,
    187      aAppendContent, NOT_FROM_PARSER);
    188 
    189  // When we aren't grabbing all of the content we, never open a doc
    190  // element, we run into trouble on the first element, so we don't append,
    191  // and simply push this onto the content stack.
    192  if (mContentStack.Length() == 0) {
    193    *aAppendContent = false;
    194  }
    195 
    196  return rv;
    197 }
    198 
    199 nsresult nsXMLFragmentContentSink::CloseElement(nsIContent* aContent) {
    200  // don't do fancy stuff in nsXMLContentSink
    201  if (mPreventScriptExecution && (aContent->IsHTMLElement(nsGkAtoms::script) ||
    202                                  aContent->IsSVGElement(nsGkAtoms::script))) {
    203    nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
    204    if (sele) {
    205      sele->PreventExecution();
    206    } else {
    207      NS_ASSERTION(nsNameSpaceManager::GetInstance()->mSVGDisabled,
    208                   "Script did QI correctly, but wasn't a disabled SVG!");
    209    }
    210  }
    211  return NS_OK;
    212 }
    213 
    214 void nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets) {}
    215 
    216 ////////////////////////////////////////////////////////////////////////
    217 
    218 NS_IMETHODIMP
    219 nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString& aSubset,
    220                                            const nsAString& aName,
    221                                            const nsAString& aSystemId,
    222                                            const nsAString& aPublicId,
    223                                            nsISupports* aCatalogData) {
    224  MOZ_ASSERT_UNREACHABLE("fragments shouldn't have doctype declarations");
    225 
    226  return NS_OK;
    227 }
    228 
    229 NS_IMETHODIMP
    230 nsXMLFragmentContentSink::HandleProcessingInstruction(const char16_t* aTarget,
    231                                                      const char16_t* aData) {
    232  FlushText();
    233 
    234  const nsDependentString target(aTarget);
    235  const nsDependentString data(aData);
    236 
    237  RefPtr<ProcessingInstruction> node =
    238      NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data);
    239 
    240  // no special processing here.  that should happen when the fragment moves
    241  // into the document
    242  return AddContentAsLeaf(node);
    243 }
    244 
    245 NS_IMETHODIMP
    246 nsXMLFragmentContentSink::HandleXMLDeclaration(const char16_t* aVersion,
    247                                               const char16_t* aEncoding,
    248                                               int32_t aStandalone) {
    249  MOZ_ASSERT_UNREACHABLE("fragments shouldn't have XML declarations");
    250  return NS_OK;
    251 }
    252 
    253 NS_IMETHODIMP
    254 nsXMLFragmentContentSink::ReportError(const char16_t* aErrorText,
    255                                      const char16_t* aSourceText,
    256                                      nsIScriptError* aError, bool* _retval) {
    257  MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
    258 
    259  // The expat driver should report the error.
    260  *_retval = true;
    261 
    262  mParseError = true;
    263 
    264 #ifdef DEBUG
    265  // Report the error to stderr.
    266  fprintf(stderr, "\n%s\n%s\n\n", NS_LossyConvertUTF16toASCII(aErrorText).get(),
    267          NS_LossyConvertUTF16toASCII(aSourceText).get());
    268 #endif
    269 
    270  // The following code is similar to the cleanup in
    271  // nsXMLContentSink::ReportError()
    272  mState = eXMLContentSinkState_InProlog;
    273 
    274  // Clear the current content
    275  while (mRoot->GetLastChild()) {
    276    mRoot->GetLastChild()->Remove();
    277  }
    278 
    279  // Clear any buffered-up text we have.  It's enough to set the length to 0.
    280  // The buffer itself is allocated when we're created and deleted in our
    281  // destructor, so don't mess with it.
    282  mTextLength = 0;
    283 
    284  return NS_OK;
    285 }
    286 
    287 nsresult nsXMLFragmentContentSink::ProcessStyleLinkFromHeader(
    288    const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
    289    const nsAString& aIntegrity, const nsAString& aType,
    290    const nsAString& aMedia, const nsAString& aReferrerPolicy,
    291    const nsAString& aFetchPriority)
    292 
    293 {
    294  MOZ_ASSERT_UNREACHABLE("Shouldn't have headers for a fragment sink");
    295  return NS_OK;
    296 }
    297 
    298 nsresult nsXMLFragmentContentSink::MaybeProcessXSLTLink(
    299    ProcessingInstruction* aProcessingInstruction, const nsAString& aHref,
    300    bool aAlternate, const nsAString& aTitle, const nsAString& aType,
    301    const nsAString& aMedia, const nsAString& aReferrerPolicy, bool* aWasXSLT) {
    302  MOZ_ASSERT(!aWasXSLT, "Our one caller doesn't care about whether we're XSLT");
    303  return NS_OK;
    304 }
    305 
    306 ////////////////////////////////////////////////////////////////////////
    307 
    308 NS_IMETHODIMP
    309 nsXMLFragmentContentSink::FinishFragmentParsing(DocumentFragment** aFragment) {
    310  mTargetDocument = nullptr;
    311  mNodeInfoManager = nullptr;
    312  mScriptLoader = nullptr;
    313  mContentStack.Clear();
    314  mDocumentURI = nullptr;
    315  mDocShell = nullptr;
    316  mDocElement = nullptr;
    317  mCurrentHead = nullptr;
    318  if (mParseError) {
    319    // XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
    320    mRoot = nullptr;
    321    mParseError = false;
    322    *aFragment = nullptr;
    323    return NS_ERROR_DOM_SYNTAX_ERR;
    324  }
    325 
    326  mRoot.forget(aFragment);
    327  return NS_OK;
    328 }
    329 
    330 NS_IMETHODIMP
    331 nsXMLFragmentContentSink::SetTargetDocument(Document* aTargetDocument) {
    332  NS_ENSURE_ARG_POINTER(aTargetDocument);
    333 
    334  mTargetDocument = aTargetDocument;
    335  mNodeInfoManager = aTargetDocument->NodeInfoManager();
    336 
    337  return NS_OK;
    338 }
    339 
    340 NS_IMETHODIMP
    341 nsXMLFragmentContentSink::WillBuildContent() {
    342  PushContent(mRoot);
    343 
    344  return NS_OK;
    345 }
    346 
    347 NS_IMETHODIMP
    348 nsXMLFragmentContentSink::DidBuildContent() {
    349  // Note: we need to FlushText() here because if we don't, we might not get
    350  // an end element to do it for us, so make sure.
    351  if (!mParseError) {
    352    FlushText();
    353  }
    354  PopContent();
    355 
    356  return NS_OK;
    357 }
    358 
    359 NS_IMETHODIMP
    360 nsXMLFragmentContentSink::DidProcessATokenImpl() { return NS_OK; }
    361 
    362 NS_IMETHODIMP
    363 nsXMLFragmentContentSink::IgnoreFirstContainer() {
    364  MOZ_ASSERT_UNREACHABLE("XML isn't as broken as HTML");
    365  return NS_ERROR_FAILURE;
    366 }
    367 
    368 NS_IMETHODIMP
    369 nsXMLFragmentContentSink::SetPreventScriptExecution(bool aPrevent) {
    370  mPreventScriptExecution = aPrevent;
    371  return NS_OK;
    372 }