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"
53 /* Xlib headers insist on this for some reason... Nuke it because
54 it'll override our member name */
55 typedef Status __StatusTmp
;
57 typedef __StatusTmp Status
;
65 class ProfileChunkedBuffer
;
74 class XMLHttpRequestUpload
;
75 class SerializedStackHolder
;
76 struct OriginAttributesDictionary
;
78 // A helper for building up an ArrayBuffer object's data
79 // before creating the ArrayBuffer itself. Will do doubling
80 // based reallocation, up to an optional maximum growth given.
82 // When all the data has been appended, call GetArrayBuffer,
83 // passing in the JSContext* for which the ArrayBuffer object
84 // is to be created. This also implicitly resets the builder.
85 class ArrayBufferBuilder
{
87 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayBufferBuilder
);
91 // Will truncate if aNewCap is < Length().
92 bool SetCapacity(uint32_t aNewCap
);
94 // Append aDataLen bytes from data to the current buffer. If we
95 // need to grow the buffer, grow by doubling the size up to a
96 // maximum of aMaxGrowth (if given). If aDataLen is greater than
97 // what the new capacity would end up as, then grow by aDataLen.
99 // The data parameter must not overlap with anything beyond the
100 // builder's current valid contents [0..length)
101 bool Append(const uint8_t* aNewData
, uint32_t aDataLen
,
102 uint32_t aMaxGrowth
= 0);
107 JSObject
* TakeArrayBuffer(JSContext
* aCx
);
109 // Memory mapping to starting position of file(aFile) in the zip
110 // package(aJarFile).
112 // The file in the zip package has to be uncompressed and the starting
113 // position of the file must be aligned according to array buffer settings
115 nsresult
MapToFileInPackage(const nsCString
& aFile
, nsIFile
* aJarFile
);
118 ~ArrayBufferBuilder();
120 ArrayBufferBuilder(const ArrayBufferBuilder
&) = delete;
121 ArrayBufferBuilder
& operator=(const ArrayBufferBuilder
&) = delete;
122 ArrayBufferBuilder
& operator=(const ArrayBufferBuilder
&&) = delete;
124 bool SetCapacityInternal(uint32_t aNewCap
, const MutexAutoLock
& aProofOfLock
)
125 MOZ_REQUIRES(mMutex
);
127 static bool AreOverlappingRegions(const uint8_t* aStart1
, uint32_t aLength1
,
128 const uint8_t* aStart2
, uint32_t aLength2
);
132 // All of these are protected by mMutex.
133 uint8_t* mDataPtr
MOZ_GUARDED_BY(mMutex
);
134 uint32_t mCapacity
MOZ_GUARDED_BY(mMutex
);
135 uint32_t mLength
MOZ_GUARDED_BY(mMutex
);
136 void* mMapPtr
MOZ_GUARDED_BY(mMutex
);
138 // This is used in assertions only.
142 class nsXMLHttpRequestXPCOMifier
;
144 class RequestHeaders
{
145 struct RequestHeader
{
149 nsTArray
<RequestHeader
> mHeaders
;
150 RequestHeader
* Find(const nsACString
& aName
);
153 class CharsetIterator
{
155 int32_t mCurPos
, mCurLen
, mCutoff
;
159 explicit CharsetIterator(nsACString
& aSource
);
160 bool Equals(const nsACString
& aOther
,
161 const nsCStringComparator
& aCmp
) const;
162 void Replace(const nsACString
& aReplacement
);
166 bool IsEmpty() const;
167 bool Has(const char* aName
);
168 bool Has(const nsACString
& aName
);
169 void Get(const char* aName
, nsACString
& aValue
);
170 void Get(const nsACString
& aName
, nsACString
& aValue
);
171 void Set(const char* aName
, const nsACString
& aValue
);
172 void Set(const nsACString
& aName
, const nsACString
& aValue
);
173 void MergeOrSet(const char* aName
, const nsACString
& aValue
);
174 void MergeOrSet(const nsACString
& aName
, const nsACString
& aValue
);
176 void ApplyToChannel(nsIHttpChannel
* aChannel
, bool aStripRequestBodyHeader
,
177 bool aStripAuth
) const;
178 void GetCORSUnsafeHeaders(nsTArray
<nsCString
>& aArray
) const;
181 class nsXHRParseEndListener
;
182 class XMLHttpRequestDoneNotifier
;
184 // Make sure that any non-DOM interfaces added here are also added to
185 // nsXMLHttpRequestXPCOMifier.
186 class XMLHttpRequestMainThread final
: public XMLHttpRequest
,
187 public nsIStreamListener
,
188 public nsIChannelEventSink
,
189 public nsIProgressEventSink
,
190 public nsIInterfaceRequestor
,
191 public nsITimerCallback
,
192 public nsISizeOfEventTarget
,
194 public MutableBlobStorageCallback
{
195 friend class nsXHRParseEndListener
;
196 friend class nsXMLHttpRequestXPCOMifier
;
197 friend class XMLHttpRequestDoneNotifier
;
200 // Make sure that any additions done to ErrorType enum are also mirrored in
201 // XHR_ERROR_TYPE enum of TelemetrySend.sys.mjs.
202 enum class ErrorType
: uint16_t {
212 explicit XMLHttpRequestMainThread(nsIGlobalObject
* aGlobalObject
);
214 void Construct(nsIPrincipal
* aPrincipal
,
215 nsICookieJarSettings
* aCookieJarSettings
, bool aForWorker
,
216 nsIURI
* aBaseURI
= nullptr, nsILoadGroup
* aLoadGroup
= nullptr,
217 PerformanceStorage
* aPerformanceStorage
= nullptr,
218 nsICSPEventListener
* aCSPEventListener
= nullptr);
220 void InitParameters(bool aAnon
, bool aSystem
);
222 void SetParameters(bool aAnon
, bool aSystem
) {
223 mIsAnon
= aAnon
|| aSystem
;
227 void SetClientInfoAndController(
228 const ClientInfo
& aClientInfo
,
229 const Maybe
<ServiceWorkerDescriptor
>& aController
);
231 NS_DECL_ISUPPORTS_INHERITED
234 NS_DECL_NSISTREAMLISTENER
236 // nsIRequestObserver
237 NS_DECL_NSIREQUESTOBSERVER
239 // nsIChannelEventSink
240 NS_DECL_NSICHANNELEVENTSINK
242 // nsIProgressEventSink
243 NS_DECL_NSIPROGRESSEVENTSINK
245 // nsIInterfaceRequestor
246 NS_DECL_NSIINTERFACEREQUESTOR
249 NS_DECL_NSITIMERCALLBACK
254 // nsISizeOfEventTarget
255 virtual size_t SizeOfEventTargetIncludingThis(
256 MallocSizeOf aMallocSizeOf
) const override
;
259 virtual uint16_t ReadyState() const override
;
262 nsresult
CreateChannel();
263 nsresult
InitiateFetch(already_AddRefed
<nsIInputStream
> aUploadStream
,
264 int64_t aUploadLength
, nsACString
& aUploadContentType
);
266 virtual void Open(const nsACString
& aMethod
, const nsAString
& aUrl
,
267 ErrorResult
& aRv
) override
;
269 virtual void Open(const nsACString
& aMethod
, const nsAString
& aUrl
,
270 bool aAsync
, const nsAString
& aUsername
,
271 const nsAString
& aPassword
, ErrorResult
& aRv
) override
;
273 void Open(const nsACString
& aMethod
, const nsACString
& aUrl
, bool aAsync
,
274 const nsAString
& aUsername
, const nsAString
& aPassword
,
277 virtual void SetRequestHeader(const nsACString
& aName
,
278 const nsACString
& aValue
,
279 ErrorResult
& aRv
) override
;
281 virtual uint32_t Timeout() const override
{ return mTimeoutMilliseconds
; }
283 virtual void SetTimeout(uint32_t aTimeout
, ErrorResult
& aRv
) override
;
285 virtual bool WithCredentials() const override
;
287 virtual void SetWithCredentials(bool aWithCredentials
,
288 ErrorResult
& aRv
) override
;
290 virtual XMLHttpRequestUpload
* GetUpload(ErrorResult
& aRv
) override
;
293 virtual ~XMLHttpRequestMainThread();
295 nsresult
MaybeSilentSendFailure(nsresult aRv
);
296 void SendInternal(const BodyExtractorBase
* aBody
,
297 bool aBodyIsDocumentOrString
, ErrorResult
& aRv
);
299 bool IsCrossSiteCORSRequest() const;
300 bool IsDeniedCrossSiteCORSRequest();
302 void ResumeTimeout();
304 void MaybeLowerChannelPriority();
307 bool CanSend(ErrorResult
& aRv
);
311 DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString
>&
313 ErrorResult
& aRv
) override
;
315 virtual void SendInputStream(nsIInputStream
* aInputStream
,
316 ErrorResult
& aRv
) override
{
320 BodyExtractor
<nsIInputStream
> body(aInputStream
);
321 SendInternal(&body
, false, aRv
);
324 void RequestErrorSteps(const ProgressEventType aEventType
,
325 const nsresult aOptionalException
, ErrorResult
& aRv
);
328 IgnoredErrorResult rv
;
330 MOZ_ASSERT(!rv
.Failed() || rv
.ErrorCodeIs(NS_ERROR_DOM_ABORT_ERR
));
333 virtual void Abort(ErrorResult
& aRv
) override
;
336 virtual void GetResponseURL(nsAString
& aUrl
) override
;
338 virtual uint32_t GetStatus(ErrorResult
& aRv
) override
;
340 virtual void GetStatusText(nsACString
& aStatusText
,
341 ErrorResult
& aRv
) override
;
343 virtual void GetResponseHeader(const nsACString
& aHeader
, nsACString
& aResult
,
344 ErrorResult
& aRv
) override
;
346 void GetResponseHeader(const nsAString
& aHeader
, nsAString
& aResult
,
348 nsAutoCString result
;
349 GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader
), result
, aRv
);
350 if (result
.IsVoid()) {
351 aResult
.SetIsVoid(true);
353 // The result value should be inflated:
354 CopyASCIItoUTF16(result
, aResult
);
358 virtual void GetAllResponseHeaders(nsACString
& aResponseHeaders
,
359 ErrorResult
& aRv
) override
;
361 bool IsSafeHeader(const nsACString
& aHeaderName
,
362 NotNull
<nsIHttpChannel
*> aHttpChannel
) const;
364 virtual void OverrideMimeType(const nsAString
& aMimeType
,
365 ErrorResult
& aRv
) override
;
367 virtual XMLHttpRequestResponseType
ResponseType() const override
{
368 return XMLHttpRequestResponseType(mResponseType
);
371 virtual void SetResponseType(XMLHttpRequestResponseType aType
,
372 ErrorResult
& aRv
) override
;
374 void SetResponseTypeRaw(XMLHttpRequestResponseType aType
) {
375 mResponseType
= aType
;
378 virtual void GetResponse(JSContext
* aCx
,
379 JS::MutableHandle
<JS::Value
> aResponse
,
380 ErrorResult
& aRv
) override
;
382 virtual void GetResponseText(DOMString
& aResponseText
,
383 ErrorResult
& aRv
) override
;
385 // GetResponse* for workers:
386 already_AddRefed
<BlobImpl
> GetResponseBlobImpl();
387 already_AddRefed
<ArrayBufferBuilder
> GetResponseArrayBufferBuilder();
388 nsresult
GetResponseTextForJSON(nsAString
& aString
);
389 void GetResponseText(XMLHttpRequestStringSnapshot
& aSnapshot
,
392 virtual Document
* GetResponseXML(ErrorResult
& aRv
) override
;
394 virtual bool MozBackgroundRequest() const override
;
396 void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest
,
399 virtual void SetMozBackgroundRequest(bool aMozBackgroundRequest
,
400 ErrorResult
& aRv
) override
;
402 void SetOriginStack(UniquePtr
<SerializedStackHolder
> aOriginStack
);
404 void SetSource(UniquePtr
<ProfileChunkedBuffer
> aSource
);
406 nsresult
ErrorDetail() const { return mErrorLoadDetail
; }
408 virtual uint16_t ErrorCode() const override
{
409 return static_cast<uint16_t>(mErrorLoad
);
412 virtual bool MozAnon() const override
;
414 virtual bool MozSystem() const override
;
416 virtual nsIChannel
* GetChannel() const override
{ return mChannel
; }
418 // We need a GetInterface callable from JS for chrome JS
419 virtual void GetInterface(JSContext
* aCx
, JS::Handle
<JS::Value
> aIID
,
420 JS::MutableHandle
<JS::Value
> aRetval
,
421 ErrorResult
& aRv
) override
;
423 // This fires a trusted readystatechange event, which is not cancelable and
425 nsresult
FireReadystatechangeEvent();
426 void DispatchProgressEvent(DOMEventTargetHelper
* aTarget
,
427 const ProgressEventType
& aType
, int64_t aLoaded
,
430 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
431 XMLHttpRequestMainThread
, XMLHttpRequest
)
432 virtual bool IsCertainlyAliveForCC() const override
;
434 bool AllowUploadProgress();
436 virtual void DisconnectFromOwner() override
;
438 static void SetDontWarnAboutSyncXHR(bool aVal
) {
439 sDontWarnAboutSyncXHR
= aVal
;
441 static bool DontWarnAboutSyncXHR() { return sDontWarnAboutSyncXHR
; }
443 virtual void SetOriginAttributes(
444 const mozilla::dom::OriginAttributesDictionary
& aAttrs
) override
;
446 void BlobStoreCompleted(MutableBlobStorage
* aBlobStorage
, BlobImpl
* aBlobImpl
,
447 nsresult aResult
) override
;
449 void LocalFileToBlobCompleted(BlobImpl
* aBlobImpl
);
452 // For logging when there's trouble
453 RefPtr
<ThreadSafeWorkerRef
> mTSWorkerRef
MOZ_GUARDED_BY(mTSWorkerRefMutex
);
454 Mutex mTSWorkerRefMutex
;
458 nsresult
DetectCharset();
459 nsresult
AppendToResponseText(Span
<const uint8_t> aBuffer
,
461 static nsresult
StreamReaderFunc(nsIInputStream
* in
, void* closure
,
462 const char* fromRawSegment
,
463 uint32_t toOffset
, uint32_t count
,
464 uint32_t* writeCount
);
465 nsresult
CreateResponseParsedJSON(JSContext
* aCx
);
466 // Change the state of the object with this. The broadcast argument
467 // determines if the onreadystatechange listener should be called.
468 nsresult
ChangeState(uint16_t aState
, bool aBroadcast
= true);
469 already_AddRefed
<nsILoadGroup
> GetLoadGroup() const;
471 // Finds a preload for this XHR. If it is found it's removed from the preload
472 // table of the document and marked as used. The called doesn't need to do
473 // any more comparative checks.
474 already_AddRefed
<PreloaderBase
> FindPreload();
475 // If no or unknown mime type is set on the channel this method ensures it's
476 // set to "text/xml".
477 void EnsureChannelContentType();
479 // Gets the value of the final content-type header from the channel.
480 bool GetContentType(nsACString
& aValue
) const;
482 already_AddRefed
<nsIHttpChannel
> GetCurrentHttpChannel();
483 already_AddRefed
<nsIJARChannel
> GetCurrentJARChannel();
485 void TruncateResponseText();
487 bool IsSystemXHR() const;
488 bool InUploadPhase() const;
490 void OnBodyParseEnd();
491 void ChangeStateToDone(bool aWasSync
);
492 void ChangeStateToDoneInternal();
494 void StartProgressEventTimer();
495 void StopProgressEventTimer();
497 void MaybeCreateBlobStorage();
499 nsresult
OnRedirectVerifyCallback(nsresult result
, bool stripAuth
= false);
501 nsIEventTarget
* GetTimerEventTarget();
503 nsresult
DispatchToMainThread(already_AddRefed
<nsIRunnable
> aRunnable
);
505 void DispatchOrStoreEvent(DOMEventTargetHelper
* aTarget
, Event
* aEvent
);
507 already_AddRefed
<nsXMLHttpRequestXPCOMifier
> EnsureXPCOMifier();
509 void SuspendEventDispatching();
510 void ResumeEventDispatching();
512 void AbortInternal(ErrorResult
& aRv
);
514 bool BadContentRangeRequested();
515 RefPtr
<mozilla::net::ContentRange
> GetRequestedContentRange() const;
516 void GetContentRangeHeader(nsACString
&) const;
518 struct PendingEvent
{
519 RefPtr
<DOMEventTargetHelper
> mTarget
;
520 RefPtr
<Event
> mEvent
;
523 nsTArray
<PendingEvent
> mPendingEvents
;
525 nsCOMPtr
<nsISupports
> mContext
;
526 nsCOMPtr
<nsIPrincipal
> mPrincipal
;
527 nsCOMPtr
<nsIChannel
> mChannel
;
528 nsCString mRequestMethod
;
529 nsCOMPtr
<nsIURI
> mRequestURL
;
530 RefPtr
<Document
> mResponseXML
;
532 nsCOMPtr
<nsIStreamListener
> mXMLParserStreamListener
;
534 nsCOMPtr
<nsICookieJarSettings
> mCookieJarSettings
;
536 RefPtr
<PerformanceStorage
> mPerformanceStorage
;
537 nsCOMPtr
<nsICSPEventListener
> mCSPEventListener
;
539 // used to implement getAllResponseHeaders()
540 class nsHeaderVisitor
: public nsIHttpHeaderVisitor
{
541 struct HeaderEntry final
{
545 HeaderEntry(const nsACString
& aName
, const nsACString
& aValue
)
546 : mName(aName
), mValue(aValue
) {}
548 bool operator==(const HeaderEntry
& aOther
) const {
549 return mName
== aOther
.mName
;
552 bool operator<(const HeaderEntry
& aOther
) const {
553 uint32_t selfLen
= mName
.Length();
554 uint32_t otherLen
= aOther
.mName
.Length();
555 uint32_t min
= XPCOM_MIN(selfLen
, otherLen
);
556 for (uint32_t i
= 0; i
< min
; ++i
) {
557 unsigned char self
= mName
[i
];
558 unsigned char other
= aOther
.mName
[i
];
559 MOZ_ASSERT(!(self
>= 'A' && self
<= 'Z'));
560 MOZ_ASSERT(!(other
>= 'A' && other
<= 'Z'));
564 if (self
>= 'a' && self
<= 'z') {
567 if (other
>= 'a' && other
<= 'z') {
572 return selfLen
< otherLen
;
578 NS_DECL_NSIHTTPHEADERVISITOR
579 nsHeaderVisitor(const XMLHttpRequestMainThread
& aXMLHttpRequest
,
580 NotNull
<nsIHttpChannel
*> aHttpChannel
);
581 const nsACString
& Headers() {
582 for (uint32_t i
= 0; i
< mHeaderList
.Length(); i
++) {
583 HeaderEntry
& header
= mHeaderList
.ElementAt(i
);
585 mHeaders
.Append(header
.mName
);
586 mHeaders
.AppendLiteral(": ");
587 mHeaders
.Append(header
.mValue
);
588 mHeaders
.AppendLiteral("\r\n");
594 virtual ~nsHeaderVisitor();
596 nsTArray
<HeaderEntry
> mHeaderList
;
598 const XMLHttpRequestMainThread
& mXHR
;
599 NotNull
<nsCOMPtr
<nsIHttpChannel
>> mHttpChannel
;
602 // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
603 // BLOB responseTypes
604 nsCString mResponseBody
;
606 // The text version of our response body. This is incrementally decoded into
607 // as we receive network data. However for the DEFAULT responseType we
608 // lazily decode into this from mResponseBody only when .responseText is
610 // Only used for DEFAULT and TEXT responseTypes.
611 XMLHttpRequestString mResponseText
;
613 // For DEFAULT responseType we use this to keep track of how far we've
614 // lazily decoded from mResponseBody to mResponseText
615 uint32_t mResponseBodyDecodedPos
;
617 // Decoder used for decoding into mResponseText
618 // Only used for DEFAULT, TEXT and JSON responseTypes.
619 // In cases where we've only received half a surrogate, the decoder itself
620 // carries the state to remember this. Next time we receive more data we
621 // simply feed the new data into the decoder which will handle the second
622 // part of the surrogate.
623 mozilla::UniquePtr
<mozilla::Decoder
> mDecoder
;
625 void MatchCharsetAndDecoderToResponseDocument();
627 XMLHttpRequestResponseType mResponseType
;
629 RefPtr
<BlobImpl
> mResponseBlobImpl
;
631 // This is the cached blob-response, created only at the first GetResponse()
633 RefPtr
<Blob
> mResponseBlob
;
635 // We stream data to mBlobStorage when response type is "blob".
636 RefPtr
<MutableBlobStorage
> mBlobStorage
;
638 nsString mOverrideMimeType
;
641 * The notification callbacks the channel had when Send() was
642 * called. We want to forward things here as needed.
644 nsCOMPtr
<nsIInterfaceRequestor
> mNotificationCallbacks
;
646 * Sink interfaces that we implement that mNotificationCallbacks may
647 * want to also be notified for. These are inited lazily if we're
648 * asked for the relevant interface.
650 nsCOMPtr
<nsIChannelEventSink
> mChannelEventSink
;
651 nsCOMPtr
<nsIProgressEventSink
> mProgressEventSink
;
653 nsCOMPtr
<nsIURI
> mBaseURI
;
654 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
656 Maybe
<ClientInfo
> mClientInfo
;
657 Maybe
<ServiceWorkerDescriptor
> mController
;
661 // If true, this object is used by the worker's XMLHttpRequest.
664 bool mFlagSynchronous
;
667 bool mFlagSyncLooping
;
668 bool mFlagBackgroundRequest
;
669 bool mFlagHadUploadListenersOnSend
;
670 bool mFlagACwithCredentials
;
674 // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
675 // finishes downloading (or an error/abort has occurred during either phase).
676 // Used to guard against the user trying to alter headers/etc when it's too
677 // late, and ensure the XHR only handles one in-flight request at once.
680 RefPtr
<XMLHttpRequestUpload
> mUpload
;
681 int64_t mUploadTransferred
;
682 int64_t mUploadTotal
;
683 bool mUploadComplete
;
684 bool mProgressSinceLastProgressEvent
;
687 PRTime mRequestSentTime
;
688 uint32_t mTimeoutMilliseconds
;
689 nsCOMPtr
<nsITimer
> mTimeoutTimer
;
690 void StartTimeoutTimer();
691 void HandleTimeoutCallback();
692 void CancelTimeoutTimer();
694 nsCOMPtr
<nsIRunnable
> mResumeTimeoutRunnable
;
696 nsCOMPtr
<nsITimer
> mSyncTimeoutTimer
;
698 enum SyncTimeoutType
{ eErrorOrExpired
, eTimerStarted
, eNoTimerNeeded
};
700 SyncTimeoutType
MaybeStartSyncTimeoutTimer();
701 void HandleSyncTimeoutTimer();
702 void CancelSyncTimeoutTimer();
704 ErrorType mErrorLoad
;
705 nsresult mErrorLoadDetail
;
706 bool mErrorParsingXML
;
707 bool mWaitingForOnStopRequest
;
708 bool mProgressTimerIsActive
;
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();
727 * Close the XMLHttpRequest's channels.
729 void CloseRequest(nsresult detail
);
731 void TerminateOngoingFetch(nsresult detail
);
734 * Close the XMLHttpRequest's channels and dispatch appropriate progress
737 * @param aType The progress event type.
739 void CloseRequestWithError(const ErrorProgressEventType
& aType
);
741 nsCOMPtr
<nsIAsyncVerifyRedirectCallback
> mRedirectCallback
;
742 nsCOMPtr
<nsIChannel
> mNewRedirectChannel
;
744 JS::Heap
<JS::Value
> mResultJSON
;
746 RefPtr
<ArrayBufferBuilder
> mArrayBufferBuilder
;
747 JS::Heap
<JSObject
*> mResultArrayBuffer
;
748 bool mIsMappedArrayBuffer
;
750 void ResetResponse();
752 bool ShouldBlockAuthPrompt();
754 RequestHeaders mAuthorRequestHeaders
;
756 // Helper object to manage our XPCOM scriptability bits
757 nsXMLHttpRequestXPCOMifier
* mXPCOMifier
;
759 // When this is set to true, the event dispatching is suspended. This is
760 // useful to change the correct state when XHR is working sync.
761 bool mEventDispatchingSuspended
;
763 // True iff mDecoder has processed the end of the stream.
764 // Used in lazy decoding to distinguish between having
765 // processed all the bytes but not the EOF and having
766 // processed all the bytes and the EOF.
769 // This flag will be set in `Send()` when we successfully reuse a "fetch"
770 // preload to satisfy this XHR.
771 bool mFromPreload
= false;
773 // Our parse-end listener, if we are parsing.
774 RefPtr
<nsXHRParseEndListener
> mParseEndListener
;
776 XMLHttpRequestDoneNotifier
* mDelayedDoneNotifier
;
777 void DisconnectDoneNotifier();
779 // Any stack information for the point the XHR was opened. This is deleted
780 // after the XHR is opened, to avoid retaining references to the worker.
781 UniquePtr
<SerializedStackHolder
> mOriginStack
;
783 static bool sDontWarnAboutSyncXHR
;
786 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
{
788 AutoDontWarnAboutSyncXHR()
789 : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
790 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
793 ~AutoDontWarnAboutSyncXHR() {
794 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal
);
801 // A shim class designed to expose the non-DOM interfaces of
802 // XMLHttpRequest via XPCOM stuff.
803 class nsXMLHttpRequestXPCOMifier final
: public nsIStreamListener
,
804 public nsIChannelEventSink
,
805 public nsIAsyncVerifyRedirectCallback
,
806 public nsIProgressEventSink
,
807 public nsIInterfaceRequestor
,
808 public nsITimerCallback
,
810 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
811 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier
,
814 explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread
* aXHR
)
818 ~nsXMLHttpRequestXPCOMifier() {
820 mXHR
->mXPCOMifier
= nullptr;
825 NS_FORWARD_NSISTREAMLISTENER(mXHR
->)
826 NS_FORWARD_NSIREQUESTOBSERVER(mXHR
->)
827 NS_FORWARD_NSICHANNELEVENTSINK(mXHR
->)
828 NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR
->)
829 NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR
->)
830 NS_FORWARD_NSITIMERCALLBACK(mXHR
->)
831 NS_FORWARD_NSINAMED(mXHR
->)
833 NS_DECL_NSIINTERFACEREQUESTOR
836 RefPtr
<XMLHttpRequestMainThread
> mXHR
;
839 class XMLHttpRequestDoneNotifier
: public Runnable
{
841 explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread
* aXHR
)
842 : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR
) {}
844 NS_IMETHOD
Run() override
{
846 RefPtr
<XMLHttpRequestMainThread
> xhr
= mXHR
;
847 // ChangeStateToDoneInternal ends up calling Disconnect();
848 xhr
->ChangeStateToDoneInternal();
854 void Disconnect() { mXHR
= nullptr; }
857 RefPtr
<XMLHttpRequestMainThread
> mXHR
;
860 class nsXHRParseEndListener
: public nsIDOMEventListener
{
863 NS_IMETHOD
HandleEvent(Event
* event
) override
{
865 mXHR
->OnBodyParseEnd();
871 explicit nsXHRParseEndListener(XMLHttpRequestMainThread
* aXHR
) : mXHR(aXHR
) {}
873 void SetIsStale() { mXHR
= nullptr; }
876 virtual ~nsXHRParseEndListener() = default;
878 XMLHttpRequestMainThread
* mXHR
;
882 } // namespace mozilla
884 #endif // mozilla_dom_XMLHttpRequestMainThread_h