no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / dom / xhr / XMLHttpRequestMainThread.h
blob3f2d39599178a3f33920a506d48455a6f65928a7
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"
51 #include "nsBaseChannel.h"
53 #ifdef Status
54 /* Xlib headers insist on this for some reason... Nuke it because
55 it'll override our member name */
56 typedef Status __StatusTmp;
57 # undef Status
58 typedef __StatusTmp Status;
59 #endif
61 class nsIHttpChannel;
62 class nsIJARChannel;
63 class nsILoadGroup;
65 namespace mozilla {
66 class ProfileChunkedBuffer;
68 namespace dom {
70 class DOMString;
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 {
83 public:
84 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ArrayBufferBuilder);
86 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);
101 uint32_t Length();
102 uint32_t Capacity();
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
111 // in JS engine.
112 nsresult MapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
114 private:
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);
127 Mutex mMutex;
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.
136 bool mNeutered;
139 class nsXMLHttpRequestXPCOMifier;
141 class RequestHeaders {
142 struct RequestHeader {
143 nsCString mName;
144 nsCString mValue;
146 nsTArray<RequestHeader> mHeaders;
147 RequestHeader* Find(const nsACString& aName);
149 public:
150 class CharsetIterator {
151 bool mValid;
152 int32_t mCurPos, mCurLen, mCutoff;
153 nsACString& mSource;
155 public:
156 explicit CharsetIterator(nsACString& aSource);
157 bool Equals(const nsACString& aOther,
158 const nsCStringComparator& aCmp) const;
159 void Replace(const nsACString& aReplacement);
160 bool Next();
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);
172 void Clear();
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,
190 public nsINamed,
191 public MutableBlobStorageCallback {
192 friend class nsXHRParseEndListener;
193 friend class nsXMLHttpRequestXPCOMifier;
194 friend class XMLHttpRequestDoneNotifier;
196 public:
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 {
200 eOK,
201 eRequest,
202 eUnreachable,
203 eChannelOpen,
204 eRedirect,
205 eTerminated,
206 ENUM_MAX
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;
221 mIsSystem = aSystem;
224 void SetClientInfoAndController(
225 const ClientInfo& aClientInfo,
226 const Maybe<ServiceWorkerDescriptor>& aController);
228 NS_DECL_ISUPPORTS_INHERITED
230 // nsIStreamListener
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
245 // nsITimerCallback
246 NS_DECL_NSITIMERCALLBACK
248 // nsINamed
249 NS_DECL_NSINAMED
251 // nsISizeOfEventTarget
252 virtual size_t SizeOfEventTargetIncludingThis(
253 MallocSizeOf aMallocSizeOf) const override;
255 // states
256 virtual uint16_t ReadyState() const override;
258 // request
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,
272 ErrorResult& aRv);
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;
289 private:
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();
303 public:
304 bool CanSend(ErrorResult& aRv);
306 virtual void Send(
307 const Nullable<
308 DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>&
309 aData,
310 ErrorResult& aRv) override;
312 virtual void SendInputStream(nsIInputStream* aInputStream,
313 ErrorResult& aRv) override {
314 if (!CanSend(aRv)) {
315 return;
317 BodyExtractor<nsIInputStream> body(aInputStream);
318 SendInternal(&body, false, aRv);
321 void RequestErrorSteps(const ProgressEventType aEventType,
322 const nsresult aOptionalException, ErrorResult& aRv);
324 void Abort() {
325 IgnoredErrorResult rv;
326 AbortInternal(rv);
327 MOZ_ASSERT(!rv.Failed() || rv.ErrorCodeIs(NS_ERROR_DOM_ABORT_ERR));
330 virtual void Abort(ErrorResult& aRv) override;
332 // response
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,
344 ErrorResult& aRv) {
345 nsAutoCString result;
346 GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
347 if (result.IsVoid()) {
348 aResult.SetIsVoid(true);
349 } else {
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,
387 ErrorResult& aRv);
389 virtual Document* GetResponseXML(ErrorResult& aRv) override;
391 virtual bool MozBackgroundRequest() const override;
393 void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest,
394 ErrorResult& aRv);
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
421 // doesn't bubble.
422 nsresult FireReadystatechangeEvent();
423 void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
424 const ProgressEventType& aType, int64_t aLoaded,
425 int64_t aTotal);
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);
448 #ifdef DEBUG
449 // For logging when there's trouble
450 RefPtr<ThreadSafeWorkerRef> mTSWorkerRef = nullptr;
451 #endif
453 protected:
454 nsresult DetectCharset();
455 nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
456 bool aLast = false);
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 {
537 nsCString mName;
538 nsCString mValue;
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'));
556 if (self == other) {
557 continue;
559 if (self >= 'a' && self <= 'z') {
560 self -= 0x20;
562 if (other >= 'a' && other <= 'z') {
563 other -= 0x20;
565 return self < other;
567 return selfLen < otherLen;
571 public:
572 NS_DECL_ISUPPORTS
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");
585 return mHeaders;
588 private:
589 virtual ~nsHeaderVisitor();
591 nsTArray<HeaderEntry> mHeaderList;
592 nsCString mHeaders;
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
604 // accessed.
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()
627 // call.
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;
654 uint16_t mState;
656 // If true, this object is used by the worker's XMLHttpRequest.
657 bool mForWorker;
659 bool mFlagSynchronous;
660 bool mFlagAborted;
661 bool mFlagParseBody;
662 bool mFlagSyncLooping;
663 bool mFlagBackgroundRequest;
664 bool mFlagHadUploadListenersOnSend;
665 bool mFlagACwithCredentials;
666 bool mFlagTimedOut;
667 bool mFlagDeleted;
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.
673 bool mFlagSend;
675 RefPtr<XMLHttpRequestUpload> mUpload;
676 int64_t mUploadTransferred;
677 int64_t mUploadTotal;
678 bool mUploadComplete;
679 bool mProgressSinceLastProgressEvent;
681 // Timeout support
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;
704 bool mIsHtml;
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();
718 bool mIsSystem;
719 bool mIsAnon;
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
730 * events.
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.
762 bool mEofDecoded;
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 {
782 public:
783 AutoDontWarnAboutSyncXHR()
784 : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
785 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
788 ~AutoDontWarnAboutSyncXHR() {
789 XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
792 private:
793 bool 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,
804 public nsINamed {
805 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
806 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
807 nsIStreamListener)
809 explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR)
810 : mXHR(aXHR) {}
812 private:
813 ~nsXMLHttpRequestXPCOMifier() {
814 if (mXHR) {
815 mXHR->mXPCOMifier = nullptr;
819 public:
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
830 private:
831 RefPtr<XMLHttpRequestMainThread> mXHR;
834 class XMLHttpRequestDoneNotifier : public Runnable {
835 public:
836 explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread* aXHR)
837 : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR) {}
839 NS_IMETHOD Run() override {
840 if (mXHR) {
841 RefPtr<XMLHttpRequestMainThread> xhr = mXHR;
842 // ChangeStateToDoneInternal ends up calling Disconnect();
843 xhr->ChangeStateToDoneInternal();
844 MOZ_ASSERT(!mXHR);
846 return NS_OK;
849 void Disconnect() { mXHR = nullptr; }
851 private:
852 RefPtr<XMLHttpRequestMainThread> mXHR;
855 class nsXHRParseEndListener : public nsIDOMEventListener {
856 public:
857 NS_DECL_ISUPPORTS
858 NS_IMETHOD HandleEvent(Event* event) override {
859 if (mXHR) {
860 mXHR->OnBodyParseEnd();
862 mXHR = nullptr;
863 return NS_OK;
866 explicit nsXHRParseEndListener(XMLHttpRequestMainThread* aXHR) : mXHR(aXHR) {}
868 void SetIsStale() { mXHR = nullptr; }
870 private:
871 virtual ~nsXHRParseEndListener() = default;
873 XMLHttpRequestMainThread* mXHR;
876 } // namespace dom
877 } // namespace mozilla
879 #endif // mozilla_dom_XMLHttpRequestMainThread_h