Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/parser/xml/nsSAXXMLReader.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "nsSAXXMLReader.h"
7
8
#include "mozilla/Encoding.h"
9
#include "mozilla/NullPrincipal.h"
10
#include "nsIInputStream.h"
11
#include "nsNetCID.h"
12
#include "nsNetUtil.h"
13
#include "nsIParser.h"
14
#include "nsParserCIID.h"
15
#include "nsStreamUtils.h"
16
#include "nsStringStream.h"
17
#include "nsIScriptError.h"
18
#include "nsSAXAttributes.h"
19
#include "nsCharsetSource.h"
20
21
using mozilla::Encoding;
22
using mozilla::NotNull;
23
24
0
#define XMLNS_URI "http://www.w3.org/2000/xmlns/"
25
26
static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
27
28
NS_IMPL_CYCLE_COLLECTION(nsSAXXMLReader,
29
                         mContentHandler,
30
                         mErrorHandler,
31
                         mBaseURI,
32
                         mListener,
33
                         mParserObserver)
34
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader)
35
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader)
36
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader)
37
0
  NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader)
38
0
  NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
39
0
  NS_INTERFACE_MAP_ENTRY(nsIContentSink)
40
0
  NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
41
0
  NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
42
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader)
43
0
NS_INTERFACE_MAP_END
44
45
nsSAXXMLReader::nsSAXXMLReader()
46
  : mIsAsyncParse(false)
47
0
{
48
0
}
49
50
// nsIContentSink
51
52
NS_IMETHODIMP
53
nsSAXXMLReader::WillBuildModel(nsDTDMode)
54
0
{
55
0
  if (mContentHandler)
56
0
    return mContentHandler->StartDocument();
57
0
58
0
  return NS_OK;
59
0
}
60
61
NS_IMETHODIMP
62
nsSAXXMLReader::DidBuildModel(bool aTerminated)
63
0
{
64
0
  if (mContentHandler)
65
0
    return mContentHandler->EndDocument();
66
0
67
0
  return NS_OK;
68
0
}
69
70
NS_IMETHODIMP
71
nsSAXXMLReader::SetParser(nsParserBase *aParser)
72
0
{
73
0
  return NS_OK;
74
0
}
75
76
// nsIExpatSink
77
78
NS_IMETHODIMP
79
nsSAXXMLReader::HandleStartElement(const char16_t *aName,
80
                                   const char16_t **aAtts,
81
                                   uint32_t aAttsCount,
82
                                   uint32_t aLineNumber,
83
                                   uint32_t aColumnNumber)
84
0
{
85
0
  if (!mContentHandler)
86
0
    return NS_OK;
87
0
88
0
  RefPtr<nsSAXAttributes> atts = new nsSAXAttributes();
89
0
  if (!atts)
90
0
    return NS_ERROR_OUT_OF_MEMORY;
91
0
  nsAutoString uri, localName, qName;
92
0
  for (; *aAtts; aAtts += 2) {
93
0
    SplitExpatName(aAtts[0], uri, localName, qName);
94
0
    // XXX don't have attr type information
95
0
    NS_NAMED_LITERAL_STRING(cdataType, "CDATA");
96
0
    // could support xmlns reporting, it's a standard SAX feature
97
0
    if (!uri.EqualsLiteral(XMLNS_URI)) {
98
0
      NS_ASSERTION(aAtts[1], "null passed to handler");
99
0
      atts->AddAttribute(uri, localName, qName, cdataType,
100
0
                         nsDependentString(aAtts[1]));
101
0
    }
102
0
  }
103
0
104
0
  // Deal with the element name
105
0
  SplitExpatName(aName, uri, localName, qName);
106
0
  return mContentHandler->StartElement(uri, localName, qName, atts);
107
0
}
108
109
NS_IMETHODIMP
110
nsSAXXMLReader::HandleEndElement(const char16_t *aName)
111
0
{
112
0
  if (mContentHandler) {
113
0
    nsAutoString uri, localName, qName;
114
0
    SplitExpatName(aName, uri, localName, qName);
115
0
    return mContentHandler->EndElement(uri, localName, qName);
116
0
  }
117
0
  return NS_OK;
118
0
}
119
120
NS_IMETHODIMP
121
nsSAXXMLReader::HandleComment(const char16_t *aName)
122
0
{
123
0
  NS_ASSERTION(aName, "null passed to handler");
124
0
  return NS_OK;
125
0
}
126
127
NS_IMETHODIMP
128
nsSAXXMLReader::HandleCDataSection(const char16_t *aData,
129
                                   uint32_t aLength)
