tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

XMLHttpRequestMainThread.h (28183B)


      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/. */
      6 
      7 #ifndef mozilla_dom_XMLHttpRequestMainThread_h
      8 #define mozilla_dom_XMLHttpRequestMainThread_h
      9 
     10 #include <bitset>
     11 
     12 #include "mozilla/Assertions.h"
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/DOMEventTargetHelper.h"
     15 #include "mozilla/Encoding.h"
     16 #include "mozilla/Maybe.h"
     17 #include "mozilla/MemoryReporting.h"
     18 #include "mozilla/NotNull.h"
     19 #include "mozilla/dom/BodyExtractor.h"
     20 #include "mozilla/dom/ClientInfo.h"
     21 #include "mozilla/dom/Document.h"
     22 #include "mozilla/dom/File.h"
     23 #include "mozilla/dom/FormData.h"
     24 #include "mozilla/dom/MimeType.h"
     25 #include "mozilla/dom/MutableBlobStorage.h"
     26 #include "mozilla/dom/PerformanceStorage.h"
     27 #include "mozilla/dom/ServiceWorkerDescriptor.h"
     28 #include "mozilla/dom/TypedArray.h"
     29 #include "mozilla/dom/URLSearchParams.h"
     30 #include "mozilla/dom/WorkerRef.h"
     31 #include "mozilla/dom/XMLHttpRequest.h"
     32 #include "mozilla/dom/XMLHttpRequestBinding.h"
     33 #include "mozilla/dom/XMLHttpRequestEventTarget.h"
     34 #include "mozilla/dom/XMLHttpRequestString.h"
     35 #include "nsIAsyncVerifyRedirectCallback.h"
     36 #include "nsIChannelEventSink.h"
     37 #include "nsIDOMEventListener.h"
     38 #include "nsIHttpHeaderVisitor.h"
     39 #include "nsIInputStream.h"
     40 #include "nsIInterfaceRequestor.h"
     41 #include "nsIPrincipal.h"
     42 #include "nsIProgressEventSink.h"
     43 #include "nsIScriptObjectPrincipal.h"
     44 #include "nsISizeOfEventTarget.h"
     45 #include "nsIStreamListener.h"
     46 #include "nsISupportsUtils.h"
     47 #include "nsITimer.h"
     48 #include "nsIURI.h"
     49 #include "nsJSUtils.h"
     50 #include "nsTArray.h"
     51 
     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
     59 
     60 class nsIHttpChannel;
     61 class nsIJARChannel;
     62 class nsILoadGroup;
     63 
     64 namespace mozilla {
     65 class ProfileChunkedBuffer;
     66 
     67 namespace net {
     68 class ContentRange;
     69 }
     70 
     71 namespace dom {
     72 
     73 class DOMString;
     74 class XMLHttpRequestUpload;
     75 class SerializedStackHolder;
     76 struct OriginAttributesDictionary;
     77 
     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.
     81 //
     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);
     88 
     89  ArrayBufferBuilder();
     90 
     91  // Will truncate if aNewCap is < Length().
     92  bool SetCapacity(uint32_t aNewCap);
     93 
     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.
     98  //
     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);
    103 
    104  uint32_t Length();
    105  uint32_t Capacity();
    106 
    107  JSObject* TakeArrayBuffer(JSContext* aCx);
    108 
    109  // Memory mapping to starting position of file(aFile) in the zip
    110  // package(aJarFile).
    111  //
    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);
    116 
    117 private:
    118  ~ArrayBufferBuilder();
    119 
    120  ArrayBufferBuilder(const ArrayBufferBuilder&) = delete;
    121  ArrayBufferBuilder& operator=(const ArrayBufferBuilder&) = delete;
    122  ArrayBufferBuilder& operator=(const ArrayBufferBuilder&&) = delete;
    123 
    124  bool SetCapacityInternal(uint32_t aNewCap, const MutexAutoLock& aProofOfLock)
    125      MOZ_REQUIRES(mMutex);
    126 
    127  static bool AreOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
    128                                    const uint8_t* aStart2, uint32_t aLength2);
    129 
    130  Mutex mMutex;
    131 
    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);
    137 
    138  // This is used in assertions only.
    139  bool mNeutered;
    140 };
    141 
    142 class nsXMLHttpRequestXPCOMifier;
    143 
    144 class RequestHeaders {
    145  struct RequestHeader {
    146    nsCString mName;
    147    nsCString mValue;
    148  };
    149  nsTArray<RequestHeader> mHeaders;
    150  RequestHeader* Find(const nsACString& aName);
    151 
    152 public:
    153  class CharsetIterator {
    154    bool mValid;
    155    int32_t mCurPos, mCurLen, mCutoff;
    156    nsACString& mSource;
    157 
    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();
    164  };
    165 
    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;
    179 };
    180 
    181 class nsXHRParseEndListener;
    182 class XMLHttpRequestDoneNotifier;
    183 
    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;
    198 
    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
    210  };
    211 
    212  explicit XMLHttpRequestMainThread(nsIGlobalObject* aGlobalObject);
    213 
    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);
    219 
    220  void InitParameters(bool aAnon, bool aSystem);
    221 
    222  void SetParameters(bool aAnon, bool aSystem) {
    223    mIsAnon = aAnon || aSystem;
    224    mIsSystem = aSystem;
    225  }
    226 
    227  void SetClientInfoAndController(
    228      const ClientInfo& aClientInfo,
    229      const Maybe<ServiceWorkerDescriptor>& aController);
    230 
    231  NS_DECL_ISUPPORTS_INHERITED
    232 
    233  // nsIStreamListener
    234  NS_DECL_NSISTREAMLISTENER
    235 
    236  // nsIRequestObserver
    237  NS_DECL_NSIREQUESTOBSERVER
    238 
    239  // nsIChannelEventSink
    240  NS_DECL_NSICHANNELEVENTSINK
    241 
    242  // nsIProgressEventSink
    243  NS_DECL_NSIPROGRESSEVENTSINK
    244 
    245  // nsIInterfaceRequestor
    246  NS_DECL_NSIINTERFACEREQUESTOR
    247 
    248  // nsITimerCallback
    249  NS_DECL_NSITIMERCALLBACK
    250 
    251  // nsINamed
    252  NS_DECL_NSINAMED
    253 
    254  // nsISizeOfEventTarget
    255  virtual size_t SizeOfEventTargetIncludingThis(
    256      MallocSizeOf aMallocSizeOf) const override;
    257 
    258  // states
    259  virtual uint16_t ReadyState() const override;
    260 
    261  // request
    262  nsresult CreateChannel();
    263  nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
    264                         int64_t aUploadLength, nsACString& aUploadContentType);
    265 
    266  virtual void Open(const nsACString& aMethod, const nsACString& aUrl,
    267                    ErrorResult& aRv) override;
    268 
    269  virtual void Open(const nsACString& aMethod, const nsACString& aUrl,
    270                    bool aAsync, const nsACString& aUsername,
    271                    const nsACString& aPassword, ErrorResult& aRv) override;
    272 
    273  virtual void SetRequestHeader(const nsACString& aName,
    274                                const nsACString& aValue,
    275                                ErrorResult& aRv) override;
    276 
    277  virtual uint32_t Timeout() const override { return mTimeoutMilliseconds; }
    278 
    279  virtual void SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
    280 
    281  virtual bool WithCredentials() const override;
    282 
    283  virtual void SetWithCredentials(bool aWithCredentials,
    284                                  ErrorResult& aRv) override;
    285 
    286  virtual XMLHttpRequestUpload* GetUpload(ErrorResult& aRv) override;
    287 
    288 private:
    289  virtual ~XMLHttpRequestMainThread();
    290 
    291  nsresult MaybeSilentSendFailure(nsresult aRv);
    292  void SendInternal(const BodyExtractorBase* aBody,
    293                    bool aBodyIsDocumentOrString, ErrorResult& aRv);
    294 
    295  bool IsCrossSiteCORSRequest() const;
    296  bool IsDeniedCrossSiteCORSRequest();
    297 
    298  void ResumeTimeout();
    299 
    300  void MaybeLowerChannelPriority();
    301 
    302 public:
    303  bool CanSend(ErrorResult& aRv);
    304 
    305  virtual void Send(
    306      const Nullable<
    307          DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString>&
    308          aData,
    309      ErrorResult& aRv) override;
    310 
    311  virtual void SendInputStream(nsIInputStream* aInputStream,
    312                               ErrorResult& aRv) override {
    313    if (!CanSend(aRv)) {
    314      return;
    315    }
    316    BodyExtractor<nsIInputStream> body(aInputStream);
    317    SendInternal(&body, false, aRv);
    318  }
    319 
    320  void RequestErrorSteps(const ProgressEventType aEventType,
    321                         const nsresult aOptionalException, ErrorResult& aRv);
    322 
    323  void Abort() {
    324    IgnoredErrorResult rv;
    325    AbortInternal(rv);
    326    MOZ_ASSERT(!rv.Failed() || rv.ErrorCodeIs(NS_ERROR_DOM_ABORT_ERR));
    327  }
    328 
    329  virtual void Abort(ErrorResult& aRv) override;
    330 
    331  // response
    332  virtual void GetResponseURL(nsACString& aUrl) override;
    333 
    334  virtual uint32_t GetStatus(ErrorResult& aRv) override;
    335 
    336  virtual void GetStatusText(nsACString& aStatusText,
    337                             ErrorResult& aRv) override;
    338 
    339  virtual void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
    340                                 ErrorResult& aRv) override;
    341 
    342  virtual void GetAllResponseHeaders(nsACString& aResponseHeaders,
    343                                     ErrorResult& aRv) override;
    344 
    345  bool IsSafeHeader(const nsACString& aHeaderName,
    346                    NotNull<nsIHttpChannel*> aHttpChannel) const;
    347 
    348  virtual void OverrideMimeType(const nsAString& aMimeType,
    349                                ErrorResult& aRv) override;
    350 
    351  virtual XMLHttpRequestResponseType ResponseType() const override {
    352    return XMLHttpRequestResponseType(mResponseType);
    353  }
    354 
    355  virtual void SetResponseType(XMLHttpRequestResponseType aType,
    356                               ErrorResult& aRv) override;
    357 
    358  void SetResponseTypeRaw(XMLHttpRequestResponseType aType) {
    359    mResponseType = aType;
    360  }
    361 
    362  virtual void GetResponse(JSContext* aCx,
    363                           JS::MutableHandle<JS::Value> aResponse,
    364                           ErrorResult& aRv) override;
    365 
    366  virtual void GetResponseText(DOMString& aResponseText,
    367                               ErrorResult& aRv) override;
    368 
    369  // GetResponse* for workers:
    370  already_AddRefed<BlobImpl> GetResponseBlobImpl();
    371  already_AddRefed<ArrayBufferBuilder> GetResponseArrayBufferBuilder();
    372  nsresult GetResponseTextForJSON(nsAString& aString);
    373  void GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
    374                       ErrorResult& aRv);
    375 
    376  virtual Document* GetResponseXML(ErrorResult& aRv) override;
    377 
    378  virtual bool MozBackgroundRequest() const override;
    379 
    380  void SetMozBackgroundRequestExternal(bool aMozBackgroundRequest,
    381                                       ErrorResult& aRv);
    382 
    383  virtual void SetMozBackgroundRequest(bool aMozBackgroundRequest,
    384                                       ErrorResult& aRv) override;
    385 
    386  void SetOriginStack(UniquePtr<SerializedStackHolder> aOriginStack);
    387 
    388  void SetSource(UniquePtr<ProfileChunkedBuffer> aSource);
    389 
    390  nsresult ErrorDetail() const { return mErrorLoadDetail; }
    391 
    392  virtual uint16_t ErrorCode() const override {
    393    return static_cast<uint16_t>(mErrorLoad);
    394  }
    395 
    396  virtual bool MozAnon() const override;
    397 
    398  virtual bool MozSystem() const override;
    399 
    400  virtual nsIChannel* GetChannel() const override { return mChannel; }
    401 
    402  // We need a GetInterface callable from JS for chrome JS
    403  virtual void GetInterface(JSContext* aCx, JS::Handle<JS::Value> aIID,
    404                            JS::MutableHandle<JS::Value> aRetval,
    405                            ErrorResult& aRv) override;
    406 
    407  // This fires a trusted readystatechange event, which is not cancelable and
    408  // doesn't bubble.
    409  nsresult FireReadystatechangeEvent();
    410  void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
    411                             const ProgressEventType& aType, int64_t aLoaded,
    412                             int64_t aTotal);
    413 
    414  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
    415      XMLHttpRequestMainThread, XMLHttpRequest)
    416  virtual bool IsCertainlyAliveForCC() const override;
    417 
    418  bool AllowUploadProgress();
    419 
    420  virtual void DisconnectFromOwner() override;
    421 
    422  static void SetDontWarnAboutSyncXHR(bool aVal) {
    423    sDontWarnAboutSyncXHR = aVal;
    424  }
    425  static bool DontWarnAboutSyncXHR() { return sDontWarnAboutSyncXHR; }
    426 
    427  virtual void SetOriginAttributes(
    428      const mozilla::dom::OriginAttributesDictionary& aAttrs) override;
    429 
    430  void BlobStoreCompleted(MutableBlobStorage* aBlobStorage, BlobImpl* aBlobImpl,
    431                          nsresult aResult) override;
    432 
    433  void LocalFileToBlobCompleted(BlobImpl* aBlobImpl);
    434 
    435 #ifdef DEBUG
    436  // For logging when there's trouble
    437  RefPtr<ThreadSafeWorkerRef> mTSWorkerRef MOZ_GUARDED_BY(mTSWorkerRefMutex);
    438  Mutex mTSWorkerRefMutex;
    439 #endif
    440 
    441 protected:
    442  nsresult DetectCharset();
    443  nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
    444                                bool aLast = false);
    445  static nsresult StreamReaderFunc(nsIInputStream* in, void* closure,
    446                                   const char* fromRawSegment,
    447                                   uint32_t toOffset, uint32_t count,
    448                                   uint32_t* writeCount);
    449  nsresult CreateResponseParsedJSON(JSContext* aCx);
    450  // Change the state of the object with this. The broadcast argument
    451  // determines if the onreadystatechange listener should be called.
    452  nsresult ChangeState(uint16_t aState, bool aBroadcast = true);
    453  already_AddRefed<nsILoadGroup> GetLoadGroup() const;
    454 
    455  // Finds a preload for this XHR.  If it is found it's removed from the preload
    456  // table of the document and marked as used.  The called doesn't need to do
    457  // any more comparative checks.
    458  already_AddRefed<PreloaderBase> FindPreload();
    459  // If no or unknown mime type is set on the channel this method ensures it's
    460  // set to "text/xml".
    461  void EnsureChannelContentType();
    462 
    463  // Gets the value of the final content-type header from the channel.
    464  bool GetContentType(nsACString& aValue) const;
    465 
    466  already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
    467  already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
    468 
    469  void TruncateResponseText();
    470 
    471  bool IsSystemXHR() const;
    472  bool InUploadPhase() const;
    473 
    474  void OnBodyParseEnd();
    475  void ChangeStateToDone(bool aWasSync);
    476  void ChangeStateToDoneInternal();
    477 
    478  void StartProgressEventTimer();
    479  void StopProgressEventTimer();
    480 
    481  void MaybeCreateBlobStorage();
    482 
    483  nsresult OnRedirectVerifyCallback(nsresult result, bool stripAuth = false);
    484 
    485  nsIEventTarget* GetTimerEventTarget();
    486 
    487  nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable);
    488 
    489  void DispatchOrStoreEvent(DOMEventTargetHelper* aTarget, Event* aEvent);
    490 
    491  already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
    492 
    493  void SuspendEventDispatching();
    494  void ResumeEventDispatching();
    495 
    496  void AbortInternal(ErrorResult& aRv);
    497 
    498  bool BadContentRangeRequested();
    499  RefPtr<mozilla::net::ContentRange> GetRequestedContentRange() const;
    500  void GetContentRangeHeader(nsACString&) const;
    501 
    502  struct PendingEvent {
    503    RefPtr<DOMEventTargetHelper> mTarget;
    504    RefPtr<Event> mEvent;
    505  };
    506 
    507  nsTArray<PendingEvent> mPendingEvents;
    508 
    509  nsCOMPtr<nsIPrincipal> mPrincipal;
    510  nsCOMPtr<nsIChannel> mChannel;
    511  nsCString mRequestMethod;
    512  nsCOMPtr<nsIURI> mRequestURL;
    513  RefPtr<Document> mResponseXML;
    514 
    515  nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
    516 
    517  nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
    518 
    519  RefPtr<PerformanceStorage> mPerformanceStorage;
    520  nsCOMPtr<nsICSPEventListener> mCSPEventListener;
    521 
    522  // used to implement getAllResponseHeaders()
    523  class nsHeaderVisitor : public nsIHttpHeaderVisitor {
    524    struct HeaderEntry final {
    525      nsCString mName;
    526      nsCString mValue;
    527 
    528      HeaderEntry(const nsACString& aName, const nsACString& aValue)
    529          : mName(aName), mValue(aValue) {}
    530 
    531      bool operator==(const HeaderEntry& aOther) const {
    532        return mName == aOther.mName;
    533      }
    534 
    535      bool operator<(const HeaderEntry& aOther) const {
    536        uint32_t selfLen = mName.Length();
    537        uint32_t otherLen = aOther.mName.Length();
    538        uint32_t min = std::min(selfLen, otherLen);
    539        for (uint32_t i = 0; i < min; ++i) {
    540          unsigned char self = mName[i];
    541          unsigned char other = aOther.mName[i];
    542          MOZ_ASSERT(!(self >= 'A' && self <= 'Z'));
    543          MOZ_ASSERT(!(other >= 'A' && other <= 'Z'));
    544          if (self == other) {
    545            continue;
    546          }
    547          if (self >= 'a' && self <= 'z') {
    548            self -= 0x20;
    549          }
    550          if (other >= 'a' && other <= 'z') {
    551            other -= 0x20;
    552          }
    553          return self < other;
    554        }
    555        return selfLen < otherLen;
    556      }
    557    };
    558 
    559   public:
    560    NS_DECL_ISUPPORTS
    561    NS_DECL_NSIHTTPHEADERVISITOR
    562    nsHeaderVisitor(const XMLHttpRequestMainThread& aXMLHttpRequest,
    563                    NotNull<nsIHttpChannel*> aHttpChannel);
    564    const nsACString& Headers() {
    565      for (uint32_t i = 0; i < mHeaderList.Length(); i++) {
    566        HeaderEntry& header = mHeaderList.ElementAt(i);
    567 
    568        mHeaders.Append(header.mName);
    569        mHeaders.AppendLiteral(": ");
    570        mHeaders.Append(header.mValue);
    571        mHeaders.AppendLiteral("\r\n");
    572      }
    573      return mHeaders;
    574    }
    575 
    576   private:
    577    virtual ~nsHeaderVisitor();
    578 
    579    nsTArray<HeaderEntry> mHeaderList;
    580    nsCString mHeaders;
    581    const XMLHttpRequestMainThread& mXHR;
    582    NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
    583  };
    584 
    585  // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
    586  // BLOB responseTypes
    587  nsCString mResponseBody;
    588 
    589  // The text version of our response body. This is incrementally decoded into
    590  // as we receive network data. However for the DEFAULT responseType we
    591  // lazily decode into this from mResponseBody only when .responseText is
    592  // accessed.
    593  // Only used for DEFAULT and TEXT responseTypes.
    594  XMLHttpRequestString mResponseText;
    595 
    596  // For DEFAULT responseType we use this to keep track of how far we've
    597  // lazily decoded from mResponseBody to mResponseText
    598  uint32_t mResponseBodyDecodedPos;
    599 
    600  // Decoder used for decoding into mResponseText
    601  // Only used for DEFAULT, TEXT and JSON responseTypes.
    602  // In cases where we've only received half a surrogate, the decoder itself
    603  // carries the state to remember this. Next time we receive more data we
    604  // simply feed the new data into the decoder which will handle the second
    605  // part of the surrogate.
    606  mozilla::UniquePtr<mozilla::Decoder> mDecoder;
    607 
    608  void MatchCharsetAndDecoderToResponseDocument();
    609 
    610  XMLHttpRequestResponseType mResponseType;
    611 
    612  RefPtr<BlobImpl> mResponseBlobImpl;
    613 
    614  // This is the cached blob-response, created only at the first GetResponse()
    615  // call.
    616  RefPtr<Blob> mResponseBlob;
    617 
    618  // We stream data to mBlobStorage when response type is "blob".
    619  RefPtr<MutableBlobStorage> mBlobStorage;
    620 
    621  nsString mOverrideMimeType;
    622 
    623  /**
    624   * The notification callbacks the channel had when Send() was
    625   * called.  We want to forward things here as needed.
    626   */
    627  nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
    628  /**
    629   * Sink interfaces that we implement that mNotificationCallbacks may
    630   * want to also be notified for.  These are inited lazily if we're
    631   * asked for the relevant interface.
    632   */
    633  nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
    634  nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
    635 
    636  nsCOMPtr<nsIURI> mBaseURI;
    637  nsCOMPtr<nsILoadGroup> mLoadGroup;
    638 
    639  Maybe<ClientInfo> mClientInfo;
    640  Maybe<ServiceWorkerDescriptor> mController;
    641 
    642  uint16_t mState;
    643 
    644  // If true, this object is used by the worker's XMLHttpRequest.
    645  bool mForWorker;
    646 
    647  bool mFlagSynchronous;
    648  bool mFlagAborted;
    649  bool mFlagParseBody;
    650  bool mFlagSyncLooping;
    651  bool mFlagBackgroundRequest;
    652  bool mFlagHadUploadListenersOnSend;
    653  bool mFlagACwithCredentials;
    654  bool mFlagTimedOut;
    655  bool mFlagDeleted;
    656 
    657  // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
    658  // finishes downloading (or an error/abort has occurred during either phase).
    659  // Used to guard against the user trying to alter headers/etc when it's too
    660  // late, and ensure the XHR only handles one in-flight request at once.
    661  bool mFlagSend;
    662 
    663  RefPtr<XMLHttpRequestUpload> mUpload;
    664  int64_t mUploadTransferred;
    665  int64_t mUploadTotal;
    666  bool mUploadComplete;
    667  bool mProgressSinceLastProgressEvent;
    668 
    669  // Timeout support
    670  PRTime mRequestSentTime;
    671  uint32_t mTimeoutMilliseconds;
    672  nsCOMPtr<nsITimer> mTimeoutTimer;
    673  void StartTimeoutTimer();
    674  void HandleTimeoutCallback();
    675  void CancelTimeoutTimer();
    676 
    677  nsCOMPtr<nsIRunnable> mResumeTimeoutRunnable;
    678 
    679  nsCOMPtr<nsITimer> mSyncTimeoutTimer;
    680 
    681  enum SyncTimeoutType { eErrorOrExpired, eTimerStarted, eNoTimerNeeded };
    682 
    683  SyncTimeoutType MaybeStartSyncTimeoutTimer();
    684  void HandleSyncTimeoutTimer();
    685  void CancelSyncTimeoutTimer();
    686 
    687  ErrorType mErrorLoad;
    688  nsresult mErrorLoadDetail;
    689  bool mErrorParsingXML;
    690  bool mWaitingForOnStopRequest;
    691  bool mProgressTimerIsActive;
    692  bool mIsHtml;
    693  bool mWarnAboutSyncHtml;
    694  int64_t mLoadTotal;  // -1 if not known.
    695  // Number of HTTP message body bytes received so far. This quantity is
    696  // in the same units as Content-Length and mLoadTotal, and hence counts
    697  // compressed bytes when the channel has gzip Content-Encoding. If the
    698  // channel does not have Content-Encoding, this will be the same as
    699  // mDataReceived except between the OnProgress that changes mLoadTransferred
    700  // and the corresponding OnDataAvailable (which changes mDataReceived).
    701  // Ordering of OnProgress and OnDataAvailable is undefined.
    702  int64_t mLoadTransferred;
    703  nsCOMPtr<nsITimer> mProgressNotifier;
    704  void HandleProgressTimerCallback();
    705 
    706  bool mIsSystem;
    707  bool mIsAnon;
    708 
    709  // Prevent duplicate OnStopRequest calls due to the explicit
    710  // OnStopRequest in the sync path of SendInternal
    711  bool mAlreadyGotStopRequest;
    712 
    713  /**
    714   * Close the XMLHttpRequest's channels.
    715   */
    716  void CloseRequest(nsresult detail);
    717 
    718  void TerminateOngoingFetch(nsresult detail);
    719 
    720  /**
    721   * Close the XMLHttpRequest's channels and dispatch appropriate progress
    722   * events.
    723   *
    724   * @param aType The progress event type.
    725   */
    726  void CloseRequestWithError(const ErrorProgressEventType& aType);
    727 
    728  nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
    729  nsCOMPtr<nsIChannel> mNewRedirectChannel;
    730 
    731  JS::Heap<JS::Value> mResultJSON;
    732 
    733  RefPtr<ArrayBufferBuilder> mArrayBufferBuilder;
    734  JS::Heap<JSObject*> mResultArrayBuffer;
    735  bool mIsMappedArrayBuffer;
    736 
    737  void ResetResponse();
    738 
    739  bool ShouldBlockAuthPrompt();
    740 
    741  RequestHeaders mAuthorRequestHeaders;
    742 
    743  // Helper object to manage our XPCOM scriptability bits
    744  nsXMLHttpRequestXPCOMifier* mXPCOMifier;
    745 
    746  // When this is set to true, the event dispatching is suspended. This is
    747  // useful to change the correct state when XHR is working sync.
    748  bool mEventDispatchingSuspended;
    749 
    750  // True iff mDecoder has processed the end of the stream.
    751  // Used in lazy decoding to distinguish between having
    752  // processed all the bytes but not the EOF and having
    753  // processed all the bytes and the EOF.
    754  bool mEofDecoded;
    755 
    756  // This flag will be set in `Send()` when we successfully reuse a "fetch"
    757  // preload to satisfy this XHR.
    758  bool mFromPreload = false;
    759 
    760  // Our parse-end listener, if we are parsing.
    761  RefPtr<nsXHRParseEndListener> mParseEndListener;
    762 
    763  XMLHttpRequestDoneNotifier* mDelayedDoneNotifier;
    764  void DisconnectDoneNotifier();
    765 
    766  // Any stack information for the point the XHR was opened. This is deleted
    767  // after the XHR is opened, to avoid retaining references to the worker.
    768  UniquePtr<SerializedStackHolder> mOriginStack;
    769 
    770  static bool sDontWarnAboutSyncXHR;
    771 };
    772 
    773 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR {
    774 public:
    775  AutoDontWarnAboutSyncXHR()
    776      : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR()) {
    777    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
    778  }
    779 
    780  ~AutoDontWarnAboutSyncXHR() {
    781    XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
    782  }
    783 
    784 private:
    785  bool mOldVal;
    786 };
    787 
    788 // A shim class designed to expose the non-DOM interfaces of
    789 // XMLHttpRequest via XPCOM stuff.
    790 class nsXMLHttpRequestXPCOMifier final : public nsIStreamListener,
    791                                         public nsIChannelEventSink,
    792                                         public nsIAsyncVerifyRedirectCallback,
    793                                         public nsIProgressEventSink,
    794                                         public nsIInterfaceRequestor,
    795                                         public nsITimerCallback,
    796                                         public nsINamed {
    797  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    798  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
    799                                           nsIStreamListener)
    800 
    801  explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR)
    802      : mXHR(aXHR) {}
    803 
    804 private:
    805  ~nsXMLHttpRequestXPCOMifier() {
    806    if (mXHR) {
    807      mXHR->mXPCOMifier = nullptr;
    808    }
    809  }
    810 
    811 public:
    812  NS_FORWARD_NSISTREAMLISTENER(mXHR->)
    813  NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
    814  NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
    815  NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR->)
    816  NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
    817  NS_FORWARD_NSITIMERCALLBACK(mXHR->)
    818  NS_FORWARD_NSINAMED(mXHR->)
    819 
    820  NS_DECL_NSIINTERFACEREQUESTOR
    821 
    822 private:
    823  RefPtr<XMLHttpRequestMainThread> mXHR;
    824 };
    825 
    826 class XMLHttpRequestDoneNotifier : public Runnable {
    827 public:
    828  explicit XMLHttpRequestDoneNotifier(XMLHttpRequestMainThread* aXHR)
    829      : Runnable("XMLHttpRequestDoneNotifier"), mXHR(aXHR) {}
    830 
    831  NS_IMETHOD Run() override {
    832    if (mXHR) {
    833      RefPtr<XMLHttpRequestMainThread> xhr = mXHR;
    834      // ChangeStateToDoneInternal ends up calling Disconnect();
    835      xhr->ChangeStateToDoneInternal();
    836      MOZ_ASSERT(!mXHR);
    837    }
    838    return NS_OK;
    839  }
    840 
    841  void Disconnect() { mXHR = nullptr; }
    842 
    843 private:
    844  RefPtr<XMLHttpRequestMainThread> mXHR;
    845 };
    846 
    847 class nsXHRParseEndListener : public nsIDOMEventListener {
    848 public:
    849  NS_DECL_ISUPPORTS
    850  NS_IMETHOD HandleEvent(Event* event) override {
    851    if (mXHR) {
    852      mXHR->OnBodyParseEnd();
    853    }
    854    mXHR = nullptr;
    855    return NS_OK;
    856  }
    857 
    858  explicit nsXHRParseEndListener(XMLHttpRequestMainThread* aXHR) : mXHR(aXHR) {}
    859 
    860  void SetIsStale() { mXHR = nullptr; }
    861 
    862 private:
    863  virtual ~nsXHRParseEndListener() = default;
    864 
    865  XMLHttpRequestMainThread* mXHR;
    866 };
    867 
    868 }  // namespace dom
    869 }  // namespace mozilla
    870 
    871 #endif  // mozilla_dom_XMLHttpRequestMainThread_h