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.

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

mercurial