Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/parser/htmlparser/nsExpatDriver.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 "nsExpatDriver.h"
7
#include "nsCOMPtr.h"
8
#include "nsParserCIID.h"
9
#include "CParserContext.h"
10
#include "nsIExpatSink.h"
11
#include "nsIContentSink.h"
12
#include "nsParserMsgUtils.h"
13
#include "nsIURL.h"
14
#include "nsIUnicharInputStream.h"
15
#include "nsIProtocolHandler.h"
16
#include "nsNetUtil.h"
17
#include "nsTextFormatter.h"
18
#include "nsDirectoryServiceDefs.h"
19
#include "nsCRT.h"
20
#include "nsIConsoleService.h"
21
#include "nsIScriptError.h"
22
#include "nsIContentPolicy.h"
23
#include "nsContentPolicyUtils.h"
24
#include "nsError.h"
25
#include "nsXPCOMCIDInternal.h"
26
#include "nsUnicharInputStream.h"
27
#include "nsContentUtils.h"
28
#include "mozilla/NullPrincipal.h"
29
30
#include "mozilla/Logging.h"
31
32
using mozilla::fallible;
33
using mozilla::LogLevel;
34
using mozilla::MakeStringSpan;
35
36
0
#define kExpatSeparatorChar 0xFFFF
37
38
static const char16_t kUTF16[] = { 'U', 'T', 'F', '-', '1', '6', '\0' };
39
40
static mozilla::LazyLogModule gExpatDriverLog("expatdriver");
41
42
/***************************** EXPAT CALL BACKS ******************************/
43
// The callback handlers that get called from the expat parser.
44
45
static void
46
Driver_HandleXMLDeclaration(void *aUserData,
47
                            const XML_Char *aVersion,
48
                            const XML_Char *aEncoding,
49
                            int aStandalone)
50
0
{
51
0
  NS_ASSERTION(aUserData, "expat driver should exist");
52
0
  if (aUserData) {
53
0
    nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
54
0
    driver->HandleXMLDeclaration(aVersion, aEncoding, aStandalone);
55
0
  }
56
0
}
57
58
static void
59
Driver_HandleStartElement(void *aUserData,
60
                          const XML_Char *aName,
61
                          const XML_Char **aAtts)
62
0
{
63
0
  NS_ASSERTION(aUserData, "expat driver should exist");
64
0
  if (aUserData) {
65
0
    static_cast<nsExpatDriver*>(aUserData)->HandleStartElement(aName,
66
0
                                                                  aAtts);
67
0
  }
68
0
}
69
70
static void
71
Driver_HandleEndElement(void *aUserData,
72
                        const XML_Char *aName)
73
0
{
74
0
  NS_ASSERTION(aUserData, "expat driver should exist");
75
0
  if (aUserData) {
76
0
    static_cast<nsExpatDriver*>(aUserData)->HandleEndElement(aName);
77
0
  }
78
0
}
79
80
static void
81
Driver_HandleCharacterData(void *aUserData,
82
                           const XML_Char *aData,
83
                           int aLength)
84
0
{
85
0
  NS_ASSERTION(aUserData, "expat driver should exist");
86
0
  if (aUserData) {
87
0
    nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
88
0
    driver->HandleCharacterData(aData, uint32_t(aLength));
89
0
  }
90
0
}
91
92
static void
93
Driver_HandleComment(void *aUserData,
94
                     const XML_Char *aName)
95
0
{
96
0
  NS_ASSERTION(aUserData, "expat driver should exist");
97
0
  if(aUserData) {
98
0
    static_cast<nsExpatDriver*>(aUserData)->HandleComment(aName);
99
0
  }
100
0
}
101
102
static void
103
Driver_HandleProcessingInstruction(void *aUserData,
104
                                   const XML_Char *aTarget,
105
                                   const XML_Char *aData)
106
0
{
107
0
  NS_ASSERTION(aUserData, "expat driver should exist");
108
0
  if (aUserData) {
109
0
    nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
110
0
    driver->HandleProcessingInstruction(aTarget, aData);
111
0
  }
112
0
}
113
114
static void
115
Driver_HandleDefault(void *aUserData,
116
                     const XML_Char *aData,
117
                     int aLength)
118
0
{
119
0
  NS_ASSERTION(aUserData, "expat driver should exist");
120
0
  if (aUserData) {
121
0
    nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
122
0
    driver->HandleDefault(aData, uint32_t(aLength));
123
0
  }
124
0
}
125
126
static void
127
Driver_HandleStartCdataSection(void *aUserData)
128
0
{
129
0
  NS_ASSERTION(aUserData, "expat driver should exist");
130
0
  if (aUserData) {
131
0
    static_cast<nsExpatDriver*>(aUserData)->HandleStartCdataSection();
132
0
  }
133
0
}
134
135
static void
136
Driver_HandleEndCdataSection(void *aUserData)
137
0
{
138
0
  NS_ASSERTION(aUserData, "expat driver should exist");
139
0
  if (aUserData) {
140
0
    static_cast<nsExpatDriver*>(aUserData)->HandleEndCdataSection();
141
0
  }
142
0
}
143
144
static void
145
Driver_HandleStartDoctypeDecl(void *aUserData,
146
                              const XML_Char *aDoctypeName,
147
                              const XML_Char *aSysid,
148
                              const XML_Char *aPubid,
149
                              int aHasInternalSubset)
150
0
{
151
0
  NS_ASSERTION(aUserData, "expat driver should exist");
152
0
  if (aUserData) {
153
0
    static_cast<nsExpatDriver*>(aUserData)->
154
0
      HandleStartDoctypeDecl(aDoctypeName, aSysid, aPubid, !!aHasInternalSubset);
155
0
  }
156
0
}
157
158
static void
159
Driver_HandleEndDoctypeDecl(void *aUserData)
160
0
{
161
0
  NS_ASSERTION(aUserData, "expat driver should exist");
162
0
  if (aUserData) {
163
0
    static_cast<nsExpatDriver*>(aUserData)->HandleEndDoctypeDecl();
164
0
  }
165
0
}
166
167
static int
168
Driver_HandleExternalEntityRef(void *aExternalEntityRefHandler,
169
                               const XML_Char *aOpenEntityNames,
170
                               const XML_Char *aBase,
171
                               const XML_Char *aSystemId,
172
                               const XML_Char *aPublicId)
