Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsXMLContentSerializer.h
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
/*
8
 * nsIContentSerializer implementation that can be used with an
9
 * nsIDocumentEncoder to convert an XML DOM to an XML string that
10
 * could be parsed into more or less the original DOM.
11
 */
12
13
#ifndef nsXMLContentSerializer_h__
14
#define nsXMLContentSerializer_h__
15
16
#include "mozilla/Attributes.h"
17
#include "nsIContentSerializer.h"
18
#include "nsISupportsUtils.h"
19
#include "nsCOMPtr.h"
20
#include "nsTArray.h"
21
#include "nsString.h"
22
23
#define kIndentStr NS_LITERAL_STRING("  ")
24
#define kEndTag NS_LITERAL_STRING("</")
25
26
class nsAtom;
27
class nsINode;
28
29
namespace mozilla {
30
class Encoding;
31
}
32
33
class nsXMLContentSerializer : public nsIContentSerializer {
34
 public:
35
  nsXMLContentSerializer();
36
37
  NS_DECL_ISUPPORTS
38
39
  NS_IMETHOD Init(uint32_t flags,
40
                  uint32_t aWrapColumn,
41
                  const mozilla::Encoding* aEncoding,
42
                  bool aIsCopying,
43
                  bool aRewriteEncodingDeclaration,
44
                  bool* aNeedsPreformatScanning) override;
45
46
  NS_IMETHOD AppendText(nsIContent* aText, int32_t aStartOffset,
47
                        int32_t aEndOffset, nsAString& aStr) override;
48
49
  NS_IMETHOD AppendCDATASection(nsIContent* aCDATASection,
50
                                int32_t aStartOffset, int32_t aEndOffset,
51
                                nsAString& aStr) override;
52
53
  NS_IMETHOD AppendProcessingInstruction(mozilla::dom::ProcessingInstruction* aPI,
54
                                         int32_t aStartOffset,
55
                                         int32_t aEndOffset,
56
                                         nsAString& aStr) override;
57
58
  NS_IMETHOD AppendComment(mozilla::dom::Comment* aComment,
59
                           int32_t aStartOffset,
60
                           int32_t aEndOffset, nsAString& aStr) override;
61
62
  NS_IMETHOD AppendDoctype(mozilla::dom::DocumentType* aDoctype,
63
                           nsAString& aStr) override;
64
65
  NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement,
66
                                mozilla::dom::Element* aOriginalElement,
67
                                nsAString& aStr) override;
68
69
  NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
70
                              nsAString& aStr) override;
71
72
0
  NS_IMETHOD Flush(nsAString& aStr) override { return NS_OK; }
73
74
  NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
75
                                 nsAString& aStr) override;
76
77
  NS_IMETHOD ScanElementForPreformat(mozilla::dom::Element* aElement) override
78
0
  {
79
0
    return NS_OK;
80
0
  }
81
  NS_IMETHOD ForgetElementForPreformat(mozilla::dom::Element* aElement) override
82
0
  {
83
0
    return NS_OK;
84
0
  }
85
86
 protected:
87
  virtual ~nsXMLContentSerializer();
88
89
  /**
90
   * Appends a char16_t character and increments the column position
91
   */
92
  MOZ_MUST_USE
93
  bool AppendToString(const char16_t aChar,
94
                      nsAString& aOutputStr);
95
96
  /**
97
   * Appends a nsAString string and increments the column position
98
   */
99
  MOZ_MUST_USE
100
  bool AppendToString(const nsAString& aStr,
101
                      nsAString& aOutputStr);
102
103
  /**
104
   * Appends a string by replacing all line-endings
105
   * by mLineBreak, except in the case of raw output.
106
   * It increments the column position.
107
   */
108
  MOZ_MUST_USE
109
  bool AppendToStringConvertLF(const nsAString& aStr,
110
                               nsAString& aOutputStr);
111
112
  /**
113
   * Appends a string by wrapping it when necessary.
114
   * It updates the column position.
115
   */
116
  MOZ_MUST_USE
117
  bool AppendToStringWrapped(const nsAString& aStr,
118
                             nsAString& aOutputStr);
