Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/dom/XMLHttpRequestMainThread.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
#ifndef mozilla_dom_XMLHttpRequestMainThread_h
8
#define mozilla_dom_XMLHttpRequestMainThread_h
9
10
#include <bitset>
11
#include "nsAutoPtr.h"
12
#include "nsISupportsUtils.h"
13
#include "nsIURI.h"
14
#include "nsIHttpChannel.h"
15
#include "nsIDocument.h"
16
#include "nsIStreamListener.h"
17
#include "nsIChannelEventSink.h"
18
#include "nsIAsyncVerifyRedirectCallback.h"
19
#include "nsIInterfaceRequestor.h"
20
#include "nsIHttpHeaderVisitor.h"
21
#include "nsIProgressEventSink.h"
22
#include "nsJSUtils.h"
23
#include "nsTArray.h"
24
#include "nsITimer.h"
25
#include "nsIPrincipal.h"
26
#include "nsIScriptObjectPrincipal.h"
27
#include "nsISizeOfEventTarget.h"
28
#include "nsIXPConnect.h"
29
#include "nsIInputStream.h"
30
#include "mozilla/Assertions.h"
31
#include "mozilla/Attributes.h"
32
#include "mozilla/DOMEventTargetHelper.h"
33
#include "mozilla/Maybe.h"
34
#include "mozilla/MemoryReporting.h"
35
#include "mozilla/NotNull.h"
36
#include "mozilla/dom/MutableBlobStorage.h"
37
#include "mozilla/dom/BodyExtractor.h"
38
#include "mozilla/dom/ClientInfo.h"
39
#include "mozilla/dom/TypedArray.h"
40
#include "mozilla/dom/File.h"
41
#include "mozilla/dom/FormData.h"
42
#include "mozilla/dom/MimeType.h"
43
#include "mozilla/dom/PerformanceStorage.h"
44
#include "mozilla/dom/ServiceWorkerDescriptor.h"
45
#include "mozilla/dom/URLSearchParams.h"
46
#include "mozilla/dom/XMLHttpRequest.h"
47
#include "mozilla/dom/XMLHttpRequestBinding.h"
48
#include "mozilla/dom/XMLHttpRequestEventTarget.h"
49
#include "mozilla/dom/XMLHttpRequestString.h"
50
#include "mozilla/Encoding.h"
51
52
#ifdef Status
53
/* Xlib headers insist on this for some reason... Nuke it because
54
   it'll override our member name */
