diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3411e44d..c65b08a7 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1666,7 +1666,7 @@ "description": "Tooltip for the toolbar icon" }, "syncErrorRelogin": { - "message": "Sync failed.\nTry to re-login in Stylus options:\nclick 'disconnect' first, then 'connect'.", + "message": "Sync failed. You have been logged out.\nTry to re-login in Stylus options.", "description": "Tooltip for the toolbar icon" }, "syncErrorLock": { diff --git a/background/sync-manager.js b/background/sync-manager.js index 91a0753a..cb51498d 100644 --- a/background/sync-manager.js +++ b/background/sync-manager.js @@ -220,6 +220,7 @@ const syncMan = (() => { function isGrantError(err) { if (err.code === 401) return true; if (err.code === 400 && /invalid_grant/.test(err.message)) return true; + if (err.name === 'TokenError') return true; return false; } diff --git a/background/token-manager.js b/background/token-manager.js index 605da94d..c50090ef 100644 --- a/background/token-manager.js +++ b/background/token-manager.js @@ -32,10 +32,11 @@ const tokenMan = (() => { }, tokenURL: 'https://oauth2.googleapis.com/token', scopes: ['https://www.googleapis.com/auth/drive.appdata'], - revoke: token => { - const params = {token}; - return postQuery(`https://accounts.google.com/o/oauth2/revoke?${new URLSearchParams(params)}`); - }, + // FIXME: https://github.com/openstyles/stylus/issues/1248 + // revoke: token => { + // const params = {token}; + // return postQuery(`https://accounts.google.com/o/oauth2/revoke?${new URLSearchParams(params)}`); + // }, }, onedrive: { flow: 'code', @@ -62,6 +63,17 @@ const tokenMan = (() => { let alwaysUseTab = FIREFOX ? false : null; + class TokenError extends Error { + constructor(provider, message) { + super(`[${provider}] ${message}`); + this.name = 'TokenError'; + this.provider = provider; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, TokenError); + } + } + } + return { buildKeys(name, hooks) { @@ -91,7 +103,7 @@ const tokenMan = (() => { } } if (!interactive) { - throw new Error(`Invalid token: ${name}`); + throw new TokenError(name, 'Token is missing'); } return authUser(k, name, interactive, hooks); }, @@ -113,7 +125,7 @@ const tokenMan = (() => { async function refreshToken(name, k, obj) { if (!obj[k.REFRESH]) { - throw new Error('No refresh token'); + throw new TokenError(name, 'No refresh token'); } const provider = AUTH[name]; const body = { @@ -179,7 +191,7 @@ const tokenMan = (() => { new URL(finalUrl).search.slice(1) ); if (params.get('state') !== state) { - throw new Error(`Unexpected state: ${params.get('state')}, expected: ${state}`); + throw new TokenError(name, `Unexpected state: ${params.get('state')}, expected: ${state}`); } let result; if (provider.flow === 'token') { diff --git a/options/options.js b/options/options.js index ded31a7c..9d8c061e 100644 --- a/options/options.js +++ b/options/options.js @@ -111,7 +111,10 @@ document.onclick = e => { [elStart, () => API.sync.start(elCloud.value)], [elStop, API.sync.stop], [elSyncNow, API.sync.syncNow], - [elLogin, API.sync.login], + [elLogin, async () => { + await API.sync.login(); + await API.sync.syncNow(); + }], ]) { btn.on('click', e => { if (getEventKeyName(e) === 'MouseL') {