From 34e0c1dbc28f47104823c75b6e2e08e21ea752e1 Mon Sep 17 00:00:00 2001 From: Nicolas Ganz Date: Thu, 20 Oct 2022 14:02:26 +0200 Subject: [PATCH 1/3] improve the fallbacks for opening tabs with hint Firefox does not allow browser.tabs.create to create new tabs with file:// urls. For those cases this workaround not just clicks the links but uses the appropriate modifier keys to open the links in tabs, either in the background or foreground. --- src/excmds.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/excmds.ts b/src/excmds.ts index 54f5721d..3b170bb1 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -5170,10 +5170,10 @@ export async function hint(...args: string[]): Promise { DOM.simulateClick(elem) break case OpenMode.Tab: - hintTabOpen(elem.href, true).catch(() => DOM.simulateClick(elem)) + hintTabOpen(elem.href, true).catch(() => DOM.mouseEvent(elem, "click", { ctrlKey: true, shiftKey: true })) break case OpenMode.BackgroundTab: - hintTabOpen(elem.href, false).catch(() => DOM.simulateClick(elem)) + hintTabOpen(elem.href, false).catch(() => DOM.mouseEvent(elem, "click", { ctrlKey: true })) break case OpenMode.Window: openInNewWindow({ url: new URL(elem.href, window.location.href).href }) From d675e5af2358e13112f0ab4601c278adfc2ca1cd Mon Sep 17 00:00:00 2001 From: Nicolas Ganz Date: Fri, 21 Oct 2022 08:29:30 +0200 Subject: [PATCH 2/3] moved the selecction of the modifier keys to simulateClick --- src/excmds.ts | 4 ++-- src/lib/dom.ts | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/excmds.ts b/src/excmds.ts index 3b170bb1..0894edc9 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -5170,10 +5170,10 @@ export async function hint(...args: string[]): Promise { DOM.simulateClick(elem) break case OpenMode.Tab: - hintTabOpen(elem.href, true).catch(() => DOM.mouseEvent(elem, "click", { ctrlKey: true, shiftKey: true })) + hintTabOpen(elem.href, true).catch(() => DOM.simulateClick(elem, DOM.TabTarget.NewTab)) break case OpenMode.BackgroundTab: - hintTabOpen(elem.href, false).catch(() => DOM.mouseEvent(elem, "click", { ctrlKey: true })) + hintTabOpen(elem.href, false).catch(() => DOM.simulateClick(elem, DOM.TabTarget.NewBackgroundTab)) break case OpenMode.Window: openInNewWindow({ url: new URL(elem.href, window.location.href).href }) diff --git a/src/lib/dom.ts b/src/lib/dom.ts index 01bea414..64106a59 100644 --- a/src/lib/dom.ts +++ b/src/lib/dom.ts @@ -668,26 +668,53 @@ export function anchors(includeInvisible = false) { ]) } +export const enum TabTarget { + CurrentTab, + NewTab, + NewBackgroundTab, + NewWindow, +} + +const tabTargetToModifierKey = { + [TabTarget.CurrentTab]: {}, + [TabTarget.NewTab]: { ctrlKey: true, shiftKey: true }, + [TabTarget.NewBackgroundTab]: { ctrlKey: true }, + [TabTarget.NewWindow]: { shiftKey: true }, +} + /** if `target === _blank` clicking the link is treated as opening a popup and is blocked. Use webext API to avoid that. */ -export function simulateClick(target: HTMLElement) { +export function simulateClick( + target: HTMLElement, + tabTarget: TabTarget = TabTarget.CurrentTab, +) { // target can be set to other stuff, and we'll fail in annoying ways. // There's no easy way around that while this code executes outside of the // magic 'short lived event handler' context. // // OTOH, hardly anyone uses that functionality any more. - if ( + let usePopupBlockerWorkaround = (target as HTMLAnchorElement).target === "_blank" || (target as HTMLAnchorElement).target === "_new" - ) { + const href = (target as HTMLAnchorElement).href + if (href !== undefined && href.startsWith("file:")) { + // file URLS cannot be opend with browser.tabs.create + // see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create#url + // still create a new tab + if (tabTarget === TabTarget.CurrentTab && usePopupBlockerWorkaround) { + tabTarget = TabTarget.NewTab + } + usePopupBlockerWorkaround = false + } + if (usePopupBlockerWorkaround) { // Try to open the new tab in the same container as the current one. activeTabContainerId().then(containerId => { if (containerId) - openInNewTab((target as HTMLAnchorElement).href, { + openInNewTab(href, { related: true, cookieStoreId: containerId, }) else - openInNewTab((target as HTMLAnchorElement).href, { + openInNewTab(href, { related: true, }) }) @@ -695,7 +722,7 @@ export function simulateClick(target: HTMLElement) { if (target instanceof HTMLDetailsElement) { target.open = !target.open } - mouseEvent(target, "click") + mouseEvent(target, "click", tabTargetToModifierKey[tabTarget]) // DOM.focus has additional logic for focusing inputs focus(target) } From 282d5eccbb1e8b99fc3c8347cb64285194f9c9d2 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 21 Oct 2022 11:14:28 +0200 Subject: [PATCH 3/3] simplified undefined check Co-authored-by: Oliver Blanthorn --- src/lib/dom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/dom.ts b/src/lib/dom.ts index 64106a59..24d03866 100644 --- a/src/lib/dom.ts +++ b/src/lib/dom.ts @@ -696,7 +696,7 @@ export function simulateClick( (target as HTMLAnchorElement).target === "_blank" || (target as HTMLAnchorElement).target === "_new" const href = (target as HTMLAnchorElement).href - if (href !== undefined && href.startsWith("file:")) { + if (href?.startsWith("file:")) { // file URLS cannot be opend with browser.tabs.create // see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/create#url // still create a new tab