55
#undef Status
56
#endif
57
58
class nsIJARChannel;
59
class nsILoadGroup;
60
class nsIJSID;
61
62
namespace mozilla {
63
namespace dom {
64
65
class DOMString;
66
class XMLHttpRequestUpload;
67
struct OriginAttributesDictionary;
68
69
// A helper for building up an ArrayBuffer object's data
70
// before creating the ArrayBuffer itself.  Will do doubling
71
// based reallocation, up to an optional maximum growth given.
72
//
73
// When all the data has been appended, call getArrayBuffer,
74
// passing in the JSContext* for which the ArrayBuffer object
75
// is to be created.  This also implicitly resets the builder,
76
// or it can be reset explicitly at any point by calling reset().
77
class ArrayBufferBuilder
78
{
79
  uint8_t* mDataPtr;
80
  uint32_t mCapacity;
81
  uint32_t mLength;
82
  void* mMapPtr;
83
public:
84
  ArrayBufferBuilder();
85
  ~ArrayBufferBuilder();
86
87
  void reset();
88
89
  // Will truncate if aNewCap is < length().
90
  bool setCapacity(uint32_t aNewCap);
91
92
  // Append aDataLen bytes from data to the current buffer.  If we
93
  // need to grow the buffer, grow by doubling the size up to a
94
  // maximum of aMaxGrowth (if given).  If aDataLen is greater than
95
  // what the new capacity would end up as, then grow by aDataLen.
96
  //
97
  // The data parameter must not overlap with anything beyond the
98
  // builder's current valid contents [0..length)
99
  bool append(const uint8_t* aNewData, uint32_t aDataLen,
100
              uint32_t aMaxGrowth = 0);
101
102
  uint32_t length()   { return mLength; }
103
  uint32_t capacity() { return mCapacity; }
104
105
  JSObject* getArrayBuffer(JSContext* aCx);
106
107
  // Memory mapping to starting position of file(aFile) in the zip
108
  // package(aJarFile).
109
  //
110
  // The file in the zip package has to be uncompressed and the starting
111
  // position of the file must be aligned according to array buffer settings
112
  // in JS engine.
113
  nsresult mapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
114
115
protected:
116
  static bool areOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
117
                                    const uint8_t* aStart2, uint32_t aLength2);
118
};
119
120
class nsXMLHttpRequestXPCOMifier;
121
122
class RequestHeaders
123
{
124
  struct RequestHeader
125
  {
126
    nsCString mName;
127
    nsCString mValue;
128
  };
129
  nsTArray<RequestHeader> mHeaders;
130
  RequestHeader* Find(const nsACString& aName);
131
132
public:
133
  class CharsetIterator
134
  {
135
    bool mValid;
136
    int32_t mCurPos, mCurLen, mCutoff;
137
    nsACString& mSource;
138
139
  public:
140
    explicit CharsetIterator(nsACString& aSource);
141
    bool Equals(const nsACString& aOther, const nsCStringComparator& aCmp) const;
142
    void Replace(const nsACString& aReplacement);
143
    bool Next();
144
  };
145
146
  bool Has(const char* aName);
147
  bool Has(const nsACString& aName);
148
  void Get(const char* aName, nsACString& aValue);
149
  void Get(const nsACString& aName, nsACString& aValue);
150
  void Set(const char* aName, const nsACString& aValue);
151
  void Set(const nsACString& aName, const nsACString& aValue);
152
  void MergeOrSet(const char* aName, const nsACString& aValue);
153
  void MergeOrSet(const nsACString& aName, const nsACString& aValue);
154
  void Clear();
155
  void ApplyToChannel(nsIHttpChannel* aChannel) const;
156
  void GetCORSUnsafeHeaders(nsTArray<nsCString>& aArray) const;
157
};
158
159
class nsXHRParseEndListener;
160
161
// Make sure that any non-DOM interfaces added here are also added to
162
// nsXMLHttpRequestXPCOMifier.
163
class XMLHttpRequestMainThread final : public XMLHttpRequest,
164
                                       public nsIStreamListener,
165
                                       public nsIChannelEventSink,
166
                                       public nsIProgressEventSink,
167
                                       public nsIInterfaceRequestor,
168
                                       public nsITimerCallback,
169
                                       public nsISizeOfEventTarget,
170
                                       public nsINamed,
171
                                       public MutableBlobStorageCallback
172
{
173
  friend class nsXHRParseEndListener;
174
  friend class nsXMLHttpRequestXPCOMifier;
175
176
public:
177
  enum class ProgressEventType : uint8_t {
178
    loadstart,
179
    progress,
180
    error,
181
    abort,
182
    timeout,
183
    load,
184
    loadend,
185
    ENUM_MAX
186
  };
187
188
  // Make sure that any additions done to ErrorType enum are also mirrored in
189
  // XHR_ERROR_TYPE enum of TelemetrySend.jsm.
190
  enum class ErrorType : uint16_t {
191
    eOK,
192
    eRequest,
193
    eUnreachable,
194
    eChannelOpen,
195
    eRedirect,
196
    eTerminated,
197
    ENUM_MAX
198
  };
199
200
  XMLHttpRequestMainThread();
201
202
  void Construct(nsIPrincipal* aPrincipal,
203
                 nsIGlobalObject* aGlobalObject,
204
                 nsIURI* aBaseURI = nullptr,
205
                 nsILoadGroup* aLoadGroup = nullptr,
206
                 PerformanceStorage* aPerformanceStorage = nullptr)
207
  {
208
    MOZ_ASSERT(aPrincipal);
209
    mPrincipal = aPrincipal;
210
    BindToOwner(aGlobalObject);
211
    mBaseURI = aBaseURI;
212
    mLoadGroup = aLoadGroup;
213
    mPerformanceStorage = aPerformanceStorage;
214
  }
215
216
  void InitParameters(bool aAnon, bool aSystem);
217
218
  void SetParameters(bool aAnon, bool aSystem)
219
  {
220
    mIsAnon = aAnon || aSystem;
221
    mIsSystem = aSystem;
222
  }
223
224
  void SetClientInfoAndController(const ClientInfo& aClientInfo,
225
                                  const Maybe<ServiceWorkerDescriptor>& aController);
226
227
  NS_DECL_ISUPPORTS_INHERITED
228
229
  // nsIStreamListener
230
  NS_DECL_NSISTREAMLISTENER
231
232
  // nsIRequestObserver
233
  NS_DECL_NSIREQUESTOBSERVER
234
235
  // nsIChannelEventSink
236
  NS_DECL_NSICHANNELEVENTSINK
237
238
  // nsIProgressEventSink
239
  NS_DECL_NSIPROGRESSEVENTSINK
240
241
  // nsIInterfaceRequestor
242
  NS_DECL_NSIINTERFACEREQUESTOR
243
244
  // nsITimerCallback
245
  NS_DECL_NSITIMERCALLBACK
246
247
  // nsINamed
248
  NS_DECL_NSINAMED
249
250
  // nsISizeOfEventTarget
251
  virtual size_t
252
    SizeOfEventTargetIncludingThis(MallocSizeOf aMallocSizeOf) const override;
253
254
  // states
255
  virtual uint16_t ReadyState() const override;
256
257
  // request
258
  nsresult CreateChannel();
259
  nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
260
                         int64_t aUploadLength,
261
                         nsACString& aUploadContentType);
262
263
  virtual void
264
  Open(const nsACString& aMethod, const nsAString& aUrl,
265
       ErrorResult& aRv) override;
266
267
  virtual void
268
  Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
269
       const nsAString& aUsername, const nsAString& aPassword,
270
       ErrorResult& aRv) override;
