소스 검색

replaced fetch with XHR

Gildas 7 년 전
부모
커밋
5ba3e404c2
3개의 변경된 파일59개의 추가작업 그리고 49개의 파일을 삭제
  1. 41 23
      lib/fetch/bg/fetch.js
  2. 3 11
      lib/fetch/content/fetch.js
  3. 15 15
      lib/single-file/single-file-browser.js

+ 41 - 23
lib/fetch/bg/fetch.js

@@ -18,11 +18,11 @@
  *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* global browser, fetch */
+/* global browser, XMLHttpRequest */
 
 (() => {
 
-	const fetchResponses = new Map();
+	const responses = new Map();
 
 	let requestId = 1;
 
@@ -40,29 +40,47 @@
 		if (request.method == "fetch") {
 			const responseId = requestId;
 			requestId = requestId + 1;
-			const response = await fetch(request.url, request.options);
-			if (response.status >= 400) {
-				throw new Error(response.statusText || response.status);
-			} else {
-				fetchResponses.set(responseId, response);
-				const headers = {};
-				for (let headerName of response.headers.keys()) {
-					headers[headerName] = response.headers.get(headerName);
+			const response = await superFetch(request.url);
+			responses.set(responseId, response);
+			response.responseId = responseId;
+			return { responseId, headers: response.headers };
+		} else if (request.method == "fetch.array") {
+			const response = responses.get(request.requestId);
+			responses.delete(response.requestId);
+			return new Promise((resolve, reject) => {
+				response.xhrRequest.onerror = event => reject(new Error(event.details));
+				if (response.xhrRequest.readyState == XMLHttpRequest.DONE) {
+					resolve(getResponse(response.xhrRequest));
+				} else {
+					response.xhrRequest.onload = () => resolve(getResponse(response.xhrRequest));
 				}
-				return { responseId, headers };
-			}
-		} else {
-			const content = fetchResponses.get(request.requestId);
-			fetchResponses.delete(request.requestId);
-			if (request.method == "fetch.array") {
-				const buffer = await content.arrayBuffer();
-				return { array: Array.from(new Uint8Array(buffer)) };
-			}
-			if (request.method == "fetch.text") {
-				const text = await content.text();
-				return { text };
-			}
+			});
 		}
 	}
 
+	function getResponse(xhrRequest) {
+		return { array: Array.from(new Uint8Array(xhrRequest.response)) };
+	}
+
+	async function superFetch(url) {
+		return new Promise((resolve, reject) => {
+			const xhrRequest = new XMLHttpRequest();
+			xhrRequest.responseType = "arraybuffer";
+			xhrRequest.onerror = event => reject(new Error(event.details));
+			xhrRequest.onreadystatechange = () => {
+				if (xhrRequest.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
+					if (xhrRequest.status >= 400) {
+						reject(new Error(xhrRequest.statusText || xhrRequest.status));
+					} else {
+						const headers = {};
+						headers["content-type"] = xhrRequest.getResponseHeader("Content-Type");
+						resolve({ xhrRequest, headers });
+					}
+				}
+			};
+			xhrRequest.open("GET", url, true);
+			xhrRequest.send();
+		});
+	}
+
 })();

+ 3 - 11
lib/fetch/content/fetch.js

@@ -18,25 +18,17 @@
  *   along with SingleFile.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* global browser, Blob */
+/* global browser */
 
 this.superFetch = (() => {
 
-	return async (url, options) => {
-		const responseFetch = await sendMessage({ method: "fetch", url, options });
+	return async url => {
+		const responseFetch = await sendMessage({ method: "fetch", url });
 		return {
 			headers: { get: headerName => responseFetch.headers[headerName] },
 			arrayBuffer: async () => {
 				const response = await sendMessage({ method: "fetch.array", requestId: responseFetch.responseId });
 				return new Uint8Array(response.array).buffer;
-			},
-			blob: async () => {
-				const response = await sendMessage({ method: "fetch.array", requestId: responseFetch.responseId });
-				return new Blob([new Uint8Array(response.array)]);
-			},
-			text: async () => {
-				const response = await sendMessage({ method: "fetch.text", requestId: responseFetch.responseId });
-				return response.text;
 			}
 		};
 	};

+ 15 - 15
lib/single-file/single-file-browser.js

@@ -31,13 +31,12 @@ this.SingleFile = (() => {
 
 	class Download {
 		static async getContent(resourceURL, options) {
-			const requestOptions = { method: "GET" };
 			let resourceContent;
 			if (!fetchResource) {
 				fetchResource = typeof superFetch == "undefined" ? fetch : superFetch;
 			}
 			try {
-				resourceContent = await fetchResource(resourceURL, requestOptions);
+				resourceContent = await fetchResource(resourceURL);
 			} catch (e) {
 				return options && options.asDataURI ? "data:base64," : "";
 			}
@@ -56,22 +55,23 @@ this.SingleFile = (() => {
 				}
 			} else {
 				const matchCharset = contentType && contentType.match(/\s*;\s*charset\s*=\s*"?([^";]*)"?(;|$)/i);
-				let textContent;
+				let charSet;
 				if (matchCharset && matchCharset[1]) {
-					const charSet = matchCharset[1].toLowerCase();
-					if (charSet != "utf-8") {
-						const arrayBuffer = await resourceContent.arrayBuffer();
-						textContent = (new TextDecoder(charSet)).decode(arrayBuffer);
+					charSet = matchCharset[1].toLowerCase();
+				}
+				if (!charSet) {
+					charSet = "utf-8";
+				}
+				try {
+					const arrayBuffer = await resourceContent.arrayBuffer();
+					const textContent = (new TextDecoder(charSet)).decode(arrayBuffer);
+					if (options.maxResourceSizeEnabled && textContent.length > options.maxResourceSize * ONE_MB) {
+						return "";
 					} else {
-						textContent = resourceContent.text();
+						return textContent;
 					}
-				} else {
-					textContent = resourceContent.text();
-				}
-				if (options.maxResourceSizeEnabled && textContent.length > options.maxResourceSize * ONE_MB) {
-					return "";
-				} else {
-					return textContent;
+				} catch (error) {
+					return "data:,";
 				}
 			}
 		}