119
120
  /**
121
   * Appends a string by formating and wrapping it when necessary
122
   * It updates the column position.
123
   */
124
  MOZ_MUST_USE
125
  bool AppendToStringFormatedWrapped(const nsAString& aStr,
126
                                     nsAString& aOutputStr);
127
128
  // used by AppendToStringWrapped
129
  MOZ_MUST_USE
130
  bool AppendWrapped_WhitespaceSequence(
131
          nsAString::const_char_iterator &aPos,
132
          const nsAString::const_char_iterator aEnd,
133
          const nsAString::const_char_iterator aSequenceStart,
134
          nsAString &aOutputStr);
135
136
  // used by AppendToStringFormatedWrapped
137
  MOZ_MUST_USE
138
  bool AppendFormatedWrapped_WhitespaceSequence(
139
          nsAString::const_char_iterator &aPos,
140
          const nsAString::const_char_iterator aEnd,
141
          const nsAString::const_char_iterator aSequenceStart,
142
          bool &aMayIgnoreStartOfLineWhitespaceSequence,
143
          nsAString &aOutputStr);
144
145
  // used by AppendToStringWrapped and AppendToStringFormatedWrapped
146
  MOZ_MUST_USE
147
  bool AppendWrapped_NonWhitespaceSequence(
148
          nsAString::const_char_iterator &aPos,
149
          const nsAString::const_char_iterator aEnd,
150
          const nsAString::const_char_iterator aSequenceStart,
151
          bool &aMayIgnoreStartOfLineWhitespaceSequence,
152
          bool &aSequenceStartAfterAWhiteSpace,
153
          nsAString &aOutputStr);
154
155
  /**
156
   * add mLineBreak to the string
157
   * It updates the column position and other flags.
158
   */
159
  MOZ_MUST_USE
160
  bool AppendNewLineToString(nsAString& aOutputStr);
161
162
163
  /**
164
   * Appends a string by translating entities
165
   * It doesn't increment the column position
166
   */
167
  MOZ_MUST_USE
168
  virtual bool AppendAndTranslateEntities(const nsAString& aStr,
169
                                          nsAString& aOutputStr);
170
171
  /**
172
   * retrieve the text content of the node and append it to the given string
173
   * It doesn't increment the column position
174
   */
175
  nsresult AppendTextData(nsIContent* aNode,
176
                          int32_t aStartOffset,
177
                          int32_t aEndOffset,
178
                          nsAString& aStr,
179
                          bool aTranslateEntities);
180
181
  virtual nsresult PushNameSpaceDecl(const nsAString& aPrefix,
182
                                     const nsAString& aURI,
183
                                     nsIContent* aOwner);
184
  void PopNameSpaceDeclsFor(nsIContent* aOwner);
185
186
  /**
187
   * The problem that ConfirmPrefix fixes is that anyone can insert nodes
188
   * through the DOM that have a namespace URI and a random or empty or
189
   * previously existing prefix that's totally unrelated to the prefixes
190
   * declared at that point through xmlns attributes.  So what ConfirmPrefix
191
   * does is ensure that we can map aPrefix to the namespace URI aURI (for
192
   * example, that the prefix is not already mapped to some other namespace).
193
   * aPrefix will be adjusted, if necessary, so the value of the prefix
194
   * _after_ this call is what should be serialized.
195
   * @param aPrefix the prefix that may need adjusting
196
   * @param aURI the namespace URI we want aPrefix to point to
197
   * @param aElement the element we're working with (needed for proper default
198
   *                 namespace handling)
199
   * @param aIsAttribute true if we're confirming a prefix for an attribute.
200
   * @return true if we need to push the (prefix, uri) pair on the namespace
201
   *                 stack (note that this can happen even if the prefix is
202
   *                 empty).
203
   */
204
  bool ConfirmPrefix(nsAString& aPrefix,
205
                       const nsAString& aURI,
206
                       nsIContent* aElement,
207
                       bool aIsAttribute);
208
  /**
209
   * GenerateNewPrefix generates a new prefix and writes it to aPrefix
210
   */
211
  void GenerateNewPrefix(nsAString& aPrefix);
212
213
  uint32_t ScanNamespaceDeclarations(mozilla::dom::Element* aContent,
214
                                     mozilla::dom::Element* aOriginalElement,
215
                                     const nsAString& aTagNamespaceURI);
