1/*
2 * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@nypop.com>
4 * Copyright (C) 2011 Google Inc. All rights reserved.
5 * Copyright (C) 2012 Intel Corporation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#pragma once
23
24#include "ActiveDOMObject.h"
25#include "ExceptionOr.h"
26#include "FormData.h"
27#include "ResourceResponse.h"
28#include "ThreadableLoaderClient.h"
29#include "UserGestureIndicator.h"
30#include <wtf/URL.h>
31#include "XMLHttpRequestEventTarget.h"
32#include "XMLHttpRequestProgressEventThrottle.h"
33#include <wtf/Variant.h>
34#include <wtf/text/StringBuilder.h>
35
36namespace JSC {
37class ArrayBuffer;
38class ArrayBufferView;
39}
40
41namespace WebCore {
42
43class Blob;
44class Document;
45class DOMFormData;
46class SecurityOrigin;
47class SharedBuffer;
48class TextResourceDecoder;
49class ThreadableLoader;
50class XMLHttpRequestUpload;
51struct OwnedString;
52
53class XMLHttpRequest final : public ActiveDOMObject, public RefCounted<XMLHttpRequest>, private ThreadableLoaderClient, public XMLHttpRequestEventTarget {
54 WTF_MAKE_ISO_ALLOCATED(XMLHttpRequest);
55public:
56 static Ref<XMLHttpRequest> create(ScriptExecutionContext&);
57 WEBCORE_EXPORT ~XMLHttpRequest();
58
59 // Keep it in 3bits.
60 enum State : uint8_t {
61 UNSENT = 0,
62 OPENED = 1,
63 HEADERS_RECEIVED = 2,
64 LOADING = 3,
65 DONE = 4
66 };
67
68 virtual void didReachTimeout();
69
70 EventTargetInterface eventTargetInterface() const override { return XMLHttpRequestEventTargetInterfaceType; }
71 ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); }
72
73 using SendTypes = Variant<RefPtr<Document>, RefPtr<Blob>, RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<DOMFormData>, String>;
74
75 const URL& url() const { return m_url; }
76 String statusText() const;
77 int status() const;
78 State readyState() const;
79 bool withCredentials() const { return m_includeCredentials; }
80 ExceptionOr<void> setWithCredentials(bool);
81 ExceptionOr<void> open(const String& method, const String& url);
82 ExceptionOr<void> open(const String& method, const URL&, bool async);
83 ExceptionOr<void> open(const String& method, const String&, bool async, const String& user, const String& password);
84 ExceptionOr<void> send(Optional<SendTypes>&&);
85 void abort();
86 ExceptionOr<void> setRequestHeader(const String& name, const String& value);
87 ExceptionOr<void> overrideMimeType(const String& override);
88 bool doneWithoutErrors() const { return !m_error && readyState() == DONE; }
89 String getAllResponseHeaders() const;
90 String getResponseHeader(const String& name) const;
91 ExceptionOr<OwnedString> responseText();
92 String responseTextIgnoringResponseType() const { return m_responseBuilder.toStringPreserveCapacity(); }
93 String responseMIMEType() const;
94
95 Document* optionalResponseXML() const { return m_responseDocument.get(); }
96 ExceptionOr<Document*> responseXML();
97
98 Ref<Blob> createResponseBlob();
99 RefPtr<JSC::ArrayBuffer> createResponseArrayBuffer();
100
101 unsigned timeout() const { return m_timeoutMilliseconds; }
102 ExceptionOr<void> setTimeout(unsigned);
103
104 bool responseCacheIsValid() const { return m_responseCacheIsValid; }
105 void didCacheResponse();
106
107 // Keep it in 3bits.
108 enum class ResponseType : uint8_t {
109 EmptyString = 0,
110 Arraybuffer = 1,
111 Blob = 2,
112 Document = 3,
113 Json = 4,
114 Text = 5,
115 };
116 ExceptionOr<void> setResponseType(ResponseType);
117 ResponseType responseType() const;
118
119 String responseURL() const;
120
121 XMLHttpRequestUpload& upload();
122 XMLHttpRequestUpload* optionalUpload() const { return m_upload.get(); }
123
124 const ResourceResponse& resourceResponse() const { return m_response; }
125
126 using RefCounted<XMLHttpRequest>::ref;
127 using RefCounted<XMLHttpRequest>::deref;
128
129 size_t memoryCost() const;
130
131 WEBCORE_EXPORT void setMaximumIntervalForUserGestureForwarding(double);
132
133private:
134 explicit XMLHttpRequest(ScriptExecutionContext&);
135
136 TextEncoding finalResponseCharset() const;
137
138 // ActiveDOMObject
139 void contextDestroyed() override;
140 bool canSuspendForDocumentSuspension() const override;
141 void suspend(ReasonForSuspension) override;
142 void resume() override;
143 void stop() override;
144 const char* activeDOMObjectName() const override;
145
146 void refEventTarget() override { ref(); }
147 void derefEventTarget() override { deref(); }
148
149 Document* document() const;
150 SecurityOrigin* securityOrigin() const;
151
152#if ENABLE(DASHBOARD_SUPPORT)
153 bool usesDashboardBackwardCompatibilityMode() const;
154#endif
155
156 // ThreadableLoaderClient
157 void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
158 void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override;
159 void didReceiveData(const char* data, int dataLength) override;
160 void didFinishLoading(unsigned long identifier) override;
161 void didFail(const ResourceError&) override;
162
163 bool responseIsXML() const;
164
165 Optional<ExceptionOr<void>> prepareToSend();
166 ExceptionOr<void> send(Document&);
167 ExceptionOr<void> send(const String& = { });
168 ExceptionOr<void> send(Blob&);
169 ExceptionOr<void> send(DOMFormData&);
170 ExceptionOr<void> send(JSC::ArrayBuffer&);
171 ExceptionOr<void> send(JSC::ArrayBufferView&);
172 ExceptionOr<void> sendBytesData(const void*, size_t);
173
174 void changeState(State);
175 void callReadyStateChangeListener();
176
177 // Returns false when cancelling the loader within internalAbort() triggers an event whose callback creates a new loader.
178 // In that case, the function calling internalAbort should exit.
179 bool internalAbort();
180
181 void clearResponse();
182 void clearResponseBuffers();
183 void clearRequest();
184
185 ExceptionOr<void> createRequest();
186
187 void genericError();
188 void networkError();
189 void abortError();
190
191 void dispatchErrorEvents(const AtomicString&);
192
193 using EventTarget::dispatchEvent;
194 void dispatchEvent(Event&) override;
195
196 void resumeTimerFired();
197 Ref<TextResourceDecoder> createDecoder() const;
198
199 void networkErrorTimerFired();
200
201 unsigned m_async : 1;
202 unsigned m_includeCredentials : 1;
203 unsigned m_sendFlag : 1;
204 unsigned m_createdDocument : 1;
205 unsigned m_error : 1;
206 unsigned m_uploadListenerFlag : 1;
207 unsigned m_uploadComplete : 1;
208 unsigned m_wasAbortedByClient : 1;
209 unsigned m_responseCacheIsValid : 1;
210 unsigned m_dispatchErrorOnResuming : 1;
211 unsigned m_readyState : 3; // State
212 unsigned m_responseType : 3; // ResponseType
213
214 unsigned m_timeoutMilliseconds { 0 };
215
216 std::unique_ptr<XMLHttpRequestUpload> m_upload;
217
218 URL m_url;
219 String m_method;
220 HTTPHeaderMap m_requestHeaders;
221 RefPtr<FormData> m_requestEntityBody;
222 String m_mimeTypeOverride;
223
224 RefPtr<ThreadableLoader> m_loader;
225
226 String m_responseEncoding;
227
228 ResourceResponse m_response;
229
230 RefPtr<TextResourceDecoder> m_decoder;
231
232 RefPtr<Document> m_responseDocument;
233
234 RefPtr<SharedBuffer> m_binaryResponseBuilder;
235
236 StringBuilder m_responseBuilder;
237
238 // Used for progress event tracking.
239 long long m_receivedLength { 0 };
240
241 XMLHttpRequestProgressEventThrottle m_progressEventThrottle;
242
243 mutable String m_allResponseHeaders;
244
245 Timer m_resumeTimer;
246 Timer m_networkErrorTimer;
247 Timer m_timeoutTimer;
248
249 MonotonicTime m_sendingTime;
250
251 Optional<ExceptionCode> m_exceptionCode;
252 RefPtr<UserGestureToken> m_userGestureToken;
253 Seconds m_maximumIntervalForUserGestureForwarding;
254};
255
256inline auto XMLHttpRequest::responseType() const -> ResponseType
257{
258 return static_cast<ResponseType>(m_responseType);
259}
260
261inline auto XMLHttpRequest::readyState() const -> State
262{
263 return static_cast<State>(m_readyState);
264}
265
266} // namespace WebCore
267