Coverage Report

Created: 2018-09-25 14:53

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