blob: ccdcff23786d98260e4265c06db729b47ab0549f [file] [log] [blame]
/*
* Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@nypop.com>
* Copyright (C) 2011 Google Inc. All rights reserved.
* Copyright (C) 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/document_parser_client.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class
ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams;
class Blob;
class BlobDataHandle;
class DOMArrayBuffer;
class DOMArrayBufferView;
class Document;
class DocumentParser;
class ExceptionState;
class ExecutionContext;
class FormData;
class ScriptState;
class SharedBuffer;
class TextResourceDecoder;
class ThreadableLoader;
class URLSearchParams;
class WebDataConsumerHandle;
class XMLHttpRequestUpload;
class XMLHttpRequest final : public XMLHttpRequestEventTarget,
public ThreadableLoaderClient,
public DocumentParserClient,
public ActiveScriptWrappable<XMLHttpRequest>,
public ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(XMLHttpRequest);
public:
static XMLHttpRequest* Create(ScriptState*);
static XMLHttpRequest* Create(ExecutionContext*);
XMLHttpRequest(ExecutionContext*,
v8::Isolate*,
bool is_isolated_world,
scoped_refptr<SecurityOrigin>);
~XMLHttpRequest() override;
// These exact numeric values are important because JS expects them.
enum State {
kUnsent = 0,
kOpened = 1,
kHeadersReceived = 2,
kLoading = 3,
kDone = 4
};
enum ResponseTypeCode {
kResponseTypeDefault,
kResponseTypeText,
kResponseTypeJSON,
kResponseTypeDocument,
kResponseTypeBlob,
kResponseTypeArrayBuffer,
};
// ContextLifecycleObserver
void ContextDestroyed(ExecutionContext*) override;
ExecutionContext* GetExecutionContext() const override;
// ScriptWrappable
bool HasPendingActivity() const final;
// XMLHttpRequestEventTarget
const AtomicString& InterfaceName() const override;
// JavaScript attributes and methods
const KURL& Url() const { return url_; }
String statusText() const;
int status() const;
State readyState() const;
bool withCredentials() const { return with_credentials_; }
void setWithCredentials(bool, ExceptionState&);
void open(const AtomicString& method, const String& url, ExceptionState&);
void open(const AtomicString& method,
const String& url,
bool async,
const String& username,
const String& password,
ExceptionState&);
void open(const AtomicString& method,
const KURL&,
bool async,
ExceptionState&);
void send(
const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams&,
ExceptionState&);
void abort();
void Dispose();
void setRequestHeader(const AtomicString& name,
const AtomicString& value,
ExceptionState&);
void overrideMimeType(const AtomicString& override, ExceptionState&);
String getAllResponseHeaders() const;
const AtomicString& getResponseHeader(const AtomicString&) const;
v8::Local<v8::String> responseText(ExceptionState&);
v8::Local<v8::String> ResponseJSONSource();
Document* responseXML(ExceptionState&);
Blob* ResponseBlob();
DOMArrayBuffer* ResponseArrayBuffer();
unsigned timeout() const {
return static_cast<unsigned>(timeout_.InMilliseconds());
}
void setTimeout(unsigned timeout, ExceptionState&);
ResponseTypeCode GetResponseTypeCode() const { return response_type_code_; }
String responseType();
void setResponseType(const String&, ExceptionState&);
String responseURL();
// For Inspector.
void SendForInspectorXHRReplay(scoped_refptr<EncodedFormData>,
ExceptionState&);
XMLHttpRequestUpload* upload();
bool IsAsync() { return async_; }
DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange, kReadystatechange);
void Trace(blink::Visitor*) override;
const char* NameInHeapSnapshot() const override { return "XMLHttpRequest"; }
private:
class BlobLoader;
Document* GetDocument() const;
// Returns the SecurityOrigin of the isolated world if the XMLHttpRequest was
// created in an isolated world. Otherwise, returns the SecurityOrigin of the
// execution context.
const SecurityOrigin* GetSecurityOrigin() const;
SecurityOrigin* GetMutableSecurityOrigin();
void DidSendData(unsigned long long bytes_sent,
unsigned long long total_bytes_to_be_sent) override;
void DidReceiveResponse(unsigned long identifier,
const ResourceResponse&,
std::unique_ptr<WebDataConsumerHandle>) override;
void DidReceiveData(const char* data, unsigned data_length) override;
// When responseType is set to "blob", didDownloadData() is called instead
// of didReceiveData().
void DidDownloadData(int data_length) override;
void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) override;
void DidFinishLoading(unsigned long identifier) override;
void DidFail(const ResourceError&) override;
void DidFailRedirectCheck() override;
// BlobLoader notifications.
void DidFinishLoadingInternal();
void DidFinishLoadingFromBlob();
void DidFailLoadingFromBlob();
// DocumentParserClient
void NotifyParserStopped() override;
void EndLoading();
// Returns the MIME type part of mime_type_override_ if present and
// successfully parsed, or returns one of the "Content-Type" header value
// of the received response.
//
// This method is named after the term "final MIME type" defined in the
// spec but doesn't convert the result to ASCII lowercase as specified in
// the spec. Must be lowered later or compared using case insensitive
// comparison functions if required.
AtomicString FinalResponseMIMEType() const;
// The same as finalResponseMIMEType() but fallbacks to "text/xml" if
// finalResponseMIMEType() returns an empty string.
AtomicString FinalResponseMIMETypeWithFallback() const;
// Returns the "final charset" defined in
// https://xhr.spec.whatwg.org/#final-charset.
String FinalResponseCharset() const;
bool ResponseIsXML() const;
bool ResponseIsHTML() const;
std::unique_ptr<TextResourceDecoder> CreateDecoder() const;
void InitResponseDocument();
void ParseDocumentChunk(const char* data, unsigned data_length);
bool AreMethodAndURLValidForSend();
void ThrowForLoadFailureIfNeeded(ExceptionState&, const String&);
bool InitSend(ExceptionState&);
void SendBytesData(const void*, size_t, ExceptionState&);
void send(Document*, ExceptionState&);
void send(const String&, ExceptionState&);
void send(Blob*, ExceptionState&);
void send(FormData*, ExceptionState&);
void send(URLSearchParams*, ExceptionState&);
void send(DOMArrayBuffer*, ExceptionState&);
void send(DOMArrayBufferView*, ExceptionState&);
bool HasContentTypeRequestHeader() const;
void SetRequestHeaderInternal(const AtomicString& name,
const AtomicString& value);
void TrackProgress(long long data_length);
// Changes m_state and dispatches a readyStateChange event if new m_state
// value is different from last one.
void ChangeState(State new_state);
void DispatchReadyStateChangeEvent();
// Clears variables used only while the resource is being loaded.
void ClearVariablesForLoading();
// Returns false iff reentry happened and a new load is started.
bool InternalAbort();
// Clears variables holding response header and body data.
void ClearResponse();
void ClearRequest();
void CreateRequest(scoped_refptr<EncodedFormData>, ExceptionState&);
// Dispatches a response ProgressEvent.
void DispatchProgressEvent(const AtomicString&, long long, long long);
// Dispatches a response ProgressEvent using values sampled from
// m_receivedLength and m_response.
void DispatchProgressEventFromSnapshot(const AtomicString&);
// Handles didFail() call not caused by cancellation or timeout.
void HandleNetworkError();
// Handles didFail() call for cancellations. For example, the
// ResourceLoader handling the load notifies m_loader of an error
// cancellation when the frame containing the XHR navigates away.
void HandleDidCancel();
// Handles didFail() call for timeout.
void HandleDidTimeout();
void HandleRequestError(DOMExceptionCode,
const AtomicString&,
long long,
long long);
void UpdateContentTypeAndCharset(const AtomicString& content_type,
const String& charset);
XMLHttpRequestProgressEventThrottle& ProgressEventThrottle();
// Report the memory usage associated with this object to V8 so that V8 can
// schedule GC accordingly. This function should be called whenever the
// internal memory usage changes except for the following members.
// - response_text_ of type TraceWrapperV8String
// ScriptString internally creates and holds a v8::String, so V8 is aware of
// its memory usage.
// - response_array_buffer_ of type DOMArrayBuffer
// DOMArrayBuffer supports the memory usage reporting system on their own,
// so there is no need.
void ReportMemoryUsageToV8();
Member<XMLHttpRequestUpload> upload_;
KURL url_;
network::mojom::blink::URLLoaderFactoryPtr blob_url_loader_factory_;
AtomicString method_;
HTTPHeaderMap request_headers_;
// Not converted to ASCII lowercase. Must be lowered later or compared
// using case insensitive comparison functions if needed.
AtomicString mime_type_override_;
TimeDelta timeout_;
TraceWrapperMember<Blob> response_blob_;
TaskHandle pending_abort_event_;
Member<ThreadableLoader> loader_;
State state_ = kUnsent;
ResourceResponse response_;
std::unique_ptr<TextResourceDecoder> decoder_;
// Avoid using a flat WTF::String here and rather use a traced v8::String
// which internally builds a string rope.
GC_PLUGIN_IGNORE("crbug.com/841830") TraceWrapperV8String response_text_;
TraceWrapperMember<Document> response_document_;
Member<DocumentParser> response_document_parser_;
scoped_refptr<SharedBuffer> binary_response_builder_;
size_t binary_response_builder_last_reported_size_ = 0;
long long length_downloaded_to_blob_ = 0;
long long length_downloaded_to_blob_last_reported_ = 0;
TraceWrapperMember<DOMArrayBuffer> response_array_buffer_;
// Used for onprogress tracking
long long received_length_ = 0;
// An exception to throw in synchronous mode. It's set when failure
// notification is received from m_loader and thrown at the end of send() if
// any.
DOMExceptionCode exception_code_ = DOMExceptionCode::kNoError;
Member<XMLHttpRequestProgressEventThrottle> progress_event_throttle_;
// An enum corresponding to the allowed string values for the responseType
// attribute.
ResponseTypeCode response_type_code_ = kResponseTypeDefault;
v8::Isolate* const isolate_;
// Set to true if the XMLHttpRequest was created in an isolated world.
bool is_isolated_world_;
// Stores the SecurityOrigin associated with the isolated world if any.
scoped_refptr<SecurityOrigin> isolated_world_security_origin_;
// This blob loader will be used if |m_downloadingToFile| is true and
// |m_responseTypeCode| is NOT ResponseTypeBlob.
Member<BlobLoader> blob_loader_;
// Positive if we are dispatching events.
// This is an integer specifying the recursion level rather than a boolean
// because in some cases we have recursive dispatching.
int event_dispatch_recursion_level_ = 0;
bool async_ = true;
bool with_credentials_ = false;
// Used to skip m_responseDocument creation if it's done previously. We need
// this separate flag since m_responseDocument can be 0 for some cases.
bool parsed_response_ = false;
bool error_ = false;
bool upload_events_allowed_ = true;
bool upload_complete_ = false;
bool same_origin_request_ = true;
// True iff the ongoing resource loading is using the downloadToBlob
// option.
bool downloading_to_blob_ = false;
bool response_text_overflow_ = false;
bool send_flag_ = false;
bool response_array_buffer_failure_ = false;
};
std::ostream& operator<<(std::ostream&, const XMLHttpRequest*);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_