216
217
  MOZ_MUST_USE
218
  virtual bool SerializeAttributes(mozilla::dom::Element* aContent,
219
                                   mozilla::dom::Element* aOriginalElement,
220
                                   nsAString& aTagPrefix,
221
                                   const nsAString& aTagNamespaceURI,
222
                                   nsAtom* aTagName,
223
                                   nsAString& aStr,
224
                                   uint32_t aSkipAttr,
225
                                   bool aAddNSAttr);
226
227
  MOZ_MUST_USE
228
  bool SerializeAttr(const nsAString& aPrefix,
229
                     const nsAString& aName,
230
                     const nsAString& aValue,
231
                     nsAString& aStr,
232
                     bool aDoEscapeEntities);
233
234
  bool IsJavaScript(nsIContent * aContent,
235
                      nsAtom* aAttrNameAtom,
236
                      int32_t aAttrNamespaceID,
237
                      const nsAString& aValueString);
238
239
  /**
240
   * This method can be redefined to check if the element can be serialized.
241
   * It is called when the serialization of the start tag is asked
242
   * (AppendElementStart)
243
   * In this method you can also force the formating
244
   * by setting aForceFormat to true.
245
   * @return boolean  true if the element can be output
246
   */
247
  virtual bool CheckElementStart(mozilla::dom::Element* aElement,
248
                                 bool & aForceFormat,
249
                                 nsAString& aStr,
250
                                 nsresult& aResult);
251
252
  /**
253
   * This method is responsible for appending the '>' at the end of the start
254
   * tag, possibly preceded by '/' and maybe a ' ' before that too.
255
   *
256
   * aElement and aOriginalElement are the same as the corresponding arguments
257
   * to AppendElementStart.
258
   */
259
  MOZ_MUST_USE
260
  bool AppendEndOfElementStart(mozilla::dom::Element* aEleemnt,
261
                               mozilla::dom::Element* aOriginalElement,
262
                               nsAString& aStr);
263
264
  /**
265
   * This method can be redefine to serialize additional things just after
266
   * after the serialization ot the start tag.
267
   * (called at the end of AppendElementStart)
268
   */
269
  MOZ_MUST_USE
270
  virtual bool AfterElementStart(nsIContent* aContent,
271
                                 nsIContent* aOriginalElement,
272
0
                                 nsAString& aStr) { return true; };
273
274
  /**
275
   * This method can be redefined to check if the element can be serialized.
276
   * It is called when the serialization of the end tag is asked
277
   * (AppendElementEnd)
278
   * In this method you can also force the formating
279
   * by setting aForceFormat to true.
280
   * @return boolean  true if the element can be output
281
   */
282
  virtual bool CheckElementEnd(mozilla::dom::Element* aElement,
283
                               bool& aForceFormat,
284
                               nsAString& aStr);
285
286
  /**
287
   * This method can be redefine to serialize additional things just after
288
   * after the serialization ot the end tag.
289
   * (called at the end of AppendElementStart)
290
   */
291
  virtual void AfterElementEnd(nsIContent * aContent,
292
0
                               nsAString& aStr) { };
293
294
  /**
295
   * Returns true if a line break should be inserted before an element open tag
296
   */
297
  virtual bool LineBreakBeforeOpen(int32_t aNamespaceID, nsAtom* aName);
298
299
  /**
300
   * Returns true if a line break should be inserted after an element open tag
301
   */
302
  virtual bool LineBreakAfterOpen(int32_t aNamespaceID, nsAtom* aName);
303
304
  /**
305
   * Returns true if a line break should be inserted after an element close tag
306
   */
307
  virtual bool LineBreakBeforeClose(int32_t aNamespaceID, nsAtom* aName);
308
309
  /**
310
   * Returns true if a line break should be inserted after an element close tag
311
   */
312
  virtual bool LineBreakAfterClose(int32_t aNamespaceID, nsAtom* aName);
313
314
  /**
315
   * add intendation. Call only in the case of formating and if the current
316
   * position is at 0. It updates the column position.
317
   */
318
  MOZ_MUST_USE
