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/. */
7 #ifndef mozilla_dom_XMLHttpRequestMainThread_h
8 #define mozilla_dom_XMLHttpRequestMainThread_h
11 #include "nsISupportsUtils.h"
13 #include "mozilla/dom/Document.h"
14 #include "nsIStreamListener.h"
15 #include "nsIChannelEventSink.h"
16 #include "nsIAsyncVerifyRedirectCallback.h"
17 #include "nsIDOMEventListener.h"
18 #include "nsIInterfaceRequestor.h"
19 #include "nsIHttpHeaderVisitor.h"
20 #include "nsIProgressEventSink.h"
21 #include "nsJSUtils.h"
24 #include "nsIPrincipal.h"
25 #include "nsIScriptObjectPrincipal.h"
26 #include "nsISizeOfEventTarget.h"
27 #include "nsIInputStream.h"
28 #include "nsIContentSecurityPolicy.h"
29 #include "mozilla/Assertions.h"
30 #include "mozilla/Attributes.h"
31 #include "mozilla/DOMEventTargetHelper.h"
32 #include "mozilla/Maybe.h"
33 #include "mozilla/MemoryReporting.h"
34 #include "mozilla/NotNull.h"
35 #include "mozilla/dom/MutableBlobStorage.h"
36 #include "mozilla/dom/BodyExtractor.h"
37 #include "mozilla/dom/ClientInfo.h"
38 #include "mozilla/dom/TypedArray.h"
39 #include "mozilla/dom/File.h"
40 #include "mozilla/dom/FormData.h"
41 #include "mozilla/dom/MimeType.h"
42 #include "mozilla/dom/PerformanceStorage.h"
43 #include "mozilla/dom/ServiceWorkerDescriptor.h"
44 #include "mozilla/dom/URLSearchParams.h"
45 #include "mozilla/dom/WorkerRef.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 #include "nsBaseChannel.h"
54 /* Xlib headers insist on this for some reason... Nuke it because
55 it'll override our member name */
56 typedef Status __StatusTmp
;
58 typedef __StatusTmp Status
;
66 class ProfileChunkedBuffer
;
71 class XMLHttpRequestUpload
;
72 class SerializedStackHolder
;
73 struct OriginAttributesDictionary
;
75 // A helper for building up an ArrayBuffer object's data
76 // before creating the ArrayBuffer itself. Will do doubling
77 // based reallocation, up to an optional maximum growth given.
79 // When all the data has been appended, call GetArrayBuffer,
80 // passing in the JSContext* for which the ArrayBuffer object
81 // is to be created. This also implicitly resets the builder.
82 class ArrayBufferBuilder
{
84 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayBufferBuilder
);
88 // Will truncate if aNewCap is < Length().
89 bool SetCapacity(uint32_t aNewCap
);
91 // Append aDataLen bytes from data to the current buffer. If we
92 // need to grow the buffer, grow by doubling the size up to a
93 // maximum of aMaxGrowth (if given). If aDataLen is greater than
94 // what the new capacity would end up as, then grow by aDataLen.
96 // The data parameter must not overlap with anything beyond the
97 // builder's current valid contents [0..length)
98 bool Append(const uint8_t* aNewData
, uint32_t aDataLen
,
99 uint32_t aMaxGrowth
= 0);
104 JSObject
* TakeArrayBuffer(JSContext
* aCx
);
106 // Memory mapping to starting position of file(aFile) in the zip
107 // package(aJarFile).
109 // The file in the zip package has to be uncompressed and the starting
110 // position of the file must be aligned according to array buffer settings
112 nsresult
MapToFileInPackage(const nsCString
& aFile
, nsIFile
* aJarFile
);
115 ~ArrayBufferBuilder();
117 ArrayBufferBuilder(const ArrayBufferBuilder
&) = delete;
118 ArrayBufferBuilder
& operator=(const ArrayBufferBuilder
&) = delete;
119 ArrayBufferBuilder
& operator=(const ArrayBufferBuilder
&&) = delete;
121 bool SetCapacityInternal(uint32_t aNewCap
, const MutexAutoLock
& aProofOfLock
)
122 MOZ_REQUIRES(mMutex
);
124 static bool AreOverlappingRegions(const uint8_t* aStart1
, uint32_t aLength1
,
125 const uint8_t* aStart2
, uint32_t aLength2
);
129 // All of these are protected by mMutex.
130 uint8_t* mDataPtr
MOZ_GUARDED_BY(mMutex
);
131 uint32_t mCapacity
MOZ_GUARDED_BY(mMutex
);
132 uint32_t mLength
MOZ_GUARDED_BY(mMutex
);
133 void* mMapPtr
MOZ_GUARDED_BY(mMutex
);
135 // This is used in assertions only.
139 class nsXMLHttpRequestXPCOMifier
;
141 class RequestHeaders
{
142 struct RequestHeader
{
146 nsTArray
<RequestHeader
> mHeaders
;
147 RequestHeader
* Find(const nsACString
& aName
);
150 class CharsetIterator
{
152 int32_t mCurPos
, mCurLen
, mCutoff
;
156 explicit CharsetIterator(nsACString
& aSource
);
157 bool Equals(const nsACString
& aOther
,
158 const nsCStringComparator
& aCmp
) const;
159 void Replace(const nsACString
& aReplacement
);
163 bool IsEmpty() const;
164 bool Has(const char* aName
);
165 bool Has(const nsACString
& aName
);
166 void Get(const char* aName
, nsACString
& aValue
);
167 void Get(const nsACString
& aName
, nsACString
& aValue
);
168 void Set(const char* aName
, const nsACString
& aValue
);
169 void Set(const nsACString
& aName
, const nsACString
& aValue
);
170 void MergeOrSet(const char* aName
, const nsACString
& aValue
);
171 void MergeOrSet(const nsACString
& aName
, const nsACString
& aValue
);
173 void ApplyToChannel(nsIHttpChannel
* aChannel
, bool aStripRequestBodyHeader
,
174 bool aStripAuth
) const;
175 void GetCORSUnsafeHeaders(nsTArray
<nsCString
>& aArray
) const;
178 class nsXHRParseEndListener
;
179 class XMLHttpRequestDoneNotifier
;
181 // Make sure that any non-DOM interfaces added here are also added to
182 // nsXMLHttpRequestXPCOMifier.
183 class XMLHttpRequestMainThread final
: public XMLHttpRequest
,
184 public nsIStreamListener
,
185 public nsIChannelEventSink
,
186 public nsIProgressEventSink
,
187 public nsIInterfaceRequestor
,
188 public nsITimerCallback
,
189 public nsISizeOfEventTarget
,
191 public MutableBlobStorageCallback
{
192 friend class nsXHRParseEndListener
;
193 friend class nsXMLHttpRequestXPCOMifier
;
194 friend class XMLHttpRequestDoneNotifier
;
197 // Make sure that any additions done to ErrorType enum are also mirrored in
198 // XHR_ERROR_TYPE enum of TelemetrySend.sys.mjs.
199 enum class ErrorType
: uint16_t {
209 explicit XMLHttpRequestMainThread(nsIGlobalObject
* aGlobalObject
);
211 void Construct(nsIPrincipal
* aPrincipal
,
212 nsICookieJarSettings
* aCookieJarSettings
, bool aForWorker
,
213 nsIURI
* aBaseURI
= nullptr, nsILoadGroup
* aLoadGroup
= nullptr,
214 PerformanceStorage
* aPerformanceStorage
= nullptr,
215 nsICSPEventListener
* aCSPEventListener
= nullptr);
217 void InitParameters(bool aAnon
, bool aSystem
);
219 void SetParameters(bool aAnon
, bool aSystem
) {
220 mIsAnon
= aAnon
|| aSystem
;
224 void SetClientInfoAndController(
225 const ClientInfo
& aClientInfo
,
226 const Maybe
<ServiceWorkerDescriptor
>& aController
);
228 NS_DECL_ISUPPORTS_INHERITED
231 NS_DECL_NSISTREAMLISTENER
233 // nsIRequestObserver
234 NS_DECL_NSIREQUESTOBSERVER
236 // nsIChannelEventSink
237 NS_DECL_NSICHANNELEVENTSINK
239 // nsIProgressEventSink
240 NS_DECL_NSIPROGRESSEVENTSINK
242 // nsIInterfaceRequestor
243 NS_DECL_NSIINTERFACEREQUESTOR
246 NS_DECL_NSITIMERCALLBACK
251 // nsISizeOfEventTarget
252 virtual size_t SizeOfEventTargetIncludingThis(
253 MallocSizeOf aMallocSizeOf
) const override
;
256 virtual uint16_t ReadyState() const override
;
259 nsresult
CreateChannel();
260 nsresult
InitiateFetch(already_AddRefed
<nsIInputStream
> aUploadStream
,
261 int64_t aUploadLength
, nsACString
& aUploadContentType
);
263 virtual void Open(const nsACString
& aMethod
, const nsAString
& aUrl
,
264 ErrorResult
& aRv
) override
;
266 virtual void Open(const nsACString
& aMethod
, const nsAString
& aUrl
,
267 bool aAsync
, const nsAString
& aUsername
,
268 const nsAString
& aPassword
, ErrorResult
& aRv
) override
;
270 void Open(const nsACString
& aMethod
, const nsACString
& aUrl
, bool aAsync
,
271 const nsAString
& aUsername
, const nsAString
& aPassword
,
274 virtual void SetRequestHeader(const nsACString
& aName
,
275 const nsACString
& aValue
,
276 ErrorResult
& aRv
) override
;
278 virtual uint32_t Timeout() const override
{ return mTimeoutMilliseconds
; }
280 virtual void SetTimeout(uint32_t aTimeout
, ErrorResult
& aRv
) override
;
282 virtual bool WithCredentials() const override
;
284 virtual void SetWithCredentials(bool aWithCredentials
,
285 ErrorResult
& aRv
) override
;
287 virtual XMLHttpRequestUpload
* GetUpload(ErrorResult
& aRv
) override
;
290 virtual ~XMLHttpRequestMainThread();
292 nsresult
MaybeSilentSendFailure(nsresult aRv
);
293 void SendInternal(const BodyExtractorBase
* aBody
,
294 bool aBodyIsDocumentOrString
, ErrorResult
& aRv
);
296 bool IsCrossSiteCORSRequest() const;
297 bool IsDeniedCrossSiteCORSRequest();
299 void ResumeTimeout();
301 void MaybeLowerChannelPriority();
304 bool CanSend(ErrorResult
& aRv
);
308 DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString
>&
310 ErrorResult
& aRv
) override
;
312 virtual void SendInputStream(nsIInputStream
* aInputStream
,
313 ErrorResult
& aRv
) override
{
317 BodyExtractor
<nsIInputStream
> body(aInputStream
);
318 SendInternal(&body
, false, aRv
);
321 void RequestErrorSteps(const ProgressEventType aEventType
,
322 const nsresult aOptionalException
, ErrorResult
& aRv
);
325 IgnoredErrorResult rv
;
327 MOZ_ASSERT(!rv
.Failed() || rv
.ErrorCodeIs(NS_ERROR_DOM_ABORT_ERR
));
330 virtual void Abort(ErrorResult
& aRv
) override
;
333 virtual void GetResponseURL(nsAString
& aUrl
) override
;
335 virtual uint32_t GetStatus(ErrorResult
& aRv
) override
;
337 virtual void GetStatusText(nsACString
& aStatusText
,
338 ErrorResult
& aRv
) override
;
340 virtual void GetResponseHeader(const nsACString
& aHeader
, nsACString
& aResult
,
341 ErrorResult
& aRv
) override
;
343 void GetResponseHeader(const nsAString
& aHeader
, nsAString
& aResult
,
345 nsAutoCString result
;
346 GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader
), result
, aRv
);
347 if (result
.IsVoid()) {
348 aResult
.SetIsVoid(true);
350 // The result value should be inflated:
351 CopyASCIItoUTF16(result
, aResult
);
355 virtual void GetAllResponseHeaders(nsACString
& aResponseHeaders
,
356 ErrorResult
& aRv
) override
;
358 bool IsSafeHeader(const nsACString
& aHeaderName
,
359 NotNull
<nsIHttpChannel
*> aHttpChannel
) const;
361 virtual void OverrideMimeType(const nsAString
& aMimeType
,
362 ErrorResult
& aRv
) override
;
364 virtual XMLHttpRequestResponseType
ResponseType() const override
{
365 return XMLHttpRequestResponseType(mResponseType
);
368 virtual void SetResponseType(XMLHttpRequestResponseType aType
,
369 ErrorResult
& aRv
) override
;
371 void SetResponseTypeRaw(XMLHttpRequestResponseType aType
) {
372 mResponseType
= aType
;
375 virtual void GetResponse(JSContext
* aCx
,
376 JS::MutableHandle
<JS::Value
> aResponse
,
377 ErrorResult
& aRv
) override
;
379 virtual void GetResponseText(DOMString
& aResponseText
,
380 ErrorResult
& aRv
) override
;
382 // GetResponse* for workers:
383 already_AddRefed
<BlobImpl
> GetResponseBlobImpl();
384 already_AddRefed
<ArrayBufferBuilder
> GetResponseArrayBufferBuilder();
385 nsresult
GetResponseTextForJSON(nsAString
& aString
);
386 void GetResponseText(XMLHttpRequestStringSnapshot
& aSnapshot
,
389 virtual Document
* GetResponseXML(ErrorResult
& aRv
) override
;
391 virtual bool MozBackgroundRequest() const override
;
393 void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest
,
396 virtual void SetMozBackgroundRequest(bool aMozBackgroundRequest
,
397 ErrorResult
& aRv
) override
;
399 void SetOriginStack(UniquePtr
<SerializedStackHolder
> aOriginStack
);
401 void SetSource(UniquePtr
<ProfileChunkedBuffer
> aSource
);
403 nsresult
ErrorDetail() const { return mErrorLoadDetail
; }
405 virtual uint16_t ErrorCode() const override
{
406 return static_cast<uint16_t>(mErrorLoad
);
409 virtual bool MozAnon() const override
;
411 virtual bool MozSystem() const override
;
413 virtual nsIChannel
* GetChannel() const override
{ return mChannel
; }
415 // We need a GetInterface callable from JS for chrome JS
416 virtual void GetInterface(JSContext
* aCx
, JS::Handle
<JS::Value
> aIID
,
417 JS::MutableHandle
<JS::Value
> aRetval
,
418 ErrorResult
& aRv
) override
;
420 // This fires a trusted readystatechange event, which is not cancelable and
422 nsresult
FireReadystatechangeEvent();
423 void DispatchProgressEvent(DOMEventTargetHelper
* aTarget
,
424 const ProgressEventType
& aType
, int64_t aLoaded
,
427 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
428 XMLHttpRequestMainThread
, XMLHttpRequest
)
429 virtual bool IsCertainlyAliveForCC() const override
;
431 bool AllowUploadProgress();
433 virtual void DisconnectFromOwner() override
;
435 static void SetDontWarnAboutSyncXHR(bool aVal
) {
436 sDontWarnAboutSyncXHR
= aVal
;
438 static bool DontWarnAboutSyncXHR() { return sDontWarnAboutSyncXHR
; }
440 virtual void SetOriginAttributes(
441 const mozilla::dom::OriginAttributesDictionary
& aAttrs
) override
;
443 void BlobStoreCompleted(MutableBlobStorage
* aBlobStorage
, BlobImpl
* aBlobImpl
,
444 nsresult aResult
) override
;
446 void LocalFileToBlobCompleted(BlobImpl
* aBlobImpl
);
449 // For logging when there's trouble
450 RefPtr
<ThreadSafeWorkerRef
> mTSWorkerRef
= nullptr;
454 nsresult
DetectCharset();
455 nsresult
AppendToResponseText(Span
<const uint8_t> aBuffer
,
457 static nsresult
StreamReaderFunc(nsIInputStream
* in
, void* closure
,
458 const char* fromRawSegment
,
459 uint32_t toOffset
, uint32_t count
,
460 uint32_t* writeCount
);
461 nsresult
CreateResponseParsedJSON(JSContext
* aCx
);
462 // Change the state of the object with this. The broadcast argument
463 // determines if the onreadystatechange listener should be called.
464 nsresult
ChangeState(uint16_t aState
, bool aBroadcast
= true);
465 already_AddRefed
<nsILoadGroup
> GetLoadGroup() const;
467 // Finds a preload for this XHR. If it is found it's removed from the preload
468 // table of the document and marked as used. The called doesn't need to do
469 // any more comparative checks.
470 already_AddRefed
<PreloaderBase
> FindPreload();
471 // If no or unknown mime type is set on the channel this method ensures it's
472 // set to "text/xml".
473 void EnsureChannelContentType();
475 // Gets the value of the final content-type header from the channel.
476 bool GetContentType(nsACString
& aValue
) const;
478 already_AddRefed
<nsIHttpChannel
> GetCurrentHttpChannel();
479 already_AddRefed
<nsIJARChannel
> GetCurrentJARChannel();
481 void TruncateResponseText();
483 bool IsSystemXHR() const;
484 bool InUploadPhase() const;
486 void OnBodyParseEnd();
487 void ChangeStateToDone(bool aWasSync
);
488 void ChangeStateToDoneInternal();
490 void StartProgressEventTimer();
491 void StopProgressEventTimer();
493 void MaybeCreateBlobStorage();
495 nsresult
OnRedirectVerifyCallback(nsresult result
, bool stripAuth
= false);
497 nsIEventTarget
* GetTimerEventTarget();
499 nsresult
DispatchToMainThread(already_AddRefed
<nsIRunnable
> aRunnable
);
501 void DispatchOrStoreEvent(DOMEventTargetHelper
* aTarget
, Event
* aEvent
);
503 already_AddRefed
<nsXMLHttpRequestXPCOMifier
> EnsureXPCOMifier();
505 void SuspendEventDispatching();
506 void ResumeEventDispatching();
508 void AbortInternal(ErrorResult
& aRv
);
510 Maybe
<nsBaseChannel::ContentRange
> GetRequestedContentRange() const;
511 void GetContentRangeHeader(nsACString
&) const;
513 struct PendingEvent
{
514 RefPtr
<DOMEventTargetHelper
> mTarget
;
515 RefPtr
<Event
> mEvent
;
518 nsTArray
<PendingEvent
> mPendingEvents
;
520 nsCOMPtr
<nsISupports
> mContext
;
521 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
522 nsCOMPtr
<nsIChannel
> mChannel
;
523 nsCString mRequestMethod
;
524 nsCOMPtr
<nsIURI
> mRequestURL
;
525 RefPtr
<Document
> mResponseXML
;
527 nsCOMPtr
<nsIStreamListener
> mXMLParserStreamListener
;
529 nsCOMPtr
<nsICookieJarSettings
> mCookieJarSettings
;
531 RefPtr
<PerformanceStorage
> mPerformanceStorage
;
532 nsCOMPtr
<nsICSPEventListener
> mCSPEventListener
;
534 // used to implement getAllResponseHeaders()
535 class nsHeaderVisitor
: public nsIHttpHeaderVisitor
{
536 struct HeaderEntry final
{
540 HeaderEntry(const nsACString
& aName
, const nsACString
& aValue
)
541 : mName(aName
), mValue(aValue
) {}
543 bool operator==(const HeaderEntry
& aOther
) const {
544 return mName
== aOther
.mName
;
547 bool operator<(const HeaderEntry
& aOther
) const {
548 uint32_t selfLen
= mName
.Length();
549 uint32_t otherLen
= aOther
.mName
.Length();
550 uint32_t min
= XPCOM_MIN(selfLen
, otherLen
);
551 for (uint32_t i
= 0; i
< min
; ++i
) {
552 unsigned char self
= mName
[i
];
553 unsigned char other
= aOther
.mName
[i
];
554 MOZ_ASSERT(!(self
>= 'A' && self
<= 'Z'));
555 MOZ_ASSERT(!(other
>= 'A' && other
<= 'Z'));
559 if (self
>= 'a' && self
<= 'z') {
562 if (other
>= 'a' && other
<= 'z') {
567 return selfLen
< otherLen
;
573 NS_DECL_NSIHTTPHEADERVISITOR
574 nsHeaderVisitor(const XMLHttpRequestMainThread
& aXMLHttpRequest
,
575 NotNull
<nsIHttpChannel
*> aHttpChannel
);
576 const nsACString
& Headers() {
577 for (uint32_t i
= 0; i
< mHeaderList
.Length(); i
++) {
578 HeaderEntry
& header
= mHeaderList
.ElementAt(i
);
580 mHeaders
.Append(header
.mName
);
581 mHeaders
.AppendLiteral(": ");
582 mHeaders
.Append(header
.mValue
);
583 mHeaders
.AppendLiteral("\r\n");
589 virtual ~nsHeaderVisitor();
591 nsTArray
<HeaderEntry
> mHeaderList
;
593 const XMLHttpRequestMainThread
& mXHR
;
594 NotNull
<nsCOMPtr
<nsIHttpChannel
>> mHttpChannel
;
597 // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
598 // BLOB responseTypes
599 nsCString mResponseBody
;
601 // The text version of our response body. This is incrementally decoded into
602 // as we receive network data. However for the DEFAULT responseType we
603 // lazily decode into this from mResponseBody only when .responseText is
605 // Only used for DEFAULT and TEXT responseTypes.
606 XMLHttpRequestString mResponseText
;
608 // For DEFAULT responseType we use this to keep track of how far we've
609 // lazily decoded from mResponseBody to mResponseText
610 uint32_t mResponseBodyDecodedPos
;
612 // Decoder used for decoding into mResponseText
613 // Only used for DEFAULT, TEXT and JSON responseTypes.
614 // In cases where we've only received half a surrogate, the decoder itself
615 // carries the state to remember this. Next time we receive more data we
616 // simply feed the new data into the decoder which will handle the second
617 // part of the surrogate.
618 mozilla::UniquePtr
<mozilla::Decoder
> mDecoder
;
620 void MatchCharsetAndDecoderToResponseDocument();
622 XMLHttpRequestResponseType mResponseType
;
624 RefPtr
<BlobImpl
> mResponseBlobImpl
;
626 // This is the cached blob-response, created only at the first GetResponse()
628 RefPtr
<Blob
> mResponseBlob
;
630 // We stream data to mBlobStorage when response type is "blob".
631 RefPtr
<MutableBlobStorage
> mBlobStorage
;
633 nsString mOverrideMimeType
;
636 * The notification callbacks the channel had when Send() was
637 * called. We want to forward things here as needed.
639 nsCOMPtr
<nsIInterfaceRequestor
> mNotificationCallbacks
;
641 * Sink interfaces that we implement that mNotificationCallbacks may
642 * want to also be notified for. These are inited lazily if we're
643 * asked for the relevant interface.
645 nsCOMPtr
<nsIChannelEventSink
> mChannelEventSink
;
646 nsCOMPtr
<nsIProgressEventSink
> mProgressEventSink
;
648 nsCOMPtr
<nsIURI
> mBaseURI
;
649 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
651 Maybe
<ClientInfo
> mClientInfo
;
652 Maybe
<ServiceWorkerDescriptor
> mController
;
656 // If true, this object is used by the worker's XMLHttpRequest.
659 bool mFlagSynchronous
;
662 bool mFlagSyncLooping
;
663 bool mFlagBackgroundRequest
;
664 bool mFlagHadUploadListenersOnSend
;
665 bool mFlagACwithCredentials
;
669 // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
670 // finishes downloading (or an error/abort has occurred during either phase).
671 // Used to guard against the user trying to alter headers/etc when it's too
672 // late, and ensure the XHR only handles one in-flight request at once.
675 RefPtr
<XMLHttpRequestUpload
> mUpload
;
676 int64_t mUploadTransferred
;
677 int64_t mUploadTotal
;
678 bool mUploadComplete
;
679 bool mProgressSinceLastProgressEvent
;
682 PRTime mRequestSentTime
;
683 uint32_t mTimeoutMilliseconds
;
684 nsCOMPtr
<nsITimer
> mTimeoutTimer
;
685 void StartTimeoutTimer();
686 void HandleTimeoutCallback();
687 void CancelTimeoutTimer();
689 nsCOMPtr
<nsIRunnable
> mResumeTimeoutRunnable
;
691 nsCOMPtr
<nsITimer
> mSyncTimeoutTimer
;
693 enum SyncTimeoutType
{ eErrorOrExpired
, eTimerStarted
, eNoTimerNeeded
};
695 SyncTimeoutType
MaybeStartSyncTimeoutTimer();
696 void HandleSyncTimeoutTimer();
697 void CancelSyncTimeoutTimer();
699 ErrorType mErrorLoad
;
700 nsresult mErrorLoadDetail
;
701 bool mErrorParsingXML
;
702 bool mWaitingForOnStopRequest
;
703 bool mProgressTimerIsActive
;
705 bool mWarnAboutSyncHtml
;
706 int64_t mLoadTotal
; // -1 if not known.
707 // Number of HTTP message body bytes received so far. This quantity is
708 // in the same units as Content-Length and mLoadTotal, and hence counts
709 // compressed bytes when the channel has gzip Content-Encoding. If the
710 // channel does not have Content-Encoding, this will be the same as
711 // mDataReceived except between the OnProgress that changes mLoadTransferred
712 // and the corresponding OnDataAvailable (which changes mDataReceived).
713 // Ordering of OnProgress and OnDataAvailable is undefined.
714 int64_t mLoadTransferred
;
715 nsCOMPtr
<nsITimer
> mProgressNotifier
;
716 void HandleProgressTimerCallback();
722 * Close the XMLHttpRequest's channels.
724 void CloseRequest(nsresult detail
);
726 void TerminateOngoingFetch(nsresult detail
);
729 * Close the XMLHttpRequest's channels and dispatch appropriate progress
732 * @param aType The progress event type.
734 void CloseRequestWithError(const ErrorProgressEventType
& aType
);
736 nsCOMPtr
<nsIAsyncVerifyRedirectCallback
> mRedirectCallback
;
737 nsCOMPtr
<nsIChannel
> mNewRedirectChannel
;
739 JS::Heap
<JS::Value
> mResultJSON
;
741 RefPtr
<ArrayBufferBuilder
> mArrayBufferBuilder
;
742 JS::Heap
<JSObject
*> mResultArrayBuffer
;
743 bool mIsMappedArrayBuffer
;
745 void ResetResponse();
747 bool ShouldBlockAuthPrompt();
749 RequestHeaders mAuthorRequestHeaders
;
751 // Helper object to manage our XPCOM scriptability bits
752 nsXMLHttpRequestXPCOMifier
* mXPCOMifier
;
754 // When this is set to true, the event dispatching is suspended. This is
755 // useful to change the correct state when XHR is working sync.
756 bool mEventDispatchingSuspended
;
758 // True iff mDecoder has processed the end of the stream.
759 // Used in lazy decoding to distinguish between having
760 // processed all the bytes but not the EOF and having
761 // processed all the bytes and the EOF.
764 // This flag will be set in `Send()` when we successfully reuse a "fetch"
765 // preload to satisfy this XHR.
766 bool mFromPreload
= false;
768 // Our parse-end listener, if we are parsing.
769 RefPtr
<nsXHRParseEndListener
> mParseEndListener
;
771 XMLHttpRequestDoneNotifier
* mDelayedDoneNotifier
;
772 void DisconnectDoneNotifier();
774 // Any stack information for the point the XHR was opened. This is deleted
775 // after the XHR is opened, to avoid retaining references to the worker.
776 UniquePtr
<SerializedStackHolder
> mOriginStack
;
778 static bool sDontWarnAboutSyncXHR
;
781 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
{
783 AutoDontWarnAboutSyncXHR()
784 : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
785 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
788 ~AutoDontWarnAboutSyncXHR() {
789 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal
);
796 // A shim class designed to expose the non-DOM interfaces of
797 // XMLHttpRequest via XPCOM stuff.
798 class nsXMLHttpRequestXPCOMifier final
: public nsIStreamListener
,
799 public nsIChannelEventSink
,
800 public nsIAsyncVerifyRedirectCallback
,
801 public nsIProgressEventSink
,
802 public nsIInterfaceRequestor
,
803 public nsITimerCallback
,
805 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
806 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier
,
809 explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread
* aXHR
)
813 ~nsXMLHttpRequestXPCOMifier() {
815 mXHR
->mXPCOMifier
= nullptr;
820 NS_FORWARD_NSISTREAMLISTENER(mXHR
->)
821 NS_FORWARD_NSIREQUESTOBSERVER(mXHR
->)
822 NS_FORWARD_NSICHANNELEVENTSINK(mXHR
->)
823 NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR
->)
824 NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR
->)
825 NS_FORWARD_NSITIMERCALLBACK(mXHR
->)
826 NS_FORWARD_NSINAMED(mXHR
->)
828 NS_DECL_NSIINTERFACEREQUESTOR
831 RefPtr
<XMLHttpRequestMainThread
> mXHR
;
834 class XMLHttpRequestDoneNotifier
: public Runnable
{
836 explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread
* aXHR
)
837 : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR
) {}
839 NS_IMETHOD
Run() override
{
841 RefPtr
<XMLHttpRequestMainThread
> xhr
= mXHR
;
842 // ChangeStateToDoneInternal ends up calling Disconnect();
843 xhr
->ChangeStateToDoneInternal();
849 void Disconnect() { mXHR
= nullptr; }
852 RefPtr
<XMLHttpRequestMainThread
> mXHR
;
855 class nsXHRParseEndListener
: public nsIDOMEventListener
{
858 NS_IMETHOD
HandleEvent(Event
* event
) override
{
860 mXHR
->OnBodyParseEnd();
866 explicit nsXHRParseEndListener(XMLHttpRequestMainThread
* aXHR
) : mXHR(aXHR
) {}
868 void SetIsStale() { mXHR
= nullptr; }
871 virtual ~nsXHRParseEndListener() = default;
873 XMLHttpRequestMainThread
* mXHR
;
877 } // namespace mozilla
879 #endif // mozilla_dom_XMLHttpRequestMainThread_h