173
0
{
174
0
  NS_ASSERTION(aExternalEntityRefHandler, "expat driver should exist");
175
0
  if (!aExternalEntityRefHandler) {
176
0
    return 1;
177
0
  }
178
0
179
0
  nsExpatDriver* driver = static_cast<nsExpatDriver*>
180
0
                                     (aExternalEntityRefHandler);
181
0
182
0
  return driver->HandleExternalEntityRef(aOpenEntityNames, aBase, aSystemId,
183
0
                                         aPublicId);
184
0
}
185
186
/***************************** END CALL BACKS ********************************/
187
188
/***************************** CATALOG UTILS *********************************/
189
190
// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus
191
// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses.
192
// Since Mozilla is not validating, no need to fetch a *huge* file at each
193
// click.
194
// XXX The cleanest solution here would be to fix Bug 98413: Implement XML
195
// Catalogs.
196
struct nsCatalogData {
197
  const char* mPublicID;
198
  const char* mLocalDTD;
199
  const char* mAgentSheet;
200
};
201
202
// The order of this table is guestimated to be in the optimum order
203
static const nsCatalogData kCatalogTable[] = {
204
  { "-//W3C//DTD XHTML 1.0 Transitional//EN",    "htmlmathml-f.ent", nullptr },
205
  { "-//W3C//DTD XHTML 1.1//EN",                 "htmlmathml-f.ent", nullptr },
206
  { "-//W3C//DTD XHTML 1.0 Strict//EN",          "htmlmathml-f.ent", nullptr },
207
  { "-//W3C//DTD XHTML 1.0 Frameset//EN",        "htmlmathml-f.ent", nullptr },
208
  { "-//W3C//DTD XHTML Basic 1.0//EN",           "htmlmathml-f.ent", nullptr },
209
  { "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "htmlmathml-f.ent", nullptr },
210
  { "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN", "htmlmathml-f.ent", nullptr },
211
  { "-//W3C//DTD MathML 2.0//EN",                "htmlmathml-f.ent", nullptr },
212
  { "-//WAPFORUM//DTD XHTML Mobile 1.0//EN",     "htmlmathml-f.ent", nullptr },
213
  { nullptr, nullptr, nullptr }
214
};
215
216
static const nsCatalogData*
217
LookupCatalogData(const char16_t* aPublicID)
218
0
{
219
0
  nsDependentString publicID(aPublicID);
220
0
221
0
  // linear search for now since the number of entries is going to
222
0
  // be negligible, and the fix for bug 98413 would get rid of this
223
0
  // code anyway
224
0
  const nsCatalogData* data = kCatalogTable;
225
0
  while (data->mPublicID) {
226
0
    if (publicID.EqualsASCII(data->mPublicID)) {
227
0
      return data;
228
0
    }
229
0
    ++data;
230
0
  }
231
0
232
0
  return nullptr;
233
0
}
234
235
// This function provides a resource URI to a local DTD 
236
// in resource://gre/res/dtd/ which may or may not exist.
237
// If aCatalogData is provided, it is used to remap the
238
// DTD instead of taking the filename from the URI.
239
static void
240
GetLocalDTDURI(const nsCatalogData* aCatalogData, nsIURI* aDTD,
241
              nsIURI** aResult)
242
0
{
243
0
  NS_ASSERTION(aDTD, "Null parameter.");
244
0
245
0
  nsAutoCString fileName;
246
0
  if (aCatalogData) {
247
0
    // remap the DTD to a known local DTD
248
0
    fileName.Assign(aCatalogData->mLocalDTD);
249
0
  }
250
0
251
0
  if (fileName.IsEmpty()) {
252
0
    // Try to see if the user has installed the DTD file -- we extract the
253
0
    // filename.ext of the DTD here. Hence, for any DTD for which we have
254
0
    // no predefined mapping, users just have to copy the DTD file to our
255
0
    // special DTD directory and it will be picked.
256
0
    nsCOMPtr<nsIURL> dtdURL = do_QueryInterface(aDTD);
257
0
    if (!dtdURL) {
258
0
      return;
259
0
    }
260
0
261
0
    dtdURL->GetFileName(fileName);
262
0
    if (fileName.IsEmpty()) {
263
0
      return;
264
0
    }
265
0
  }
266
0
267
0
  nsAutoCString respath("resource://gre/res/dtd/");
268
0
  respath += fileName;
269
0
  NS_NewURI(aResult, respath);
270
0
}
271
272
/***************************** END CATALOG UTILS *****************************/
273
274
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsExpatDriver)
275
0
  NS_INTERFACE_MAP_ENTRY(nsITokenizer)
276
0
  NS_INTERFACE_MAP_ENTRY(nsIDTD)
277
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDTD)
278
0
NS_INTERFACE_MAP_END
279
280
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsExpatDriver)
281
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsExpatDriver)
282
283
NS_IMPL_CYCLE_COLLECTION(nsExpatDriver, mSink)
284
285
nsExpatDriver::nsExpatDriver()
286
  : mExpatParser(nullptr),
287
    mInCData(false),
288
    mInInternalSubset(false),
289
    mInExternalDTD(false),
290
    mMadeFinalCallToExpat(false),
291
    mIsFinalChunk(false),
292
    mInternalState(NS_OK),
293
    mExpatBuffered(0),
294
    mCatalogData(nullptr),
295
    mInnerWindowID(0)
296
0
{
297
0
}
298
299
nsExpatDriver::~nsExpatDriver()
300
0
{
301
0
  if (mExpatParser) {
302
0
    XML_ParserFree(mExpatParser);
303
0
  }
304
0
}
305
306
nsresult
307
nsExpatDriver::HandleStartElement(const char16_t *aValue,
308
                                  const char16_t **aAtts)
309
0
{
310
0
  NS_ASSERTION(mSink, "content sink not found!");
311
0
312
0
  // Calculate the total number of elements in aAtts.
313
0
  // XML_GetSpecifiedAttributeCount will only give us the number of specified
314
0
  // attrs (twice that number, actually), so we have to check for default attrs
315
0
  // ourselves.
316
0
  uint32_t attrArrayLength;
317
0
  for (attrArrayLength = XML_GetSpecifiedAttributeCount(mExpatParser);
318
0
       aAtts[attrArrayLength];
319
0
       attrArrayLength += 2) {
320
0
    // Just looping till we find out what the length is
321
0
  }
322
0
323
0
  if (mSink) {
324
0
    nsresult rv = mSink->
325
0
      HandleStartElement(aValue, aAtts, attrArrayLength,
326
0
                         XML_GetCurrentLineNumber(mExpatParser),
327
0
                         XML_GetCurrentColumnNumber(mExpatParser));
328
0
    MaybeStopParser(rv);
329
0
  }
330
0
331
0
  return NS_OK;
332
0
}
333
334
nsresult
335
nsExpatDriver::HandleEndElement(const char16_t *aValue)
336
0
{
337
0
  NS_ASSERTION(mSink, "content sink not found!");
338
0
  NS_ASSERTION(mInternalState != NS_ERROR_HTMLPARSER_BLOCK,
339
0
               "Shouldn't block from HandleStartElement.");
340
0
341
0
  if (mSink && mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
342
0
    nsresult rv = mSink->HandleEndElement(aValue);
343
0
    MaybeStopParser(rv);
344
0
  }
345
0
346
0
  return NS_OK;
347
0
}
348
349
nsresult
350
nsExpatDriver::HandleCharacterData(const char16_t *aValue,
351
                                   const uint32_t aLength)