271
272
  nsresult
273
  Open(const nsACString& aMethod,
274
       const nsACString& aUrl,
275
       bool aAsync,
276
       const nsAString& aUsername,
277
       const nsAString& aPassword);
278
279
  virtual void
280
  SetRequestHeader(const nsACString& aName, const nsACString& aValue,
281
                   ErrorResult& aRv) override;
282
283
  virtual uint32_t
284
  Timeout() const override
285
  {
286
    return mTimeoutMilliseconds;
287
  }
288
289
  virtual void
290
  SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
291
292
  virtual bool WithCredentials() const override;
293
294
  virtual void
295
  SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) override;
296
297
  virtual XMLHttpRequestUpload*
298
  GetUpload(ErrorResult& aRv) override;
299
300
private:
301
  virtual ~XMLHttpRequestMainThread();
302
303
  nsresult MaybeSilentSendFailure(nsresult aRv);
304
  nsresult SendInternal(const BodyExtractorBase* aBody, bool aBodyIsDocumentOrString = false);
305
306
  bool IsCrossSiteCORSRequest() const;
307
  bool IsDeniedCrossSiteCORSRequest();
308
309
  void UnsuppressEventHandlingAndResume();
310
311
  // Check pref "dom.mapped_arraybuffer.enabled" to make sure ArrayBuffer is
312
  // supported.
313
  static bool IsMappedArrayBufferEnabled();
314
315
  // Check pref "dom.xhr.lowercase_header.enabled" to make sure lowercased
316
  // response header is supported.
317
  static bool IsLowercaseResponseHeader();
318
319
  void MaybeLowerChannelPriority();
320
321
public:
322
  virtual void
323
  Send(JSContext* aCx,
324
       const Nullable<DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>& aData,
325
       ErrorResult& aRv) override;
326
327
  virtual void
328
  SendInputStream(nsIInputStream* aInputStream, ErrorResult& aRv) override
329
  {
330
    BodyExtractor<nsIInputStream> body(aInputStream);
331
    aRv = SendInternal(&body);
332
  }
333
334
  void
335
  RequestErrorSteps(const ProgressEventType aEventType,
336
                    const nsresult aOptionalException,
337
                    ErrorResult& aRv);
338
339
  void
340
  Abort()
341
  {
342
    IgnoredErrorResult rv;
343
    AbortInternal(rv);
344
    MOZ_ASSERT(!rv.Failed());
345
  }
346
347
  virtual void
348
  Abort(ErrorResult& aRv) override;
349
350
  // response
351
  virtual void
352
  GetResponseURL(nsAString& aUrl) override;
353
354
  virtual uint32_t
355
  GetStatus(ErrorResult& aRv) override;
356
357
  virtual void
358
  GetStatusText(nsACString& aStatusText, ErrorResult& aRv) override;
359
360
  virtual void
361
  GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