130
0
{
131
0
  if (mContentHandler) {
132
0
    nsresult rv = mContentHandler->Characters(Substring(aData, aData+aLength));
133
0
    NS_ENSURE_SUCCESS(rv, rv);
134
0
  }
135
0
  return NS_OK;
136
0
}
137
138
NS_IMETHODIMP
139
nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset,
140
                                  const nsAString & aName,
141
                                  const nsAString & aSystemId,
142
                                  const nsAString & aPublicId,
143
                                  nsISupports* aCatalogData)
144
0
{
145
0
  return NS_OK;
146
0
}
147
148
NS_IMETHODIMP
149
nsSAXXMLReader::HandleCharacterData(const char16_t *aData,
150
                                    uint32_t aLength)
151
0
{
152
0
  if (mContentHandler)
153
0
    return mContentHandler->Characters(Substring(aData, aData+aLength));
154
0
155
0
  return NS_OK;
156
0
}
157
158
NS_IMETHODIMP
159
nsSAXXMLReader::HandleProcessingInstruction(const char16_t *aTarget,
160
                                            const char16_t *aData)
161
0
{
162
0
  NS_ASSERTION(aTarget && aData, "null passed to handler");
163
0
  if (mContentHandler) {
164
0
    return mContentHandler->ProcessingInstruction(nsDependentString(aTarget),
165
0
                                                  nsDependentString(aData));
166
0
  }
167
0
168
0
  return NS_OK;
169
0
}
170
171
NS_IMETHODIMP
172
nsSAXXMLReader::HandleXMLDeclaration(const char16_t *aVersion,
173
                                     const char16_t *aEncoding,
174
                                     int32_t aStandalone)
175
0
{
176
0
  NS_ASSERTION(aVersion, "null passed to handler");
177
0
  return NS_OK;
178
0
}
179
180
NS_IMETHODIMP
181
nsSAXXMLReader::ReportError(const char16_t* aErrorText,
182
                            const char16_t* aSourceText,
183
                            nsIScriptError *aError,
184
                            bool *_retval)
185
0
{
186
0
  MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
187
0
  // Normally, the expat driver should report the error.
188
0
  *_retval = true;
189
0
190
0
  if (mErrorHandler) {
191
0
    nsresult rv = mErrorHandler->FatalError(nsDependentString(aErrorText));
192
0
    if (NS_SUCCEEDED(rv)) {
193
0
      // The error handler has handled the script error.  Don't log to console.
194
0
      *_retval = false;
195
0
    }
196
0
  }
197
0
198
0
  return NS_OK;
199
0
}
200
201
// nsISAXXMLReader
202
203
NS_IMETHODIMP
204
nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI)
205
0
{
206
0
  NS_IF_ADDREF(*aBaseURI = mBaseURI);
207
0
  return NS_OK;
208
0
}
209
210
NS_IMETHODIMP
211
nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI)
212
0
{
213
0
  mBaseURI = aBaseURI;
214
0
  return NS_OK;
215
0
}
216
217
NS_IMETHODIMP
218
nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler)
219
0
{
220
0
  NS_IF_ADDREF(*aContentHandler = mContentHandler);
221
0
  return NS_OK;
222
0
}
223
224
NS_IMETHODIMP
225
nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler)
226
0
{
227
0
  mContentHandler = aContentHandler;
228
0
  return NS_OK;
229
0
}
230
231
NS_IMETHODIMP
232
nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler)
233
0
{
234
0
  NS_IF_ADDREF(*aErrorHandler = mErrorHandler);
235
0
  return NS_OK;
236
0
}
237
238
NS_IMETHODIMP
239
nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
240
0
{
241
0
  mErrorHandler = aErrorHandler;
242
0
  return NS_OK;
243
0
}
244
245
NS_IMETHODIMP
246
nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver)
247
0
{
248
0
  mParserObserver = aObserver;
249
0
  mIsAsyncParse = true;
250
0
  return NS_OK;
251
0
}
252
253
// nsIRequestObserver
254
255
NS_IMETHODIMP
256
nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
257
0
{
258
0
  NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
259
0
  nsresult rv;
260
0
  rv = EnsureBaseURI();
261
0
  NS_ENSURE_SUCCESS(rv, rv);
262
0
  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
263
0
  rv = InitParser(mParserObserver, channel);
264
0
  NS_ENSURE_SUCCESS(rv, rv);
265
0
  // we don't need or want this anymore
266
0
  mParserObserver = nullptr;
267
0
  return mListener->OnStartRequest(aRequest, aContext);
268
0
}
269
270
NS_IMETHODIMP
271
nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
272
                              nsresult status)