352
0
{
353
0
  NS_ASSERTION(mSink, "content sink not found!");
354
0
355
0
  if (mInCData) {
356
0
    if (!mCDataText.Append(aValue, aLength, fallible)) {
357
0
      MaybeStopParser(NS_ERROR_OUT_OF_MEMORY);
358
0
    }
359
0
  }
360
0
  else if (mSink) {
361
0
    nsresult rv = mSink->HandleCharacterData(aValue, aLength);
362
0
    MaybeStopParser(rv);
363
0
  }
364
0
365
0
  return NS_OK;
366
0
}
367
368
nsresult
369
nsExpatDriver::HandleComment(const char16_t *aValue)
370
0
{
371
0
  NS_ASSERTION(mSink, "content sink not found!");
372
0
373
0
  if (mInExternalDTD) {
374
0
    // Ignore comments from external DTDs
375
0
    return NS_OK;
376
0
  }
377
0
378
0
  if (mInInternalSubset) {
379
0
    mInternalSubset.AppendLiteral("<!--");
380
0
    mInternalSubset.Append(aValue);
381
0
    mInternalSubset.AppendLiteral("-->");
382
0
  }
383
0
  else if (mSink) {
384
0
    nsresult rv = mSink->HandleComment(aValue);
385
0
    MaybeStopParser(rv);
386
0
  }
387
0
388
0
  return NS_OK;
389
0
}
390
391
nsresult
392
nsExpatDriver::HandleProcessingInstruction(const char16_t *aTarget,
393
                                           const char16_t *aData)
394
0
{
395
0
  NS_ASSERTION(mSink, "content sink not found!");
396
0
397
0
  if (mInExternalDTD) {
398
0
    // Ignore PIs in external DTDs for now.  Eventually we want to
399
0
    // pass them to the sink in a way that doesn't put them in the DOM
400
0
    return NS_OK;
401
0
  }
402
0
403
0
  if (mInInternalSubset) {
404
0
    mInternalSubset.AppendLiteral("<?");
405
0
    mInternalSubset.Append(aTarget);
406
0
    mInternalSubset.Append(' ');
407
0
    mInternalSubset.Append(aData);
408
0
    mInternalSubset.AppendLiteral("?>");
409
0
  }
410
0
  else if (mSink) {
411
0
    nsresult rv = mSink->HandleProcessingInstruction(aTarget, aData);
412
0
    MaybeStopParser(rv);
413
0
  }
414
0
415
0
  return NS_OK;
416
0
}
417
418
nsresult
419
nsExpatDriver::HandleXMLDeclaration(const char16_t *aVersion,
420
                                    const char16_t *aEncoding,
421
                                    int32_t aStandalone)
422
0
{
423
0
  if (mSink) {
424
0
    nsresult rv = mSink->HandleXMLDeclaration(aVersion, aEncoding, aStandalone);
425
0
    MaybeStopParser(rv);
426
0
  }
427
0
428
0
  return NS_OK;
429
0
}
430
431
nsresult
432
nsExpatDriver::HandleDefault(const char16_t *aValue,
433
                             const uint32_t aLength)
434
0
{
435
0
  NS_ASSERTION(mSink, "content sink not found!");
436
0
437
0
  if (mInExternalDTD) {
438
0
    // Ignore newlines in external DTDs
439
0
    return NS_OK;
440
0
  }
441
0
442
0
  if (mInInternalSubset) {
443
0
    mInternalSubset.Append(aValue, aLength);
444
0
  }
445
0
  else if (mSink) {
446
0
    uint32_t i;
447
0
    nsresult rv = mInternalState;
448
0
    for (i = 0; i < aLength && NS_SUCCEEDED(rv); ++i) {
449
0
      if (aValue[i] == '\n' || aValue[i] == '\r') {
450
0
        rv = mSink->HandleCharacterData(&aValue[i], 1);
451
0
      }
452
0
    }
453
0
    MaybeStopParser(rv);
454
0
  }
455
0
456
0
  return NS_OK;
457
0
}
458
459
nsresult
460
nsExpatDriver::HandleStartCdataSection()
461
0
{
462
0
  mInCData = true;
463
0
464
0
  return NS_OK;
465
0
}
466
467
nsresult
468
nsExpatDriver::HandleEndCdataSection()
469
0
{
470
0
  NS_ASSERTION(mSink, "content sink not found!");
471
0
472
0
  mInCData = false;
473
0
  if (mSink) {
474
0
    nsresult rv = mSink->HandleCDataSection(mCDataText.get(),
475
0
                                            mCDataText.Length());
476
0
    MaybeStopParser(rv);
477
0
  }
478
0
  mCDataText.Truncate();
479
0
480
0
  return NS_OK;
481
0
}
482
483
nsresult
484
nsExpatDriver::HandleStartDoctypeDecl(const char16_t* aDoctypeName,
485
                                      const char16_t* aSysid,
486
                                      const char16_t* aPubid,
487
                                      bool aHasInternalSubset)