362
                    ErrorResult& aRv) override;
363
364
  void
365
  GetResponseHeader(const nsAString& aHeader, nsAString& aResult,
366
                    ErrorResult& aRv)
367
  {
368
    nsAutoCString result;
369
    GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
370
    if (result.IsVoid()) {
371
      aResult.SetIsVoid(true);
372
    }
373
    else {
374
      // The result value should be inflated:
375
      CopyASCIItoUTF16(result, aResult);
376
    }
377
  }
378
379
  virtual void
380
  GetAllResponseHeaders(nsACString& aResponseHeaders,
381
                        ErrorResult& aRv) override;
382
383
  bool IsSafeHeader(const nsACString& aHeaderName,
384
                    NotNull<nsIHttpChannel*> aHttpChannel) const;
385
386
  virtual void
387
  OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) override;
388
389
  virtual XMLHttpRequestResponseType
390
  ResponseType() const override
391
  {
392
    return XMLHttpRequestResponseType(mResponseType);
393
  }
394
395
  virtual void
396
  SetResponseType(XMLHttpRequestResponseType aType,
397
                  ErrorResult& aRv) override;
398
399
  virtual void
400
  GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
401
              ErrorResult& aRv) override;
402
403
  virtual void
404
  GetResponseText(DOMString& aResponseText, ErrorResult& aRv) override;
405
406
  void
407
  GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
408
                  ErrorResult& aRv);
409
410
  virtual nsIDocument*
411
  GetResponseXML(ErrorResult& aRv) override;
412
413
  virtual bool
414
  MozBackgroundRequest() const override;
415
416
  nsresult
417
  SetMozBackgroundRequest(bool aMozBackgroundRequest);
418
419
  virtual void
420
  SetMozBackgroundRequest(bool aMozBackgroundRequest, ErrorResult& aRv) override;
421
422
  virtual uint16_t
423
  ErrorCode() const override
424
  {
425
    return static_cast<uint16_t>(mErrorLoad);
426
  }
427
428
  virtual bool
429
  MozAnon() const override;
430
431
  virtual bool
432
  MozSystem() const override;
433
434
  virtual nsIChannel*
435
  GetChannel() const override
436
  {
437
    return mChannel;
438
  }
439
440
  // We need a GetInterface callable from JS for chrome JS
441
  virtual void
442
  GetInterface(JSContext* aCx, nsIJSID* aIID,
443
               JS::MutableHandle<JS::Value> aRetval,
444
               ErrorResult& aRv) override;
445
446
  // This fires a trusted readystatechange event, which is not cancelable and
447
  // doesn't bubble.
448
  nsresult FireReadystatechangeEvent();
449
  void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
450
                             const ProgressEventType aType,
451
                             int64_t aLoaded, int64_t aTotal);
452
453
  void SetRequestObserver(nsIRequestObserver* aObserver);
454
455
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(XMLHttpRequestMainThread,
456
                                                         XMLHttpRequest)
457
  virtual bool IsCertainlyAliveForCC() const override;
458
459
  bool AllowUploadProgress();
460
461
  virtual void DisconnectFromOwner() override;
462
463
  static void SetDontWarnAboutSyncXHR(bool aVal)
464
0
  {
465
0
    sDontWarnAboutSyncXHR = aVal;
466
0
  }
467
  static bool DontWarnAboutSyncXHR()
468
  {
469
    return sDontWarnAboutSyncXHR;
470
  }
471
472
  virtual void
473
  SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary& aAttrs) override;
474
475
  void BlobStoreCompleted(MutableBlobStorage* aBlobStorage,
476
                          Blob* aBlob,
477
                          nsresult aResult) override;
478
479
  void
480
  LocalFileToBlobCompleted(Blob* aBlob);
481
482
protected:
483
  nsresult DetectCharset();
484
  nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
485
                                bool aLast = false);
486
  static nsresult StreamReaderFunc(nsIInputStream* in,
487
                                   void* closure,
488
                                   const char* fromRawSegment,
489
                                   uint32_t toOffset,
490
                                   uint32_t count,
491
                                   uint32_t *writeCount);
492
  nsresult CreateResponseParsedJSON(JSContext* aCx);
493
  // Change the state of the object with this. The broadcast argument
494
  // determines if the onreadystatechange listener should be called.
495
  nsresult ChangeState(uint16_t aState, bool aBroadcast = true);
