External scheme handler launched by an add-on can be blocked despite user action
Categories
(WebExtensions :: Untriaged, defect, P3)
Tracking
(firefox95 affected, firefox96 affected, firefox97 affected)
People
(Reporter: manikulin, Unassigned, NeedInfo)
References
Details
(Keywords: regressionwindow-wanted)
Attachments
(1 file)
|
85.90 KB,
image/png
|
Details |
User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0
Steps to reproduce:
Consider an extension that launches external handler for a special scheme in response to a user action (browser action, command, context menu item). Some await calls are unavoidable before URI parameters can be determined. Add-on may be called from a page with privileged content: PDF file, reader mode, add-on catalogue. It looks like gray zone even for non-privileged pages due to security and privacy restrictions. The following approach still allows to detect error due to improper configuration of desktop environment (but not popup blocker activation):
const fr = document.createElement("iframe");
fr.setAttribute("src", "org-protocol:/capture?url=https://addons.mozilla.org");
document.body.append(fr);
Currently it mostly works in the context of background page (reliably in Chromium and with the following problem in Firefox).
Example is saving a note to a Emacs Org Mode file https://orgmode.org/manual/Protocols.html Sometimes user may wish to save links to several already opened bookmark to read them later. I faced the issue during testing such approach. I expect more severe problems if I will implement automatic tests.
So I clicked on browser action toolbar button with interval of a second or two.
Actual results:
First time scheme handler was invoked, second time the following message appeared in extension console:
Iframe with external protocol was blocked due to lack of user activation, or because not enough time has passed since the last such iframe was loaded.
Expected results:
External handler invoked two times.
Since there are complications with determining user action context when async-await calls are involved in Firefox, I suggest to reset popup blocker state for add-on background page before calling a listeners of user actions:
- browser and page actions,
- context menus,
- commands.
I appreciate that Firefox tries to protect against web pages that can spam by attempts of calls of external application, tries to resist against fingerprinting. However currently a valid use case causes false alarm.
Besides add-on background page, a new tab may be created, but it makes user experience worse when no further interaction is expected. Another approach to launch external protocol handler is to execute a content script that updates window.location. It does not allow to bookmark e.g. a page of extension on addons.mozilla.org and extension has no chance to notice a problem with handler configuration in desktop environment.
Text of the error appeared in a patch for Bug #1679456 "Remove popup opening tokens (replacing them by user activation consumption)." but its description is too brief to figure out intentions of that changes.
I hope, it is possible to improve popup blocker policy for extensions to avoid false alarms in valid user scenarios.
Comment 1•4 years ago
|
||
The Bugbug bot thinks this bug should belong to the 'WebExtensions::Untriaged' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.
Comment 2•4 years ago
|
||
Hello,
I’m from QA and attempting to reproduce and confirm the issue however I’m unsure if what add-on to use to replicate this.
Would you be so kind as to provide the add-on you used when you encountered this issue and maybe a screen capture of the issue as it occurs?
Thank you !
Have you tried to configure scheme handlers? I am asking because it is a prerequisite and it can be tricky. I am developing an extension that uses org-protocol, but I do not think it suitable for those who are not familiar with Emacs Org Mode. E.g. mailto: scheme is likely whitelisted, so not suitable for testing related to this issue. Maybe you can suggest some known for you application that can be used for debugging with no undesired side effects.
On linux some dialog tool may be used as a handler, e.g. zenity. For "fox-bug:" scheme "fox-bug.desktop" maybe something like
[Desktop Entry]
Name=Bug 1744018 fox-bug handler
Exec=zenity --title "Test fox-bug handler" --info --text %u
Type=Application
Terminal=false
MimeType=x-scheme-handler/fox-bug
Instructions how to configure handler for some desktop environments may be found at https://github.com/sprig/org-capture-extension/
To confirm that you managed to configure external handler, you may try from console for any page
window.location = "fox-bug:test1"
Actually there are 3 states of scheme handlers:
- Never configured
- Configured
- Configured but later uninstalled (Firefox remembers earlier used handler)
Later I will prepare a test extension, in meanwhile you can suggest other schemes you prefer.
I am sorry for fuzzy steps to reproduce, but I really do not feel firm ground. Everything depends on OS and desktop environment. Errors are often quiet. Firefox may behave differently even when it is installed as .deb or snap package.
Actually it even does not necessary to configure external handler in desktop environment, the error appears anyway.
Load the following add-on, "Inspect" it, switch to console and click on the browser action button several times with interval ~1sec. First couple of times the error appears that handler is not configured then it is changed to
Iframe with external protocol was blocked due to lack of user activation, or because not enough time has passed since the last such iframe was loaded.
manifest.json
{
"manifest_version": 2,
"name": "Bug 1744018 External scheme handler",
"version": "0.1",
"browser_action": { "default_title": "Bug 1744018 External scheme handler" },
"permissions": [ "menus" ],
"background": { "scripts": [ "bg-scheme-handler.js" ] }
}
bg-scheme-handler.js
"use strict";
async function launchIframe(url, id = "tst_ext_scheme_handler") {
if (!url) {
throw new TypeError("No url specified to launch scheme handler");
}
if (id) {
const existing = document.getElementById(id);
if (existing) {
existing.remove();
}
}
const iframe = document.createElement('iframe');
iframe.setAttribute("src", url);
iframe.style.display = "none";
if (id) {
iframe.setAttribute("id", id);
}
try {
document.body.append(iframe);
await new Promise(r => setTimeout(r, 500));
const innerDoc = iframe.contentDocument;
if (!innerDoc) {
throw new Error("Handler is not configured");
}
} catch (ex) {
iframe.remove();
throw ex;
}
return iframe;
}
function createMenuItem(details) {
return browser.menus.create(details, function createMenuCallback() {
if (browser.runtime.lastError) {
console.error("createMenu %o %o", details, browser.runtime.lastError);
}
});
}
async function createMenu() {
await browser.menus.removeAll();
const items = [
{ id: "TST_UNCONFIGURED", title: "Launch fox-unconfigured:" },
{ id: "TST_BROKEN", title: "Launch fox-broken:" },
]
for (const details of items) {
createMenuItem({ ...details, contexts: [ "browser_action" ], enabled: true, });
}
}
async function contextMenuHandler(clickData, tab) {
const urlMap = {
TST_BUG: "fox-bug:test",
TST_UNCONFIGURED: "fox-unconfigured:test",
TST_BROKEN: "fox-broken:test",
};
let urlBase = urlMap[clickData.menuItemId];
if (!urlBase) {
throw new Error("Unsupported menu item");
}
const url = urlBase + "?time=" + new Date().toISOString();
try {
await launchIframe(url);
console.log("launched: %o", url);
} catch (ex) {
console.error("contextMenuHandler(%o, %o): %o: error: %o",
clickData, tab, url, ex);
}
}
function tstMain() {
browser.menus.onClicked.addListener((clickData, tab) => contextMenuHandler(clickData, tab));
browser.browserAction.onClicked.addListener(
(clickData, tab) => contextMenuHandler({ ...(clickData||{}), menuItemId: "TST_BUG" }, tab));
createMenu();
}
tstMain();
Likely it is a subject for a separate bug: when iframe is created in background window and external handler is properly configured then no popup appears that is intended to confirm launching of external handler. You can extract launchIframe function into an ordinary HTML page and compare.
Another issue that unconfigured handler invoked from a regular page causes appearance of a dialog to choose application if Firefox is installed to Ubuntu-21.10 as a snap package (preinstalled default option). If the same version of Firefox is installed using apt as .deb package then there is not such dialog. Anyway I have not managed to run selected application even when selection dialog appears.
Comment 6•4 years ago
|
||
Comment 7•4 years ago
|
||
Thank you for the additional details !
Based on Comment 4, I obtained the results shown in the attachment.
Tested on the latest Nightly (97.0a1/20211206215435), Beta (95.0/20211129150630) and Release (94.0.2/20211119140621) under Windows 10 x64.
As per my understanding this should confirm the issue. Is this correct?
Thank you, Alex. I mean exactly these messages. I suppose, it does not matter that handler is not configured.
So attempts to launch external handler in response to explicit user action are swallowed by Firefox and add-on has no chance to notify user that something goes wrong.
Comment 9•4 years ago
|
||
Thank you for the confirmation !
I’ll set the issue to New based on this and set the appropriate flags.
I’ve also tested the latest Beta (96.0b1/20211206194555) and the issue occurs there as well.
| Reporter | ||
Comment 10•4 years ago
|
||
- It seems,
tabs.updatewith custom scheme URI has no rate limit, but current (privileged but not regular one) page may be replaced by error: Bug #1745008 - It seems "Allow this site to open ... link?" popup is not shown at all if external handler is launched from extension context using any method: Bug #1744960
| Reporter | ||
Comment 11•4 years ago
|
||
(In reply to Alex Cornestean from comment #9)
I’ll set the issue to New based on this and set the appropriate flags.
It seems, the bug is still in UNCONFIRMED status.
Comment 12•4 years ago
|
||
(In reply to max from comment #11)
(In reply to Alex Cornestean from comment #9)
I’ll set the issue to New based on this and set the appropriate flags.
It seems, the bug is still in UNCONFIRMED status.
My bad. Changing it now. Thank you for letting me know !
Updated•4 years ago
|
Comment 13•4 years ago
|
||
Hello,
Narrowed the regression range to 2020-12-01 before mozregression was unable to find any more data to bisect and stopped.
The corresponding pushlog which was generated is this: https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=6659b306f58551bc4b7414bba47b4e3c94da722d&tochange=71ca5351d995d6a8a91a2a7c04191d13557da546
Tried several times to perform the bisection with the same result. Will attempt again in the near future.
| Reporter | ||
Comment 14•4 years ago
|
||
It seems Firefox-78 has active popup blocker (or something similar preventing launching of external handler) but it acts completely quietly. Neither browser console nor add-on console show any messages.
Comment 15•4 years ago
|
||
The severity field is not set for this bug.
:mixedpuppy, could you have a look please?
For more information, please visit auto_nag documentation.
Comment 16•4 years ago
|
||
Hi Max,
Pairing the extension with a native application and use the nativeMessaging API seems a better fit for the use case you are describing, is there any particular reasons that are making the "triggering an external protocol from an iframe injected in the the background page" approach the preferred approach from your perspective?
| Reporter | ||
Comment 17•4 years ago
|
||
(In reply to Luca Greco [:rpl] [:luca] [:lgreco] from comment #16)
Pairing the extension with a native application and use the nativeMessaging API seems a better fit for the use case you are describing, is there any particular reasons that are making the "triggering an external protocol from an iframe injected in the the background page" approach the preferred approach from your perspective?
Actually I have implemented native messaging option for transferring data captured by my add-on, it even allows additional feature (query the user already has URL in the notes). I agree that it is a better variant for error handling unlike shoot-and-forget external scheme handler. I even consider globally configured scheme handler as insecure since web pages might try to inject something weird through links with the same scheme.
Reasons why I still would like to have a reliable way to launch external scheme handler from extension:
- A scheme handler is the recommended approach for years, so users who already configured desktop-wide scheme handler may just try my add-on with minimal configuration.
- Snap (and likely flatpack) packages have problems with native manifests. I failed to setup native messaging backend with default firefox pre-installed to Ubuntu-21.10. Firefox is still available as .deb package, but Chromium is not even in Ubuntu-20.04 LTS. Making it working with additional isolation level requires additional efforts. See
- Bug #1661935 Snap: cannot install/manage extensions from extensions.gnome.org
- Bug #1621763 - [flatpak] native messaging support missing
- https://bugs.launchpad.net/bugs/1741074 [snap] chrome-gnome-shell extension fails to dete...
- For native messaging it is necessary to provide binaries for several OSes
- Native messaging apps are not supported on Android. I have not tried if scheme handler workflow acceptable yet.
- I am afraid that it would be a kind of quest for users to find error messages from native app if something is going wrong. It is hard to ensure that unexpected errors are formatted as JSON messages with binary size header.
P.S. I am a bit surprised that I have not faced an issue with white list of schemes in snap https://bugs.launchpad.net/bugs/1776873 yet
P.P.S. I was wrong when I wrote that iframe from background page works in chromium, at least on linux it crashes: https://crbug.com/1280940
window.location does not work at all, fortunately at least tabs.update does not have a bug similar to Firefox' one.
Comment 18•4 years ago
|
||
I cannot reproduce on osx with nightly. Perhaps this issue is linux specific?
Comment 19•4 years ago
|
||
The severity field is not set for this bug.
:mixedpuppy, could you have a look please?
For more information, please visit auto_nag documentation.
Updated•4 years ago
|
Comment 20•4 years ago
|
||
The severity field is not set for this bug.
:mixedpuppy, could you have a look please?
For more information, please visit auto_nag documentation.
| Reporter | ||
Comment 21•4 years ago
|
||
(In reply to Shane Caraveo (:mixedpuppy) from comment #18)
I cannot reproduce on osx with nightly. Perhaps this issue is linux specific?
I can not confirm it, but accordingly to comment #7 Windows 10 is affected as well.
Comment 22•3 years ago
|
||
Redirecting needinfo to Rob, given he is already looking into other bugs in the same area.
Description
•