488
0
{
489
0
  mDoctypeName = aDoctypeName;
490
0
  mSystemID = aSysid;
491
0
  mPublicID = aPubid;
492
0
493
0
  if (aHasInternalSubset) {
494
0
    // Consuming a huge internal subset translates to numerous
495
0
    // allocations. In an effort to avoid too many allocations
496
0
    // setting mInternalSubset's capacity to be 1K ( just a guesstimate! ).
497
0
    mInInternalSubset = true;
498
0
    mInternalSubset.SetCapacity(1024);
499
0
  } else {
500
0
    // Distinguish missing internal subset from an empty one
501
0
    mInternalSubset.SetIsVoid(true);
502
0
  }
503
0
504
0
  return NS_OK;
505
0
}
506
507
nsresult
508
nsExpatDriver::HandleEndDoctypeDecl()
509
0
{
510
0
  NS_ASSERTION(mSink, "content sink not found!");
511
0
512
0
  mInInternalSubset = false;
513
0
514
0
  if (mSink) {
515
0
    // let the sink know any additional knowledge that we have about the
516
0
    // document (currently, from bug 124570, we only expect to pass additional
517
0
    // agent sheets needed to layout the XML vocabulary of the document)
518
0
    nsCOMPtr<nsIURI> data;
519
#if 0
520
    if (mCatalogData && mCatalogData->mAgentSheet) {
521
      NS_NewURI(getter_AddRefs(data), mCatalogData->mAgentSheet);
522
    }
523
#endif
524
525
0
    // The unused support for "catalog style sheets" was removed. It doesn't
526
0
    // look like we'll ever fix bug 98413 either.
527
0
    MOZ_ASSERT(!mCatalogData || !mCatalogData->mAgentSheet,
528
0
               "Need to add back support for catalog style sheets");
529
0
530
0
    // Note: mInternalSubset already doesn't include the [] around it.
531
0
    nsresult rv = mSink->HandleDoctypeDecl(mInternalSubset, mDoctypeName,
532
0
                                           mSystemID, mPublicID, data);
533
0
    MaybeStopParser(rv);
534
0
  }
535
0
  
536
0
  mInternalSubset.Truncate();
537
0
538
0
  return NS_OK;
539
0
}
540
541
static nsresult
542
ExternalDTDStreamReaderFunc(nsIUnicharInputStream* aIn,
543
                            void* aClosure,
544
                            const char16_t* aFromSegment,
545
                            uint32_t aToOffset,
546
                            uint32_t aCount,
547
                            uint32_t *aWriteCount)
548
0
{
549
0
  // Pass the buffer to expat for parsing.
550
0
  if (XML_Parse((XML_Parser)aClosure, (const char *)aFromSegment,
551
0
                aCount * sizeof(char16_t), 0) == XML_STATUS_OK) {
552
0
    *aWriteCount = aCount;
553
0
554
0
    return NS_OK;
555
0
  }
556
0
557
0
  *aWriteCount = 0;
558
0
559
0
  return NS_ERROR_FAILURE;
560
0
}
561
562
int
563
nsExpatDriver::HandleExternalEntityRef(const char16_t *openEntityNames,
564
                                       const char16_t *base,
565
                                       const char16_t *systemId,
566
                                       const char16_t *publicId)
567
0
{
568
0
  if (mInInternalSubset && !mInExternalDTD && openEntityNames) {
569
0
    mInternalSubset.Append(char16_t('%'));
570
0
    mInternalSubset.Append(nsDependentString(openEntityNames));
571
0
    mInternalSubset.Append(char16_t(';'));
572
0
  }
573
0
574
0
  // Load the external entity into a buffer.
575
0
  nsCOMPtr<nsIInputStream> in;
576
0
  nsAutoString absURL;
577
0
  nsresult rv = OpenInputStreamFromExternalDTD(publicId, systemId, base,
578
0
                                               getter_AddRefs(in), absURL);
579
0
  if (NS_FAILED(rv)) {
580
#ifdef DEBUG
581
    nsCString message("Failed to open external DTD: publicId \"");
582
    AppendUTF16toUTF8(MakeStringSpan(publicId), message);
583
    message += "\" systemId \"";
584
    AppendUTF16toUTF8(MakeStringSpan(systemId), message);
585
    message += "\" base \"";
586
    AppendUTF16toUTF8(MakeStringSpan(base), message);
587
    message += "\" URL \"";
588
    AppendUTF16toUTF8(absURL, message);
589
    message += "\"";
590
    NS_WARNING(message.get());
591
#endif
592
    return 1;
593
0
  }
594
0
595
0
  nsCOMPtr<nsIUnicharInputStream> uniIn;
596
0
  rv = NS_NewUnicharInputStream(in, getter_AddRefs(uniIn));
597
0
  NS_ENSURE_SUCCESS(rv, 1);
598
0
599
0
  int result = 1;
600
0
  if (uniIn) {
601
0
    XML_Parser entParser = XML_ExternalEntityParserCreate(mExpatParser, 0,
602
0
                                                          kUTF16);
603
0
    if (entParser) {
604
0
      XML_SetBase(entParser, absURL.get());
605
0
606
0
      mInExternalDTD = true;
607
0
608
0
      uint32_t totalRead;
609
0
      do {
610
0
        rv = uniIn->ReadSegments(ExternalDTDStreamReaderFunc, entParser,
611
0
                                 uint32_t(-1), &totalRead);
612
0
      } while (NS_SUCCEEDED(rv) && totalRead > 0);
613
0
614
0
      result = XML_Parse(entParser, nullptr, 0, 1);
615
0
616
0
      mInExternalDTD = false;
617
0
618
0
      XML_ParserFree(entParser);
619
0
    }
620
0
  }
621
0
622
0
  return result;
623
0
}
624
625
nsresult
626
nsExpatDriver::OpenInputStreamFromExternalDTD(const char16_t* aFPIStr,
627
                                              const char16_t* aURLStr,
628
                                              const char16_t* aBaseURL,
629
                                              nsIInputStream** aStream,
630
                                              nsAString& aAbsURL)
631
0
{
632
0
  nsCOMPtr<nsIURI> baseURI;
633
0
  nsresult rv = NS_NewURI(getter_AddRefs(baseURI),
634
0
                          NS_ConvertUTF16toUTF8(aBaseURL));
635
0
  NS_ENSURE_SUCCESS(rv, rv);
636
0
637
0
  nsCOMPtr<nsIURI> uri;
638
0
  rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURLStr), nullptr,
639
0
                 baseURI);
640
0
  NS_ENSURE_SUCCESS(rv, rv);
641
0
642
0
  // make sure the URI is allowed to be loaded in sync
643
0
  bool isUIResource = false;
644
0
  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
645
0
                           &isUIResource);
646
0
  NS_ENSURE_SUCCESS(rv, rv);
647
0
648
0
  nsCOMPtr<nsIURI> localURI;
649
0
  if (!isUIResource) {
650
0
    // Check to see if we can map the DTD to a known local DTD, or if a DTD
651
0
    // file of the same name exists in the special DTD directory
652
0
    if (aFPIStr) {
653
0
      // see if the Formal Public Identifier (FPI) maps to a catalog entry
654
0
      mCatalogData = LookupCatalogData(aFPIStr);
655
0
      GetLocalDTDURI(mCatalogData, uri, getter_AddRefs(localURI));
656
0
    }
657
0
    if (!localURI) {
658
0
      return NS_ERROR_NOT_IMPLEMENTED;
659
0
    }
660
0
  }
661
0
662
0
  nsCOMPtr<nsIChannel> channel;