496
  already_AddRefed<nsILoadGroup> GetLoadGroup() const;
497
  nsIURI *GetBaseURI();
498
499
  already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
500
  already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
501
502
  void TruncateResponseText();
503
504
  bool IsSystemXHR() const;
505
  bool InUploadPhase() const;
506
507
  void OnBodyParseEnd();
508
  void ChangeStateToDone();
509
510
  void StartProgressEventTimer();
511
  void StopProgressEventTimer();
512
513
  void MaybeCreateBlobStorage();
514
515
  nsresult OnRedirectVerifyCallback(nsresult result);
516
517
  void SetTimerEventTarget(nsITimer* aTimer);
518
519
  nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable);
520
521
  void DispatchOrStoreEvent(DOMEventTargetHelper* aTarget, Event* aEvent);
522
523
  already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
524
525
  void SuspendEventDispatching();
526
  void ResumeEventDispatching();
527
528
  void
529
  AbortInternal(ErrorResult& aRv);
530
531
  struct PendingEvent
532
  {
533
    RefPtr<DOMEventTargetHelper> mTarget;
534
    RefPtr<Event> mEvent;
535
  };
536
537
  nsTArray<PendingEvent> mPendingEvents;
538
539
  nsCOMPtr<nsISupports> mContext;
540
  nsCOMPtr<nsIPrincipal> mPrincipal;
541
  nsCOMPtr<nsIChannel> mChannel;
542
  nsCString mRequestMethod;
543
  nsCOMPtr<nsIURI> mRequestURL;
544
  nsCOMPtr<nsIDocument> mResponseXML;
545
546
  nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
547
548
  RefPtr<PerformanceStorage> mPerformanceStorage;
549
550
  // used to implement getAllResponseHeaders()
551
  class nsHeaderVisitor : public nsIHttpHeaderVisitor
552
  {
553
    struct HeaderEntry final
554
    {
555
      nsCString mName;
556
      nsCString mValue;
557
558
      HeaderEntry(const nsACString& aName, const nsACString& aValue)
559
        : mName(aName), mValue(aValue)
560
      {}
561
562
      bool
563
      operator==(const HeaderEntry& aOther) const
564
      {
565
        return mName == aOther.mName;
566
      }
567
568
      bool
569
      operator<(const HeaderEntry& aOther) const
570
      {
571
        return mName < aOther.mName;
572
      }
573
    };
574
575
  public:
576
    NS_DECL_ISUPPORTS
577
    NS_DECL_NSIHTTPHEADERVISITOR
578
    nsHeaderVisitor(const XMLHttpRequestMainThread& aXMLHttpRequest,
579
                    NotNull<nsIHttpChannel*> aHttpChannel)
580
      : mXHR(aXMLHttpRequest), mHttpChannel(aHttpChannel) {}
581
    const nsACString &Headers()
582
    {
583
      for (uint32_t i = 0; i < mHeaderList.Length(); i++) {
584
        HeaderEntry& header = mHeaderList.ElementAt(i);
585
586
        mHeaders.Append(header.mName);
587
        mHeaders.AppendLiteral(": ");
588
        mHeaders.Append(header.mValue);
589
        mHeaders.AppendLiteral("\r\n");
590
      }
591
      return mHeaders;
592
    }
593
594
  private:
595
    virtual ~nsHeaderVisitor() {}
596
597
    nsTArray<HeaderEntry> mHeaderList;
598
    nsCString mHeaders;
599
    const XMLHttpRequestMainThread& mXHR;
600
    NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
601
  };
602
603
  // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
604
  // BLOB responseTypes
605
  nsCString mResponseBody;
606
607
  // The text version of our response body. This is incrementally decoded into
608
  // as we receive network data. However for the DEFAULT responseType we
609
  // lazily decode into this from mResponseBody only when .responseText is
610
  // accessed.
611
  // Only used for DEFAULT and TEXT responseTypes.
612
  XMLHttpRequestString mResponseText;
613
614
  // For DEFAULT responseType we use this to keep track of how far we've
615
  // lazily decoded from mResponseBody to mResponseText
616
  uint32_t mResponseBodyDecodedPos;
617
618
  // Decoder used for decoding into mResponseText
619
  // Only used for DEFAULT, TEXT and JSON responseTypes.
620
  // In cases where we've only received half a surrogate, the decoder itself
621
  // carries the state to remember this. Next time we receive more data we
622
  // simply feed the new data into the decoder which will handle the second
623
  // part of the surrogate.
624
  mozilla::UniquePtr<mozilla::Decoder> mDecoder;
625
626
  void MatchCharsetAndDecoderToResponseDocument();
627
628
  XMLHttpRequestResponseType mResponseType;
629
630
  // It is either a cached blob-response from the last call to GetResponse,
631
  // but is also explicitly set in OnStopRequest.
632
  RefPtr<Blob> mResponseBlob;
633
  // We stream data to mBlobStorage when response type is "blob".
634
  RefPtr<MutableBlobStorage> mBlobStorage;
635
636
  nsString mOverrideMimeType;
637
638
  /**
639
   * The notification callbacks the channel had when Send() was
640
   * called.  We want to forward things here as needed.
641
   */
642
  nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
643
  /**
644
   * Sink interfaces that we implement that mNotificationCallbacks may
645
   * want to also be notified for.  These are inited lazily if we're
646
   * asked for the relevant interface.
647
   */
648
  nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
649
  nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
650
651
  nsIRequestObserver* mRequestObserver;
652
653
  nsCOMPtr<nsIURI> mBaseURI;
654
  nsCOMPtr<nsILoadGroup> mLoadGroup;
655
656
  Maybe<ClientInfo> mClientInfo;
657
  Maybe<ServiceWorkerDescriptor> mController;
658
659
  uint16_t mState;
660
661
  bool mFlagSynchronous;
662
  bool mFlagAborted;
663
  bool mFlagParseBody;
664
  bool mFlagSyncLooping;
665
  bool mFlagBackgroundRequest;
666
  bool mFlagHadUploadListenersOnSend;
667
  bool mFlagACwithCredentials;
668
  bool mFlagTimedOut;
669
  bool mFlagDeleted;
670
671
  // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
672
  // finishes downloading (or an error/abort has occurred during either phase).
673
  // Used to guard against the user trying to alter headers/etc when it's too
674
  // late, and ensure the XHR only handles one in-flight request at once.
675
  bool mFlagSend;
676
677
  RefPtr<XMLHttpRequestUpload> mUpload;
678
  int64_t mUploadTransferred;
679
  int64_t mUploadTotal;
680
  bool mUploadComplete;
681
  bool mProgressSinceLastProgressEvent;
682
683
  // Timeout support
684
  PRTime mRequestSentTime;
685
  uint32_t mTimeoutMilliseconds;
686
  nsCOMPtr<nsITimer> mTimeoutTimer;
687
  void StartTimeoutTimer();
688
  void HandleTimeoutCallback();
689
690
  nsCOMPtr<nsIDocument> mSuspendedDoc;
691
  nsCOMPtr<nsIRunnable> mResumeTimeoutRunnable;
692
693
  nsCOMPtr<nsITimer> mSyncTimeoutTimer;
694
695
  enum SyncTimeoutType {
696
    eErrorOrExpired,
697
    eTimerStarted,
698
    eNoTimerNeeded
699
  };
700
701
  SyncTimeoutType MaybeStartSyncTimeoutTimer();
702
  void HandleSyncTimeoutTimer();
703
  void CancelSyncTimeoutTimer();
704
705
  ErrorType mErrorLoad;
706
  bool mErrorParsingXML;
707
  bool mWaitingForOnStopRequest;
708
  bool mProgressTimerIsActive;
709
  bool mIsHtml;
710
  bool mWarnAboutSyncHtml;
711
  int64_t mLoadTotal; // -1 if not known.
712
  // Number of HTTP message body bytes received so far. This quantity is
713
  // in the same units as Content-Length and mLoadTotal, and hence counts
714
  // compressed bytes when the channel has gzip Content-Encoding. If the
715
  // channel does not have Content-Encoding, this will be the same as
716
  // mDataReceived except between the OnProgress that changes mLoadTransferred
717
  // and the corresponding OnDataAvailable (which changes mDataReceived).
718
  // Ordering of OnProgress and OnDataAvailable is undefined.
719
  int64_t mLoadTransferred;
720
  nsCOMPtr<nsITimer> mProgressNotifier;
721
  void HandleProgressTimerCallback();
722
723
  bool mIsSystem;
724
  bool mIsAnon;
