LCOV - code coverage report
Current view: top level - dom/xhr - XMLHttpRequestMainThread.h (source / functions) Hit Total Coverage
Test: output.info Lines: 38 133 28.6 %
Date: 2017-07-14 16:53:18 Functions: 28 79 35.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "nsAutoPtr.h"
      12             : #include "nsIXMLHttpRequest.h"
      13             : #include "nsISupportsUtils.h"
      14             : #include "nsIURI.h"
      15             : #include "nsIHttpChannel.h"
      16             : #include "nsIDocument.h"
      17             : #include "nsIStreamListener.h"
      18             : #include "nsWeakReference.h"
      19             : #include "nsIChannelEventSink.h"
      20             : #include "nsIAsyncVerifyRedirectCallback.h"
      21             : #include "nsIInterfaceRequestor.h"
      22             : #include "nsIHttpHeaderVisitor.h"
      23             : #include "nsIProgressEventSink.h"
      24             : #include "nsJSUtils.h"
      25             : #include "nsTArray.h"
      26             : #include "nsITimer.h"
      27             : #include "nsIPrincipal.h"
      28             : #include "nsIScriptObjectPrincipal.h"
      29             : #include "nsISizeOfEventTarget.h"
      30             : #include "nsIXPConnect.h"
      31             : #include "nsIInputStream.h"
      32             : #include "mozilla/Assertions.h"
      33             : #include "mozilla/Attributes.h"
      34             : #include "mozilla/DOMEventTargetHelper.h"
      35             : #include "mozilla/MemoryReporting.h"
      36             : #include "mozilla/NotNull.h"
      37             : #include "mozilla/dom/MutableBlobStorage.h"
      38             : #include "mozilla/dom/BodyExtractor.h"
      39             : #include "mozilla/dom/TypedArray.h"
      40             : #include "mozilla/dom/File.h"
      41             : #include "mozilla/dom/FormData.h"
      42             : #include "mozilla/dom/URLSearchParams.h"
      43             : #include "mozilla/dom/XMLHttpRequest.h"
      44             : #include "mozilla/dom/XMLHttpRequestBinding.h"
      45             : #include "mozilla/dom/XMLHttpRequestEventTarget.h"
      46             : #include "mozilla/dom/XMLHttpRequestString.h"
      47             : #include "mozilla/Encoding.h"
      48             : 
      49             : #ifdef Status
      50             : /* Xlib headers insist on this for some reason... Nuke it because
      51             :    it'll override our member name */
      52             : #undef Status
      53             : #endif
      54             : 
      55             : class nsIJARChannel;
      56             : class nsILoadGroup;
      57             : class nsIJSID;
      58             : 
      59             : namespace mozilla {
      60             : namespace dom {
      61             : 
      62             : class BlobSet;
      63             : class DOMString;
      64             : class XMLHttpRequestUpload;
      65             : struct OriginAttributesDictionary;
      66             : 
      67             : // A helper for building up an ArrayBuffer object's data
      68             : // before creating the ArrayBuffer itself.  Will do doubling
      69             : // based reallocation, up to an optional maximum growth given.
      70             : //
      71             : // When all the data has been appended, call getArrayBuffer,
      72             : // passing in the JSContext* for which the ArrayBuffer object
      73             : // is to be created.  This also implicitly resets the builder,
      74             : // or it can be reset explicitly at any point by calling reset().
      75             : class ArrayBufferBuilder
      76             : {
      77             :   uint8_t* mDataPtr;
      78             :   uint32_t mCapacity;
      79             :   uint32_t mLength;
      80             :   void* mMapPtr;
      81             : public:
      82             :   ArrayBufferBuilder();
      83             :   ~ArrayBufferBuilder();
      84             : 
      85             :   void reset();
      86             : 
      87             :   // Will truncate if aNewCap is < length().
      88             :   bool setCapacity(uint32_t aNewCap);
      89             : 
      90             :   // Append aDataLen bytes from data to the current buffer.  If we
      91             :   // need to grow the buffer, grow by doubling the size up to a
      92             :   // maximum of aMaxGrowth (if given).  If aDataLen is greater than
      93             :   // what the new capacity would end up as, then grow by aDataLen.
      94             :   //
      95             :   // The data parameter must not overlap with anything beyond the
      96             :   // builder's current valid contents [0..length)
      97             :   bool append(const uint8_t* aNewData, uint32_t aDataLen,
      98             :               uint32_t aMaxGrowth = 0);
      99             : 
     100           0 :   uint32_t length()   { return mLength; }
     101           0 :   uint32_t capacity() { return mCapacity; }
     102             : 
     103             :   JSObject* getArrayBuffer(JSContext* aCx);
     104             : 
     105             :   // Memory mapping to starting position of file(aFile) in the zip
     106             :   // package(aJarFile).
     107             :   //
     108             :   // The file in the zip package has to be uncompressed and the starting
     109             :   // position of the file must be aligned according to array buffer settings
     110             :   // in JS engine.
     111             :   nsresult mapToFileInPackage(const nsCString& aFile, nsIFile* aJarFile);
     112             : 
     113             : protected:
     114             :   static bool areOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
     115             :                                     const uint8_t* aStart2, uint32_t aLength2);
     116             : };
     117             : 
     118             : class nsXMLHttpRequestXPCOMifier;
     119             : 
     120           3 : class RequestHeaders
     121             : {
     122           0 :   struct RequestHeader
     123             :   {
     124             :     nsCString mName;
     125             :     nsCString mValue;
     126             :   };
     127             :   nsTArray<RequestHeader> mHeaders;
     128             :   RequestHeader* Find(const nsACString& aName);
     129             : 
     130             : public:
     131             :   class CharsetIterator
     132             :   {
     133             :     bool mValid;
     134             :     int32_t mCurPos, mCurLen, mCutoff;
     135             :     nsACString& mSource;
     136             : 
     137             :   public:
     138             :     explicit CharsetIterator(nsACString& aSource);
     139             :     bool Equals(const nsACString& aOther, const nsCStringComparator& aCmp) const;
     140             :     void Replace(const nsACString& aReplacement);
     141             :     bool Next();
     142             :   };
     143             : 
     144             :   bool Has(const char* aName);
     145             :   bool Has(const nsACString& aName);
     146             :   void Get(const char* aName, nsACString& aValue);
     147             :   void Get(const nsACString& aName, nsACString& aValue);
     148             :   void Set(const char* aName, const nsACString& aValue);
     149             :   void Set(const nsACString& aName, const nsACString& aValue);
     150             :   void MergeOrSet(const char* aName, const nsACString& aValue);
     151             :   void MergeOrSet(const nsACString& aName, const nsACString& aValue);
     152             :   void Clear();
     153             :   void ApplyToChannel(nsIHttpChannel* aChannel) const;
     154             :   void GetCORSUnsafeHeaders(nsTArray<nsCString>& aArray) const;
     155             : };
     156             : 
     157             : // Make sure that any non-DOM interfaces added here are also added to
     158             : // nsXMLHttpRequestXPCOMifier.
     159             : class XMLHttpRequestMainThread final : public XMLHttpRequest,
     160             :                                        public nsIXMLHttpRequest,
     161             :                                        public nsIJSXMLHttpRequest,
     162             :                                        public nsIStreamListener,
     163             :                                        public nsIChannelEventSink,
     164             :                                        public nsIProgressEventSink,
     165             :                                        public nsIInterfaceRequestor,
     166             :                                        public nsSupportsWeakReference,
     167             :                                        public nsITimerCallback,
     168             :                                        public nsISizeOfEventTarget,
     169             :                                        public nsINamed,
     170             :                                        public MutableBlobStorageCallback
     171             : {
     172             :   friend class nsXHRParseEndListener;
     173             :   friend class nsXMLHttpRequestXPCOMifier;
     174             : 
     175             : public:
     176             :   enum class ProgressEventType : uint8_t {
     177             :     loadstart,
     178             :     progress,
     179             :     error,
     180             :     abort,
     181             :     timeout,
     182             :     load,
     183             :     loadend,
     184             :     ENUM_MAX
     185             :   };
     186             : 
     187             :   enum class ErrorType : uint16_t {
     188             :     eOK,
     189             :     eRequest,
     190             :     eUnreachable,
     191             :     eChannelOpen,
     192             :     eRedirect,
     193             :     ENUM_MAX
     194             :   };
     195             : 
     196             :   XMLHttpRequestMainThread();
     197             : 
     198           3 :   void Construct(nsIPrincipal* aPrincipal,
     199             :                  nsIGlobalObject* aGlobalObject,
     200             :                  nsIURI* aBaseURI = nullptr,
     201             :                  nsILoadGroup* aLoadGroup = nullptr)
     202             :   {
     203           3 :     MOZ_ASSERT(aPrincipal);
     204           3 :     MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(
     205             :       aGlobalObject), win->IsInnerWindow());
     206           3 :     mPrincipal = aPrincipal;
     207           3 :     BindToOwner(aGlobalObject);
     208           3 :     mBaseURI = aBaseURI;
     209           3 :     mLoadGroup = aLoadGroup;
     210           3 :   }
     211             : 
     212             :   void InitParameters(bool aAnon, bool aSystem);
     213             : 
     214           3 :   void SetParameters(bool aAnon, bool aSystem)
     215             :   {
     216           3 :     mIsAnon = aAnon || aSystem;
     217           3 :     mIsSystem = aSystem;
     218           3 :   }
     219             : 
     220             :   NS_DECL_ISUPPORTS_INHERITED
     221             : 
     222             :   // nsIXMLHttpRequest
     223             :   NS_DECL_NSIXMLHTTPREQUEST
     224             : 
     225             :   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(XMLHttpRequestEventTarget::)
     226             : 
     227             :   // nsIStreamListener
     228             :   NS_DECL_NSISTREAMLISTENER
     229             : 
     230             :   // nsIRequestObserver
     231             :   NS_DECL_NSIREQUESTOBSERVER
     232             : 
     233             :   // nsIChannelEventSink
     234             :   NS_DECL_NSICHANNELEVENTSINK
     235             : 
     236             :   // nsIProgressEventSink
     237             :   NS_DECL_NSIPROGRESSEVENTSINK
     238             : 
     239             :   // nsIInterfaceRequestor
     240             :   NS_DECL_NSIINTERFACEREQUESTOR
     241             : 
     242             :   // nsITimerCallback
     243             :   NS_DECL_NSITIMERCALLBACK
     244             : 
     245             :   // nsINamed
     246             :   NS_DECL_NSINAMED
     247             : 
     248             :   // nsISizeOfEventTarget
     249             :   virtual size_t
     250             :     SizeOfEventTargetIncludingThis(MallocSizeOf aMallocSizeOf) const override;
     251             : 
     252         192 :   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(XMLHttpRequestEventTarget)
     253             : 
     254             :   // states
     255             :   virtual uint16_t ReadyState() const override;
     256             : 
     257             :   // request
     258             :   nsresult CreateChannel();
     259             :   nsresult InitiateFetch(nsIInputStream* aUploadStream,
     260             :                          int64_t aUploadLength,
     261             :                          nsACString& aUploadContentType);
     262             : 
     263             :   virtual void
     264             :   Open(const nsACString& aMethod, const nsAString& aUrl,
     265             :        ErrorResult& aRv) override;
     266             : 
     267             :   virtual void
     268             :   Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
     269             :        const nsAString& aUsername, const nsAString& aPassword,
     270             :        ErrorResult& aRv) override;
     271             : 
     272             :   nsresult
     273             :   Open(const nsACString& aMethod,
     274             :        const nsACString& aUrl,
     275             :        bool aAsync,
     276             :        const nsAString& aUsername,
     277             :        const nsAString& aPassword);
     278             : 
     279             :   virtual void
     280           0 :   SetRequestHeader(const nsACString& aName, const nsACString& aValue,
     281             :                    ErrorResult& aRv) override
     282             :   {
     283           0 :     aRv = SetRequestHeader(aName, aValue);
     284           0 :   }
     285             : 
     286             :   virtual uint32_t
     287           0 :   Timeout() const override
     288             :   {
     289           0 :     return mTimeoutMilliseconds;
     290             :   }
     291             : 
     292             :   virtual void
     293             :   SetTimeout(uint32_t aTimeout, ErrorResult& aRv) override;
     294             : 
     295             :   virtual bool WithCredentials() const override;
     296             : 
     297             :   virtual void
     298             :   SetWithCredentials(bool aWithCredentials, ErrorResult& aRv) override;
     299             : 
     300             :   virtual XMLHttpRequestUpload*
     301             :   GetUpload(ErrorResult& aRv) override;
     302             : 
     303             : private:
     304             :   virtual ~XMLHttpRequestMainThread();
     305             : 
     306             :   nsresult SendInternal(const BodyExtractorBase* aBody);
     307             : 
     308             :   bool IsCrossSiteCORSRequest() const;
     309             :   bool IsDeniedCrossSiteCORSRequest();
     310             : 
     311             :   // Tell our channel what network interface ID we were told to use.
     312             :   // If it's an HTTP channel and we were told to use a non-default
     313             :   // interface ID.
     314             :   void PopulateNetworkInterfaceId();
     315             : 
     316             :   void UnsuppressEventHandlingAndResume();
     317             : 
     318             :   // Check pref "dom.mapped_arraybuffer.enabled" to make sure ArrayBuffer is
     319             :   // supported.
     320             :   static bool IsMappedArrayBufferEnabled();
     321             : 
     322             :   // Check pref "dom.xhr.lowercase_header.enabled" to make sure lowercased
     323             :   // response header is supported.
     324             :   static bool IsLowercaseResponseHeader();
     325             : 
     326             :   void MaybeLowerChannelPriority();
     327             : 
     328             : public:
     329             :   virtual void
     330           0 :   Send(JSContext* /*aCx*/, ErrorResult& aRv) override
     331             :   {
     332           0 :     aRv = SendInternal(nullptr);
     333           0 :   }
     334             : 
     335             :   virtual void
     336           0 :   Send(JSContext* /*aCx*/, const ArrayBuffer& aArrayBuffer,
     337             :        ErrorResult& aRv) override
     338             :   {
     339           0 :     BodyExtractor<const ArrayBuffer> body(&aArrayBuffer);
     340           0 :     aRv = SendInternal(&body);
     341           0 :   }
     342             : 
     343             :   virtual void
     344           0 :   Send(JSContext* /*aCx*/, const ArrayBufferView& aArrayBufferView,
     345             :        ErrorResult& aRv) override
     346             :   {
     347           0 :     BodyExtractor<const ArrayBufferView> body(&aArrayBufferView);
     348           0 :     aRv = SendInternal(&body);
     349           0 :   }
     350             : 
     351             :   virtual void
     352           0 :   Send(JSContext* /*aCx*/, Blob& aBlob, ErrorResult& aRv) override
     353             :   {
     354           0 :     BodyExtractor<nsIXHRSendable> body(&aBlob);
     355           0 :     aRv = SendInternal(&body);
     356           0 :   }
     357             : 
     358           0 :   virtual void Send(JSContext* /*aCx*/, URLSearchParams& aURLSearchParams,
     359             :                     ErrorResult& aRv) override
     360             :   {
     361           0 :     BodyExtractor<nsIXHRSendable> body(&aURLSearchParams);
     362           0 :     aRv = SendInternal(&body);
     363           0 :   }
     364             : 
     365             :   virtual void
     366           0 :   Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv) override
     367             :   {
     368           0 :     BodyExtractor<nsIDocument> body(&aDoc);
     369           0 :     aRv = SendInternal(&body);
     370           0 :   }
     371             : 
     372             :   virtual void
     373           0 :   Send(JSContext* aCx, const nsAString& aString, ErrorResult& aRv) override
     374             :   {
     375           0 :     if (DOMStringIsNull(aString)) {
     376           0 :       Send(aCx, aRv);
     377             :     } else {
     378           0 :       BodyExtractor<const nsAString> body(&aString);
     379           0 :       aRv = SendInternal(&body);
     380             :     }
     381           0 :   }
     382             : 
     383             :   virtual void
     384           0 :   Send(JSContext* /*aCx*/, FormData& aFormData, ErrorResult& aRv) override
     385             :   {
     386           0 :     BodyExtractor<nsIXHRSendable> body(&aFormData);
     387           0 :     aRv = SendInternal(&body);
     388           0 :   }
     389             : 
     390             :   virtual void
     391           0 :   Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv) override
     392             :   {
     393           0 :     NS_ASSERTION(aStream, "Null should go to string version");
     394           0 :     BodyExtractor<nsIInputStream> body(aStream);
     395           0 :     aRv = SendInternal(&body);
     396           0 :   }
     397             : 
     398             :   void
     399             :   RequestErrorSteps(const ProgressEventType aEventType,
     400             :                     const nsresult aOptionalException,
     401             :                     ErrorResult& aRv);
     402             : 
     403             :   void
     404           0 :   Abort()
     405             :   {
     406           0 :     ErrorResult rv;
     407           0 :     Abort(rv);
     408           0 :     MOZ_ASSERT(!rv.Failed());
     409           0 :   }
     410             : 
     411             :   virtual void
     412             :   Abort(ErrorResult& aRv) override;
     413             : 
     414             :   // response
     415             :   virtual void
     416             :   GetResponseURL(nsAString& aUrl) override;
     417             : 
     418             :   virtual uint32_t
     419             :   GetStatus(ErrorResult& aRv) override;
     420             : 
     421             :   virtual void
     422             :   GetStatusText(nsACString& aStatusText, ErrorResult& aRv) override;
     423             : 
     424             :   virtual void
     425             :   GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
     426             :                     ErrorResult& aRv) override;
     427             : 
     428             :   void
     429             :   GetResponseHeader(const nsAString& aHeader, nsAString& aResult,
     430             :                     ErrorResult& aRv)
     431             :   {
     432             :     nsAutoCString result;
     433             :     GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
     434             :     if (result.IsVoid()) {
     435             :       aResult.SetIsVoid(true);
     436             :     }
     437             :     else {
     438             :       // The result value should be inflated:
     439             :       CopyASCIItoUTF16(result, aResult);
     440             :     }
     441             :   }
     442             : 
     443             :   virtual void
     444             :   GetAllResponseHeaders(nsACString& aResponseHeaders,
     445             :                         ErrorResult& aRv) override;
     446             : 
     447             :   bool IsSafeHeader(const nsACString& aHeaderName,
     448             :                     NotNull<nsIHttpChannel*> aHttpChannel) const;
     449             : 
     450             :   virtual void
     451             :   OverrideMimeType(const nsAString& aMimeType, ErrorResult& aRv) override;
     452             : 
     453             :   virtual XMLHttpRequestResponseType
     454           2 :   ResponseType() const override
     455             :   {
     456           2 :     return XMLHttpRequestResponseType(mResponseType);
     457             :   }
     458             : 
     459             :   virtual void
     460             :   SetResponseType(XMLHttpRequestResponseType aType,
     461             :                   ErrorResult& aRv) override;
     462             : 
     463             :   virtual void
     464             :   GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
     465             :               ErrorResult& aRv) override;
     466             : 
     467             :   virtual void
     468             :   GetResponseText(DOMString& aResponseText, ErrorResult& aRv) override;
     469             : 
     470             :   void
     471             :   GetResponseText(XMLHttpRequestStringSnapshot& aSnapshot,
     472             :                   ErrorResult& aRv);
     473             : 
     474             :   virtual nsIDocument*
     475             :   GetResponseXML(ErrorResult& aRv) override;
     476             : 
     477             :   virtual bool
     478             :   MozBackgroundRequest() const override;
     479             : 
     480             :   virtual void
     481             :   SetMozBackgroundRequest(bool aMozBackgroundRequest, ErrorResult& aRv) override;
     482             : 
     483             :   virtual uint16_t
     484           0 :   ErrorCode() const override
     485             :   {
     486           0 :     return static_cast<uint16_t>(mErrorLoad);
     487             :   }
     488             : 
     489             :   virtual bool
     490             :   MozAnon() const override;
     491             : 
     492             :   virtual bool
     493             :   MozSystem() const override;
     494             : 
     495             :   virtual nsIChannel*
     496           0 :   GetChannel() const override
     497             :   {
     498           0 :     return mChannel;
     499             :   }
     500             : 
     501             :   virtual void
     502           0 :   GetNetworkInterfaceId(nsACString& aId) const override
     503             :   {
     504           0 :     aId = mNetworkInterfaceId;
     505           0 :   }
     506             : 
     507             :   virtual void
     508           0 :   SetNetworkInterfaceId(const nsACString& aId) override
     509             :   {
     510           0 :     mNetworkInterfaceId = aId;
     511           0 :   }
     512             : 
     513             :   // We need a GetInterface callable from JS for chrome JS
     514             :   virtual void
     515             :   GetInterface(JSContext* aCx, nsIJSID* aIID,
     516             :                JS::MutableHandle<JS::Value> aRetval,
     517             :                ErrorResult& aRv) override;
     518             : 
     519             :   // This fires a trusted readystatechange event, which is not cancelable and
     520             :   // doesn't bubble.
     521             :   nsresult FireReadystatechangeEvent();
     522             :   void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
     523             :                              const ProgressEventType aType,
     524             :                              int64_t aLoaded, int64_t aTotal);
     525             : 
     526             :   // This is called by the factory constructor.
     527             :   nsresult Init();
     528             : 
     529             :   nsresult init(nsIPrincipal* principal,
     530             :                 nsPIDOMWindowInner* globalObject,
     531             :                 nsIURI* baseURI);
     532             : 
     533             :   void SetRequestObserver(nsIRequestObserver* aObserver);
     534             : 
     535          65 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(XMLHttpRequestMainThread,
     536             :                                                          XMLHttpRequest)
     537             :   virtual bool IsCertainlyAliveForCC() const override;
     538             : 
     539             :   bool AllowUploadProgress();
     540             : 
     541             :   virtual void DisconnectFromOwner() override;
     542             : 
     543          18 :   static void SetDontWarnAboutSyncXHR(bool aVal)
     544             :   {
     545          18 :     sDontWarnAboutSyncXHR = aVal;
     546          18 :   }
     547           9 :   static bool DontWarnAboutSyncXHR()
     548             :   {
     549           9 :     return sDontWarnAboutSyncXHR;
     550             :   }
     551             : 
     552             :   virtual void
     553             :   SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary& aAttrs) override;
     554             : 
     555             :   void BlobStoreCompleted(MutableBlobStorage* aBlobStorage,
     556             :                           Blob* aBlob,
     557             :                           nsresult aResult) override;
     558             : 
     559             :   void
     560             :   LocalFileToBlobCompleted(Blob* aBlob);
     561             : 
     562             : protected:
     563             :   // XHR states are meant to mirror the XHR2 spec:
     564             :   //   https://xhr.spec.whatwg.org/#states
     565             :   enum class State : uint8_t {
     566             :     unsent,           // object has been constructed.
     567             :     opened,           // open() has been successfully invoked.
     568             :     headers_received, // redirects followed and response headers received.
     569             :     loading,          // response body is being received.
     570             :     done,             // data transfer concluded, whether success or error.
     571             :   };
     572             : 
     573             :   nsresult DetectCharset();
     574             :   nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen);
     575             :   static nsresult StreamReaderFunc(nsIInputStream* in,
     576             :                                    void* closure,
     577             :                                    const char* fromRawSegment,
     578             :                                    uint32_t toOffset,
     579             :                                    uint32_t count,
     580             :                                    uint32_t *writeCount);
     581             :   nsresult CreateResponseParsedJSON(JSContext* aCx);
     582             :   void CreatePartialBlob(ErrorResult& aRv);
     583             :   // Change the state of the object with this. The broadcast argument
     584             :   // determines if the onreadystatechange listener should be called.
     585             :   nsresult ChangeState(State aState, bool aBroadcast = true);
     586             :   already_AddRefed<nsILoadGroup> GetLoadGroup() const;
     587             :   nsIURI *GetBaseURI();
     588             : 
     589             :   already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
     590             :   already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
     591             : 
     592             :   void TruncateResponseText();
     593             : 
     594             :   bool IsSystemXHR() const;
     595             :   bool InUploadPhase() const;
     596             : 
     597             :   void OnBodyParseEnd();
     598             :   void ChangeStateToDone();
     599             : 
     600             :   void StartProgressEventTimer();
     601             :   void StopProgressEventTimer();
     602             : 
     603             :   void MaybeCreateBlobStorage();
     604             : 
     605             :   nsresult OnRedirectVerifyCallback(nsresult result);
     606             : 
     607             :   void SetTimerEventTarget(nsITimer* aTimer);
     608             : 
     609             :   nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable);
     610             : 
     611             :   void DispatchOrStoreEvent(DOMEventTargetHelper* aTarget, Event* aEvent);
     612             : 
     613             :   already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
     614             : 
     615             :   void SuspendEventDispatching();
     616             :   void ResumeEventDispatching();
     617             : 
     618           0 :   struct PendingEvent
     619             :   {
     620             :     RefPtr<DOMEventTargetHelper> mTarget;
     621             :     RefPtr<Event> mEvent;
     622             :   };
     623             : 
     624             :   nsTArray<PendingEvent> mPendingEvents;
     625             : 
     626             :   nsCOMPtr<nsISupports> mContext;
     627             :   nsCOMPtr<nsIPrincipal> mPrincipal;
     628             :   nsCOMPtr<nsIChannel> mChannel;
     629             :   nsCString mRequestMethod;
     630             :   nsCOMPtr<nsIURI> mRequestURL;
     631             :   nsCOMPtr<nsIDocument> mResponseXML;
     632             : 
     633             :   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
     634             : 
     635             :   // used to implement getAllResponseHeaders()
     636             :   class nsHeaderVisitor : public nsIHttpHeaderVisitor
     637             :   {
     638           0 :     struct HeaderEntry final
     639             :     {
     640             :       nsCString mName;
     641             :       nsCString mValue;
     642             : 
     643           0 :       HeaderEntry(const nsACString& aName, const nsACString& aValue)
     644           0 :         : mName(aName), mValue(aValue)
     645           0 :       {}
     646             : 
     647             :       bool
     648           0 :       operator==(const HeaderEntry& aOther) const
     649             :       {
     650           0 :         return mName == aOther.mName;
     651             :       }
     652             : 
     653             :       bool
     654           0 :       operator<(const HeaderEntry& aOther) const
     655             :       {
     656           0 :         return mName < aOther.mName;
     657             :       }
     658             :     };
     659             : 
     660             :   public:
     661             :     NS_DECL_ISUPPORTS
     662             :     NS_DECL_NSIHTTPHEADERVISITOR
     663           0 :     nsHeaderVisitor(const XMLHttpRequestMainThread& aXMLHttpRequest,
     664             :                     NotNull<nsIHttpChannel*> aHttpChannel)
     665           0 :       : mXHR(aXMLHttpRequest), mHttpChannel(aHttpChannel) {}
     666           0 :     const nsACString &Headers()
     667             :     {
     668           0 :       for (uint32_t i = 0; i < mHeaderList.Length(); i++) {
     669           0 :         HeaderEntry& header = mHeaderList.ElementAt(i);
     670             : 
     671           0 :         mHeaders.Append(header.mName);
     672           0 :         mHeaders.AppendLiteral(": ");
     673           0 :         mHeaders.Append(header.mValue);
     674           0 :         mHeaders.AppendLiteral("\r\n");
     675             :       }
     676           0 :       return mHeaders;
     677             :     }
     678             : 
     679             :   private:
     680           0 :     virtual ~nsHeaderVisitor() {}
     681             : 
     682             :     nsTArray<HeaderEntry> mHeaderList;
     683             :     nsCString mHeaders;
     684             :     const XMLHttpRequestMainThread& mXHR;
     685             :     NotNull<nsCOMPtr<nsIHttpChannel>> mHttpChannel;
     686             :   };
     687             : 
     688             :   // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
     689             :   // BLOB responseTypes
     690             :   nsCString mResponseBody;
     691             : 
     692             :   // The text version of our response body. This is incrementally decoded into
     693             :   // as we receive network data. However for the DEFAULT responseType we
     694             :   // lazily decode into this from mResponseBody only when .responseText is
     695             :   // accessed.
     696             :   // Only used for DEFAULT and TEXT responseTypes.
     697             :   XMLHttpRequestString mResponseText;
     698             : 
     699             :   // For DEFAULT responseType we use this to keep track of how far we've
     700             :   // lazily decoded from mResponseBody to mResponseText
     701             :   uint32_t mResponseBodyDecodedPos;
     702             : 
     703             :   // Decoder used for decoding into mResponseText
     704             :   // Only used for DEFAULT, TEXT and JSON responseTypes.
     705             :   // In cases where we've only received half a surrogate, the decoder itself
     706             :   // carries the state to remember this. Next time we receive more data we
     707             :   // simply feed the new data into the decoder which will handle the second
     708             :   // part of the surrogate.
     709             :   mozilla::UniquePtr<mozilla::Decoder> mDecoder;
     710             : 
     711             :   const Encoding* mResponseCharset;
     712             : 
     713             :   void MatchCharsetAndDecoderToResponseDocument();
     714             : 
     715             :   XMLHttpRequestResponseType mResponseType;
     716             : 
     717             :   // It is either a cached blob-response from the last call to GetResponse,
     718             :   // but is also explicitly set in OnStopRequest.
     719             :   RefPtr<Blob> mResponseBlob;
     720             :   // We stream data to mBlobStorage when response type is "blob".
     721             :   RefPtr<MutableBlobStorage> mBlobStorage;
     722             :   // We stream data to mBlobSet when response type is "moz-blob".
     723             :   nsAutoPtr<BlobSet> mBlobSet;
     724             : 
     725             :   nsString mOverrideMimeType;
     726             : 
     727             :   /**
     728             :    * The notification callbacks the channel had when Send() was
     729             :    * called.  We want to forward things here as needed.
     730             :    */
     731             :   nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
     732             :   /**
     733             :    * Sink interfaces that we implement that mNotificationCallbacks may
     734             :    * want to also be notified for.  These are inited lazily if we're
     735             :    * asked for the relevant interface.
     736             :    */
     737             :   nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
     738             :   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
     739             : 
     740             :   nsIRequestObserver* mRequestObserver;
     741             : 
     742             :   nsCOMPtr<nsIURI> mBaseURI;
     743             :   nsCOMPtr<nsILoadGroup> mLoadGroup;
     744             : 
     745             :   State mState;
     746             : 
     747             :   bool mFlagSynchronous;
     748             :   bool mFlagAborted;
     749             :   bool mFlagParseBody;
     750             :   bool mFlagSyncLooping;
     751             :   bool mFlagBackgroundRequest;
     752             :   bool mFlagHadUploadListenersOnSend;
     753             :   bool mFlagACwithCredentials;
     754             :   bool mFlagTimedOut;
     755             :   bool mFlagDeleted;
     756             : 
     757             :   // The XHR2 spec's send() flag. Set when the XHR begins uploading, until it
     758             :   // finishes downloading (or an error/abort has occurred during either phase).
     759             :   // Used to guard against the user trying to alter headers/etc when it's too
     760             :   // late, and ensure the XHR only handles one in-flight request at once.
     761             :   bool mFlagSend;
     762             : 
     763             :   RefPtr<XMLHttpRequestUpload> mUpload;
     764             :   int64_t mUploadTransferred;
     765             :   int64_t mUploadTotal;
     766             :   bool mUploadComplete;
     767             :   bool mProgressSinceLastProgressEvent;
     768             : 
     769             :   // Timeout support
     770             :   PRTime mRequestSentTime;
     771             :   uint32_t mTimeoutMilliseconds;
     772             :   nsCOMPtr<nsITimer> mTimeoutTimer;
     773             :   void StartTimeoutTimer();
     774             :   void HandleTimeoutCallback();
     775             : 
     776             :   nsCOMPtr<nsIDocument> mSuspendedDoc;
     777             :   nsCOMPtr<nsIRunnable> mResumeTimeoutRunnable;
     778             : 
     779             :   nsCOMPtr<nsITimer> mSyncTimeoutTimer;
     780             : 
     781             :   enum SyncTimeoutType {
     782             :     eErrorOrExpired,
     783             :     eTimerStarted,
     784             :     eNoTimerNeeded
     785             :   };
     786             : 
     787             :   SyncTimeoutType MaybeStartSyncTimeoutTimer();
     788             :   void HandleSyncTimeoutTimer();
     789             :   void CancelSyncTimeoutTimer();
     790             : 
     791             :   ErrorType mErrorLoad;
     792             :   bool mErrorParsingXML;
     793             :   bool mWaitingForOnStopRequest;
     794             :   bool mProgressTimerIsActive;
     795             :   bool mIsHtml;
     796             :   bool mWarnAboutSyncHtml;
     797             :   int64_t mLoadTotal; // -1 if not known.
     798             :   // Number of HTTP message body bytes received so far. This quantity is
     799             :   // in the same units as Content-Length and mLoadTotal, and hence counts
     800             :   // compressed bytes when the channel has gzip Content-Encoding. If the
     801             :   // channel does not have Content-Encoding, this will be the same as
     802             :   // mDataReceived except between the OnProgress that changes mLoadTransferred
     803             :   // and the corresponding OnDataAvailable (which changes mDataReceived).
     804             :   // Ordering of OnProgress and OnDataAvailable is undefined.
     805             :   int64_t mLoadTransferred;
     806             :   nsCOMPtr<nsITimer> mProgressNotifier;
     807             :   void HandleProgressTimerCallback();
     808             : 
     809             :   bool mIsSystem;
     810             :   bool mIsAnon;
     811             : 
     812             :   // A platform-specific identifer to represent the network interface
     813             :   // that this request is associated with.
     814             :   nsCString mNetworkInterfaceId;
     815             : 
     816             :   /**
     817             :    * Close the XMLHttpRequest's channels.
     818             :    */
     819             :   void CloseRequest();
     820             : 
     821             :   /**
     822             :    * Close the XMLHttpRequest's channels and dispatch appropriate progress
     823             :    * events.
     824             :    *
     825             :    * @param aType The progress event type.
     826             :    */
     827             :   void CloseRequestWithError(const ProgressEventType aType);
     828             : 
     829             :   bool mFirstStartRequestSeen;
     830             :   bool mInLoadProgressEvent;
     831             : 
     832             :   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
     833             :   nsCOMPtr<nsIChannel> mNewRedirectChannel;
     834             : 
     835             :   JS::Heap<JS::Value> mResultJSON;
     836             : 
     837             :   ArrayBufferBuilder mArrayBufferBuilder;
     838             :   JS::Heap<JSObject*> mResultArrayBuffer;
     839             :   bool mIsMappedArrayBuffer;
     840             : 
     841             :   void ResetResponse();
     842             : 
     843             :   bool ShouldBlockAuthPrompt();
     844             : 
     845             :   RequestHeaders mAuthorRequestHeaders;
     846             : 
     847             :   // Helper object to manage our XPCOM scriptability bits
     848             :   nsXMLHttpRequestXPCOMifier* mXPCOMifier;
     849             : 
     850             :   // When this is set to true, the event dispatching is suspended. This is
     851             :   // useful to change the correct state when XHR is working sync.
     852             :   bool mEventDispatchingSuspended;
     853             : 
     854             :   static bool sDontWarnAboutSyncXHR;
     855             : };
     856             : 
     857             : class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
     858             : {
     859             : public:
     860           9 :   AutoDontWarnAboutSyncXHR() : mOldVal(XMLHttpRequestMainThread::DontWarnAboutSyncXHR())
     861             :   {
     862           9 :     XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(true);
     863           9 :   }
     864             : 
     865           9 :   ~AutoDontWarnAboutSyncXHR()
     866           9 :   {
     867           9 :     XMLHttpRequestMainThread::SetDontWarnAboutSyncXHR(mOldVal);
     868           9 :   }
     869             : 
     870             : private:
     871             :   bool mOldVal;
     872             : };
     873             : 
     874             : // A shim class designed to expose the non-DOM interfaces of
     875             : // XMLHttpRequest via XPCOM stuff.
     876             : class nsXMLHttpRequestXPCOMifier final : public nsIStreamListener,
     877             :                                          public nsIChannelEventSink,
     878             :                                          public nsIAsyncVerifyRedirectCallback,
     879             :                                          public nsIProgressEventSink,
     880             :                                          public nsIInterfaceRequestor,
     881             :                                          public nsITimerCallback
     882             : {
     883             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     884          24 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
     885             :                                            nsIStreamListener)
     886             : 
     887           2 :   explicit nsXMLHttpRequestXPCOMifier(XMLHttpRequestMainThread* aXHR) :
     888           2 :     mXHR(aXHR)
     889             :   {
     890           2 :   }
     891             : 
     892             : private:
     893           4 :   ~nsXMLHttpRequestXPCOMifier() {
     894           2 :     if (mXHR) {
     895           2 :       mXHR->mXPCOMifier = nullptr;
     896             :     }
     897           2 :   }
     898             : 
     899             : public:
     900           0 :   NS_FORWARD_NSISTREAMLISTENER(mXHR->)
     901           0 :   NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
     902           0 :   NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
     903           0 :   NS_FORWARD_NSIASYNCVERIFYREDIRECTCALLBACK(mXHR->)
     904           2 :   NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
     905           0 :   NS_FORWARD_NSITIMERCALLBACK(mXHR->)
     906             : 
     907             :   NS_DECL_NSIINTERFACEREQUESTOR
     908             : 
     909             : private:
     910             :   RefPtr<XMLHttpRequestMainThread> mXHR;
     911             : };
     912             : 
     913             : class nsXHRParseEndListener : public nsIDOMEventListener
     914             : {
     915             : public:
     916             :   NS_DECL_ISUPPORTS
     917           0 :   NS_IMETHOD HandleEvent(nsIDOMEvent *event) override
     918             :   {
     919           0 :     nsCOMPtr<nsIXMLHttpRequest> xhr = do_QueryReferent(mXHR);
     920           0 :     if (xhr) {
     921           0 :       static_cast<XMLHttpRequestMainThread*>(xhr.get())->OnBodyParseEnd();
     922             :     }
     923           0 :     mXHR = nullptr;
     924           0 :     return NS_OK;
     925             :   }
     926           0 :   explicit nsXHRParseEndListener(nsIXMLHttpRequest* aXHR)
     927           0 :     : mXHR(do_GetWeakReference(aXHR)) {}
     928             : private:
     929           0 :   virtual ~nsXHRParseEndListener() {}
     930             : 
     931             :   nsWeakPtr mXHR;
     932             : };
     933             : 
     934             : } // dom namespace
     935             : } // mozilla namespace
     936             : 
     937             : #endif // mozilla_dom_XMLHttpRequestMainThread_h

Generated by: LCOV version 1.13