663
0
  if (localURI) {
664
0
    localURI.swap(uri);
665
0
    rv = NS_NewChannel(getter_AddRefs(channel),
666
0
                       uri,
667
0
                       nsContentUtils::GetSystemPrincipal(),
668
0
                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
669
0
                       nsIContentPolicy::TYPE_DTD);
670
0
  }
671
0
  else {
672
0
    NS_ASSERTION(mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)),
673
0
                 "In nsExpatDriver::OpenInputStreamFromExternalDTD: "
674
0
                 "mOriginalSink not the same object as mSink?");
675
0
    nsCOMPtr<nsIPrincipal> loadingPrincipal;
676
0
    if (mOriginalSink) {
677
0
      nsCOMPtr<nsIDocument> doc;
678
0
      doc = do_QueryInterface(mOriginalSink->GetTarget());
679
0
      if (doc) {
680
0
        loadingPrincipal = doc->NodePrincipal();
681
0
      }
682
0
    }
683
0
    if (!loadingPrincipal) {
684
0
      loadingPrincipal = mozilla::NullPrincipal::CreateWithoutOriginAttributes();
685
0
    }
686
0
    rv = NS_NewChannel(getter_AddRefs(channel),
687
0
                       uri,
688
0
                       loadingPrincipal,
689
0
                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
690
0
                       nsILoadInfo::SEC_ALLOW_CHROME,
691
0
                       nsIContentPolicy::TYPE_DTD);
692
0
  }
693
0
  NS_ENSURE_SUCCESS(rv, rv);
694
0
695
0
  nsAutoCString absURL;
696
0
  rv = uri->GetSpec(absURL);
697
0
  NS_ENSURE_SUCCESS(rv, rv);
698
0
  CopyUTF8toUTF16(absURL, aAbsURL);
699
0
700
0
  channel->SetContentType(NS_LITERAL_CSTRING("application/xml"));
701
0
  return channel->Open2(aStream);
702
0
}
703
704
static nsresult
705
CreateErrorText(const char16_t* aDescription,
706
                const char16_t* aSourceURL,
707
                const uint32_t aLineNumber,
708
                const uint32_t aColNumber,
709
                nsString& aErrorString)
710
0
{
711
0
  aErrorString.Truncate();
712
0
713
0
  nsAutoString msg;
714
0
  nsresult rv =
715
0
    nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,
716
0
                                               "XMLParsingError", msg);
717
0
  NS_ENSURE_SUCCESS(rv, rv);
718
0
719
0
  // XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$u, Column %4$u:
720
0
  nsTextFormatter::ssprintf(aErrorString, msg.get(), aDescription,
721
0
                            aSourceURL, aLineNumber, aColNumber);
722
0
  return NS_OK;
723
0
}
724
725
static nsresult
726
AppendErrorPointer(const int32_t aColNumber,
727
                   const char16_t *aSourceLine,
728
                   nsString& aSourceString)
729
0
{
730
0
  aSourceString.Append(char16_t('\n'));
731
0
732
0
  // Last character will be '^'.
733
0
  int32_t last = aColNumber - 1;
734
0
  int32_t i;
735
0
  uint32_t minuses = 0;
736
0
  for (i = 0; i < last; ++i) {
737
0
    if (aSourceLine[i] == '\t') {
738
0
      // Since this uses |white-space: pre;| a tab stop equals 8 spaces.
739
0
      uint32_t add = 8 - (minuses % 8);
740
0
      aSourceString.AppendASCII("--------", add);
741
0
      minuses += add;
742
0
    }
743
0
    else {
744
0
      aSourceString.Append(char16_t('-'));
745
0
      ++minuses;
746
0
    }
747
0
  }
748
0
  aSourceString.Append(char16_t('^'));
749
0
750
0
  return NS_OK;
751
0
}
752
753
nsresult
754
nsExpatDriver::HandleError()
755
0
{
756
0
  int32_t code = XML_GetErrorCode(mExpatParser);
757
0
  NS_ASSERTION(code > XML_ERROR_NONE, "unexpected XML error code");
758
0
759
0
  // Map Expat error code to an error string
760
0
  // XXX Deal with error returns.
761
0
  nsAutoString description;
762
0
  nsParserMsgUtils::GetLocalizedStringByID(XMLPARSER_PROPERTIES, code,
763
0
                                           description);
764
0
765
0
  if (code == XML_ERROR_TAG_MISMATCH) {
766
0
    /**
767
0
     *  Expat can send the following:
768
0
     *    localName
769
0
     *    namespaceURI<separator>localName
770
0
     *    namespaceURI<separator>localName<separator>prefix
771
0
     *
772
0
     *  and we use 0xFFFF for the <separator>.
773
0
     *
774
0
     */
775
0
    const char16_t *mismatch = MOZ_XML_GetMismatchedTag(mExpatParser);
776
0
    const char16_t *uriEnd = nullptr;
777
0
    const char16_t *nameEnd = nullptr;
778
0
    const char16_t *pos;
779
0
    for (pos = mismatch; *pos; ++pos) {
780
0
      if (*pos == kExpatSeparatorChar) {
781
0
        if (uriEnd) {
782
0
          nameEnd = pos;
783
0
        }
784
0
        else {
785
0
          uriEnd = pos;
786
0
        }
787
0
      }
788
0
    }
789
0
790
0
    nsAutoString tagName;
791
0
    if (uriEnd && nameEnd) {
792
0
      // We have a prefix.
793
0
      tagName.Append(nameEnd + 1, pos - nameEnd - 1);
794
0
      tagName.Append(char16_t(':'));
795
0
    }
796
0
    const char16_t *nameStart = uriEnd ? uriEnd + 1 : mismatch;
797
0
    tagName.Append(nameStart, (nameEnd ? nameEnd : pos) - nameStart);
798
0
799
0
    nsAutoString msg;
800
0
    nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,
801
0
                                               "Expected", msg);
802
0
803
0
    // . Expected: </%S>.
804
0
    nsAutoString message;
805
0
    nsTextFormatter::ssprintf(message, msg.get(), tagName.get());
806
0
    description.Append(message);
807
0
  }
808
0
809
0
  // Adjust the column number so that it is one based rather than zero based.
810
0
  uint32_t colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
811
0
  uint32_t lineNumber = XML_GetCurrentLineNumber(mExpatParser);
812
0
813
0
  nsAutoString errorText;
814
0
  CreateErrorText(description.get(), XML_GetBase(mExpatParser), lineNumber,
815
0
                  colNumber, errorText);
816
0
817
0
  NS_ASSERTION(mSink, "no sink?");
