From cf1f51af0a404cf62c67761c9efd0965e2a82bc4 Mon Sep 17 00:00:00 2001 From: tophf Date: Mon, 22 Feb 2021 15:12:19 +0300 Subject: [PATCH] vivaldi bug workaround: open webAuth flow in a tab (#1186) --- background/token-manager.js | 37 ++++++++++++++++++++++++++++++++++++- js/toolbox.js | 15 +++++++++++++++ popup/preinit.js | 19 ++----------------- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/background/token-manager.js b/background/token-manager.js index 4aac046a..67cefe51 100644 --- a/background/token-manager.js +++ b/background/token-manager.js @@ -1,4 +1,4 @@ -/* global FIREFOX */// toolbox.js +/* global FIREFOX getActiveTab waitForTabUrl */// toolbox.js /* global chromeLocal */// storage-util.js 'use strict'; @@ -51,6 +51,8 @@ const tokenMan = (() => { }; const NETWORK_LATENCY = 30; // seconds + let alwaysUseTab = FIREFOX ? false : null; + return { buildKeys(name) { @@ -138,11 +140,20 @@ const tokenMan = (() => { if (provider.authQuery) { Object.assign(query, provider.authQuery); } + if (alwaysUseTab == null) { + alwaysUseTab = await detectVivaldiWebRequestBug(); + } const url = `${provider.authURL}?${new URLSearchParams(query)}`; const finalUrl = await webextLaunchWebAuthFlow({ url, + alwaysUseTab, interactive, redirect_uri: query.redirect_uri, + windowOptions: { + state: 'normal', + width: Math.min(screen.width - 100, 800), + height: Math.min(screen.height - 100, 800), + }, }); const params = new URLSearchParams( provider.flow === 'token' ? @@ -203,4 +214,28 @@ const tokenMan = (() => { err.code = r.status; throw err; } + + async function detectVivaldiWebRequestBug() { + // Workaround for https://github.com/openstyles/stylus/issues/1182 + // Note that modern Vivaldi isn't exposed in `navigator.userAgent` but it adds `extData` to tabs + const anyTab = await getActiveTab() || (await browser.tabs.query({}))[0]; + if (anyTab && !anyTab.extData) { + return false; + } + let bugged = true; + const TEST_URL = chrome.runtime.getURL('manifest.json'); + const check = ({url}) => { + bugged = url !== TEST_URL; + }; + chrome.webRequest.onBeforeRequest.addListener(check, {urls: [TEST_URL], types: ['main_frame']}); + const {tabs: [tab]} = await browser.windows.create({ + type: 'popup', + state: 'minimized', + url: TEST_URL, + }); + await waitForTabUrl(tab); + chrome.windows.remove(tab.windowId); + chrome.webRequest.onBeforeRequest.removeListener(check); + return bugged; + } })(); diff --git a/js/toolbox.js b/js/toolbox.js index 7c4eb442..8307aea8 100644 --- a/js/toolbox.js +++ b/js/toolbox.js @@ -18,6 +18,7 @@ stringAsRegExp tryCatch tryRegExp + waitForTabUrl */ const CHROME = Boolean(chrome.app) && parseInt(navigator.userAgent.match(/Chrom\w+\/(\d+)|$/)[1]); @@ -469,6 +470,20 @@ async function closeCurrentTab() { if (tab) chrome.tabs.remove(tab.id); } +function waitForTabUrl(tab) { + return new Promise(resolve => { + browser.tabs.onUpdated.addListener(...[ + function onUpdated(tabId, info, updatedTab) { + if (info.url && tabId === tab.id) { + browser.tabs.onUpdated.removeListener(onUpdated); + resolve(updatedTab); + } + }, + ...'UpdateFilter' in browser.tabs ? [{tabId: tab.id}] : [], // FF only + ]); + }); +} + function capitalize(s) { return s[0].toUpperCase() + s.slice(1); } diff --git a/popup/preinit.js b/popup/preinit.js index b70dd546..750f0d37 100644 --- a/popup/preinit.js +++ b/popup/preinit.js @@ -1,5 +1,5 @@ /* global API */// msg.js -/* global URLS */// toolbox.js +/* global URLS waitForTabUrl */// toolbox.js 'use strict'; const ABOUT_BLANK = 'about:blank'; @@ -7,7 +7,7 @@ const ABOUT_BLANK = 'about:blank'; const preinit = (async () => { let [tab] = await browser.tabs.query({currentWindow: true, active: true}); if (!chrome.app && tab.status === 'loading' && tab.url === ABOUT_BLANK) { - tab = await waitForTabUrlFF(tab); + tab = await waitForTabUrl(tab); } const frames = sortTabFrames(await browser.webNavigation.getAllFrames({tabId: tab.id})); let url = tab.pendingUrl || tab.url || ''; // new Chrome uses pendingUrl while connecting @@ -60,18 +60,3 @@ function sortTabFrames(frames) { } return sortedFrames; } - -function waitForTabUrlFF(tab) { - return new Promise(resolve => { - browser.tabs.onUpdated.addListener(...[ - function onUpdated(tabId, info, updatedTab) { - if (info.url && tabId === tab.id) { - browser.tabs.onUpdated.removeListener(onUpdated); - resolve(updatedTab); - } - }, - ...'UpdateFilter' in browser.tabs ? [{tabId: tab.id}] : [], - // TODO: remove both spreads and tabId check when strict_min_version >= 61 - ]); - }); -}