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,
20  *  MA 02110-1301 USA
21  */
22 
23 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
24 #define THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
25 
26 #include <memory>
27 
28 #include "base/memory/scoped_refptr.h"
29 #include "mojo/public/cpp/bindings/pending_remote.h"
30 #include "services/network/public/mojom/trust_tokens.mojom-blink.h"
31 #include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
32 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
33 #include "third_party/blink/renderer/core/dom/document_parser_client.h"
34 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
35 #include "third_party/blink/renderer/core/fetch/trust_token.h"
36 #include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
37 #include "third_party/blink/renderer/core/probe/async_task_id.h"
38 #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h"
39 #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h"
40 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
41 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
42 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h"
43 #include "third_party/blink/renderer/platform/heap/handle.h"
44 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
45 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
46 #include "third_party/blink/renderer/platform/network/http_header_map.h"
47 #include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
48 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
49 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
50 #include "third_party/blink/renderer/platform/wtf/forward.h"
51 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
52 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
53 
54 namespace blink {
55 
56 class
57     ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams;
58 class Blob;
59 class BlobDataHandle;
60 class DOMArrayBuffer;
61 class DOMArrayBufferView;
62 class Document;
63 class DocumentParser;
64 class ExceptionState;
65 class ExecutionContext;
66 class FormData;
67 class ScriptState;
68 class TextResourceDecoder;
69 class ThreadableLoader;
70 class URLSearchParams;
71 class XMLHttpRequestUpload;
72 
73 class XMLHttpRequest final : public XMLHttpRequestEventTarget,
74                              public ThreadableLoaderClient,
75                              public DocumentParserClient,
76                              public ActiveScriptWrappable<XMLHttpRequest>,
77                              public ExecutionContextLifecycleObserver {
78   DEFINE_WRAPPERTYPEINFO();
79   USING_GARBAGE_COLLECTED_MIXIN(XMLHttpRequest);
80 
81  public:
82   static XMLHttpRequest* Create(ScriptState*);
83   static XMLHttpRequest* Create(ExecutionContext*);
84 
85   XMLHttpRequest(ExecutionContext*,
86                  v8::Isolate*,
87                  bool is_isolated_world,
88                  scoped_refptr<SecurityOrigin>);
89   ~XMLHttpRequest() override;
90 
91   // These exact numeric values are important because JS expects them.
92   enum State {
93     kUnsent = 0,
94     kOpened = 1,
95     kHeadersReceived = 2,
96     kLoading = 3,
97     kDone = 4
98   };
99 
100   enum ResponseTypeCode {
101     kResponseTypeDefault,
102     kResponseTypeText,
103     kResponseTypeJSON,
104     kResponseTypeDocument,
105     kResponseTypeBlob,
106     kResponseTypeArrayBuffer,
107   };
108 
109   // ExecutionContextLifecycleObserver
110   void ContextDestroyed() override;
111   ExecutionContext* GetExecutionContext() const override;
112 
113   // ScriptWrappable
114   bool HasPendingActivity() const final;
115 
116   // XMLHttpRequestEventTarget
117   const AtomicString& InterfaceName() const override;
118 
119   // JavaScript attributes and methods
Url()120   const KURL& Url() const { return url_; }
121   String statusText() const;
122   int status() const;
123   State readyState() const;
withCredentials()124   bool withCredentials() const { return with_credentials_; }
125   void setWithCredentials(bool, ExceptionState&);
126   void open(const AtomicString& method, const String& url, ExceptionState&);
127   void open(const AtomicString& method,
128             const String& url,
129             bool async,
130             const String& username,
131             const String& password,
132             ExceptionState&);
133   void open(const AtomicString& method,
134             const KURL&,
135             bool async,
136             ExceptionState&);
137   void send(
138       const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams&,
139       ExceptionState&);
140   void abort();
141   void Dispose();
142   void setRequestHeader(const AtomicString& name,
143                         const AtomicString& value,
144                         ExceptionState&);
145   void setTrustToken(const TrustToken*, ExceptionState&);
146   void overrideMimeType(const AtomicString& override, ExceptionState&);
147   String getAllResponseHeaders() const;
148   const AtomicString& getResponseHeader(const AtomicString&) const;
149   v8::Local<v8::String> responseText(ExceptionState&);
150   v8::Local<v8::String> ResponseJSONSource();
151   Document* responseXML(ExceptionState&);
152   Blob* ResponseBlob();
153   DOMArrayBuffer* ResponseArrayBuffer();
timeout()154   unsigned timeout() const {
155     return static_cast<unsigned>(timeout_.InMilliseconds());
156   }
157   void setTimeout(unsigned timeout, ExceptionState&);
GetResponseTypeCode()158   ResponseTypeCode GetResponseTypeCode() const { return response_type_code_; }
159   String responseType();
160   void setResponseType(const String&, ExceptionState&);
161   String responseURL();
162 
163   // For Inspector.
164   void SendForInspectorXHRReplay(scoped_refptr<EncodedFormData>,
165                                  ExceptionState&);
166 
167   XMLHttpRequestUpload* upload();
IsAsync()168   bool IsAsync() { return async_; }
169 
async_task_id()170   probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
171 
172   DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange, kReadystatechange)
173 
174   void Trace(Visitor*) override;
NameInHeapSnapshot()175   const char* NameInHeapSnapshot() const override { return "XMLHttpRequest"; }
176 
177  private:
178   class BlobLoader;
179 
180   Document* GetDocument() const;
181 
182   void DidSendData(uint64_t bytes_sent,
183                    uint64_t total_bytes_to_be_sent) override;
184   void DidReceiveResponse(uint64_t identifier,
185                           const ResourceResponse&) override;
186   void DidReceiveData(const char* data, unsigned data_length) override;
187   // When responseType is set to "blob", didDownloadData() is called instead
188   // of didReceiveData().
189   void DidDownloadData(uint64_t data_length) override;
190   void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) override;
191   void DidFinishLoading(uint64_t identifier) override;
192   void DidFail(const ResourceError&) override;
193   void DidFailRedirectCheck() override;
194 
195   // BlobLoader notifications.
196   void DidFinishLoadingInternal();
197   void DidFinishLoadingFromBlob();
198   void DidFailLoadingFromBlob();
199 
200   // DocumentParserClient
201   void NotifyParserStopped() override;
202 
203   void EndLoading();
204 
205   // Returns the MIME type part of mime_type_override_ if present and
206   // successfully parsed, or returns one of the "Content-Type" header value
207   // of the received response.
208   //
209   // This method is named after the term "final MIME type" defined in the
210   // spec but doesn't convert the result to ASCII lowercase as specified in
211   // the spec. Must be lowered later or compared using case insensitive
212   // comparison functions if required.
213   AtomicString FinalResponseMIMEType() const;
214   // The same as finalResponseMIMEType() but fallbacks to "text/xml" if
215   // finalResponseMIMEType() returns an empty string.
216   AtomicString FinalResponseMIMETypeWithFallback() const;
217   // Returns the "final charset" defined in
218   // https://xhr.spec.whatwg.org/#final-charset.
219   WTF::TextEncoding FinalResponseCharset() const;
220   bool ResponseIsXML() const;
221   bool ResponseIsHTML() const;
222 
223   std::unique_ptr<TextResourceDecoder> CreateDecoder() const;
224 
225   void InitResponseDocument();
226   void ParseDocumentChunk(const char* data, unsigned data_length);
227 
228   bool AreMethodAndURLValidForSend();
229 
230   void ThrowForLoadFailureIfNeeded(ExceptionState&, const String&);
231 
232   bool InitSend(ExceptionState&);
233   void SendBytesData(const void*, size_t, ExceptionState&);
234   void send(Document*, ExceptionState&);
235   void send(const String&, ExceptionState&);
236   void send(Blob*, ExceptionState&);
237   void send(FormData*, ExceptionState&);
238   void send(URLSearchParams*, ExceptionState&);
239   void send(DOMArrayBuffer*, ExceptionState&);
240   void send(DOMArrayBufferView*, ExceptionState&);
241 
242   bool HasContentTypeRequestHeader() const;
243   void SetRequestHeaderInternal(const AtomicString& name,
244                                 const AtomicString& value);
245 
246   void TrackProgress(uint64_t data_length);
247   // Changes m_state and dispatches a readyStateChange event if new m_state
248   // value is different from last one.
249   void ChangeState(State new_state);
250   void DispatchReadyStateChangeEvent();
251 
252   // Clears variables used only while the resource is being loaded.
253   void ClearVariablesForLoading();
254   // Clears state and cancels loader.
255   void InternalAbort();
256   // Clears variables holding response header and body data.
257   void ClearResponse();
258   void ClearRequest();
259 
260   void CreateRequest(scoped_refptr<EncodedFormData>, ExceptionState&);
261 
262   // Dispatches a response ProgressEvent.
263   void DispatchProgressEvent(const AtomicString&, int64_t, int64_t);
264   // Dispatches a response ProgressEvent using values sampled from
265   // m_receivedLength and m_response.
266   void DispatchProgressEventFromSnapshot(const AtomicString&);
267 
268   // Handles didFail() call not caused by cancellation or timeout.
269   void HandleNetworkError();
270   // Handles didFail() call for cancellations. For example, the
271   // ResourceLoader handling the load notifies m_loader of an error
272   // cancellation when the frame containing the XHR navigates away.
273   void HandleDidCancel();
274   // Handles didFail() call for timeout.
275   void HandleDidTimeout();
276 
277   void HandleRequestError(DOMExceptionCode,
278                           const AtomicString&,
279                           int64_t,
280                           int64_t);
281 
282   void UpdateContentTypeAndCharset(const AtomicString& content_type,
283                                    const String& charset);
284 
285   XMLHttpRequestProgressEventThrottle& ProgressEventThrottle();
286 
287   // Report the memory usage associated with this object to V8 so that V8 can
288   // schedule GC accordingly.  This function should be called whenever the
289   // internal memory usage changes except for the following members.
290   // - response_text_ of type TraceWrapperV8String
291   //   ScriptString internally creates and holds a v8::String, so V8 is aware of
292   //   its memory usage.
293   // - response_array_buffer_ of type DOMArrayBuffer
294   //   DOMArrayBuffer supports the memory usage reporting system on their own,
295   //   so there is no need.
296   void ReportMemoryUsageToV8();
297 
298   Member<XMLHttpRequestUpload> upload_;
299 
300   KURL url_;
301   mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
302       blob_url_loader_factory_;
303   AtomicString method_;
304   HTTPHeaderMap request_headers_;
305   network::mojom::blink::TrustTokenParamsPtr trust_token_params_;
306   // Not converted to ASCII lowercase. Must be lowered later or compared
307   // using case insensitive comparison functions if needed.
308   AtomicString mime_type_override_;
309   base::TimeDelta timeout_;
310   Member<Blob> response_blob_;
311 
312   TaskHandle pending_abort_event_;
313 
314   Member<ThreadableLoader> loader_;
315   State state_ = kUnsent;
316 
317   ResourceResponse response_;
318 
319   std::unique_ptr<TextResourceDecoder> decoder_;
320 
321   // Avoid using a flat WTF::String here and rather use a traced v8::String
322   // which internally builds a string rope.
323   GC_PLUGIN_IGNORE("crbug.com/841830") TraceWrapperV8String response_text_;
324   Member<Document> response_document_;
325   Member<DocumentParser> response_document_parser_;
326 
327   scoped_refptr<SharedBuffer> binary_response_builder_;
328   size_t binary_response_builder_last_reported_size_ = 0;
329   int64_t length_downloaded_to_blob_ = 0;
330   int64_t length_downloaded_to_blob_last_reported_ = 0;
331 
332   Member<DOMArrayBuffer> response_array_buffer_;
333 
334   // Used for onprogress tracking
335   int64_t received_length_ = 0;
336 
337   // An exception to throw in synchronous mode. It's set when failure
338   // notification is received from m_loader and thrown at the end of send() if
339   // any.
340   DOMExceptionCode exception_code_ = DOMExceptionCode::kNoError;
341 
342   Member<XMLHttpRequestProgressEventThrottle> progress_event_throttle_;
343 
344   // An enum corresponding to the allowed string values for the responseType
345   // attribute.
346   ResponseTypeCode response_type_code_ = kResponseTypeDefault;
347 
348   v8::Isolate* const isolate_;
349   // Set to true if the XMLHttpRequest was created in an isolated world.
350   bool is_isolated_world_;
351   // Stores the SecurityOrigin associated with the isolated world if any.
352   scoped_refptr<SecurityOrigin> isolated_world_security_origin_;
353 
354   // This blob loader will be used if |m_downloadingToFile| is true and
355   // |m_responseTypeCode| is NOT ResponseTypeBlob.
356   Member<BlobLoader> blob_loader_;
357 
358   // Positive if we are dispatching events.
359   // This is an integer specifying the recursion level rather than a boolean
360   // because in some cases we have recursive dispatching.
361   int event_dispatch_recursion_level_ = 0;
362 
363   bool async_ = true;
364 
365   bool with_credentials_ = false;
366 
367   // Used to skip m_responseDocument creation if it's done previously. We need
368   // this separate flag since m_responseDocument can be 0 for some cases.
369   bool parsed_response_ = false;
370   bool error_ = false;
371   bool upload_events_allowed_ = true;
372   bool upload_complete_ = false;
373   // True iff the ongoing resource loading is using the downloadToBlob
374   // option.
375   bool downloading_to_blob_ = false;
376   bool response_text_overflow_ = false;
377   bool send_flag_ = false;
378   bool response_array_buffer_failure_ = false;
379 
380   probe::AsyncTaskId async_task_id_;
381 };
382 
383 std::ostream& operator<<(std::ostream&, const XMLHttpRequest*);
384 
385 }  // namespace blink
386 
387 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
388