818
0
819
0
  nsAutoString sourceText(mLastLine);
820
0
  AppendErrorPointer(colNumber, mLastLine.get(), sourceText);
821
0
822
0
  // Try to create and initialize the script error.
823
0
  nsCOMPtr<nsIScriptError> serr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
824
0
  nsresult rv = NS_ERROR_FAILURE;
825
0
  if (serr) {
826
0
    rv = serr->InitWithWindowID(errorText,
827
0
                                mURISpec,
828
0
                                mLastLine,
829
0
                                lineNumber, colNumber,
830
0
                                nsIScriptError::errorFlag, "malformed-xml",
831
0
                                mInnerWindowID);
832
0
  }
833
0
834
0
  // If it didn't initialize, we can't do any logging.
835
0
  bool shouldReportError = NS_SUCCEEDED(rv);
836
0
837
0
  if (mSink && shouldReportError) {
838
0
    rv = mSink->ReportError(errorText.get(), 
839
0
                            sourceText.get(), 
840
0
                            serr, 
841
0
                            &shouldReportError);
842
0
    if (NS_FAILED(rv)) {
843
0
      shouldReportError = true;
844
0
    }
845
0
  }
846
0
847
0
  if (mOriginalSink) {
848
0
    nsCOMPtr<nsIDocument> doc = do_QueryInterface(mOriginalSink->GetTarget());
849
0
    if (doc && doc->SuppressParserErrorConsoleMessages()) {
850
0
      shouldReportError = false;
851
0
    }
852
0
  }
853
0
854
0
  if (shouldReportError) {
855
0
    nsCOMPtr<nsIConsoleService> cs
856
0
      (do_GetService(NS_CONSOLESERVICE_CONTRACTID));  
857
0
    if (cs) {
858
0
      cs->LogMessage(serr);
859
0
    }
860
0
  }
861
0
862
0
  return NS_ERROR_HTMLPARSER_STOPPARSING;
863
0
}
864
865
void
866
nsExpatDriver::ParseBuffer(const char16_t *aBuffer,
867
                           uint32_t aLength,
868
                           bool aIsFinal,
869
                           uint32_t *aConsumed)
870
0
{
871
0
  NS_ASSERTION((aBuffer && aLength != 0) || (!aBuffer && aLength == 0), "?");
872
0
  NS_ASSERTION(mInternalState != NS_OK || aIsFinal || aBuffer,
873
0
               "Useless call, we won't call Expat");
874
0
  MOZ_ASSERT(!BlockedOrInterrupted() || !aBuffer,
875
0
             "Non-null buffer when resuming");
876
0
  MOZ_ASSERT(XML_GetCurrentByteIndex(mExpatParser) % sizeof(char16_t) == 0,
877
0
             "Consumed part of a char16_t?");
878
0
879
0
  if (mExpatParser && (mInternalState == NS_OK || BlockedOrInterrupted())) {
880
0
    int32_t parserBytesBefore = XML_GetCurrentByteIndex(mExpatParser);
881
0
    NS_ASSERTION(parserBytesBefore >= 0, "Unexpected value");
882
0
883
0
    XML_Status status;
884
0
    if (BlockedOrInterrupted()) {
885
0
      mInternalState = NS_OK; // Resume in case we're blocked.
886
0
      status = XML_ResumeParser(mExpatParser);
887
0
    }
888
0
    else {
889
0
      status = XML_Parse(mExpatParser,
890
0
                         reinterpret_cast<const char*>(aBuffer),
891
0
                         aLength * sizeof(char16_t), aIsFinal);
892
0
    }
893
0
894
0
    int32_t parserBytesConsumed = XML_GetCurrentByteIndex(mExpatParser);
895
0
896
0
    NS_ASSERTION(parserBytesConsumed >= 0, "Unexpected value");
897
0
    NS_ASSERTION(parserBytesConsumed >= parserBytesBefore,
898
0
                 "How'd this happen?");
899
0
    NS_ASSERTION(parserBytesConsumed % sizeof(char16_t) == 0,
900
0
                 "Consumed part of a char16_t?");
901
0
902
0
    // Consumed something.
903
0
    *aConsumed = (parserBytesConsumed - parserBytesBefore) / sizeof(char16_t);
904
0
    NS_ASSERTION(*aConsumed <= aLength + mExpatBuffered,
905
0
                 "Too many bytes consumed?");
906
0
907
0
    NS_ASSERTION(status != XML_STATUS_SUSPENDED || BlockedOrInterrupted(), 
908
0
                 "Inconsistent expat suspension state.");
909
0
910
0
    if (status == XML_STATUS_ERROR) {
911
0
      mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
912
0
    }
913
0
  }
914
0
  else {
915
0
    *aConsumed = 0;
916
0
  }
917
0
}
918
919
NS_IMETHODIMP
920
nsExpatDriver::ConsumeToken(nsScanner& aScanner, bool& aFlushTokens)
921
0
{
922
0
  // We keep the scanner pointing to the position where Expat will start
923
0
  // parsing.
924
0
  nsScannerIterator currentExpatPosition;
925
0
  aScanner.CurrentPosition(currentExpatPosition);
926
0
927
0
  // This is the start of the first buffer that we need to pass to Expat.
928
0
  nsScannerIterator start = currentExpatPosition;
929
0
  start.advance(mExpatBuffered);
930
0
931
0
  // This is the end of the last buffer (at this point, more data could come in
932
0
  // later).
933
0
  nsScannerIterator end;
934
0
  aScanner.EndReading(end);
935
0
936
0
  MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
937
0
         ("Remaining in expat's buffer: %i, remaining in scanner: %zu.",
938
0
          mExpatBuffered, Distance(start, end)));
939
0
940
0
  // We want to call Expat if we have more buffers, or if we know there won't
941
0
  // be more buffers (and so we want to flush the remaining data), or if we're
942
0
  // currently blocked and there's data in Expat's buffer.
943
0
  while (start != end || (mIsFinalChunk && !mMadeFinalCallToExpat) ||
944
0
         (BlockedOrInterrupted() && mExpatBuffered > 0)) {
945
0
    bool noMoreBuffers = start == end && mIsFinalChunk;
946
0
    bool blocked = BlockedOrInterrupted();
947
0
948
0
    const char16_t *buffer;
949
0
    uint32_t length;
950
0
    if (blocked || noMoreBuffers) {
951
0
      // If we're blocked we just resume Expat so we don't need a buffer, if
952
0
      // there aren't any more buffers we pass a null buffer to Expat.
953
0
      buffer = nullptr;
954
0
      length = 0;
955
0
956
0
      if (blocked) {
957
0
        MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
958
0
               ("Resuming Expat, will parse data remaining in Expat's "
959
0
                "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
960
0
                NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
961
0
                                      mExpatBuffered).get()));
962
0
      }
