content/base/src/nsXMLHttpRequest.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 nsXMLHttpRequest_h__
     8 #define nsXMLHttpRequest_h__
    10 #include "mozilla/Attributes.h"
    11 #include "nsIXMLHttpRequest.h"
    12 #include "nsISupportsUtils.h"
    13 #include "nsString.h"
    14 #include "nsIURI.h"
    15 #include "nsIHttpChannel.h"
    16 #include "nsIDocument.h"
    17 #include "nsIContent.h"
    18 #include "nsIStreamListener.h"
    19 #include "nsWeakReference.h"
    20 #include "nsIChannelEventSink.h"
    21 #include "nsIAsyncVerifyRedirectCallback.h"
    22 #include "nsIInterfaceRequestor.h"
    23 #include "nsIHttpHeaderVisitor.h"
    24 #include "nsIProgressEventSink.h"
    25 #include "nsJSUtils.h"
    26 #include "nsTArray.h"
    27 #include "nsITimer.h"
    28 #include "nsIPrincipal.h"
    29 #include "nsIScriptObjectPrincipal.h"
    30 #include "nsISizeOfEventTarget.h"
    31 #include "nsIXPConnect.h"
    32 #include "nsIInputStream.h"
    33 #include "mozilla/Assertions.h"
    34 #include "mozilla/DOMEventTargetHelper.h"
    35 #include "mozilla/MemoryReporting.h"
    36 #include "mozilla/dom/TypedArray.h"
    37 #include "mozilla/dom/XMLHttpRequestBinding.h"
    39 #ifdef Status
    40 /* Xlib headers insist on this for some reason... Nuke it because
    41    it'll override our member name */
    42 #undef Status
    43 #endif
    45 class AsyncVerifyRedirectCallbackForwarder;
    46 class BlobSet;
    47 class nsDOMFile;
    48 class nsFormData;
    49 class nsIJARChannel;
    50 class nsILoadGroup;
    51 class nsIUnicodeDecoder;
    52 class nsIJSID;
    54 namespace mozilla {
    56 // A helper for building up an ArrayBuffer object's data
    57 // before creating the ArrayBuffer itself.  Will do doubling
    58 // based reallocation, up to an optional maximum growth given.
    59 //
    60 // When all the data has been appended, call getArrayBuffer,
    61 // passing in the JSContext* for which the ArrayBuffer object
    62 // is to be created.  This also implicitly resets the builder,
    63 // or it can be reset explicitly at any point by calling reset().
    64 class ArrayBufferBuilder
    65 {
    66   uint8_t* mDataPtr;
    67   uint32_t mCapacity;
    68   uint32_t mLength;
    69 public:
    70   ArrayBufferBuilder();
    71   ~ArrayBufferBuilder();
    73   void reset();
    75   // Will truncate if aNewCap is < length().
    76   bool setCapacity(uint32_t aNewCap);
    78   // Append aDataLen bytes from data to the current buffer.  If we
    79   // need to grow the buffer, grow by doubling the size up to a
    80   // maximum of aMaxGrowth (if given).  If aDataLen is greater than
    81   // what the new capacity would end up as, then grow by aDataLen.
    82   //
    83   // The data parameter must not overlap with anything beyond the
    84   // builder's current valid contents [0..length)
    85   bool append(const uint8_t* aNewData, uint32_t aDataLen,
    86               uint32_t aMaxGrowth = 0);
    88   uint32_t length()   { return mLength; }
    89   uint32_t capacity() { return mCapacity; }
    91   JSObject* getArrayBuffer(JSContext* aCx);
    93 protected:
    94   static bool areOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1,
    95                                     const uint8_t* aStart2, uint32_t aLength2);
    96 };
    98 } // namespace mozilla
   100 class nsXHREventTarget : public mozilla::DOMEventTargetHelper,
   101                          public nsIXMLHttpRequestEventTarget
   102 {
   103 protected:
   104   nsXHREventTarget(mozilla::DOMEventTargetHelper* aOwner)
   105     : mozilla::DOMEventTargetHelper(aOwner)
   106   {
   107   }
   109   nsXHREventTarget()
   110   {
   111   }
   113 public:
   114   typedef mozilla::dom::XMLHttpRequestResponseType
   115           XMLHttpRequestResponseType;
   116   typedef mozilla::ErrorResult
   117           ErrorResult;
   119   virtual ~nsXHREventTarget() {}
   120   NS_DECL_ISUPPORTS_INHERITED
   121   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
   122                                            mozilla::DOMEventTargetHelper)
   123   NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
   124   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
   126   IMPL_EVENT_HANDLER(loadstart)
   127   IMPL_EVENT_HANDLER(progress)
   128   IMPL_EVENT_HANDLER(abort)
   129   IMPL_EVENT_HANDLER(error)
   130   IMPL_EVENT_HANDLER(load)
   131   IMPL_EVENT_HANDLER(timeout)
   132   IMPL_EVENT_HANDLER(loadend)
   134   virtual void DisconnectFromOwner();
   135 };
   137 class nsXMLHttpRequestUpload MOZ_FINAL : public nsXHREventTarget,
   138                                          public nsIXMLHttpRequestUpload
   139 {
   140 public:
   141   nsXMLHttpRequestUpload(mozilla::DOMEventTargetHelper* aOwner)
   142     : nsXHREventTarget(aOwner)
   143   {
   144   }
   146   NS_DECL_ISUPPORTS_INHERITED
   147   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
   148   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget)
   149   NS_DECL_NSIXMLHTTPREQUESTUPLOAD
   151   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
   152   nsISupports* GetParentObject()
   153   {
   154     return GetOwner();
   155   }
   157   bool HasListeners()
   158   {
   159     return mListenerManager && mListenerManager->HasListeners();
   160   }
   161 };
   163 class nsXMLHttpRequestXPCOMifier;
   165 // Make sure that any non-DOM interfaces added here are also added to
   166 // nsXMLHttpRequestXPCOMifier.
   167 class nsXMLHttpRequest : public nsXHREventTarget,
   168                          public nsIXMLHttpRequest,
   169                          public nsIJSXMLHttpRequest,
   170                          public nsIStreamListener,
   171                          public nsIChannelEventSink,
   172                          public nsIProgressEventSink,
   173                          public nsIInterfaceRequestor,
   174                          public nsSupportsWeakReference,
   175                          public nsITimerCallback,
   176                          public nsISizeOfEventTarget
   177 {
   178   friend class nsXHRParseEndListener;
   179   friend class nsXMLHttpRequestXPCOMifier;
   181 public:
   182   nsXMLHttpRequest();
   183   virtual ~nsXMLHttpRequest();
   185   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE
   186   {
   187     return mozilla::dom::XMLHttpRequestBinding::Wrap(cx, this);
   188   }
   189   nsISupports* GetParentObject()
   190   {
   191     return GetOwner();
   192   }
   194   // The WebIDL constructors.
   195   static already_AddRefed<nsXMLHttpRequest>
   196   Constructor(const mozilla::dom::GlobalObject& aGlobal,
   197               JSContext* aCx,
   198               const mozilla::dom::MozXMLHttpRequestParameters& aParams,
   199               ErrorResult& aRv)
   200   {
   201     nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
   202     nsCOMPtr<nsIScriptObjectPrincipal> principal =
   203       do_QueryInterface(aGlobal.GetAsSupports());
   204     if (!global || ! principal) {
   205       aRv.Throw(NS_ERROR_FAILURE);
   206       return nullptr;
   207     }
   209     nsRefPtr<nsXMLHttpRequest> req = new nsXMLHttpRequest();
   210     req->Construct(principal->GetPrincipal(), global);
   211     req->InitParameters(aParams.mMozAnon, aParams.mMozSystem);
   212     return req.forget();
   213   }
   215   static already_AddRefed<nsXMLHttpRequest>
   216   Constructor(const mozilla::dom::GlobalObject& aGlobal,
   217               JSContext* aCx,
   218               const nsAString& ignored,
   219               ErrorResult& aRv)
   220   {
   221     // Pretend like someone passed null, so we can pick up the default values
   222     mozilla::dom::MozXMLHttpRequestParameters params;
   223     if (!params.Init(aCx, JS::NullHandleValue)) {
   224       aRv.Throw(NS_ERROR_UNEXPECTED);
   225       return nullptr;
   226     }
   228     return Constructor(aGlobal, aCx, params, aRv);
   229   }
   231   void Construct(nsIPrincipal* aPrincipal,
   232                  nsIGlobalObject* aGlobalObject,
   233                  nsIURI* aBaseURI = nullptr)
   234   {
   235     MOZ_ASSERT(aPrincipal);
   236     MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(
   237       aGlobalObject), win->IsInnerWindow());
   238     mPrincipal = aPrincipal;
   239     BindToOwner(aGlobalObject);
   240     mBaseURI = aBaseURI;
   241   }
   243   void InitParameters(bool aAnon, bool aSystem);
   245   void SetParameters(bool aAnon, bool aSystem)
   246   {
   247     mIsAnon = aAnon || aSystem;
   248     mIsSystem = aSystem;
   249   }
   251   NS_DECL_ISUPPORTS_INHERITED
   253   // nsIXMLHttpRequest
   254   NS_DECL_NSIXMLHTTPREQUEST
   256   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
   258   // nsIStreamListener
   259   NS_DECL_NSISTREAMLISTENER
   261   // nsIRequestObserver
   262   NS_DECL_NSIREQUESTOBSERVER
   264   // nsIChannelEventSink
   265   NS_DECL_NSICHANNELEVENTSINK
   267   // nsIProgressEventSink
   268   NS_DECL_NSIPROGRESSEVENTSINK
   270   // nsIInterfaceRequestor
   271   NS_DECL_NSIINTERFACEREQUESTOR
   273   // nsITimerCallback
   274   NS_DECL_NSITIMERCALLBACK
   276   // nsISizeOfEventTarget
   277   virtual size_t
   278     SizeOfEventTargetIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   280   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget)
   282 #ifdef DEBUG
   283   void StaticAssertions();
   284 #endif
   286   // event handler
   287   IMPL_EVENT_HANDLER(readystatechange)
   289   // states
   290   uint16_t ReadyState();
   292   // request
   293   void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
   294   {
   295     Open(aMethod, aUrl, true,
   296          mozilla::dom::Optional<nsAString>(),
   297          mozilla::dom::Optional<nsAString>(),
   298          aRv);
   299   }
   300   void Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
   301             const mozilla::dom::Optional<nsAString>& aUser,
   302             const mozilla::dom::Optional<nsAString>& aPassword,
   303             ErrorResult& aRv)
   304   {
   305     aRv = Open(aMethod, NS_ConvertUTF16toUTF8(aUrl),
   306                aAsync, aUser, aPassword);
   307   }
   308   void SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
   309                         ErrorResult& aRv)
   310   {
   311     aRv = SetRequestHeader(aHeader, aValue);
   312   }
   313   uint32_t Timeout()
   314   {
   315     return mTimeoutMilliseconds;
   316   }
   317   void SetTimeout(uint32_t aTimeout, ErrorResult& aRv);
   318   bool WithCredentials();
   319   void SetWithCredentials(bool aWithCredentials, ErrorResult& aRv);
   320   nsXMLHttpRequestUpload* Upload();
   322 private:
   323   class RequestBody
   324   {
   325   public:
   326     RequestBody() : mType(Uninitialized)
   327     {
   328     }
   329     RequestBody(const mozilla::dom::ArrayBuffer* aArrayBuffer) : mType(ArrayBuffer)
   330     {
   331       mValue.mArrayBuffer = aArrayBuffer;
   332     }
   333     RequestBody(const mozilla::dom::ArrayBufferView* aArrayBufferView) : mType(ArrayBufferView)
   334     {
   335       mValue.mArrayBufferView = aArrayBufferView;
   336     }
   337     RequestBody(nsIDOMBlob* aBlob) : mType(Blob)
   338     {
   339       mValue.mBlob = aBlob;
   340     }
   341     RequestBody(nsIDocument* aDocument) : mType(Document)
   342     {
   343       mValue.mDocument = aDocument;
   344     }
   345     RequestBody(const nsAString& aString) : mType(DOMString)
   346     {
   347       mValue.mString = &aString;
   348     }
   349     RequestBody(nsFormData& aFormData) : mType(FormData)
   350     {
   351       mValue.mFormData = &aFormData;
   352     }
   353     RequestBody(nsIInputStream* aStream) : mType(InputStream)
   354     {
   355       mValue.mStream = aStream;
   356     }
   358     enum Type {
   359       Uninitialized,
   360       ArrayBuffer,
   361       ArrayBufferView,
   362       Blob,
   363       Document,
   364       DOMString,
   365       FormData,
   366       InputStream
   367     };
   368     union Value {
   369       const mozilla::dom::ArrayBuffer* mArrayBuffer;
   370       const mozilla::dom::ArrayBufferView* mArrayBufferView;
   371       nsIDOMBlob* mBlob;
   372       nsIDocument* mDocument;
   373       const nsAString* mString;
   374       nsFormData* mFormData;
   375       nsIInputStream* mStream;
   376     };
   378     Type GetType() const
   379     {
   380       MOZ_ASSERT(mType != Uninitialized);
   381       return mType;
   382     }
   383     Value GetValue() const
   384     {
   385       MOZ_ASSERT(mType != Uninitialized);
   386       return mValue;
   387     }
   389   private:
   390     Type mType;
   391     Value mValue;
   392   };
   394   static nsresult GetRequestBody(nsIVariant* aVariant,
   395                                  const Nullable<RequestBody>& aBody,
   396                                  nsIInputStream** aResult,
   397                                  uint64_t* aContentLength,
   398                                  nsACString& aContentType,
   399                                  nsACString& aCharset);
   401   nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
   402   nsresult Send(const Nullable<RequestBody>& aBody)
   403   {
   404     return Send(nullptr, aBody);
   405   }
   406   nsresult Send(const RequestBody& aBody)
   407   {
   408     return Send(Nullable<RequestBody>(aBody));
   409   }
   411 public:
   412   void Send(JSContext* /*aCx*/, ErrorResult& aRv)
   413   {
   414     aRv = Send(Nullable<RequestBody>());
   415   }
   416   void Send(JSContext* /*aCx*/,
   417             const mozilla::dom::ArrayBuffer& aArrayBuffer,
   418             ErrorResult& aRv)
   419   {
   420     aRv = Send(RequestBody(&aArrayBuffer));
   421   }
   422   void Send(JSContext* /*aCx*/,
   423             const mozilla::dom::ArrayBufferView& aArrayBufferView,
   424             ErrorResult& aRv)
   425   {
   426     aRv = Send(RequestBody(&aArrayBufferView));
   427   }
   428   void Send(JSContext* /*aCx*/, nsIDOMBlob* aBlob, ErrorResult& aRv)
   429   {
   430     NS_ASSERTION(aBlob, "Null should go to string version");
   431     aRv = Send(RequestBody(aBlob));
   432   }
   433   void Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv)
   434   {
   435     aRv = Send(RequestBody(&aDoc));
   436   }
   437   void Send(JSContext* aCx, const nsAString& aString, ErrorResult& aRv)
   438   {
   439     if (DOMStringIsNull(aString)) {
   440       Send(aCx, aRv);
   441     }
   442     else {
   443       aRv = Send(RequestBody(aString));
   444     }
   445   }
   446   void Send(JSContext* /*aCx*/, nsFormData& aFormData, ErrorResult& aRv)
   447   {
   448     aRv = Send(RequestBody(aFormData));
   449   }
   450   void Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv)
   451   {
   452     NS_ASSERTION(aStream, "Null should go to string version");
   453     nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aStream);
   454     if (wjs) {
   455       JSObject* data = wjs->GetJSObject();
   456       if (!data) {
   457         aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
   458         return;
   459       }
   460       JS::Rooted<JS::Value> dataAsValue(aCx, JS::ObjectValue(*data));
   461       mozilla::dom::binding_detail::FakeDependentString dataAsString;
   462       if (ConvertJSValueToString(aCx, dataAsValue, &dataAsValue, mozilla::dom::eNull,
   463                                  mozilla::dom::eNull, dataAsString)) {
   464         Send(aCx, dataAsString, aRv);
   465       } else {
   466         aRv.Throw(NS_ERROR_FAILURE);
   467       }
   468       return;
   469     }
   470     aRv = Send(RequestBody(aStream));
   471   }
   472   void SendAsBinary(const nsAString& aBody, ErrorResult& aRv);
   474   void Abort();
   476   // response
   477   uint32_t Status();
   478   void GetStatusText(nsCString& aStatusText);
   479   void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
   480                          ErrorResult& aRv);
   481   void GetResponseHeader(const nsAString& aHeader, nsString& aResult,
   482                          ErrorResult& aRv)
   483   {
   484     nsCString result;
   485     GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
   486     if (result.IsVoid()) {
   487       aResult.SetIsVoid(true);
   488     }
   489     else {
   490       // The result value should be inflated:
   491       CopyASCIItoUTF16(result, aResult);
   492     }
   493   }
   494   void GetAllResponseHeaders(nsCString& aResponseHeaders);
   495   bool IsSafeHeader(const nsACString& aHeaderName, nsIHttpChannel* aHttpChannel);
   496   void OverrideMimeType(const nsAString& aMimeType)
   497   {
   498     // XXX Should we do some validation here?
   499     mOverrideMimeType = aMimeType;
   500   }
   501   XMLHttpRequestResponseType ResponseType()
   502   {
   503     return XMLHttpRequestResponseType(mResponseType);
   504   }
   505   void SetResponseType(XMLHttpRequestResponseType aType, ErrorResult& aRv);
   506   void GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse,
   507                    ErrorResult& aRv);
   508   void GetResponseText(nsString& aResponseText, ErrorResult& aRv);
   509   nsIDocument* GetResponseXML(ErrorResult& aRv);
   511   bool MozBackgroundRequest();
   512   void SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv);
   514   bool MozAnon();
   515   bool MozSystem();
   517   nsIChannel* GetChannel()
   518   {
   519     return mChannel;
   520   }
   522   // We need a GetInterface callable from JS for chrome JS
   523   void GetInterface(JSContext* aCx, nsIJSID* aIID,
   524                     JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
   526   // This creates a trusted readystatechange event, which is not cancelable and
   527   // doesn't bubble.
   528   nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   529   void DispatchProgressEvent(mozilla::DOMEventTargetHelper* aTarget,
   530                              const nsAString& aType,
   531                              bool aLengthComputable,
   532                              uint64_t aLoaded, uint64_t aTotal);
   534   // Dispatch the "progress" event on the XHR or XHR.upload object if we've
   535   // received data since the last "progress" event. Also dispatches
   536   // "uploadprogress" as needed.
   537   void MaybeDispatchProgressEvents(bool aFinalProgress);
   539   // This is called by the factory constructor.
   540   nsresult Init();
   542   nsresult init(nsIPrincipal* principal,
   543                 nsIScriptContext* scriptContext,
   544                 nsPIDOMWindow* globalObject,
   545                 nsIURI* baseURI);
   547   void SetRequestObserver(nsIRequestObserver* aObserver);
   549   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
   550                                                                    nsXHREventTarget)
   551   bool AllowUploadProgress();
   552   void RootJSResultObjects();
   554   virtual void DisconnectFromOwner() MOZ_OVERRIDE;
   556   static void SetDontWarnAboutSyncXHR(bool aVal)
   557   {
   558     sDontWarnAboutSyncXHR = aVal;
   559   }
   560   static bool DontWarnAboutSyncXHR()
   561   {
   562     return sDontWarnAboutSyncXHR;
   563   }
   564 protected:
   565   nsresult DetectCharset();
   566   nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen);
   567   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
   568                 void* closure,
   569                 const char* fromRawSegment,
   570                 uint32_t toOffset,
   571                 uint32_t count,
   572                 uint32_t *writeCount);
   573   nsresult CreateResponseParsedJSON(JSContext* aCx);
   574   void CreatePartialBlob();
   575   bool CreateDOMFile(nsIRequest *request);
   576   // Change the state of the object with this. The broadcast argument
   577   // determines if the onreadystatechange listener should be called.
   578   nsresult ChangeState(uint32_t aState, bool aBroadcast = true);
   579   already_AddRefed<nsILoadGroup> GetLoadGroup() const;
   580   nsIURI *GetBaseURI();
   582   already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
   583   already_AddRefed<nsIJARChannel> GetCurrentJARChannel();
   585   bool IsSystemXHR();
   587   void ChangeStateToDone();
   589   /**
   590    * Check if aChannel is ok for a cross-site request by making sure no
   591    * inappropriate headers are set, and no username/password is set.
   592    *
   593    * Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit.
   594    */
   595   nsresult CheckChannelForCrossSiteRequest(nsIChannel* aChannel);
   597   void StartProgressEventTimer();
   599   friend class AsyncVerifyRedirectCallbackForwarder;
   600   void OnRedirectVerifyCallback(nsresult result);
   602   nsresult Open(const nsACString& method, const nsACString& url, bool async,
   603                 const mozilla::dom::Optional<nsAString>& user,
   604                 const mozilla::dom::Optional<nsAString>& password);
   606   already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
   608   nsCOMPtr<nsISupports> mContext;
   609   nsCOMPtr<nsIPrincipal> mPrincipal;
   610   nsCOMPtr<nsIChannel> mChannel;
   611   nsCOMPtr<nsIDocument> mResponseXML;
   612   nsCOMPtr<nsIChannel> mCORSPreflightChannel;
   613   nsTArray<nsCString> mCORSUnsafeHeaders;
   615   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
   617   // used to implement getAllResponseHeaders()
   618   class nsHeaderVisitor : public nsIHttpHeaderVisitor {
   619   public:
   620     NS_DECL_ISUPPORTS
   621     NS_DECL_NSIHTTPHEADERVISITOR
   622     nsHeaderVisitor(nsXMLHttpRequest* aXMLHttpRequest, nsIHttpChannel* aHttpChannel)
   623       : mXHR(aXMLHttpRequest), mHttpChannel(aHttpChannel) {}
   624     virtual ~nsHeaderVisitor() {}
   625     const nsACString &Headers() { return mHeaders; }
   626   private:
   627     nsCString mHeaders;
   628     nsXMLHttpRequest* mXHR;
   629     nsCOMPtr<nsIHttpChannel> mHttpChannel;
   630   };
   632   // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and
   633   // BLOB responseTypes
   634   nsCString mResponseBody;
   636   // The text version of our response body. This is incrementally decoded into
   637   // as we receive network data. However for the DEFAULT responseType we
   638   // lazily decode into this from mResponseBody only when .responseText is
   639   // accessed.
   640   // Only used for DEFAULT and TEXT responseTypes.
   641   nsString mResponseText;
   643   // For DEFAULT responseType we use this to keep track of how far we've
   644   // lazily decoded from mResponseBody to mResponseText
   645   uint32_t mResponseBodyDecodedPos;
   647   // Decoder used for decoding into mResponseText
   648   // Only used for DEFAULT, TEXT and JSON responseTypes.
   649   // In cases where we've only received half a surrogate, the decoder itself
   650   // carries the state to remember this. Next time we receive more data we
   651   // simply feed the new data into the decoder which will handle the second
   652   // part of the surrogate.
   653   nsCOMPtr<nsIUnicodeDecoder> mDecoder;
   655   nsCString mResponseCharset;
   657   enum ResponseTypeEnum {
   658     XML_HTTP_RESPONSE_TYPE_DEFAULT,
   659     XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER,
   660     XML_HTTP_RESPONSE_TYPE_BLOB,
   661     XML_HTTP_RESPONSE_TYPE_DOCUMENT,
   662     XML_HTTP_RESPONSE_TYPE_JSON,
   663     XML_HTTP_RESPONSE_TYPE_TEXT,
   664     XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT,
   665     XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER,
   666     XML_HTTP_RESPONSE_TYPE_MOZ_BLOB
   667   };
   669   void SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aType, ErrorResult& aRv);
   671   ResponseTypeEnum mResponseType;
   673   // It is either a cached blob-response from the last call to GetResponse,
   674   // but is also explicitly set in OnStopRequest.
   675   nsCOMPtr<nsIDOMBlob> mResponseBlob;
   676   // Non-null only when we are able to get a os-file representation of the
   677   // response, i.e. when loading from a file.
   678   nsRefPtr<nsDOMFile> mDOMFile;
   679   // We stream data to mBlobSet when response type is "blob" or "moz-blob"
   680   // and mDOMFile is null.
   681   nsAutoPtr<BlobSet> mBlobSet;
   683   nsString mOverrideMimeType;
   685   /**
   686    * The notification callbacks the channel had when Send() was
   687    * called.  We want to forward things here as needed.
   688    */
   689   nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks;
   690   /**
   691    * Sink interfaces that we implement that mNotificationCallbacks may
   692    * want to also be notified for.  These are inited lazily if we're
   693    * asked for the relevant interface.
   694    */
   695   nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
   696   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
   698   nsIRequestObserver* mRequestObserver;
   700   nsCOMPtr<nsIURI> mBaseURI;
   702   uint32_t mState;
   704   nsRefPtr<nsXMLHttpRequestUpload> mUpload;
   705   uint64_t mUploadTransferred;
   706   uint64_t mUploadTotal;
   707   bool mUploadLengthComputable;
   708   bool mUploadComplete;
   709   bool mProgressSinceLastProgressEvent;
   711   // Timeout support
   712   PRTime mRequestSentTime;
   713   uint32_t mTimeoutMilliseconds;
   714   nsCOMPtr<nsITimer> mTimeoutTimer;
   715   void StartTimeoutTimer();
   716   void HandleTimeoutCallback();
   718   bool mErrorLoad;
   719   bool mWaitingForOnStopRequest;
   720   bool mProgressTimerIsActive;
   721   bool mIsHtml;
   722   bool mWarnAboutMultipartHtml;
   723   bool mWarnAboutSyncHtml;
   724   bool mLoadLengthComputable;
   725   uint64_t mLoadTotal; // 0 if not known.
   726   uint64_t mLoadTransferred;
   727   nsCOMPtr<nsITimer> mProgressNotifier;
   728   void HandleProgressTimerCallback();
   730   bool mIsSystem;
   731   bool mIsAnon;
   733   /**
   734    * Close the XMLHttpRequest's channels and dispatch appropriate progress
   735    * events.
   736    *
   737    * @param aType The progress event type.
   738    * @param aFlag A XML_HTTP_REQUEST_* state flag defined in
   739    *              nsXMLHttpRequest.cpp.
   740    */
   741   void CloseRequestWithError(const nsAString& aType, const uint32_t aFlag);
   743   bool mFirstStartRequestSeen;
   744   bool mInLoadProgressEvent;
   746   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   747   nsCOMPtr<nsIChannel> mNewRedirectChannel;
   749   JS::Heap<JS::Value> mResultJSON;
   751   mozilla::ArrayBufferBuilder mArrayBufferBuilder;
   752   JS::Heap<JSObject*> mResultArrayBuffer;
   754   void ResetResponse();
   756   struct RequestHeader
   757   {
   758     nsCString header;
   759     nsCString value;
   760   };
   761   nsTArray<RequestHeader> mModifiedRequestHeaders;
   763   nsTHashtable<nsCStringHashKey> mAlreadySetHeaders;
   765   // Helper object to manage our XPCOM scriptability bits
   766   nsXMLHttpRequestXPCOMifier* mXPCOMifier;
   768   static bool sDontWarnAboutSyncXHR;
   769 };
   771 class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR
   772 {
   773 public:
   774   AutoDontWarnAboutSyncXHR() : mOldVal(nsXMLHttpRequest::DontWarnAboutSyncXHR())
   775   {
   776     nsXMLHttpRequest::SetDontWarnAboutSyncXHR(true);
   777   }
   779   ~AutoDontWarnAboutSyncXHR()
   780   {
   781     nsXMLHttpRequest::SetDontWarnAboutSyncXHR(mOldVal);
   782   }
   784 private:
   785   bool mOldVal;
   786 };
   788 // A shim class designed to expose the non-DOM interfaces of
   789 // XMLHttpRequest via XPCOM stuff.
   790 class nsXMLHttpRequestXPCOMifier MOZ_FINAL : public nsIStreamListener,
   791                                              public nsIChannelEventSink,
   792                                              public nsIProgressEventSink,
   793                                              public nsIInterfaceRequestor,
   794                                              public nsITimerCallback
   795 {
   796   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   797   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
   798                                            nsIStreamListener)
   800   nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) :
   801     mXHR(aXHR)
   802   {
   803   }
   805   ~nsXMLHttpRequestXPCOMifier() {
   806     if (mXHR) {
   807       mXHR->mXPCOMifier = nullptr;
   808     }
   809   }
   811   NS_FORWARD_NSISTREAMLISTENER(mXHR->)
   812   NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
   813   NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
   814   NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
   815   NS_FORWARD_NSITIMERCALLBACK(mXHR->)
   817   NS_DECL_NSIINTERFACEREQUESTOR
   819 private:
   820   nsRefPtr<nsXMLHttpRequest> mXHR;
   821 };
   823 class nsXHRParseEndListener : public nsIDOMEventListener
   824 {
   825 public:
   826   NS_DECL_ISUPPORTS
   827   NS_IMETHOD HandleEvent(nsIDOMEvent *event) MOZ_OVERRIDE
   828   {
   829     nsCOMPtr<nsIXMLHttpRequest> xhr = do_QueryReferent(mXHR);
   830     if (xhr) {
   831       static_cast<nsXMLHttpRequest*>(xhr.get())->ChangeStateToDone();
   832     }
   833     mXHR = nullptr;
   834     return NS_OK;
   835   }
   836   nsXHRParseEndListener(nsIXMLHttpRequest* aXHR)
   837     : mXHR(do_GetWeakReference(aXHR)) {}
   838   virtual ~nsXHRParseEndListener() {}
   839 private:
   840   nsWeakPtr mXHR;
   841 };
   843 #endif

mercurial