319
  bool AppendIndentation(nsAString& aStr);
320
321
  MOZ_MUST_USE
322
  bool IncrIndentation(nsAtom* aName);
323
  void DecrIndentation(nsAtom* aName);
324
325
  // Functions to check for newlines that needs to be added between nodes in
326
  // the root of a document. See mAddNewlineForRootNode
327
  MOZ_MUST_USE
328
  bool MaybeAddNewlineForRootNode(nsAString& aStr);
329
  void MaybeFlagNewlineForRootNode(nsINode* aNode);
330
331
  // Functions to check if we enter in or leave from a preformated content
332
  virtual void MaybeEnterInPreContent(nsIContent* aNode);
333
  virtual void MaybeLeaveFromPreContent(nsIContent* aNode);
334
335
  bool ShouldMaintainPreLevel() const;
336
0
  int32_t PreLevel() const {
337
0
    MOZ_ASSERT(ShouldMaintainPreLevel());
338
0
    return mPreLevel;
339
0
  }
340
0
  int32_t& PreLevel() {
341
0
    MOZ_ASSERT(ShouldMaintainPreLevel());
342
0
    return mPreLevel;
343
0
  }
344
345
  bool MaybeSerializeIsValue(mozilla::dom::Element* aElement, nsAString& aStr);
346
347
  int32_t mPrefixIndex;
348
349
  struct NameSpaceDecl {
350
    nsString mPrefix;
351
    nsString mURI;
352
    nsIContent* mOwner;
353
  };
354
355
  nsTArray<NameSpaceDecl> mNameSpaceStack;
356
357
  // nsIDocumentEncoder flags
358
  MOZ_INIT_OUTSIDE_CTOR uint32_t  mFlags;
359
360
  // characters to use for line break
361
  nsString  mLineBreak;
362
363
  // The charset that was passed to Init()
364
  nsCString mCharset;
365
366
  // current column position on the current line
367
  uint32_t   mColPos;
368
369
  // true = pretty formating should be done (OutputFormated flag)
370
  MOZ_INIT_OUTSIDE_CTOR bool mDoFormat;
371
372
  // true = no formatting,(OutputRaw flag)
373
  // no newline convertion and no rewrap long lines even if OutputWrap is set.
374
  MOZ_INIT_OUTSIDE_CTOR bool mDoRaw;
375
376
  // true = wrapping should be done (OutputWrap flag)
377
  MOZ_INIT_OUTSIDE_CTOR bool mDoWrap;
378
379
  // true = we can break lines (OutputDisallowLineBreaking flag)
380
  MOZ_INIT_OUTSIDE_CTOR bool mAllowLineBreaking;
381
382
  // number of maximum column in a line, in the wrap mode
383
  MOZ_INIT_OUTSIDE_CTOR uint32_t   mMaxColumn;
384
385
  // current indent value
386
  nsString   mIndent;
387
388
  // this is the indentation level after the indentation reached
389
  // the maximum length of indentation
390
  int32_t    mIndentOverflow;
391
392
  // says if the indentation has been already added on the current line
393
  bool mIsIndentationAddedOnCurrentLine;
394
395
  // the string which is currently added is in an attribute
396
  bool mInAttribute;
397
398
  // true = a newline character should be added. It's only
399
  // useful when serializing root nodes. see MaybeAddNewlineForRootNode and
400
  // MaybeFlagNewlineForRootNode
401
  bool mAddNewlineForRootNode;
402
403
  // Indicates that a space will be added if and only if content is
404
  // continued on the same line while serializing source.  Otherwise,
405
  // the newline character acts as the whitespace and no space is needed.
406
  // used when mDoFormat = true
407
  bool          mAddSpace;
408
409
  // says that if the next string to add contains a newline character at the
410
  // begining, then this newline character should be ignored, because a
411
  // such character has already been added into the output string
412
  bool          mMayIgnoreLineBreakSequence;
413
414
  bool          mBodyOnly;
415
  int32_t       mInBody;
416
417
private:
418
  // number of nested elements which have preformated content
419
  MOZ_INIT_OUTSIDE_CTOR int32_t mPreLevel;
420
};
421
422
nsresult
423
NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer);
424
425
#endif