1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsXMLHttpRequest.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,843 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsXMLHttpRequest_h__ 1.11 +#define nsXMLHttpRequest_h__ 1.12 + 1.13 +#include "mozilla/Attributes.h" 1.14 +#include "nsIXMLHttpRequest.h" 1.15 +#include "nsISupportsUtils.h" 1.16 +#include "nsString.h" 1.17 +#include "nsIURI.h" 1.18 +#include "nsIHttpChannel.h" 1.19 +#include "nsIDocument.h" 1.20 +#include "nsIContent.h" 1.21 +#include "nsIStreamListener.h" 1.22 +#include "nsWeakReference.h" 1.23 +#include "nsIChannelEventSink.h" 1.24 +#include "nsIAsyncVerifyRedirectCallback.h" 1.25 +#include "nsIInterfaceRequestor.h" 1.26 +#include "nsIHttpHeaderVisitor.h" 1.27 +#include "nsIProgressEventSink.h" 1.28 +#include "nsJSUtils.h" 1.29 +#include "nsTArray.h" 1.30 +#include "nsITimer.h" 1.31 +#include "nsIPrincipal.h" 1.32 +#include "nsIScriptObjectPrincipal.h" 1.33 +#include "nsISizeOfEventTarget.h" 1.34 +#include "nsIXPConnect.h" 1.35 +#include "nsIInputStream.h" 1.36 +#include "mozilla/Assertions.h" 1.37 +#include "mozilla/DOMEventTargetHelper.h" 1.38 +#include "mozilla/MemoryReporting.h" 1.39 +#include "mozilla/dom/TypedArray.h" 1.40 +#include "mozilla/dom/XMLHttpRequestBinding.h" 1.41 + 1.42 +#ifdef Status 1.43 +/* Xlib headers insist on this for some reason... Nuke it because 1.44 + it'll override our member name */ 1.45 +#undef Status 1.46 +#endif 1.47 + 1.48 +class AsyncVerifyRedirectCallbackForwarder; 1.49 +class BlobSet; 1.50 +class nsDOMFile; 1.51 +class nsFormData; 1.52 +class nsIJARChannel; 1.53 +class nsILoadGroup; 1.54 +class nsIUnicodeDecoder; 1.55 +class nsIJSID; 1.56 + 1.57 +namespace mozilla { 1.58 + 1.59 +// A helper for building up an ArrayBuffer object's data 1.60 +// before creating the ArrayBuffer itself. Will do doubling 1.61 +// based reallocation, up to an optional maximum growth given. 1.62 +// 1.63 +// When all the data has been appended, call getArrayBuffer, 1.64 +// passing in the JSContext* for which the ArrayBuffer object 1.65 +// is to be created. This also implicitly resets the builder, 1.66 +// or it can be reset explicitly at any point by calling reset(). 1.67 +class ArrayBufferBuilder 1.68 +{ 1.69 + uint8_t* mDataPtr; 1.70 + uint32_t mCapacity; 1.71 + uint32_t mLength; 1.72 +public: 1.73 + ArrayBufferBuilder(); 1.74 + ~ArrayBufferBuilder(); 1.75 + 1.76 + void reset(); 1.77 + 1.78 + // Will truncate if aNewCap is < length(). 1.79 + bool setCapacity(uint32_t aNewCap); 1.80 + 1.81 + // Append aDataLen bytes from data to the current buffer. If we 1.82 + // need to grow the buffer, grow by doubling the size up to a 1.83 + // maximum of aMaxGrowth (if given). If aDataLen is greater than 1.84 + // what the new capacity would end up as, then grow by aDataLen. 1.85 + // 1.86 + // The data parameter must not overlap with anything beyond the 1.87 + // builder's current valid contents [0..length) 1.88 + bool append(const uint8_t* aNewData, uint32_t aDataLen, 1.89 + uint32_t aMaxGrowth = 0); 1.90 + 1.91 + uint32_t length() { return mLength; } 1.92 + uint32_t capacity() { return mCapacity; } 1.93 + 1.94 + JSObject* getArrayBuffer(JSContext* aCx); 1.95 + 1.96 +protected: 1.97 + static bool areOverlappingRegions(const uint8_t* aStart1, uint32_t aLength1, 1.98 + const uint8_t* aStart2, uint32_t aLength2); 1.99 +}; 1.100 + 1.101 +} // namespace mozilla 1.102 + 1.103 +class nsXHREventTarget : public mozilla::DOMEventTargetHelper, 1.104 + public nsIXMLHttpRequestEventTarget 1.105 +{ 1.106 +protected: 1.107 + nsXHREventTarget(mozilla::DOMEventTargetHelper* aOwner) 1.108 + : mozilla::DOMEventTargetHelper(aOwner) 1.109 + { 1.110 + } 1.111 + 1.112 + nsXHREventTarget() 1.113 + { 1.114 + } 1.115 + 1.116 +public: 1.117 + typedef mozilla::dom::XMLHttpRequestResponseType 1.118 + XMLHttpRequestResponseType; 1.119 + typedef mozilla::ErrorResult 1.120 + ErrorResult; 1.121 + 1.122 + virtual ~nsXHREventTarget() {} 1.123 + NS_DECL_ISUPPORTS_INHERITED 1.124 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget, 1.125 + mozilla::DOMEventTargetHelper) 1.126 + NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET 1.127 + NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper) 1.128 + 1.129 + IMPL_EVENT_HANDLER(loadstart) 1.130 + IMPL_EVENT_HANDLER(progress) 1.131 + IMPL_EVENT_HANDLER(abort) 1.132 + IMPL_EVENT_HANDLER(error) 1.133 + IMPL_EVENT_HANDLER(load) 1.134 + IMPL_EVENT_HANDLER(timeout) 1.135 + IMPL_EVENT_HANDLER(loadend) 1.136 + 1.137 + virtual void DisconnectFromOwner(); 1.138 +}; 1.139 + 1.140 +class nsXMLHttpRequestUpload MOZ_FINAL : public nsXHREventTarget, 1.141 + public nsIXMLHttpRequestUpload 1.142 +{ 1.143 +public: 1.144 + nsXMLHttpRequestUpload(mozilla::DOMEventTargetHelper* aOwner) 1.145 + : nsXHREventTarget(aOwner) 1.146 + { 1.147 + } 1.148 + 1.149 + NS_DECL_ISUPPORTS_INHERITED 1.150 + NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::) 1.151 + NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget) 1.152 + NS_DECL_NSIXMLHTTPREQUESTUPLOAD 1.153 + 1.154 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; 1.155 + nsISupports* GetParentObject() 1.156 + { 1.157 + return GetOwner(); 1.158 + } 1.159 + 1.160 + bool HasListeners() 1.161 + { 1.162 + return mListenerManager && mListenerManager->HasListeners(); 1.163 + } 1.164 +}; 1.165 + 1.166 +class nsXMLHttpRequestXPCOMifier; 1.167 + 1.168 +// Make sure that any non-DOM interfaces added here are also added to 1.169 +// nsXMLHttpRequestXPCOMifier. 1.170 +class nsXMLHttpRequest : public nsXHREventTarget, 1.171 + public nsIXMLHttpRequest, 1.172 + public nsIJSXMLHttpRequest, 1.173 + public nsIStreamListener, 1.174 + public nsIChannelEventSink, 1.175 + public nsIProgressEventSink, 1.176 + public nsIInterfaceRequestor, 1.177 + public nsSupportsWeakReference, 1.178 + public nsITimerCallback, 1.179 + public nsISizeOfEventTarget 1.180 +{ 1.181 + friend class nsXHRParseEndListener; 1.182 + friend class nsXMLHttpRequestXPCOMifier; 1.183 + 1.184 +public: 1.185 + nsXMLHttpRequest(); 1.186 + virtual ~nsXMLHttpRequest(); 1.187 + 1.188 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE 1.189 + { 1.190 + return mozilla::dom::XMLHttpRequestBinding::Wrap(cx, this); 1.191 + } 1.192 + nsISupports* GetParentObject() 1.193 + { 1.194 + return GetOwner(); 1.195 + } 1.196 + 1.197 + // The WebIDL constructors. 1.198 + static already_AddRefed<nsXMLHttpRequest> 1.199 + Constructor(const mozilla::dom::GlobalObject& aGlobal, 1.200 + JSContext* aCx, 1.201 + const mozilla::dom::MozXMLHttpRequestParameters& aParams, 1.202 + ErrorResult& aRv) 1.203 + { 1.204 + nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); 1.205 + nsCOMPtr<nsIScriptObjectPrincipal> principal = 1.206 + do_QueryInterface(aGlobal.GetAsSupports()); 1.207 + if (!global || ! principal) { 1.208 + aRv.Throw(NS_ERROR_FAILURE); 1.209 + return nullptr; 1.210 + } 1.211 + 1.212 + nsRefPtr<nsXMLHttpRequest> req = new nsXMLHttpRequest(); 1.213 + req->Construct(principal->GetPrincipal(), global); 1.214 + req->InitParameters(aParams.mMozAnon, aParams.mMozSystem); 1.215 + return req.forget(); 1.216 + } 1.217 + 1.218 + static already_AddRefed<nsXMLHttpRequest> 1.219 + Constructor(const mozilla::dom::GlobalObject& aGlobal, 1.220 + JSContext* aCx, 1.221 + const nsAString& ignored, 1.222 + ErrorResult& aRv) 1.223 + { 1.224 + // Pretend like someone passed null, so we can pick up the default values 1.225 + mozilla::dom::MozXMLHttpRequestParameters params; 1.226 + if (!params.Init(aCx, JS::NullHandleValue)) { 1.227 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.228 + return nullptr; 1.229 + } 1.230 + 1.231 + return Constructor(aGlobal, aCx, params, aRv); 1.232 + } 1.233 + 1.234 + void Construct(nsIPrincipal* aPrincipal, 1.235 + nsIGlobalObject* aGlobalObject, 1.236 + nsIURI* aBaseURI = nullptr) 1.237 + { 1.238 + MOZ_ASSERT(aPrincipal); 1.239 + MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface( 1.240 + aGlobalObject), win->IsInnerWindow()); 1.241 + mPrincipal = aPrincipal; 1.242 + BindToOwner(aGlobalObject); 1.243 + mBaseURI = aBaseURI; 1.244 + } 1.245 + 1.246 + void InitParameters(bool aAnon, bool aSystem); 1.247 + 1.248 + void SetParameters(bool aAnon, bool aSystem) 1.249 + { 1.250 + mIsAnon = aAnon || aSystem; 1.251 + mIsSystem = aSystem; 1.252 + } 1.253 + 1.254 + NS_DECL_ISUPPORTS_INHERITED 1.255 + 1.256 + // nsIXMLHttpRequest 1.257 + NS_DECL_NSIXMLHTTPREQUEST 1.258 + 1.259 + NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::) 1.260 + 1.261 + // nsIStreamListener 1.262 + NS_DECL_NSISTREAMLISTENER 1.263 + 1.264 + // nsIRequestObserver 1.265 + NS_DECL_NSIREQUESTOBSERVER 1.266 + 1.267 + // nsIChannelEventSink 1.268 + NS_DECL_NSICHANNELEVENTSINK 1.269 + 1.270 + // nsIProgressEventSink 1.271 + NS_DECL_NSIPROGRESSEVENTSINK 1.272 + 1.273 + // nsIInterfaceRequestor 1.274 + NS_DECL_NSIINTERFACEREQUESTOR 1.275 + 1.276 + // nsITimerCallback 1.277 + NS_DECL_NSITIMERCALLBACK 1.278 + 1.279 + // nsISizeOfEventTarget 1.280 + virtual size_t 1.281 + SizeOfEventTargetIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 1.282 + 1.283 + NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget) 1.284 + 1.285 +#ifdef DEBUG 1.286 + void StaticAssertions(); 1.287 +#endif 1.288 + 1.289 + // event handler 1.290 + IMPL_EVENT_HANDLER(readystatechange) 1.291 + 1.292 + // states 1.293 + uint16_t ReadyState(); 1.294 + 1.295 + // request 1.296 + void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv) 1.297 + { 1.298 + Open(aMethod, aUrl, true, 1.299 + mozilla::dom::Optional<nsAString>(), 1.300 + mozilla::dom::Optional<nsAString>(), 1.301 + aRv); 1.302 + } 1.303 + void Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync, 1.304 + const mozilla::dom::Optional<nsAString>& aUser, 1.305 + const mozilla::dom::Optional<nsAString>& aPassword, 1.306 + ErrorResult& aRv) 1.307 + { 1.308 + aRv = Open(aMethod, NS_ConvertUTF16toUTF8(aUrl), 1.309 + aAsync, aUser, aPassword); 1.310 + } 1.311 + void SetRequestHeader(const nsACString& aHeader, const nsACString& aValue, 1.312 + ErrorResult& aRv) 1.313 + { 1.314 + aRv = SetRequestHeader(aHeader, aValue); 1.315 + } 1.316 + uint32_t Timeout() 1.317 + { 1.318 + return mTimeoutMilliseconds; 1.319 + } 1.320 + void SetTimeout(uint32_t aTimeout, ErrorResult& aRv); 1.321 + bool WithCredentials(); 1.322 + void SetWithCredentials(bool aWithCredentials, ErrorResult& aRv); 1.323 + nsXMLHttpRequestUpload* Upload(); 1.324 + 1.325 +private: 1.326 + class RequestBody 1.327 + { 1.328 + public: 1.329 + RequestBody() : mType(Uninitialized) 1.330 + { 1.331 + } 1.332 + RequestBody(const mozilla::dom::ArrayBuffer* aArrayBuffer) : mType(ArrayBuffer) 1.333 + { 1.334 + mValue.mArrayBuffer = aArrayBuffer; 1.335 + } 1.336 + RequestBody(const mozilla::dom::ArrayBufferView* aArrayBufferView) : mType(ArrayBufferView) 1.337 + { 1.338 + mValue.mArrayBufferView = aArrayBufferView; 1.339 + } 1.340 + RequestBody(nsIDOMBlob* aBlob) : mType(Blob) 1.341 + { 1.342 + mValue.mBlob = aBlob; 1.343 + } 1.344 + RequestBody(nsIDocument* aDocument) : mType(Document) 1.345 + { 1.346 + mValue.mDocument = aDocument; 1.347 + } 1.348 + RequestBody(const nsAString& aString) : mType(DOMString) 1.349 + { 1.350 + mValue.mString = &aString; 1.351 + } 1.352 + RequestBody(nsFormData& aFormData) : mType(FormData) 1.353 + { 1.354 + mValue.mFormData = &aFormData; 1.355 + } 1.356 + RequestBody(nsIInputStream* aStream) : mType(InputStream) 1.357 + { 1.358 + mValue.mStream = aStream; 1.359 + } 1.360 + 1.361 + enum Type { 1.362 + Uninitialized, 1.363 + ArrayBuffer, 1.364 + ArrayBufferView, 1.365 + Blob, 1.366 + Document, 1.367 + DOMString, 1.368 + FormData, 1.369 + InputStream 1.370 + }; 1.371 + union Value { 1.372 + const mozilla::dom::ArrayBuffer* mArrayBuffer; 1.373 + const mozilla::dom::ArrayBufferView* mArrayBufferView; 1.374 + nsIDOMBlob* mBlob; 1.375 + nsIDocument* mDocument; 1.376 + const nsAString* mString; 1.377 + nsFormData* mFormData; 1.378 + nsIInputStream* mStream; 1.379 + }; 1.380 + 1.381 + Type GetType() const 1.382 + { 1.383 + MOZ_ASSERT(mType != Uninitialized); 1.384 + return mType; 1.385 + } 1.386 + Value GetValue() const 1.387 + { 1.388 + MOZ_ASSERT(mType != Uninitialized); 1.389 + return mValue; 1.390 + } 1.391 + 1.392 + private: 1.393 + Type mType; 1.394 + Value mValue; 1.395 + }; 1.396 + 1.397 + static nsresult GetRequestBody(nsIVariant* aVariant, 1.398 + const Nullable<RequestBody>& aBody, 1.399 + nsIInputStream** aResult, 1.400 + uint64_t* aContentLength, 1.401 + nsACString& aContentType, 1.402 + nsACString& aCharset); 1.403 + 1.404 + nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody); 1.405 + nsresult Send(const Nullable<RequestBody>& aBody) 1.406 + { 1.407 + return Send(nullptr, aBody); 1.408 + } 1.409 + nsresult Send(const RequestBody& aBody) 1.410 + { 1.411 + return Send(Nullable<RequestBody>(aBody)); 1.412 + } 1.413 + 1.414 +public: 1.415 + void Send(JSContext* /*aCx*/, ErrorResult& aRv) 1.416 + { 1.417 + aRv = Send(Nullable<RequestBody>()); 1.418 + } 1.419 + void Send(JSContext* /*aCx*/, 1.420 + const mozilla::dom::ArrayBuffer& aArrayBuffer, 1.421 + ErrorResult& aRv) 1.422 + { 1.423 + aRv = Send(RequestBody(&aArrayBuffer)); 1.424 + } 1.425 + void Send(JSContext* /*aCx*/, 1.426 + const mozilla::dom::ArrayBufferView& aArrayBufferView, 1.427 + ErrorResult& aRv) 1.428 + { 1.429 + aRv = Send(RequestBody(&aArrayBufferView)); 1.430 + } 1.431 + void Send(JSContext* /*aCx*/, nsIDOMBlob* aBlob, ErrorResult& aRv) 1.432 + { 1.433 + NS_ASSERTION(aBlob, "Null should go to string version"); 1.434 + aRv = Send(RequestBody(aBlob)); 1.435 + } 1.436 + void Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv) 1.437 + { 1.438 + aRv = Send(RequestBody(&aDoc)); 1.439 + } 1.440 + void Send(JSContext* aCx, const nsAString& aString, ErrorResult& aRv) 1.441 + { 1.442 + if (DOMStringIsNull(aString)) { 1.443 + Send(aCx, aRv); 1.444 + } 1.445 + else { 1.446 + aRv = Send(RequestBody(aString)); 1.447 + } 1.448 + } 1.449 + void Send(JSContext* /*aCx*/, nsFormData& aFormData, ErrorResult& aRv) 1.450 + { 1.451 + aRv = Send(RequestBody(aFormData)); 1.452 + } 1.453 + void Send(JSContext* aCx, nsIInputStream* aStream, ErrorResult& aRv) 1.454 + { 1.455 + NS_ASSERTION(aStream, "Null should go to string version"); 1.456 + nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aStream); 1.457 + if (wjs) { 1.458 + JSObject* data = wjs->GetJSObject(); 1.459 + if (!data) { 1.460 + aRv.Throw(NS_ERROR_DOM_TYPE_ERR); 1.461 + return; 1.462 + } 1.463 + JS::Rooted<JS::Value> dataAsValue(aCx, JS::ObjectValue(*data)); 1.464 + mozilla::dom::binding_detail::FakeDependentString dataAsString; 1.465 + if (ConvertJSValueToString(aCx, dataAsValue, &dataAsValue, mozilla::dom::eNull, 1.466 + mozilla::dom::eNull, dataAsString)) { 1.467 + Send(aCx, dataAsString, aRv); 1.468 + } else { 1.469 + aRv.Throw(NS_ERROR_FAILURE); 1.470 + } 1.471 + return; 1.472 + } 1.473 + aRv = Send(RequestBody(aStream)); 1.474 + } 1.475 + void SendAsBinary(const nsAString& aBody, ErrorResult& aRv); 1.476 + 1.477 + void Abort(); 1.478 + 1.479 + // response 1.480 + uint32_t Status(); 1.481 + void GetStatusText(nsCString& aStatusText); 1.482 + void GetResponseHeader(const nsACString& aHeader, nsACString& aResult, 1.483 + ErrorResult& aRv); 1.484 + void GetResponseHeader(const nsAString& aHeader, nsString& aResult, 1.485 + ErrorResult& aRv) 1.486 + { 1.487 + nsCString result; 1.488 + GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv); 1.489 + if (result.IsVoid()) { 1.490 + aResult.SetIsVoid(true); 1.491 + } 1.492 + else { 1.493 + // The result value should be inflated: 1.494 + CopyASCIItoUTF16(result, aResult); 1.495 + } 1.496 + } 1.497 + void GetAllResponseHeaders(nsCString& aResponseHeaders); 1.498 + bool IsSafeHeader(const nsACString& aHeaderName, nsIHttpChannel* aHttpChannel); 1.499 + void OverrideMimeType(const nsAString& aMimeType) 1.500 + { 1.501 + // XXX Should we do some validation here? 1.502 + mOverrideMimeType = aMimeType; 1.503 + } 1.504 + XMLHttpRequestResponseType ResponseType() 1.505 + { 1.506 + return XMLHttpRequestResponseType(mResponseType); 1.507 + } 1.508 + void SetResponseType(XMLHttpRequestResponseType aType, ErrorResult& aRv); 1.509 + void GetResponse(JSContext* aCx, JS::MutableHandle<JS::Value> aResponse, 1.510 + ErrorResult& aRv); 1.511 + void GetResponseText(nsString& aResponseText, ErrorResult& aRv); 1.512 + nsIDocument* GetResponseXML(ErrorResult& aRv); 1.513 + 1.514 + bool MozBackgroundRequest(); 1.515 + void SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv); 1.516 + 1.517 + bool MozAnon(); 1.518 + bool MozSystem(); 1.519 + 1.520 + nsIChannel* GetChannel() 1.521 + { 1.522 + return mChannel; 1.523 + } 1.524 + 1.525 + // We need a GetInterface callable from JS for chrome JS 1.526 + void GetInterface(JSContext* aCx, nsIJSID* aIID, 1.527 + JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv); 1.528 + 1.529 + // This creates a trusted readystatechange event, which is not cancelable and 1.530 + // doesn't bubble. 1.531 + nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent); 1.532 + void DispatchProgressEvent(mozilla::DOMEventTargetHelper* aTarget, 1.533 + const nsAString& aType, 1.534 + bool aLengthComputable, 1.535 + uint64_t aLoaded, uint64_t aTotal); 1.536 + 1.537 + // Dispatch the "progress" event on the XHR or XHR.upload object if we've 1.538 + // received data since the last "progress" event. Also dispatches 1.539 + // "uploadprogress" as needed. 1.540 + void MaybeDispatchProgressEvents(bool aFinalProgress); 1.541 + 1.542 + // This is called by the factory constructor. 1.543 + nsresult Init(); 1.544 + 1.545 + nsresult init(nsIPrincipal* principal, 1.546 + nsIScriptContext* scriptContext, 1.547 + nsPIDOMWindow* globalObject, 1.548 + nsIURI* baseURI); 1.549 + 1.550 + void SetRequestObserver(nsIRequestObserver* aObserver); 1.551 + 1.552 + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest, 1.553 + nsXHREventTarget) 1.554 + bool AllowUploadProgress(); 1.555 + void RootJSResultObjects(); 1.556 + 1.557 + virtual void DisconnectFromOwner() MOZ_OVERRIDE; 1.558 + 1.559 + static void SetDontWarnAboutSyncXHR(bool aVal) 1.560 + { 1.561 + sDontWarnAboutSyncXHR = aVal; 1.562 + } 1.563 + static bool DontWarnAboutSyncXHR() 1.564 + { 1.565 + return sDontWarnAboutSyncXHR; 1.566 + } 1.567 +protected: 1.568 + nsresult DetectCharset(); 1.569 + nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen); 1.570 + static NS_METHOD StreamReaderFunc(nsIInputStream* in, 1.571 + void* closure, 1.572 + const char* fromRawSegment, 1.573 + uint32_t toOffset, 1.574 + uint32_t count, 1.575 + uint32_t *writeCount); 1.576 + nsresult CreateResponseParsedJSON(JSContext* aCx); 1.577 + void CreatePartialBlob(); 1.578 + bool CreateDOMFile(nsIRequest *request); 1.579 + // Change the state of the object with this. The broadcast argument 1.580 + // determines if the onreadystatechange listener should be called. 1.581 + nsresult ChangeState(uint32_t aState, bool aBroadcast = true); 1.582 + already_AddRefed<nsILoadGroup> GetLoadGroup() const; 1.583 + nsIURI *GetBaseURI(); 1.584 + 1.585 + already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel(); 1.586 + already_AddRefed<nsIJARChannel> GetCurrentJARChannel(); 1.587 + 1.588 + bool IsSystemXHR(); 1.589 + 1.590 + void ChangeStateToDone(); 1.591 + 1.592 + /** 1.593 + * Check if aChannel is ok for a cross-site request by making sure no 1.594 + * inappropriate headers are set, and no username/password is set. 1.595 + * 1.596 + * Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit. 1.597 + */ 1.598 + nsresult CheckChannelForCrossSiteRequest(nsIChannel* aChannel); 1.599 + 1.600 + void StartProgressEventTimer(); 1.601 + 1.602 + friend class AsyncVerifyRedirectCallbackForwarder; 1.603 + void OnRedirectVerifyCallback(nsresult result); 1.604 + 1.605 + nsresult Open(const nsACString& method, const nsACString& url, bool async, 1.606 + const mozilla::dom::Optional<nsAString>& user, 1.607 + const mozilla::dom::Optional<nsAString>& password); 1.608 + 1.609 + already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier(); 1.610 + 1.611 + nsCOMPtr<nsISupports> mContext; 1.612 + nsCOMPtr<nsIPrincipal> mPrincipal; 1.613 + nsCOMPtr<nsIChannel> mChannel; 1.614 + nsCOMPtr<nsIDocument> mResponseXML; 1.615 + nsCOMPtr<nsIChannel> mCORSPreflightChannel; 1.616 + nsTArray<nsCString> mCORSUnsafeHeaders; 1.617 + 1.618 + nsCOMPtr<nsIStreamListener> mXMLParserStreamListener; 1.619 + 1.620 + // used to implement getAllResponseHeaders() 1.621 + class nsHeaderVisitor : public nsIHttpHeaderVisitor { 1.622 + public: 1.623 + NS_DECL_ISUPPORTS 1.624 + NS_DECL_NSIHTTPHEADERVISITOR 1.625 + nsHeaderVisitor(nsXMLHttpRequest* aXMLHttpRequest, nsIHttpChannel* aHttpChannel) 1.626 + : mXHR(aXMLHttpRequest), mHttpChannel(aHttpChannel) {} 1.627 + virtual ~nsHeaderVisitor() {} 1.628 + const nsACString &Headers() { return mHeaders; } 1.629 + private: 1.630 + nsCString mHeaders; 1.631 + nsXMLHttpRequest* mXHR; 1.632 + nsCOMPtr<nsIHttpChannel> mHttpChannel; 1.633 + }; 1.634 + 1.635 + // The bytes of our response body. Only used for DEFAULT, ARRAYBUFFER and 1.636 + // BLOB responseTypes 1.637 + nsCString mResponseBody; 1.638 + 1.639 + // The text version of our response body. This is incrementally decoded into 1.640 + // as we receive network data. However for the DEFAULT responseType we 1.641 + // lazily decode into this from mResponseBody only when .responseText is 1.642 + // accessed. 1.643 + // Only used for DEFAULT and TEXT responseTypes. 1.644 + nsString mResponseText; 1.645 + 1.646 + // For DEFAULT responseType we use this to keep track of how far we've 1.647 + // lazily decoded from mResponseBody to mResponseText 1.648 + uint32_t mResponseBodyDecodedPos; 1.649 + 1.650 + // Decoder used for decoding into mResponseText 1.651 + // Only used for DEFAULT, TEXT and JSON responseTypes. 1.652 + // In cases where we've only received half a surrogate, the decoder itself 1.653 + // carries the state to remember this. Next time we receive more data we 1.654 + // simply feed the new data into the decoder which will handle the second 1.655 + // part of the surrogate. 1.656 + nsCOMPtr<nsIUnicodeDecoder> mDecoder; 1.657 + 1.658 + nsCString mResponseCharset; 1.659 + 1.660 + enum ResponseTypeEnum { 1.661 + XML_HTTP_RESPONSE_TYPE_DEFAULT, 1.662 + XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER, 1.663 + XML_HTTP_RESPONSE_TYPE_BLOB, 1.664 + XML_HTTP_RESPONSE_TYPE_DOCUMENT, 1.665 + XML_HTTP_RESPONSE_TYPE_JSON, 1.666 + XML_HTTP_RESPONSE_TYPE_TEXT, 1.667 + XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT, 1.668 + XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER, 1.669 + XML_HTTP_RESPONSE_TYPE_MOZ_BLOB 1.670 + }; 1.671 + 1.672 + void SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aType, ErrorResult& aRv); 1.673 + 1.674 + ResponseTypeEnum mResponseType; 1.675 + 1.676 + // It is either a cached blob-response from the last call to GetResponse, 1.677 + // but is also explicitly set in OnStopRequest. 1.678 + nsCOMPtr<nsIDOMBlob> mResponseBlob; 1.679 + // Non-null only when we are able to get a os-file representation of the 1.680 + // response, i.e. when loading from a file. 1.681 + nsRefPtr<nsDOMFile> mDOMFile; 1.682 + // We stream data to mBlobSet when response type is "blob" or "moz-blob" 1.683 + // and mDOMFile is null. 1.684 + nsAutoPtr<BlobSet> mBlobSet; 1.685 + 1.686 + nsString mOverrideMimeType; 1.687 + 1.688 + /** 1.689 + * The notification callbacks the channel had when Send() was 1.690 + * called. We want to forward things here as needed. 1.691 + */ 1.692 + nsCOMPtr<nsIInterfaceRequestor> mNotificationCallbacks; 1.693 + /** 1.694 + * Sink interfaces that we implement that mNotificationCallbacks may 1.695 + * want to also be notified for. These are inited lazily if we're 1.696 + * asked for the relevant interface. 1.697 + */ 1.698 + nsCOMPtr<nsIChannelEventSink> mChannelEventSink; 1.699 + nsCOMPtr<nsIProgressEventSink> mProgressEventSink; 1.700 + 1.701 + nsIRequestObserver* mRequestObserver; 1.702 + 1.703 + nsCOMPtr<nsIURI> mBaseURI; 1.704 + 1.705 + uint32_t mState; 1.706 + 1.707 + nsRefPtr<nsXMLHttpRequestUpload> mUpload; 1.708 + uint64_t mUploadTransferred; 1.709 + uint64_t mUploadTotal; 1.710 + bool mUploadLengthComputable; 1.711 + bool mUploadComplete; 1.712 + bool mProgressSinceLastProgressEvent; 1.713 + 1.714 + // Timeout support 1.715 + PRTime mRequestSentTime; 1.716 + uint32_t mTimeoutMilliseconds; 1.717 + nsCOMPtr<nsITimer> mTimeoutTimer; 1.718 + void StartTimeoutTimer(); 1.719 + void HandleTimeoutCallback(); 1.720 + 1.721 + bool mErrorLoad; 1.722 + bool mWaitingForOnStopRequest; 1.723 + bool mProgressTimerIsActive; 1.724 + bool mIsHtml; 1.725 + bool mWarnAboutMultipartHtml; 1.726 + bool mWarnAboutSyncHtml; 1.727 + bool mLoadLengthComputable; 1.728 + uint64_t mLoadTotal; // 0 if not known. 1.729 + uint64_t mLoadTransferred; 1.730 + nsCOMPtr<nsITimer> mProgressNotifier; 1.731 + void HandleProgressTimerCallback(); 1.732 + 1.733 + bool mIsSystem; 1.734 + bool mIsAnon; 1.735 + 1.736 + /** 1.737 + * Close the XMLHttpRequest's channels and dispatch appropriate progress 1.738 + * events. 1.739 + * 1.740 + * @param aType The progress event type. 1.741 + * @param aFlag A XML_HTTP_REQUEST_* state flag defined in 1.742 + * nsXMLHttpRequest.cpp. 1.743 + */ 1.744 + void CloseRequestWithError(const nsAString& aType, const uint32_t aFlag); 1.745 + 1.746 + bool mFirstStartRequestSeen; 1.747 + bool mInLoadProgressEvent; 1.748 + 1.749 + nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback; 1.750 + nsCOMPtr<nsIChannel> mNewRedirectChannel; 1.751 + 1.752 + JS::Heap<JS::Value> mResultJSON; 1.753 + 1.754 + mozilla::ArrayBufferBuilder mArrayBufferBuilder; 1.755 + JS::Heap<JSObject*> mResultArrayBuffer; 1.756 + 1.757 + void ResetResponse(); 1.758 + 1.759 + struct RequestHeader 1.760 + { 1.761 + nsCString header; 1.762 + nsCString value; 1.763 + }; 1.764 + nsTArray<RequestHeader> mModifiedRequestHeaders; 1.765 + 1.766 + nsTHashtable<nsCStringHashKey> mAlreadySetHeaders; 1.767 + 1.768 + // Helper object to manage our XPCOM scriptability bits 1.769 + nsXMLHttpRequestXPCOMifier* mXPCOMifier; 1.770 + 1.771 + static bool sDontWarnAboutSyncXHR; 1.772 +}; 1.773 + 1.774 +class MOZ_STACK_CLASS AutoDontWarnAboutSyncXHR 1.775 +{ 1.776 +public: 1.777 + AutoDontWarnAboutSyncXHR() : mOldVal(nsXMLHttpRequest::DontWarnAboutSyncXHR()) 1.778 + { 1.779 + nsXMLHttpRequest::SetDontWarnAboutSyncXHR(true); 1.780 + } 1.781 + 1.782 + ~AutoDontWarnAboutSyncXHR() 1.783 + { 1.784 + nsXMLHttpRequest::SetDontWarnAboutSyncXHR(mOldVal); 1.785 + } 1.786 + 1.787 +private: 1.788 + bool mOldVal; 1.789 +}; 1.790 + 1.791 +// A shim class designed to expose the non-DOM interfaces of 1.792 +// XMLHttpRequest via XPCOM stuff. 1.793 +class nsXMLHttpRequestXPCOMifier MOZ_FINAL : public nsIStreamListener, 1.794 + public nsIChannelEventSink, 1.795 + public nsIProgressEventSink, 1.796 + public nsIInterfaceRequestor, 1.797 + public nsITimerCallback 1.798 +{ 1.799 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.800 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier, 1.801 + nsIStreamListener) 1.802 + 1.803 + nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) : 1.804 + mXHR(aXHR) 1.805 + { 1.806 + } 1.807 + 1.808 + ~nsXMLHttpRequestXPCOMifier() { 1.809 + if (mXHR) { 1.810 + mXHR->mXPCOMifier = nullptr; 1.811 + } 1.812 + } 1.813 + 1.814 + NS_FORWARD_NSISTREAMLISTENER(mXHR->) 1.815 + NS_FORWARD_NSIREQUESTOBSERVER(mXHR->) 1.816 + NS_FORWARD_NSICHANNELEVENTSINK(mXHR->) 1.817 + NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->) 1.818 + NS_FORWARD_NSITIMERCALLBACK(mXHR->) 1.819 + 1.820 + NS_DECL_NSIINTERFACEREQUESTOR 1.821 + 1.822 +private: 1.823 + nsRefPtr<nsXMLHttpRequest> mXHR; 1.824 +}; 1.825 + 1.826 +class nsXHRParseEndListener : public nsIDOMEventListener 1.827 +{ 1.828 +public: 1.829 + NS_DECL_ISUPPORTS 1.830 + NS_IMETHOD HandleEvent(nsIDOMEvent *event) MOZ_OVERRIDE 1.831 + { 1.832 + nsCOMPtr<nsIXMLHttpRequest> xhr = do_QueryReferent(mXHR); 1.833 + if (xhr) { 1.834 + static_cast<nsXMLHttpRequest*>(xhr.get())->ChangeStateToDone(); 1.835 + } 1.836 + mXHR = nullptr; 1.837 + return NS_OK; 1.838 + } 1.839 + nsXHRParseEndListener(nsIXMLHttpRequest* aXHR) 1.840 + : mXHR(do_GetWeakReference(aXHR)) {} 1.841 + virtual ~nsXHRParseEndListener() {} 1.842 +private: 1.843 + nsWeakPtr mXHR; 1.844 +}; 1.845 + 1.846 +#endif