Bug 1911684: Part 1- Refactor Homepage UI components to use the refactored wallpaper...
[gecko.git] / dom / xhr / XMLHttpRequestMainThread.h
blobb860f041fb10eaea923e87c415a2501f19c6a170
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/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"
52 #ifdef Status
53 /* Xlib headers insist on this for some reason... Nuke it because
54 it'll override our member name */
55 typedef Status __StatusTmp;
56 # undef Status
57 typedef __StatusTmp Status;
58 #endif
60 class nsIHttpChannel;
61 class nsIJARChannel;
62 class nsILoadGroup;
64 namespace mozilla {
65 class ProfileChunkedBuffer;
67 namespace net {
68 class ContentRange;
71 namespace dom {
73 class DOMString;
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 {
86 public:
87 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayBufferBuilder);
89 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);
104 uint32_t Length();
105 uint32_t Capacity();
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
114 // in JS engine.
115 nsresult MapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
117 private:
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);
130 Mutex mMutex;
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.
139 bool mNeutered;
142 class nsXMLHttpRequestXPCOMifier;
144 class RequestHeaders {
145 struct RequestHeader {
146 nsCString mName;
147 nsCString mValue;
149 nsTArray<RequestHeader> mHeaders;
150 RequestHeader* Find(const nsACString& aName);
152 public:
153 class CharsetIterator {
154 bool mValid;
155 int32_t mCurPos, mCurLen, mCutoff;
156 nsACString& mSource;
158 public:
159 explicit CharsetIterator(nsACString& aSource);
160 bool Equals(const nsACString& aOther,
161 const nsCStringComparator& aCmp) const;
162 void Replace(const nsACString& aReplacement);
163 bool Next();
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);
175 void Clear();
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,
193 public nsINamed,
194 public MutableBlobStorageCallback {
195 friend class nsXHRParseEndListener;
196 friend class nsXMLHttpRequestXPCOMifier;
197 friend class XMLHttpRequestDoneNotifier;
199 public:
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 {
203 eOK,
204 eRequest,
205 eUnreachable,
206 eChannelOpen,
207 eRedirect,
208 eTerminated,
209 ENUM_MAX
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;
224 mIsSystem = aSystem;
227 void SetClientInfoAndController(
228 const ClientInfo& aClientInfo,
229 const Maybe<ServiceWorkerDescriptor>& aController);
231 NS_DECL_ISUPPORTS_INHERITED
233 // nsIStreamListener
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
248 // nsITimerCallback
249 NS_DECL_NSITIMERCALLBACK
251 // nsINamed
252 NS_DECL_NSINAMED
254 // nsISizeOfEventTarget
255 virtual size_t SizeOfEventTargetIncludingThis(
256 MallocSizeOf aMallocSizeOf) const override;
258 // states
259 virtual uint16_t ReadyState() const override;
261 // request
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,
275 ErrorResult& aRv);
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;
292 private:
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();
306 public:
307 bool CanSend(ErrorResult& aRv);
309 virtual void Send(
310 const Nullable<
311 DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>&
312 aData,
313 ErrorResult& aRv) override;
315 virtual void SendInputStream(nsIInputStream* aInputStream,
316 ErrorResult& aRv) override {
317 if (!CanSend(aRv)) {
318 return;
320 BodyExtractor<nsIInputStream> body(aInputStream);
321 SendInternal(&body, false, aRv);
324 void RequestErrorSteps(const ProgressEventType aEventType,
325 const nsresult aOptionalException, ErrorResult& aRv);
327 void Abort() {
328 IgnoredErrorResult rv;
329 AbortInternal(rv);
330 MOZ_ASSERT(!rv.Failed() || rv.ErrorCodeIs(NS_ERROR_DOM_ABORT_ERR));
333 virtual void Abort(ErrorResult& aRv) override;
335 // response
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,
347 ErrorResult& aRv) {
348 nsAutoCString result;
349 GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
350 if (result.IsVoid()) {
351 aResult.SetIsVoid(true);
352 } else {
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,
390 ErrorResult& aRv);
392 virtual Document* GetResponseXML(ErrorResult& aRv) override;
394 virtual bool MozBackgroundRequest() const override;
396 void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest,
397 ErrorResult& aRv);
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
424 // doesn't bubble.
425 nsresult FireReadystatechangeEvent();
426 void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
427 const ProgressEventType& aType, int64_t aLoaded,
428 int64_t aTotal);
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);
451 #ifdef DEBUG
452 // For logging when there's trouble
453 RefPtr<ThreadSafeWorkerRef> mTSWorkerRef MOZ_GUARDED_BY(mTSWorkerRefMutex);
454 Mutex mTSWorkerRefMutex;
455 #endif
457 protected:
458 nsresult DetectCharset();
459 nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
460 bool aLast = false);
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 {
542 nsCString mName;
543 nsCString mValue;
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'));
561 if (self == other) {
562 continue;
564 if (self >= 'a' && self <= 'z') {
565 self -= 0x20;
567 if (other >= 'a' && other <= 'z') {
568 other -= 0x20;
570 return self < other;
572 return selfLen < otherLen;
576 public:
577 NS_DECL_ISUPPORTS
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");
590 return mHeaders;
593 private:
594 virtual ~nsHeaderVisitor();
596 nsTArray<HeaderEntry> mHeaderList;
597 nsCString mHeaders;
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
609 // accessed.
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()
632 // call.
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;
659 uint16_t mState;
661 // If true, this object is used by the worker's XMLHttpRequest.
662 bool mForWorker;
664 bool mFlagSynchronous;
665 bool mFlagAborted;
666 bool mFlagParseBody;
667 bool mFlagSyncLooping;
668 bool mFlagBackgroundRequest;
669 bool mFlagHadUploadListenersOnSend;
670 bool mFlagACwithCredentials;
671 bool mFlagTimedOut;
672 bool mFlagDeleted;
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.
678 bool mFlagSend;
680 RefPtr<XMLHttpRequestUpload> mUpload;
681 int64_t mUploadTransferred;
682 int64_t mUploadTotal;
683 bool mUploadComplete;
684 bool mProgressSinceLastProgressEvent;
686 // Timeout support
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;
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();
723 bool mIsSystem;
724 bool mIsAnon;
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
735 * events.
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.
767 bool mEofDecoded;
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 {
787 public:
788 AutoDontWarnAboutSyncXHR()
789 : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
790 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
793 ~AutoDontWarnAboutSyncXHR() {
794 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
797 private:
798 bool 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,
809 public nsINamed {
810 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
811 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
812 nsIStreamListener)
814 explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR)
815 : mXHR(aXHR) {}
817 private:
818 ~nsXMLHttpRequestXPCOMifier() {
819 if (mXHR) {
820 mXHR->mXPCOMifier = nullptr;
824 public:
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
835 private:
836 RefPtr<XMLHttpRequestMainThread> mXHR;
839 class XMLHttpRequestDoneNotifier : public Runnable {
840 public:
841 explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread* aXHR)
842 : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR) {}
844 NS_IMETHOD Run() override {
845 if (mXHR) {
846 RefPtr<XMLHttpRequestMainThread> xhr = mXHR;
847 // ChangeStateToDoneInternal ends up calling Disconnect();
848 xhr->ChangeStateToDoneInternal();
849 MOZ_ASSERT(!mXHR);
851 return NS_OK;
854 void Disconnect() { mXHR = nullptr; }
856 private:
857 RefPtr<XMLHttpRequestMainThread> mXHR;
860 class nsXHRParseEndListener : public nsIDOMEventListener {
861 public:
862 NS_DECL_ISUPPORTS
863 NS_IMETHOD HandleEvent(Event* event) override {
864 if (mXHR) {
865 mXHR->OnBodyParseEnd();
867 mXHR = nullptr;
868 return NS_OK;
871 explicit nsXHRParseEndListener(XMLHttpRequestMainThread* aXHR) : mXHR(aXHR) {}
873 void SetIsStale() { mXHR = nullptr; }
875 private:
876 virtual ~nsXHRParseEndListener() = default;
878 XMLHttpRequestMainThread* mXHR;
881 } // namespace dom
882 } // namespace mozilla
884 #endif // mozilla_dom_XMLHttpRequestMainThread_h