963
0
      else {
964
0
        NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end),
965
0
                     "Didn't pass all the data to Expat?");
966
0
        MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
967
0
               ("Last call to Expat, will parse data remaining in Expat's "
968
0
                "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
969
0
                NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
970
0
                                      mExpatBuffered).get()));
971
0
      }
972
0
    }
973
0
    else {
974
0
      buffer = start.get();
975
0
      length = uint32_t(start.size_forward());
976
0
977
0
      MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
978
0
             ("Calling Expat, will parse data remaining in Expat's buffer and "
979
0
              "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew "
980
0
              "data:\n-----\n%s\n-----\n",
981
0
              NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
982
0
                                    mExpatBuffered).get(),
983
0
              NS_ConvertUTF16toUTF8(start.get(), length).get()));
984
0
    }
985
0
986
0
    uint32_t consumed;
987
0
    ParseBuffer(buffer, length, noMoreBuffers, &consumed);
988
0
    if (consumed > 0) {
989
0
      nsScannerIterator oldExpatPosition = currentExpatPosition;
990
0
      currentExpatPosition.advance(consumed);
991
0
992
0
      // We consumed some data, we want to store the last line of data that
993
0
      // was consumed in case we run into an error (to show the line in which
994
0
      // the error occurred).
995
0
996
0
      // The length of the last line that Expat has parsed.
997
0
      XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
998
0
999
0
      if (lastLineLength <= consumed) {
1000
0
        // The length of the last line was less than what expat consumed, so
1001
0
        // there was at least one line break in the consumed data. Store the
1002
0
        // last line until the point where we stopped parsing.
1003
0
        nsScannerIterator startLastLine = currentExpatPosition;
1004
0
        startLastLine.advance(-((ptrdiff_t)lastLineLength));
1005
0
        if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
1006
0
          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
1007
0
        }
1008
0
      }
1009
0
      else {
1010
0
        // There was no line break in the consumed data, append the consumed
1011
0
        // data.
1012
0
        if (!AppendUnicodeTo(oldExpatPosition,
1013
0
                             currentExpatPosition,
1014
0
                             mLastLine)) {
1015
0
          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
1016
0
        }
1017
0
      }
1018
0
    }
1019
0
1020
0
    mExpatBuffered += length - consumed;
1021
0
1022
0
    if (BlockedOrInterrupted()) {
1023
0
      MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
1024
0
             ("Blocked or interrupted parser (probably for loading linked "
1025
0
              "stylesheets or scripts)."));
1026
0
1027
0
      aScanner.SetPosition(currentExpatPosition, true);
1028
0
      aScanner.Mark();
1029
0
1030
0
      return mInternalState;
1031
0
    }
1032
0
1033
0
    if (noMoreBuffers && mExpatBuffered == 0) {
1034
0
      mMadeFinalCallToExpat = true;
1035
0
    }
1036
0
1037
0
    if (NS_FAILED(mInternalState)) {
1038
0
      if (XML_GetErrorCode(mExpatParser) != XML_ERROR_NONE) {
1039
0
        NS_ASSERTION(mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING,
1040
0
                     "Unexpected error");
1041
0
1042
0
        // Look for the next newline after the last one we consumed
1043
0
        nsScannerIterator lastLine = currentExpatPosition;
1044
0
        while (lastLine != end) {
1045
0
          length = uint32_t(lastLine.size_forward());
1046
0
          uint32_t endOffset = 0;
1047
0
          const char16_t *buffer = lastLine.get();
1048
0
          while (endOffset < length && buffer[endOffset] != '\n' &&
1049
0
                 buffer[endOffset] != '\r') {
1050
0
            ++endOffset;
1051
0
          }
1052
0
          mLastLine.Append(Substring(buffer, buffer + endOffset));
1053
0
          if (endOffset < length) {
1054
0
            // We found a newline.
1055
0
            break;
1056
0
          }
1057
0
1058
0
          lastLine.advance(length);
1059
0
        }
1060
0
1061
0
        HandleError();
1062
0
      }
1063
0
1064
0
      return mInternalState;
1065
0
    }
1066
0
1067
0
    // Either we have more buffers, or we were blocked (and we'll flush in the
1068
0
    // next iteration), or we should have emptied Expat's buffer.
1069
0
    NS_ASSERTION(!noMoreBuffers || blocked ||
1070
0
                 (mExpatBuffered == 0 && currentExpatPosition == end),
1071
0
                 "Unreachable data left in Expat's buffer");
1072
0
1073
0
    start.advance(length);
1074
0
1075
0
    // It's possible for start to have passed end if we received more data
1076
0
    // (e.g. if we spun the event loop in an inline script). Reload end now
1077
0
    // to compensate.
1078
0
    aScanner.EndReading(end);
1079
0
  }
1080
0
1081
0
  aScanner.SetPosition(currentExpatPosition, true);
1082
0
  aScanner.Mark();
1083
0
1084
0
  MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
1085
0
         ("Remaining in expat's buffer: %i, remaining in scanner: %zu.",
1086
0
          mExpatBuffered, Distance(currentExpatPosition, end)));
1087
0
1088
0
  return NS_SUCCEEDED(mInternalState) ? NS_ERROR_HTMLPARSER_EOF : NS_OK;
1089
0
}
1090
1091
NS_IMETHODIMP
1092
nsExpatDriver::WillBuildModel(const CParserContext& aParserContext,
1093
                              nsITokenizer* aTokenizer,
1094
                              nsIContentSink* aSink)
