Skip to content

obsidian:// handoff silently fails on Firefox profiles that confirm external protocols #18

Description

@mlsimon734

Summary

On Firefox/Zen, the obsidian:// handoff silently fails on any profile that has not
disabled the external-protocol confirmation. Both the popup's Devour and the bridge's
tab_clip are affected: extraction succeeds, the tool reports success with a file path,
and no note is ever written.

This has been invisible in development because bun run start launches the dev profile
with the two prefs that suppress the confirmation. A user installing from AMO gets the
failing path.

Cause

openObsidianUrl (src/background.ts) launches the protocol into a background tab and
destroys it 500ms later:

const ephemeral = await browser.tabs.create({ url: launchUrl, active: false });
if (ephemeral.id !== undefined) {
  const ephemeralId = ephemeral.id;
  setTimeout(() => { void browser.tabs.remove(ephemeralId).catch(() => {}); }, 500);
}

When Firefox wants to confirm the launch, the confirmation is raised against a tab that is
never visible and is gone before it could be answered. The launch is discarded with no
error surfaced to either the popup or the bridge.

package.json's start script sets:

--pref=network.protocol-handler.external.obsidian=true
--pref=network.protocol-handler.warn-external.obsidian=false

so the dialog never appears in dev. A real profile has neither pref.

Reproduction

  1. Use a Firefox/Zen profile without network.protocol-handler.warn-external.obsidian=false.
    (handlers.json holding obsidian: {"action": 4} is not sufficient — there is no
    ask: false alongside it.)
  2. Devour any tab from the popup, or call tab_clip over the bridge.
  3. Extraction succeeds and the call reports success; no note appears in any vault.

Setting both prefs manually in about:config makes it work immediately, which confirms
the diagnosis. Obsidian additionally shows a one-time "trust this source / allow the new
command" prompt on first successful launch; that one is expected and is not part of this bug.

Verified on Zen 1.21.9b, extension 0.2.0.2, macOS. Driving the same URL through
open "obsidian://new?file=...&vault=...&content=..." writes the note correctly, which
isolates the failure to the browser-side launch rather than to Obsidian or the URL builder.

Why the pref is not the fix

Telling users to set an about:config pref is not a shippable remedy for a store build.
The structural problem is that the launch is fired into a background tab that is
immediately destroyed, which discards any confirmation UI the browser needs to show — and
with it the "always allow" checkbox that would make subsequent launches silent.

Chrome already solves the equivalent problem by launching from the extension-origin page
redirect/obsidian-redirect.html, so the one-time approval is rememberable. Firefox
currently bypasses that page entirely and launches the protocol directly.

Secondary issue

tab_clip reports success without any confirmation that Obsidian received the handoff — it
returns the path it intended to write. That is how this bug stayed silent. It matters more
for tab_clip({ close: true }), which would close the tab on the strength of that
unverified success, filing a tab into the void and then closing it.

Scope

Pre-existing; unrelated to the vault-override (#16) or global-config (#17) work, both of
which are otherwise verified working.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions