1 /*
2  * Copyright 2016 The Emscripten Authors.  All rights reserved.
3  * Emscripten is available under two separate licenses, the MIT license and the
4  * University of Illinois/NCSA Open Source License.  Both these licenses can be
5  * found in the LICENSE file.
6  */
7 
8 #pragma once
9 
10 #include <limits.h>
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <emscripten/html5.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 // Emscripten fetch attributes:
20 // If passed, the body of the request will be present in full in the onsuccess() handler.
21 #define EMSCRIPTEN_FETCH_LOAD_TO_MEMORY  1
22 
23 // If passed, the intermediate streamed bytes will be passed in to the onprogress() handler. If not specified, the
24 // onprogress() handler will still be called, but without data bytes.
25 // Note: Firefox only as it depends on 'moz-chunked-arraybuffer'.
26 #define EMSCRIPTEN_FETCH_STREAM_DATA 2
27 
28 // If passed, the final download will be stored in IndexedDB. If not specified, the file will only reside in browser memory.
29 #define EMSCRIPTEN_FETCH_PERSIST_FILE 4
30 
31 // Looks up if the file already exists in IndexedDB, and if so, it is returned without redownload. If a partial transfer
32 // exists in IndexedDB, the download will resume from where it left off and run to completion.
33 // EMSCRIPTEN_FETCH_APPEND, EMSCRIPTEN_FETCH_REPLACE and EMSCRIPTEN_FETCH_NO_DOWNLOAD are mutually exclusive.
34 // If none of these three flags is specified, the fetch operation is implicitly treated as if EMSCRIPTEN_FETCH_APPEND
35 // had been passed.
36 #define EMSCRIPTEN_FETCH_APPEND 8
37 
38 // If the file already exists in IndexedDB, the old file will be deleted and a new download is started.
39 // EMSCRIPTEN_FETCH_APPEND, EMSCRIPTEN_FETCH_REPLACE and EMSCRIPTEN_FETCH_NO_DOWNLOAD are mutually exclusive.
40 // If you would like to perform an XHR that neither reads or writes to IndexedDB, pass this flag EMSCRIPTEN_FETCH_REPLACE,
41 // and do not pass the flag EMSCRIPTEN_FETCH_PERSIST_FILE.
42 #define EMSCRIPTEN_FETCH_REPLACE 16
43 
44 // If specified, the file will only be looked up in IndexedDB, but if it does not exist, it is not attempted to be downloaded
45 // over the network but an error is raised.
46 // EMSCRIPTEN_FETCH_APPEND, EMSCRIPTEN_FETCH_REPLACE and EMSCRIPTEN_FETCH_NO_DOWNLOAD are mutually exclusive.
47 #define EMSCRIPTEN_FETCH_NO_DOWNLOAD 32
48 
49 // If specified, emscripten_fetch() will synchronously run to completion before returning.
50 // The callback handlers will be called from within emscripten_fetch() while the operation is in progress.
51 #define EMSCRIPTEN_FETCH_SYNCHRONOUS 64
52 
53 // If specified, it will be possible to call emscripten_fetch_wait() on the fetch
54 // to test or wait for its completion.
55 #define EMSCRIPTEN_FETCH_WAITABLE 128
56 
57 struct emscripten_fetch_t;
58 
59 // Specifies the parameters for a newly initiated fetch operation.
60 typedef struct emscripten_fetch_attr_t
61 {
62 	// 'POST', 'GET', etc.
63 	char requestMethod[32];
64 
65 	// Custom data that can be tagged along the process.
66 	void *userData;
67 
68 	void (*onsuccess)(struct emscripten_fetch_t *fetch);
69 	void (*onerror)(struct emscripten_fetch_t *fetch);
70 	void (*onprogress)(struct emscripten_fetch_t *fetch);
71 	void (*onreadystatechange)(struct emscripten_fetch_t *fetch);
72 
73 	// EMSCRIPTEN_FETCH_* attributes
74 	uint32_t attributes;
75 
76 	// Specifies the amount of time the request can take before failing due to a timeout.
77 	unsigned long timeoutMSecs;
78 
79 	// Indicates whether cross-site access control requests should be made using credentials.
80 	EM_BOOL withCredentials;
81 
82 	// Specifies the destination path in IndexedDB where to store the downloaded content body. If this is empty, the transfer
83 	// is not stored to IndexedDB at all.
84 	// Note that this struct does not contain space to hold this string, it only carries a pointer.
85 	// Calling emscripten_fetch() will make an internal copy of this string.
86 	const char *destinationPath;
87 
88 	// Specifies the authentication username to use for the request, if necessary.
89 	// Note that this struct does not contain space to hold this string, it only carries a pointer.
90 	// Calling emscripten_fetch() will make an internal copy of this string.
91 	const char *userName;
92 
93 	// Specifies the authentication username to use for the request, if necessary.
94 	// Note that this struct does not contain space to hold this string, it only carries a pointer.
95 	// Calling emscripten_fetch() will make an internal copy of this string.
96 	const char *password;
97 
98 	// Points to an array of strings to pass custom headers to the request. This array takes the form
99 	// {"key1", "value1", "key2", "value2", "key3", "value3", ..., 0 }; Note especially that the array
100 	// needs to be terminated with a null pointer.
101 	const char * const *requestHeaders;
102 
103 	// Pass a custom MIME type here to force the browser to treat the received data with the given type.
104 	const char *overriddenMimeType;
105 
106 	// If non-zero, specifies a pointer to the data that is to be passed as the body (payload) of the request
107 	// that is being performed. Leave as zero if no request body needs to be sent.
108 	// The memory pointed to by this field is provided by the user, and needs to be valid throughout the
109 	// duration of the fetch operation. If passing a non-zero pointer into this field, make sure to implement
110 	// *both* the onsuccess and onerror handlers to be notified when the fetch finishes to know when this memory
111 	// block can be freed. Do not pass a pointer to memory on the stack or other temporary area here.
112 	const char *requestData;
113 
114 	// Specifies the length of the buffer pointed by 'requestData'. Leave as 0 if no request body needs to be sent.
115 	size_t requestDataSize;
116 } emscripten_fetch_attr_t;
117 
118 typedef struct emscripten_fetch_t
119 {
120 	// Unique identifier for this fetch in progress.
121 	unsigned int id;
122 
123 	// Custom data that can be tagged along the process.
124 	void *userData;
125 
126 	// The remote URL that is being downloaded.
127 	const char *url;
128 
129 	// In onsuccess() handler:
130 	//   - If the EMSCRIPTEN_FETCH_LOAD_TO_MEMORY attribute was specified for the transfer, this points to the
131 	//     body of the downloaded data. Otherwise this will be null.
132 	// In onprogress() handler:
133 	//   - If the EMSCRIPTEN_FETCH_STREAM_DATA attribute was specified for the transfer, this points to a partial
134 	//     chunk of bytes related to the transfer. Otherwise this will be null.
135 	// The data buffer provided here has identical lifetime with the emscripten_fetch_t object itself, and is freed by
136 	// calling emscripten_fetch_close() on the emscripten_fetch_t pointer.
137 	const char *data;
138 
139 	// Specifies the length of the above data block in bytes. When the download finishes, this field will be valid even if
140 	// EMSCRIPTEN_FETCH_LOAD_TO_MEMORY was not specified.
141 	uint64_t numBytes;
142 
143 	// If EMSCRIPTEN_FETCH_STREAM_DATA is being performed, this indicates the byte offset from the start of the stream
144 	// that the data block specifies. (for onprogress() streaming XHR transfer, the number of bytes downloaded so far before this chunk)
145 	uint64_t dataOffset;
146 
147 	// Specifies the total number of bytes that the response body will be.
148 	// Note: This field may be zero, if the server does not report the Content-Length field.
149 	uint64_t totalBytes;
150 
151 	// Specifies the readyState of the XHR request:
152 	// 0: UNSENT: request not sent yet
153 	// 1: OPENED: emscripten_fetch has been called.
154 	// 2: HEADERS_RECEIVED: emscripten_fetch has been called, and headers and status are available.
155 	// 3: LOADING: download in progress.
156 	// 4: DONE: download finished.
157 	// See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
158 	unsigned short readyState;
159 
160 	// Specifies the status code of the response.
161 	unsigned short status;
162 
163 	// Specifies a human-readable form of the status code.
164 	char statusText[64];
165 
166 	uint32_t __proxyState;
167 
168 	// For internal use only.
169 	emscripten_fetch_attr_t __attributes;
170 } emscripten_fetch_t;
171 
172 // Clears the fields of an emscripten_fetch_attr_t structure to their default values in a future-compatible manner.
173 void emscripten_fetch_attr_init(emscripten_fetch_attr_t *fetch_attr);
174 
175 // Initiates a new Emscripten fetch operation, which downloads data from the given URL or from IndexedDB database.
176 emscripten_fetch_t *emscripten_fetch(emscripten_fetch_attr_t *fetch_attr, const char *url);
177 
178 // Synchronously blocks to wait for the given fetch operation to complete. This operation is not allowed in the main browser
179 // thread, in which case it will return EMSCRIPTEN_RESULT_NOT_SUPPORTED. Pass timeoutMSecs=infinite to wait indefinitely. If
180 // the wait times out, the return value will be EMSCRIPTEN_RESULT_TIMEOUT.
181 // The onsuccess()/onerror()/onprogress() handlers will be called in the calling thread from within this function before
182 // this function returns.
183 EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t *fetch, double timeoutMSecs);
184 
185 // Closes a finished or an executing fetch operation and frees up all memory. If the fetch operation was still executing, the
186 // onerror() handler will be called in the calling thread before this function returns.
187 EMSCRIPTEN_RESULT emscripten_fetch_close(emscripten_fetch_t *fetch);
188 
189 // Gets the size (in bytes) of the response headers as plain text.
190 // This must be called on the same thread as the fetch originated on.
191 // Note that this will return 0 if readyState < HEADERS_RECEIVED.
192 size_t emscripten_fetch_get_response_headers_length(emscripten_fetch_t *fetch);
193 
194 // Gets the response headers as plain text. dstSizeBytes should be headers_length + 1 (for the null terminator).
195 // This must be called on the same thread as the fetch originated on.
196 size_t emscripten_fetch_get_response_headers(emscripten_fetch_t *fetch, char *dst, size_t dstSizeBytes);
197 
198 // Converts the plain text headers into an array of strings. This array takes the form
199 // {"key1", "value1", "key2", "value2", "key3", "value3", ..., 0 }; Note especially that the array
200 // is terminated with a null pointer.
201 char **emscripten_fetch_unpack_response_headers(const char *headersString);
202 
203 // This frees the memory used by the array of headers. Call this when finished with the data returned
204 // by emscripten_fetch_unpack_response_headers.
205 void emscripten_fetch_free_unpacked_response_headers(char **unpackedHeaders);
206 
207 #define emscripten_asmfs_open_t int
208 
209 // The following flags specify how opening files for reading works (from strictest behavior to most flexible)
210 
211 // When a file is opened for reading, the file data must already fully reside in memory. (most similar to MEMFS behavior)
212 #define EMSCRIPTEN_ASMFS_OPEN_MEMORY    0
213 
214 // The file data does not need to be already in memory, but can reside in IndexedDB.
215 #define EMSCRIPTEN_ASMFS_OPEN_INDEXEDDB 1
216 
217 // The file will be downloaded from remote server, as long as it has an index entry in local filesystem.
218 #define EMSCRIPTEN_ASMFS_OPEN_REMOTE    2
219 
220 // A file entry does not need to exist on the local filesystem, but discovery will be attempted from remote server via an XHR first.
221 #define EMSCRIPTEN_ASMFS_OPEN_REMOTE_DISCOVER 3
222 
223 // Specifies how calls to non-truncating open(), fopen(), std::ifstream etc. behave on the calling thread.
224 void emscripten_asmfs_set_file_open_behavior(emscripten_asmfs_open_t behavior);
225 
226 // Returns the current file open behavior modein the calling thread.
227 emscripten_asmfs_open_t emscripten_asmfs_get_file_open_behavior();
228 
229 // Records the URL from where the given file on the ASMFS filesystem can be obtained from.
230 void emscripten_asmfs_set_remote_url(const char *filename, const char *remoteUrl);
231 
232 // Given a filename, outputs the remote URL address that file can be located in.
233 void emscripten_asmfs_remote_url(const char *filename, char *outRemoteUrl, int maxBytesToWrite);
234 
235 // Unloads the given file from the ASMFS filesystem. Call this function to save memory from files that have been already loaded
236 // in to memory and will no longer be needed.
237 void emscripten_asmfs_unload_data(const char *pathname);
238 
239 // Starts an asynchronous preload of a file from the given URL to the local filesystem to destination path 'pathname' for synchronous
240 // access on the main thread. Specify a onsuccess callback in options structure to be notified of when the transfer finishes.
241 // The resulting download will always be performed with the flag EMSCRIPTEN_FETCH_LOAD_TO_MEMORY and without the flags
242 // EMSCRIPTEN_FETCH_SYNCHRONOUS | EMSCRIPTEN_FETCH_WAITABLE | EMSCRIPTEN_FETCH_STREAM_DATA. The remaining flags
243 // EMSCRIPTEN_FETCH_NO_DOWNLOAD, EMSCRIPTEN_FETCH_PERSIST_FILE, EMSCRIPTEN_FETCH_APPEND/REPLACE are
244 // customizable in the options field. In particular, if EMSCRIPTEN_FETCH_NO_DOWNLOAD is passed, then the file is loaded to memory for
245 // synchronous access by looking at IndexedDB only.
246 EMSCRIPTEN_RESULT emscripten_asmfs_preload_file(const char *url, const char *pathname, int mode, emscripten_fetch_attr_t *options);
247 
248 // Computes the total amount of bytes in memory utilized by the filesystem at the moment.
249 // Note: This function can be slow since it walks through the whole filesystem.
250 uint64_t emscripten_asmfs_compute_memory_usage();
251 
252 #ifdef __cplusplus
253 }
254 #endif
255