725
726
  /**
727
   * Close the XMLHttpRequest's channels.
728
   */
729
  void CloseRequest();
730
731
  void TerminateOngoingFetch();
732
733
  /**
734
   * Close the XMLHttpRequest's channels and dispatch appropriate progress
735
   * events.
736
   *
737
   * @param aType The progress event type.
738
   */
739
  void CloseRequestWithError(const ProgressEventType aType);
740
741
  bool mFirstStartRequestSeen;
742
  bool mInLoadProgressEvent;
743
744
  nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
745
  nsCOMPtr<nsIChannel> mNewRedirectChannel;
746
747
  JS::Heap<JS::Value> mResultJSON;
748
749
  ArrayBufferBuilder mArrayBufferBuilder;
750
  JS::Heap<JSObject*> mResultArrayBuffer;
751
  bool mIsMappedArrayBuffer;
752
753
  void ResetResponse();
754
755
  bool ShouldBlockAuthPrompt();
756
757
  RequestHeaders mAuthorRequestHeaders;
758
759
  // Helper object to manage our XPCOM scriptability bits
760
  nsXMLHttpRequestXPCOMifier* mXPCOMifier;
761
762
  // When this is set to true, the event dispatching is suspended. This is
763
  // useful to change the correct state when XHR is working sync.
764
  bool mEventDispatchingSuspended;
765
766
  // True iff mDecoder has processed the end of the stream.
767
  // Used in lazy decoding to distinguish between having
768
  // processed all the bytes but not the EOF and having
769
  // processed all the bytes and the EOF.
770
  bool mEofDecoded;
771
772
  // Our parse-end listener, if we are parsing.
773
  RefPtr<nsXHRParseEndListener> mParseEndListener;
774
775
  static bool sDontWarnAboutSyncXHR;
776
};
777
778
class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
779
{
780
public:
781
  AutoDontWarnAboutSyncXHR() : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR())
782
0
  {
783
0
    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
784
0
  }
785
786
  ~AutoDontWarnAboutSyncXHR()
787
0
  {
788
0
    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
789
0
  }
790
791
private:
792
  bool mOldVal;
793
};
794
795
// A shim class designed to expose the non-DOM interfaces of
796
// XMLHttpRequest via XPCOM stuff.
797
class nsXMLHttpRequestXPCOMifier final : public nsIStreamListener,
798
                                         public nsIChannelEventSink,
799
                                         public nsIAsyncVerifyRedirectCallback,
800
                                         public nsIProgressEventSink,
801
                                         public nsIInterfaceRequestor,
802
                                         public nsITimerCallback,
803
                                         public nsINamed
804
{
805
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
806
  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
807
                                           nsIStreamListener)
808
809
  explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR) :
810
    mXHR(aXHR)
811
  {
812
  }
813
814
private:
815
  ~nsXMLHttpRequestXPCOMifier() {
816
    if (mXHR) {
817
      mXHR->mXPCOMifier = nullptr;
818
    }
819
  }
820
821
public:
822
  NS_FORWARD_NSISTREAMLISTENER(mXHR->)
823
  NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
824
  NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
825
  NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR->)
826
  NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
827
  NS_FORWARD_NSITIMERCALLBACK(mXHR->)
828
  NS_FORWARD_NSINAMED(mXHR->)
829
830
  NS_DECL_NSIINTERFACEREQUESTOR
831
832
private:
833
  RefPtr<XMLHttpRequestMainThread> mXHR;
834
};
835
836
class nsXHRParseEndListener : public nsIDOMEventListener
837
{
838
public:
839
  NS_DECL_ISUPPORTS
840
  NS_IMETHOD HandleEvent(Event *event) override
841
  {
842
    if (mXHR) {
843
      mXHR->OnBodyParseEnd();
844
    }
845
    mXHR = nullptr;
846
    return NS_OK;
847
  }
848
849
  explicit nsXHRParseEndListener(XMLHttpRequestMainThread* aXHR)
850
    : mXHR(aXHR) {}
851
852
  void SetIsStale() {
853
    mXHR = nullptr;
854
  }
855
private:
856
  virtual ~nsXHRParseEndListener() {}
857
858
  XMLHttpRequestMainThread* mXHR;
859
};
860
861
} // dom namespace
862
} // mozilla namespace
863
864
#endif // mozilla_dom_XMLHttpRequestMainThread_h