Bug 1828523 [wpt PR 39579] - Only restore dialog focus if focus is in the dialog...
[gecko.git] / dom / xhr / XMLHttpRequestMainThread.h
blobb248e0366401d748306e40f9d64f96670750210c
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
10 #include <bitset>
11 #include "nsISupportsUtils.h"
12 #include "nsIURI.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"
22 #include "nsTArray.h"
23 #include "nsITimer.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/XMLHttpRequest.h"
46 #include "mozilla/dom/XMLHttpRequestBinding.h"
47 #include "mozilla/dom/XMLHttpRequestEventTarget.h"
48 #include "mozilla/dom/XMLHttpRequestString.h"
49 #include "mozilla/Encoding.h"
51 #ifdef Status
52 /* Xlib headers insist on this for some reason... Nuke it because
53 it'll override our member name */
54 typedef Status __StatusTmp;
55 # undef Status
56 typedef __StatusTmp Status;
57 #endif
59 class nsIHttpChannel;
60 class nsIJARChannel;
61 class nsILoadGroup;
63 namespace mozilla {
64 class ProfileChunkedBuffer;
66 namespace dom {
68 class DOMString;
69 class XMLHttpRequestUpload;
70 class SerializedStackHolder;
71 struct OriginAttributesDictionary;
73 // A helper for building up an ArrayBuffer object's data
74 // before creating the ArrayBuffer itself. Will do doubling
75 // based reallocation, up to an optional maximum growth given.
77 // When all the data has been appended, call GetArrayBuffer,
78 // passing in the JSContext* for which the ArrayBuffer object
79 // is to be created. This also implicitly resets the builder.
80 class ArrayBufferBuilder {
81 public:
82 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayBufferBuilder);
84 ArrayBufferBuilder();
86 // Will truncate if aNewCap is < Length().
87 bool SetCapacity(uint32_t aNewCap);
89 // Append aDataLen bytes from data to the current buffer. If we
90 // need to grow the buffer, grow by doubling the size up to a
91 // maximum of aMaxGrowth (if given). If aDataLen is greater than
92 // what the new capacity would end up as, then grow by aDataLen.
94 // The data parameter must not overlap with anything beyond the
95 // builder's current valid contents [0..length)
96 bool Append(const uint8_t* aNewData, uint32_t aDataLen,
97 uint32_t aMaxGrowth = 0);
99 uint32_t Length();
100 uint32_t Capacity();
102 JSObject* TakeArrayBuffer(JSContext* aCx);
104 // Memory mapping to starting position of file(aFile) in the zip
105 // package(aJarFile).
107 // The file in the zip package has to be uncompressed and the starting
108 // position of the file must be aligned according to array buffer settings
109 // in JS engine.
110 nsresult MapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
112 private:
113 ~ArrayBufferBuilder();
115 ArrayBufferBuilder(const ArrayBufferBuilder&) = delete;
116 ArrayBufferBuilder& operator=(const ArrayBufferBuilder&) = delete;
117 ArrayBufferBuilder& operator=(const ArrayBufferBuilder&&) = delete;
119 bool SetCapacityInternal(uint32_t aNewCap, const MutexAutoLock& aProofOfLock)
120 MOZ_REQUIRES(mMutex);
122 static bool AreOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
123 const uint8_t* aStart2, uint32_t aLength2);
125 Mutex mMutex;
127 // All of these are protected by mMutex.
128 uint8_t* mDataPtr MOZ_GUARDED_BY(mMutex);
129 uint32_t mCapacity MOZ_GUARDED_BY(mMutex);
130 uint32_t mLength MOZ_GUARDED_BY(mMutex);
131 void* mMapPtr MOZ_GUARDED_BY(mMutex);
133 // This is used in assertions only.
134 bool mNeutered;
137 class nsXMLHttpRequestXPCOMifier;
139 class RequestHeaders {
140 struct RequestHeader {
141 nsCString mName;
142 nsCString mValue;
144 nsTArray<RequestHeader> mHeaders;
145 RequestHeader* Find(const nsACString& aName);
147 public:
148 class CharsetIterator {
149 bool mValid;
150 int32_t mCurPos, mCurLen, mCutoff;
151 nsACString& mSource;
153 public:
154 explicit CharsetIterator(nsACString& aSource);
155 bool Equals(const nsACString& aOther,
156 const nsCStringComparator& aCmp) const;
157 void Replace(const nsACString& aReplacement);
158 bool Next();
161 bool IsEmpty() const;
162 bool Has(const char* aName);
163 bool Has(const nsACString& aName);
164 void Get(const char* aName, nsACString& aValue);
165 void Get(const nsACString& aName, nsACString& aValue);
166 void Set(const char* aName, const nsACString& aValue);
167 void Set(const nsACString& aName, const nsACString& aValue);
168 void MergeOrSet(const char* aName, const nsACString& aValue);
169 void MergeOrSet(const nsACString& aName, const nsACString& aValue);
170 void Clear();
171 void ApplyToChannel(nsIHttpChannel* aChannel, bool aStripRequestBodyHeader,
172 bool aStripAuth) const;
173 void GetCORSUnsafeHeaders(nsTArray<nsCString>& aArray) const;
176 class nsXHRParseEndListener;
177 class XMLHttpRequestDoneNotifier;
179 // Make sure that any non-DOM interfaces added here are also added to
180 // nsXMLHttpRequestXPCOMifier.
181 class XMLHttpRequestMainThread final : public XMLHttpRequest,
182 public nsIStreamListener,
183 public nsIChannelEventSink,
184 public nsIProgressEventSink,
185 public nsIInterfaceRequestor,
186 public nsITimerCallback,
187 public nsISizeOfEventTarget,
188 public nsINamed,
189 public MutableBlobStorageCallback {
190 friend class nsXHRParseEndListener;
191 friend class nsXMLHttpRequestXPCOMifier;
192 friend class XMLHttpRequestDoneNotifier;
194 public:
195 enum class ProgressEventType : uint8_t {
196 loadstart,
197 progress,
198 error,
199 abort,
200 timeout,
201 load,
202 loadend,
203 ENUM_MAX
206 // Make sure that any additions done to ErrorType enum are also mirrored in
207 // XHR_ERROR_TYPE enum of TelemetrySend.sys.mjs.
208 enum class ErrorType : uint16_t {
209 eOK,
210 eRequest,
211 eUnreachable,
212 eChannelOpen,
213 eRedirect,
214 eTerminated,
215 ENUM_MAX
218 explicit XMLHttpRequestMainThread(nsIGlobalObject* aGlobalObject);
220 void Construct(nsIPrincipal* aPrincipal,
221 nsICookieJarSettings* aCookieJarSettings, bool aForWorker,
222 nsIURI* aBaseURI = nullptr, nsILoadGroup* aLoadGroup = nullptr,
223 PerformanceStorage* aPerformanceStorage = nullptr,
224 nsICSPEventListener* aCSPEventListener = nullptr);
226 void InitParameters(bool aAnon, bool aSystem);
228 void SetParameters(bool aAnon, bool aSystem) {
229 mIsAnon = aAnon || aSystem;
230 mIsSystem = aSystem;
233 void SetClientInfoAndController(
234 const ClientInfo& aClientInfo,
235 const Maybe<ServiceWorkerDescriptor>& aController);
237 NS_DECL_ISUPPORTS_INHERITED
239 // nsIStreamListener
240 NS_DECL_NSISTREAMLISTENER
242 // nsIRequestObserver
243 NS_DECL_NSIREQUESTOBSERVER
245 // nsIChannelEventSink
246 NS_DECL_NSICHANNELEVENTSINK
248 // nsIProgressEventSink
249 NS_DECL_NSIPROGRESSEVENTSINK
251 // nsIInterfaceRequestor
252 NS_DECL_NSIINTERFACEREQUESTOR
254 // nsITimerCallback
255 NS_DECL_NSITIMERCALLBACK
257 // nsINamed
258 NS_DECL_NSINAMED
260 // nsISizeOfEventTarget
261 virtual size_t SizeOfEventTargetIncludingThis(
262 MallocSizeOf aMallocSizeOf) const override;
264 // states
265 virtual uint16_t ReadyState() const override;
267 // request
268 nsresult CreateChannel();
269 nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
270 int64_t aUploadLength, nsACString& aUploadContentType);
272 virtual void Open(const nsACString& aMethod, const nsAString& aUrl,
273 ErrorResult& aRv) override;
275 virtual void Open(const nsACString& aMethod, const nsAString& aUrl,
276 bool aAsync, const nsAString& aUsername,
277 const nsAString& aPassword, ErrorResult& aRv) override;
279 void Open(const nsACString& aMethod, const nsACString& aUrl, bool aAsync,
280 const nsAString& aUsername, const nsAString& aPassword,
281 ErrorResult& aRv);
283 virtual void SetRequestHeader(const nsACString& aName,
284 const nsACString& aValue,
285 ErrorResult& aRv) override;
287 virtual uint32_t Timeout() const override { return mTimeoutMilliseconds; }
289 virtual void SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
291 virtual bool WithCredentials() const override;
293 virtual void SetWithCredentials(bool aWithCredentials,
294 ErrorResult& aRv) override;
296 virtual XMLHttpRequestUpload* GetUpload(ErrorResult& aRv) override;
298 private:
299 virtual ~XMLHttpRequestMainThread();
301 nsresult MaybeSilentSendFailure(nsresult aRv);
302 void SendInternal(const BodyExtractorBase* aBody,
303 bool aBodyIsDocumentOrString, ErrorResult& aRv);
305 bool IsCrossSiteCORSRequest() const;
306 bool IsDeniedCrossSiteCORSRequest();
308 void ResumeTimeout();
310 void MaybeLowerChannelPriority();
312 public:
313 bool CanSend(ErrorResult& aRv);
315 virtual void Send(
316 const Nullable<
317 DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>&
318 aData,
319 ErrorResult& aRv) override;
321 virtual void SendInputStream(nsIInputStream* aInputStream,
322 ErrorResult& aRv) override {
323 if (!CanSend(aRv)) {
324 return;
326 BodyExtractor<nsIInputStream> body(aInputStream);
327 SendInternal(&body, false, aRv);
330 void RequestErrorSteps(const ProgressEventType aEventType,
331 const nsresult aOptionalException, ErrorResult& aRv);
333 void Abort() {
334 IgnoredErrorResult rv;
335 AbortInternal(rv);
336 MOZ_ASSERT(!rv.Failed());
339 virtual void Abort(ErrorResult& aRv) override;
341 // response
342 virtual void GetResponseURL(nsAString& aUrl) override;
344 virtual uint32_t GetStatus(ErrorResult& aRv) override;
346 virtual void GetStatusText(nsACString& aStatusText,
347 ErrorResult& aRv) override;
349 virtual void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
350 ErrorResult& aRv) override;
352 void GetResponseHeader(const nsAString& aHeader, nsAString& aResult,
353 ErrorResult& aRv) {
354 nsAutoCString result;
355 GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
356 if (result.IsVoid()) {
357 aResult.SetIsVoid(true);
358 } else {
359 // The result value should be inflated:
360 CopyASCIItoUTF16(result, aResult);
364 virtual void GetAllResponseHeaders(nsACString& aResponseHeaders,
365 ErrorResult& aRv) override;
367 bool IsSafeHeader(const nsACString& aHeaderName,
368 NotNull<nsIHttpChannel*> aHttpChannel) const;
370 virtual void OverrideMimeType(const nsAString& aMimeType,
371 ErrorResult& aRv) override;
373 virtual XMLHttpRequestResponseType ResponseType() const override {
374 return XMLHttpRequestResponseType(mResponseType);
377 virtual void SetResponseType(XMLHttpRequestResponseType aType,
378 ErrorResult& aRv) override;
380 void SetResponseTypeRaw(XMLHttpRequestResponseType aType) {
381 mResponseType = aType;
384 virtual void GetResponse(JSContext* aCx,
385 JS::MutableHandle<JS::Value> aResponse,
386 ErrorResult& aRv) override;
388 virtual void GetResponseText(DOMString& aResponseText,
389 ErrorResult& aRv) override;
391 // GetResponse* for workers:
392 already_AddRefed<BlobImpl> GetResponseBlobImpl();
393 already_AddRefed<ArrayBufferBuilder> GetResponseArrayBufferBuilder();
394 nsresult GetResponseTextForJSON(nsAString& aString);
395 void GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
396 ErrorResult& aRv);
398 virtual Document* GetResponseXML(ErrorResult& aRv) override;
400 virtual bool MozBackgroundRequest() const override;
402 void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest,
403 ErrorResult& aRv);
405 virtual void SetMozBackgroundRequest(bool aMozBackgroundRequest,
406 ErrorResult& aRv) override;
408 void SetOriginStack(UniquePtr<SerializedStackHolder> aOriginStack);
410 void SetSource(UniquePtr<ProfileChunkedBuffer> aSource);
412 virtual uint16_t ErrorCode() const override {
413 return static_cast<uint16_t>(mErrorLoad);
416 virtual bool MozAnon() const override;
418 virtual bool MozSystem() const override;
420 virtual nsIChannel* GetChannel() const override { return mChannel; }
422 // We need a GetInterface callable from JS for chrome JS
423 virtual void GetInterface(JSContext* aCx, JS::Handle<JS::Value> aIID,
424 JS::MutableHandle<JS::Value> aRetval,
425 ErrorResult& aRv) override;
427 // This fires a trusted readystatechange event, which is not cancelable and
428 // doesn't bubble.
429 nsresult FireReadystatechangeEvent();
430 void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
431 const ProgressEventType aType, int64_t aLoaded,
432 int64_t aTotal);
434 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
435 XMLHttpRequestMainThread, XMLHttpRequest)
436 virtual bool IsCertainlyAliveForCC() const override;
438 bool AllowUploadProgress();
440 virtual void DisconnectFromOwner() override;
442 static void SetDontWarnAboutSyncXHR(bool aVal) {
443 sDontWarnAboutSyncXHR = aVal;
445 static bool DontWarnAboutSyncXHR() { return sDontWarnAboutSyncXHR; }
447 virtual void SetOriginAttributes(
448 const mozilla::dom::OriginAttributesDictionary& aAttrs) override;
450 void BlobStoreCompleted(MutableBlobStorage* aBlobStorage, BlobImpl* aBlobImpl,
451 nsresult aResult) override;
453 void LocalFileToBlobCompleted(BlobImpl* aBlobImpl);
455 protected:
456 nsresult DetectCharset();
457 nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
458 bool aLast = false);
459 static nsresult StreamReaderFunc(nsIInputStream* in, void* closure,
460 const char* fromRawSegment,
461 uint32_t toOffset, uint32_t count,
462 uint32_t* writeCount);
463 nsresult CreateResponseParsedJSON(JSContext* aCx);
464 // Change the state of the object with this. The broadcast argument
465 // determines if the onreadystatechange listener should be called.
466 nsresult ChangeState(uint16_t aState, bool aBroadcast = true);
467 already_AddRefed<nsILoadGroup> GetLoadGroup() const;
469 // Finds a preload for this XHR. If it is found it's removed from the preload
470 // table of the document and marked as used. The called doesn't need to do
471 // any more comparative checks.
472 already_AddRefed<PreloaderBase> FindPreload();
473 // If no or unknown mime type is set on the channel this method ensures it's
474 // set to "text/xml".
475 void EnsureChannelContentType();
477 already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
478 already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
480 void TruncateResponseText();
482 bool IsSystemXHR() const;
483 bool InUploadPhase() const;
485 void OnBodyParseEnd();
486 void ChangeStateToDone(bool aWasSync);
487 void ChangeStateToDoneInternal();
489 void StartProgressEventTimer();
490 void StopProgressEventTimer();
492 void MaybeCreateBlobStorage();
494 nsresult OnRedirectVerifyCallback(nsresult result, bool stripAuth = false);
496 nsIEventTarget* GetTimerEventTarget();
498 nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable);
500 void DispatchOrStoreEvent(DOMEventTargetHelper* aTarget, Event* aEvent);
502 already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
504 void SuspendEventDispatching();
505 void ResumeEventDispatching();
507 void AbortInternal(ErrorResult& aRv);
509 struct PendingEvent {
510 RefPtr<DOMEventTargetHelper> mTarget;
511 RefPtr<Event> mEvent;
514 nsTArray<PendingEvent> mPendingEvents;
516 nsCOMPtr<nsISupports> mContext;
517 nsCOMPtr<nsIPrincipal> mPrincipal;
518 nsCOMPtr<nsIChannel> mChannel;
519 nsCString mRequestMethod;
520 nsCOMPtr<nsIURI> mRequestURL;
521 RefPtr<Document> mResponseXML;
523 nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
525 nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
527 RefPtr<PerformanceStorage> mPerformanceStorage;
528 nsCOMPtr<nsICSPEventListener> mCSPEventListener;
530 // used to implement getAllResponseHeaders()
531 class nsHeaderVisitor : public nsIHttpHeaderVisitor {
532 struct HeaderEntry final {
533 nsCString mName;
534 nsCString mValue;
536 HeaderEntry(const nsACString& aName, const nsACString& aValue)
537 : mName(aName), mValue(aValue) {}
539 bool operator==(const HeaderEntry& aOther) const {
540 return mName == aOther.mName;
543 bool operator<(const HeaderEntry& aOther) const {
544 uint32_t selfLen = mName.Length();
545 uint32_t otherLen = aOther.mName.Length();
546 uint32_t min = XPCOM_MIN(selfLen, otherLen);
547 for (uint32_t i = 0; i < min; ++i) {
548 unsigned char self = mName[i];
549 unsigned char other = aOther.mName[i];
550 MOZ_ASSERT(!(self >= 'A' && self <= 'Z'));
551 MOZ_ASSERT(!(other >= 'A' && other <= 'Z'));
552 if (self == other) {
553 continue;
555 if (self >= 'a' && self <= 'z') {
556 self -= 0x20;
558 if (other >= 'a' && other <= 'z') {
559 other -= 0x20;
561 return self < other;
563 return selfLen < otherLen;
567 public:
568 NS_DECL_ISUPPORTS
569 NS_DECL_NSIHTTPHEADERVISITOR
570 nsHeaderVisitor(const XMLHttpRequestMainThread& aXMLHttpRequest,
571 NotNull<nsIHttpChannel*> aHttpChannel);
572 const nsACString& Headers() {
573 for (uint32_t i = 0; i < mHeaderList.Length(); i++) {
574 HeaderEntry& header = mHeaderList.ElementAt(i);
576 mHeaders.Append(header.mName);
577 mHeaders.AppendLiteral(": ");
578 mHeaders.Append(header.mValue);
579 mHeaders.AppendLiteral("\r\n");
581 return mHeaders;
584 private:
585 virtual ~nsHeaderVisitor();
587 nsTArray<HeaderEntry> mHeaderList;
588 nsCString mHeaders;
589 const XMLHttpRequestMainThread& mXHR;
590 NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
593 // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
594 // BLOB responseTypes
595 nsCString mResponseBody;
597 // The text version of our response body. This is incrementally decoded into
598 // as we receive network data. However for the DEFAULT responseType we
599 // lazily decode into this from mResponseBody only when .responseText is
600 // accessed.
601 // Only used for DEFAULT and TEXT responseTypes.
602 XMLHttpRequestString mResponseText;
604 // For DEFAULT responseType we use this to keep track of how far we've
605 // lazily decoded from mResponseBody to mResponseText
606 uint32_t mResponseBodyDecodedPos;
608 // Decoder used for decoding into mResponseText
609 // Only used for DEFAULT, TEXT and JSON responseTypes.
610 // In cases where we've only received half a surrogate, the decoder itself
611 // carries the state to remember this. Next time we receive more data we
612 // simply feed the new data into the decoder which will handle the second
613 // part of the surrogate.
614 mozilla::UniquePtr<mozilla::Decoder> mDecoder;
616 void MatchCharsetAndDecoderToResponseDocument();
618 XMLHttpRequestResponseType mResponseType;
620 RefPtr<BlobImpl> mResponseBlobImpl;
622 // This is the cached blob-response, created only at the first GetResponse()
623 // call.
624 RefPtr<Blob> mResponseBlob;
626 // We stream data to mBlobStorage when response type is "blob".
627 RefPtr<MutableBlobStorage> mBlobStorage;
629 nsString mOverrideMimeType;
632 * The notification callbacks the channel had when Send() was
633 * called. We want to forward things here as needed.
635 nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
637 * Sink interfaces that we implement that mNotificationCallbacks may
638 * want to also be notified for. These are inited lazily if we're
639 * asked for the relevant interface.
641 nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
642 nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
644 nsCOMPtr<nsIURI> mBaseURI;
645 nsCOMPtr<nsILoadGroup> mLoadGroup;
647 Maybe<ClientInfo> mClientInfo;
648 Maybe<ServiceWorkerDescriptor> mController;
650 uint16_t mState;
652 // If true, this object is used by the worker's XMLHttpRequest.
653 bool mForWorker;
655 bool mFlagSynchronous;
656 bool mFlagAborted;
657 bool mFlagParseBody;
658 bool mFlagSyncLooping;
659 bool mFlagBackgroundRequest;
660 bool mFlagHadUploadListenersOnSend;
661 bool mFlagACwithCredentials;
662 bool mFlagTimedOut;
663 bool mFlagDeleted;
665 // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
666 // finishes downloading (or an error/abort has occurred during either phase).
667 // Used to guard against the user trying to alter headers/etc when it's too
668 // late, and ensure the XHR only handles one in-flight request at once.
669 bool mFlagSend;
671 RefPtr<XMLHttpRequestUpload> mUpload;
672 int64_t mUploadTransferred;
673 int64_t mUploadTotal;
674 bool mUploadComplete;
675 bool mProgressSinceLastProgressEvent;
677 // Timeout support
678 PRTime mRequestSentTime;
679 uint32_t mTimeoutMilliseconds;
680 nsCOMPtr<nsITimer> mTimeoutTimer;
681 void StartTimeoutTimer();
682 void HandleTimeoutCallback();
684 nsCOMPtr<nsIRunnable> mResumeTimeoutRunnable;
686 nsCOMPtr<nsITimer> mSyncTimeoutTimer;
688 enum SyncTimeoutType { eErrorOrExpired, eTimerStarted, eNoTimerNeeded };
690 SyncTimeoutType MaybeStartSyncTimeoutTimer();
691 void HandleSyncTimeoutTimer();
692 void CancelSyncTimeoutTimer();
694 ErrorType mErrorLoad;
695 bool mErrorParsingXML;
696 bool mWaitingForOnStopRequest;
697 bool mProgressTimerIsActive;
698 bool mIsHtml;
699 bool mWarnAboutSyncHtml;
700 int64_t mLoadTotal; // -1 if not known.
701 // Number of HTTP message body bytes received so far. This quantity is
702 // in the same units as Content-Length and mLoadTotal, and hence counts
703 // compressed bytes when the channel has gzip Content-Encoding. If the
704 // channel does not have Content-Encoding, this will be the same as
705 // mDataReceived except between the OnProgress that changes mLoadTransferred
706 // and the corresponding OnDataAvailable (which changes mDataReceived).
707 // Ordering of OnProgress and OnDataAvailable is undefined.
708 int64_t mLoadTransferred;
709 nsCOMPtr<nsITimer> mProgressNotifier;
710 void HandleProgressTimerCallback();
712 bool mIsSystem;
713 bool mIsAnon;
716 * Close the XMLHttpRequest's channels.
718 void CloseRequest();
720 void TerminateOngoingFetch();
723 * Close the XMLHttpRequest's channels and dispatch appropriate progress
724 * events.
726 * @param aType The progress event type.
728 void CloseRequestWithError(const ProgressEventType aType);
730 nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
731 nsCOMPtr<nsIChannel> mNewRedirectChannel;
733 JS::Heap<JS::Value> mResultJSON;
735 RefPtr<ArrayBufferBuilder> mArrayBufferBuilder;
736 JS::Heap<JSObject*> mResultArrayBuffer;
737 bool mIsMappedArrayBuffer;
739 void ResetResponse();
741 bool ShouldBlockAuthPrompt();
743 RequestHeaders mAuthorRequestHeaders;
745 // Helper object to manage our XPCOM scriptability bits
746 nsXMLHttpRequestXPCOMifier* mXPCOMifier;
748 // When this is set to true, the event dispatching is suspended. This is
749 // useful to change the correct state when XHR is working sync.
750 bool mEventDispatchingSuspended;
752 // True iff mDecoder has processed the end of the stream.
753 // Used in lazy decoding to distinguish between having
754 // processed all the bytes but not the EOF and having
755 // processed all the bytes and the EOF.
756 bool mEofDecoded;
758 // This flag will be set in `Send()` when we successfully reuse a "fetch"
759 // preload to satisfy this XHR.
760 bool mFromPreload = false;
762 // Our parse-end listener, if we are parsing.
763 RefPtr<nsXHRParseEndListener> mParseEndListener;
765 XMLHttpRequestDoneNotifier* mDelayedDoneNotifier;
766 void DisconnectDoneNotifier();
768 // Any stack information for the point the XHR was opened. This is deleted
769 // after the XHR is opened, to avoid retaining references to the worker.
770 UniquePtr<SerializedStackHolder> mOriginStack;
772 static bool sDontWarnAboutSyncXHR;
775 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR {
776 public:
777 AutoDontWarnAboutSyncXHR()
778 : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
779 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
782 ~AutoDontWarnAboutSyncXHR() {
783 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
786 private:
787 bool mOldVal;
790 // A shim class designed to expose the non-DOM interfaces of
791 // XMLHttpRequest via XPCOM stuff.
792 class nsXMLHttpRequestXPCOMifier final : public nsIStreamListener,
793 public nsIChannelEventSink,
794 public nsIAsyncVerifyRedirectCallback,
795 public nsIProgressEventSink,
796 public nsIInterfaceRequestor,
797 public nsITimerCallback,
798 public nsINamed {
799 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
800 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
801 nsIStreamListener)
803 explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR)
804 : mXHR(aXHR) {}
806 private:
807 ~nsXMLHttpRequestXPCOMifier() {
808 if (mXHR) {
809 mXHR->mXPCOMifier = nullptr;
813 public:
814 NS_FORWARD_NSISTREAMLISTENER(mXHR->)
815 NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
816 NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
817 NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR->)
818 NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
819 NS_FORWARD_NSITIMERCALLBACK(mXHR->)
820 NS_FORWARD_NSINAMED(mXHR->)
822 NS_DECL_NSIINTERFACEREQUESTOR
824 private:
825 RefPtr<XMLHttpRequestMainThread> mXHR;
828 class XMLHttpRequestDoneNotifier : public Runnable {
829 public:
830 explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread* aXHR)
831 : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR) {}
833 NS_IMETHOD Run() override {
834 if (mXHR) {
835 RefPtr<XMLHttpRequestMainThread> xhr = mXHR;
836 // ChangeStateToDoneInternal ends up calling Disconnect();
837 xhr->ChangeStateToDoneInternal();
838 MOZ_ASSERT(!mXHR);
840 return NS_OK;
843 void Disconnect() { mXHR = nullptr; }
845 private:
846 RefPtr<XMLHttpRequestMainThread> mXHR;
849 class nsXHRParseEndListener : public nsIDOMEventListener {
850 public:
851 NS_DECL_ISUPPORTS
852 NS_IMETHOD HandleEvent(Event* event) override {
853 if (mXHR) {
854 mXHR->OnBodyParseEnd();
856 mXHR = nullptr;
857 return NS_OK;
860 explicit nsXHRParseEndListener(XMLHttpRequestMainThread* aXHR) : mXHR(aXHR) {}
862 void SetIsStale() { mXHR = nullptr; }
864 private:
865 virtual ~nsXHRParseEndListener() = default;
867 XMLHttpRequestMainThread* mXHR;
870 } // namespace dom
871 } // namespace mozilla
873 #endif // mozilla_dom_XMLHttpRequestMainThread_h