273
0
{
274
0
  NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
275
0
  NS_ENSURE_STATE(mListener);
276
0
  nsresult rv = mListener->OnStopRequest(aRequest, aContext, status);
277
0
  mListener = nullptr;
278
0
  mIsAsyncParse = false;
279
0
  return rv;
280
0
}
281
282
// nsIStreamListener
283
284
NS_IMETHODIMP
285
nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
286
                                nsIInputStream *aInputStream, uint64_t offset,
287
                                uint32_t count)
288
0
{
289
0
  NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
290
0
  NS_ENSURE_STATE(mListener);
291
0
  return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset,
292
0
                                    count);
293
0
}
294
295
nsresult
296
nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel)
297
0
{
298
0
  nsresult rv;
299
0
300
0
  // setup the parser
301
0
  nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID, &rv);
302
0
  NS_ENSURE_SUCCESS(rv, rv);
303
0
304
0
  parser->SetContentSink(this);
305
0
306
0
  int32_t charsetSource = kCharsetFromDocTypeDefault;
307
0
  auto encoding = UTF_8_ENCODING;
308
0
  TryChannelCharset(aChannel, charsetSource, encoding);
309
0
  parser->SetDocumentCharset(encoding, charsetSource);
310
0
311
0
  rv = parser->Parse(mBaseURI, aObserver);
312
0
  NS_ENSURE_SUCCESS(rv, rv);
313
0
314
0
  mListener = do_QueryInterface(parser, &rv);
315
0
316
0
  return rv;
317
0
}
318
319
// from nsDocument.cpp
320
bool
321
nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel,
322
                                  int32_t& aCharsetSource,
323
                                  NotNull<const Encoding*>& aEncoding)
324
0
{
325
0
  if (aCharsetSource >= kCharsetFromChannel)
326
0
    return true;
327
0
  
328
0
  if (aChannel) {
329
0
    nsAutoCString charsetVal;
330
0
    nsresult rv = aChannel->GetContentCharset(charsetVal);
331
0
    if (NS_SUCCEEDED(rv)) {
332
0
      const Encoding* preferred = Encoding::ForLabel(charsetVal);
333
0
      if (!preferred)
334
0
        return false;
335
0
336
0
      aEncoding = WrapNotNull(preferred);
337
0
      aCharsetSource = kCharsetFromChannel;
338
0
      return true;
339
0
    }
340
0
  }
341
0
342
0
  return false;
343
0
}
344
345
nsresult
346
nsSAXXMLReader::EnsureBaseURI()
347
0
{
348
0
  if (mBaseURI) 
349
0
    return NS_OK;
350
0
351
0
  return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank");
352
0
}
353
354
nsresult
355
nsSAXXMLReader::SplitExpatName(const char16_t *aExpatName,
356
                               nsString &aURI,
357
                               nsString &aLocalName,
358
                               nsString &aQName)
359
0
{
360
0
  /**
361
0
   * Adapted from RDFContentSinkImpl
362
0
   *
363
0
   * Expat can send the following:
364
0
   *    localName
365
0
   *    namespaceURI<separator>localName
366
0
   *    namespaceURI<separator>localName<separator>prefix
367
0
   *
368
0
   * and we use 0xFFFF for the <separator>.
369
0
   *
370
0
   */
371
0
372
0
  NS_ASSERTION(aExpatName, "null passed to handler");
373
0
  nsDependentString expatStr(aExpatName);
374
0
  int32_t break1, break2 = kNotFound;
375
0
  break1 = expatStr.FindChar(char16_t(0xFFFF));
376
0
377
0
  if (break1 == kNotFound) {
378
0
    aLocalName = expatStr; // no namespace
379
0
    aURI.Truncate();
380
0
    aQName = expatStr;
381
0
  } else {
382
0
    aURI = StringHead(expatStr, break1);
383
0
    break2 = expatStr.FindChar(char16_t(0xFFFF), break1 + 1);
384
0
    if (break2 == kNotFound) { // namespace, but no prefix
385
0
      aLocalName = Substring(expatStr, break1 + 1);
386
0
      aQName = aLocalName;
387
0
    } else { // namespace with prefix
388
0
      aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1);
389
0
      aQName = Substring(expatStr, break2 + 1) +
390
0
        NS_LITERAL_STRING(":") + aLocalName;
391
0
    }
392
0
  }
393
0
394
0
  return NS_OK;
395
0
}