Răsfoiți Sursa

implented fallback of identity.launchWebAuthFlow

Former-commit-id: 010bb6a14c70cb64b98b60f723850ceb3e93f277
Gildas 6 ani în urmă
părinte
comite
9ecdf4c85b

+ 7 - 1
extension/core/bg/config.js

@@ -79,6 +79,7 @@ singlefile.extension.core.bg.config = (() => {
 		saveRawPage: false,
 		saveToClipboard: false,
 		saveToGDrive: false,
+		forceWebAuthFlow: false,
 		resolveFragmentIdentifierURLs: false,
 		userScriptEnabled: false,
 		openEditor: false
@@ -97,7 +98,8 @@ singlefile.extension.core.bg.config = (() => {
 		updateRule,
 		addRule,
 		getAuthInfo,
-		setAuthInfo
+		setAuthInfo,
+		removeAuthInfo
 	};
 
 	async function upgrade() {
@@ -365,6 +367,10 @@ singlefile.extension.core.bg.config = (() => {
 		await browser.storage.local.set({ authInfo });
 	}
 
+	async function removeAuthInfo() {
+		await browser.storage.local.remove(["authInfo"]);
+	}
+
 	async function resetProfiles() {
 		await pendingUpgradePromise;
 		const tabsData = await singlefile.extension.core.bg.tabsData.get();

+ 31 - 35
extension/core/bg/downloads.js

@@ -40,9 +40,9 @@ singlefile.extension.core.bg.downloads = (() => {
 	const SCOPES = ["https://www.googleapis.com/auth/drive.file"];
 
 	const manifest = browser.runtime.getManifest();
+	const requestPermissionIdentity = manifest.optional_permissions && manifest.optional_permissions.includes("identity");
 	const gDrive = new GDrive(CLIENT_ID, SCOPES);
-	let permissionIdentityRequested = manifest.optional_permissions && manifest.optional_permissions.includes("identity");
-
+	gDrive.launchWebAuthFlow = async options => singlefile.extension.core.bg.tabs.launchWebAuthFlow(options);
 	return {
 		onMessage,
 		download,
@@ -86,7 +86,7 @@ singlefile.extension.core.bg.downloads = (() => {
 						const blob = new Blob([contents], { type: MIMETYPE_HTML });
 						try {
 							if (message.saveToGDrive) {
-								await uploadPage(message.filename, blob, sender.tab.id);
+								await uploadPage(message.filename, blob, sender.tab.id, { forceWebAuthFlow: message.forceWebAuthFlow });
 							} else {
 								message.url = URL.createObjectURL(blob);
 								await downloadPage(message, {
@@ -110,16 +110,12 @@ singlefile.extension.core.bg.downloads = (() => {
 			}
 			return {};
 		}
-		if (message.method.endsWith(".enableGDrive")) {
-			if (permissionIdentityRequested) {
-				await requestPermissionIdentity();
-			}
-			return {};
-		}
 		if (message.method.endsWith(".disableGDrive")) {
 			const authInfo = await singlefile.extension.core.bg.config.getAuthInfo();
-			singlefile.extension.core.bg.config.setAuthInfo(null);
-			await gDrive.revokeAuthToken(authInfo.accessToken);
+			if (authInfo) {
+				singlefile.extension.core.bg.config.removeAuthInfo();
+				await gDrive.revokeAuthToken(authInfo.accessToken);
+			}
 			return {};
 		}
 		if (message.method.endsWith(".end")) {
@@ -130,16 +126,18 @@ singlefile.extension.core.bg.downloads = (() => {
 		}
 	}
 
-	async function getAuthInfo(force) {
+	async function getAuthInfo(uploadOptions, force) {
 		let code, cancelled, authInfo = await singlefile.extension.core.bg.config.getAuthInfo();
-		gDrive.setAuthInfo(authInfo);
-		const options = { interactive: true, auto: true };
-		if (permissionIdentityRequested) {
-			await requestPermissionIdentity();
-		}
-		if (!authInfo || force || gDrive.managedToken()) {
+		const options = {
+			interactive: true,
+			auto: true,
+			forceWebAuthFlow: uploadOptions.forceWebAuthFlow,
+			requestPermissionIdentity
+		};
+		gDrive.setAuthInfo(authInfo, options);
+		if (!authInfo || force || gDrive.managedToken(options)) {
 			try {
-				if (!gDrive.managedToken()) {
+				if (!gDrive.managedToken(options)) {
 					singlefile.extension.core.bg.tabs.getAuthCode(gDrive.getAuthURL(options))
 						.then(authCode => code = authCode)
 						.catch(() => { cancelled = true; });
@@ -156,24 +154,18 @@ singlefile.extension.core.bg.downloads = (() => {
 					throw error;
 				}
 			}
-			await singlefile.extension.core.bg.config.setAuthInfo(authInfo);
+			if (authInfo) {
+				await singlefile.extension.core.bg.config.setAuthInfo(authInfo);
+			} else {
+				await singlefile.extension.core.bg.config.removeAuthInfo();
+			}
 		}
 		return authInfo;
 	}
 
-	async function requestPermissionIdentity() {
+	async function uploadPage(filename, blob, tabId, options) {
 		try {
-			await browser.permissions.request({ permissions: ["identity"] });
-			permissionIdentityRequested = false;
-		}
-		catch (error) {
-			// ignored;
-		}
-	}
-
-	async function uploadPage(filename, blob, tabId) {
-		try {
-			await getAuthInfo();
+			await getAuthInfo(options);
 			await gDrive.upload(filename, blob);
 		}
 		catch (error) {
@@ -183,13 +175,17 @@ singlefile.extension.core.bg.downloads = (() => {
 					authInfo = await gDrive.refreshAuthToken();
 				} catch (error) {
 					if (error.message == "unknown_token") {
-						authInfo = await getAuthInfo(true);
+						authInfo = await getAuthInfo(options, true);
 					} else {
 						throw error;
 					}
 				}
-				await singlefile.extension.core.bg.config.setAuthInfo(authInfo);
-				await uploadPage(filename, blob, tabId);
+				if (authInfo) {
+					await singlefile.extension.core.bg.config.setAuthInfo(authInfo);
+				} else {
+					await singlefile.extension.core.bg.config.removeAuthInfo();
+				}
+				await uploadPage(filename, blob, tabId, options);
 			} else {
 				throw error;
 			}

+ 12 - 0
extension/core/bg/tabs.js

@@ -100,6 +100,18 @@ singlefile.extension.core.bg.tabs = (() => {
 					}
 				}
 			});
+		},
+		launchWebAuthFlow: async options => {
+			const tab = await browser.tabs.create({ url: options.url, active: true });
+			return new Promise((resolve, reject) => {
+				browser.tabs.onRemoved.addListener(onTabRemoved);
+				function onTabRemoved(tabId) {
+					if (tabId == tab.id) {
+						browser.tabs.onRemoved.removeListener(onTabRemoved);
+						reject(new Error("code_required"));
+					}
+				}
+			});
 		}
 	};
 

+ 1 - 0
extension/core/content/content-download.js

@@ -44,6 +44,7 @@ this.singlefile.extension.core.content.download = this.singlefile.extension.core
 					filename: pageData.filename,
 					saveToClipboard: options.saveToClipboard,
 					saveToGDrive: options.saveToGDrive,
+					forceWebAuthFlow: options.forceWebAuthFlow,
 					filenameReplacementCharacter: options.filenameReplacementCharacter,
 					openEditor: options.openEditor,
 					compressHTML: options.compressHTMLEdit,

+ 41 - 11
extension/lib/gdrive/gdrive.js

@@ -33,6 +33,8 @@ this.GDrive = this.GDrive || (() => {
 	const GDRIVE_URL = "https://www.googleapis.com/drive/v3/files";
 	const GDRIVE_UPLOAD_URL = "https://www.googleapis.com/upload/drive/v3/files";
 
+	let requestPermissionIdentityNeeded;
+
 	class GDrive {
 		constructor(clientId, scopes) {
 			this.clientId = clientId;
@@ -40,8 +42,14 @@ this.GDrive = this.GDrive || (() => {
 			this.folderIds = new Map();
 			setInterval(() => this.folderIds.clear(), 60 * 1000);
 		}
+		async requestPermissionIdentity(options) {
+			if (options.requestPermissionIdentity) {
+				await requestPermissionIdentity();
+			}
+		}
 		async auth(options = { interactive: true, auto: true }) {
-			if (this.managedToken()) {
+			if (this.managedToken(options)) {
+				await this.requestPermissionIdentity(options);
 				const token = await browser.identity.getAuthToken({ interactive: options.interactive });
 				if (token) {
 					this.accessToken = token;
@@ -52,11 +60,11 @@ this.GDrive = this.GDrive || (() => {
 				return options.code ? authFromCode(this, options) : initAuth(this, options);
 			}
 		}
-		managedToken() {
-			return Boolean(browser.identity.getAuthToken);
+		managedToken(options) {
+			return Boolean(browser.identity.getAuthToken) && !options.forceWebAuthFlow;
 		}
-		setAuthInfo(authInfo) {
-			if (!browser.identity.getAuthToken) {
+		setAuthInfo(authInfo, options) {
+			if (!this.managedToken(options)) {
 				if (authInfo) {
 					this.accessToken = authInfo.accessToken;
 					this.refreshToken = authInfo.refreshToken;
@@ -103,8 +111,12 @@ this.GDrive = this.GDrive || (() => {
 		}
 		async revokeAuthToken(accessToken) {
 			if (accessToken) {
-				if (this.managedToken()) {
-					await browser.identity.removeCachedAuthToken({ token: accessToken });
+				if (browser.identity.removeCachedAuthToken) {
+					try {
+						await browser.identity.removeCachedAuthToken({ token: accessToken });
+					} catch (error) {
+						// ignored
+					}
 				}
 				const httpResponse = await fetch(REVOKE_ACCESS_URL, {
 					method: "POST",
@@ -182,6 +194,18 @@ this.GDrive = this.GDrive || (() => {
 
 	return GDrive;
 
+	async function requestPermissionIdentity() {
+		if (requestPermissionIdentityNeeded) {
+			try {
+				await browser.permissions.request({ permissions: ["identity"] });
+				requestPermissionIdentityNeeded = false;
+			}
+			catch (error) {
+				// ignored;
+			}
+		}
+	}
+
 	async function authFromCode(gdrive, options) {
 		const httpResponse = await fetch(TOKEN_URL, {
 			method: "POST",
@@ -200,10 +224,16 @@ this.GDrive = this.GDrive || (() => {
 
 	async function initAuth(gdrive, options) {
 		try {
-			return await browser.identity.launchWebAuthFlow({
-				interactive: options.interactive,
-				url: gdrive.authURL
-			});
+			if (gdrive.managedToken(options)) {
+				return await browser.identity.launchWebAuthFlow({
+					interactive: options.interactive,
+					url: gdrive.authURL
+				});
+			} else if (gdrive.launchWebAuthFlow) {
+				return await gdrive.launchWebAuthFlow({ url: gdrive.authURL });
+			} else {
+				throw new Error("auth_not_supported");
+			}
 		}
 		catch (error) {
 			if (error.message && error.message.includes("access")) {

+ 1 - 3
extension/ui/bg/ui-options.js

@@ -345,9 +345,7 @@
 		}
 	}, false);
 	saveToGDriveInput.addEventListener("click", async () => {
-		if (saveToGDriveInput.checked) {
-			await browser.runtime.sendMessage({ method: "downloads.enableGDrive" });
-		} else {
+		if (!saveToGDriveInput.checked) {
 			await browser.runtime.sendMessage({ method: "downloads.disableGDrive" });
 		}
 	}, false);