1095
0
{
1096
0
  mSink = do_QueryInterface(aSink);
1097
0
  if (!mSink) {
1098
0
    NS_ERROR("nsExpatDriver didn't get an nsIExpatSink");
1099
0
    // Make sure future calls to us bail out as needed
1100
0
    mInternalState = NS_ERROR_UNEXPECTED;
1101
0
    return mInternalState;
1102
0
  }
1103
0
1104
0
  mOriginalSink = aSink;
1105
0
1106
0
  static const XML_Memory_Handling_Suite memsuite = {
1107
0
    malloc,
1108
0
    realloc,
1109
0
    free
1110
0
  };
1111
0
1112
0
  static const char16_t kExpatSeparator[] = { kExpatSeparatorChar, '\0' };
1113
0
1114
0
  mExpatParser = XML_ParserCreate_MM(kUTF16, &memsuite, kExpatSeparator);
1115
0
  NS_ENSURE_TRUE(mExpatParser, NS_ERROR_FAILURE);
1116
0
1117
0
  XML_SetReturnNSTriplet(mExpatParser, XML_TRUE);
1118
0
1119
0
#ifdef XML_DTD
1120
0
  XML_SetParamEntityParsing(mExpatParser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1121
0
#endif
1122
0
1123
0
  mURISpec = aParserContext.mScanner->GetFilename();
1124
0
1125
0
  XML_SetBase(mExpatParser, mURISpec.get());
1126
0
1127
0
  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mOriginalSink->GetTarget());
1128
0
  if (doc) {
1129
0
    nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
1130
0
    nsCOMPtr<nsPIDOMWindowInner> inner;
1131
0
    if (win) {
1132
0
      inner = win->GetCurrentInnerWindow();
1133
0
    } else {
1134
0
      bool aHasHadScriptHandlingObject;
1135
0
      nsIScriptGlobalObject *global =
1136
0
        doc->GetScriptHandlingObject(aHasHadScriptHandlingObject);
1137
0
      if (global) {
1138
0
        inner = do_QueryInterface(global);
1139
0
      }
1140
0
    }
1141
0
    if (inner) {
1142
0
      mInnerWindowID = inner->WindowID();
1143
0
    }
1144
0
  }
1145
0
1146
0
  // Set up the callbacks
1147
0
  XML_SetXmlDeclHandler(mExpatParser, Driver_HandleXMLDeclaration); 
1148
0
  XML_SetElementHandler(mExpatParser, Driver_HandleStartElement,
1149
0
                        Driver_HandleEndElement);
1150
0
  XML_SetCharacterDataHandler(mExpatParser, Driver_HandleCharacterData);
1151
0
  XML_SetProcessingInstructionHandler(mExpatParser,
1152
0
                                      Driver_HandleProcessingInstruction);
1153
0
  XML_SetDefaultHandlerExpand(mExpatParser, Driver_HandleDefault);
1154
0
  XML_SetExternalEntityRefHandler(mExpatParser,
1155
0
                                  (XML_ExternalEntityRefHandler)
1156
0
                                          Driver_HandleExternalEntityRef);
1157
0
  XML_SetExternalEntityRefHandlerArg(mExpatParser, this);
1158
0
  XML_SetCommentHandler(mExpatParser, Driver_HandleComment);
1159
0
  XML_SetCdataSectionHandler(mExpatParser, Driver_HandleStartCdataSection,
1160
0
                             Driver_HandleEndCdataSection);
1161
0
1162
0
  XML_SetParamEntityParsing(mExpatParser,
1163
0
                            XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1164
0
  XML_SetDoctypeDeclHandler(mExpatParser, Driver_HandleStartDoctypeDecl,
1165
0
                            Driver_HandleEndDoctypeDecl);
1166
0
1167
0
  // Set up the user data.
1168
0
  XML_SetUserData(mExpatParser, this);
1169
0
1170
0
  return mInternalState;
1171
0
}
1172
1173
NS_IMETHODIMP
1174
nsExpatDriver::BuildModel(nsITokenizer* aTokenizer, nsIContentSink* aSink)
1175
0
{
1176
0
  return mInternalState;
1177
0
}
1178
1179
NS_IMETHODIMP
1180
nsExpatDriver::DidBuildModel(nsresult anErrorCode)
1181
0
{
1182
0
  mOriginalSink = nullptr;
1183
0
  mSink = nullptr;
1184
0
  return NS_OK;
1185
0
}
1186
1187
NS_IMETHODIMP
1188
nsExpatDriver::WillTokenize(bool aIsFinalChunk)
1189
0
{
1190
0
  mIsFinalChunk = aIsFinalChunk;
1191
0
  return NS_OK;
1192
0
}
1193
1194
NS_IMETHODIMP_(void)
1195
nsExpatDriver::Terminate()
1196
0
{
1197
0
  // XXX - not sure what happens to the unparsed data.
1198
0
  if (mExpatParser) {
1199
0
    XML_StopParser(mExpatParser, XML_FALSE);
1200
0
  }
1201
0
  mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
1202
0
}
1203
1204
NS_IMETHODIMP_(int32_t)
1205
nsExpatDriver::GetType()
1206
0
{
1207
0
  return NS_IPARSER_FLAG_XML;
1208
0
}
1209
1210
NS_IMETHODIMP_(nsDTDMode)
1211
nsExpatDriver::GetMode() const
1212
0
{
1213
0
  return eDTDMode_full_standards;
1214
0
}
1215
1216
/*************************** Unused methods **********************************/
1217
1218
NS_IMETHODIMP_(bool)
1219
nsExpatDriver::IsContainer(int32_t aTag) const
1220
0
{
1221
0
  return true;
1222
0
}
1223
1224
NS_IMETHODIMP_(bool)
1225
nsExpatDriver::CanContain(int32_t aParent,int32_t aChild) const
1226
0
{
1227
0
  return true;
1228
0
}
1229
1230
void
1231
nsExpatDriver::MaybeStopParser(nsresult aState)
1232
0
{
1233
0
  if (NS_FAILED(aState)) {
1234
0
    // If we had a failure we want to override NS_ERROR_HTMLPARSER_INTERRUPTED
1235
0
    // and we want to override NS_ERROR_HTMLPARSER_BLOCK but not with
1236
0
    // NS_ERROR_HTMLPARSER_INTERRUPTED.
1237
0
    if (NS_SUCCEEDED(mInternalState) ||
1238
0
        mInternalState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
1239
0
        (mInternalState == NS_ERROR_HTMLPARSER_BLOCK &&
1240
0
         aState != NS_ERROR_HTMLPARSER_INTERRUPTED)) {
1241
0
      mInternalState = (aState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
1242
0
                        aState == NS_ERROR_HTMLPARSER_BLOCK) ?
1243
0
                       aState :
1244
0
                       NS_ERROR_HTMLPARSER_STOPPARSING;
1245
0
    }
1246
0
1247
0
    // If we get an error then we need to stop Expat (by calling XML_StopParser
1248
0
    // with false as the last argument). If the parser should be blocked or
1249
0
    // interrupted we need to pause Expat (by calling XML_StopParser with
1250
0
    // true as the last argument).
1251
0
    XML_StopParser(mExpatParser, BlockedOrInterrupted());
1252
0
  }
1253
0
  else if (NS_SUCCEEDED(mInternalState)) {
1254
0
    // Only clobber mInternalState with the success code if we didn't block or
1255
0
    // interrupt before.
1256
0
    mInternalState = aState;
1257
0
  }
1258
0
}