Open link by default browser

I want links to open in the default browser. So, if a user clicks a link and the default browser is Chrome, it will open in Chrome.

Is it doable?

P.S. I intent to use the WebExtenions API

There is an addon called “Open with” which you can use to open links in Firefox Nightly, Firefox Dev, Firefox Beta, Google Chrome, Internet Explorer, Edge, and Opera. They are seperate addons it seems:

https://addons.mozilla.org/en-US/firefox/search/?q=open+with

These addons do another thing. They add a context menu item to open in another browser.

These extensions do not support what I’m trying to do.

I want links to open in the default browser normally. Like: you click a link, and it opens in Chrome instead of Firefox.

An addon is not out there, but you can modify the addons above to do it as default action. The first and easiest method is to addEventListener to all links.

And how do I open the url in the default browser then?

Oh yeah that’s an issue. To detect default browser I don’t know if there is pre-existing code. I did do it last year with js-ctypes - I don’t think I completed it for cross platform use. If you want to go that route I’ll dig up the code and share it. It would be awesome if you can touch it up. Are you an experienced programmer? No need for super advanced knowledge like binaries and compiling stuff, this is just javascript, but you need to be able to search the net and docs on platform specific C based APIs.

However there might be a non-ctypes method. It will be an XPCOM method. Try searching DXR. Because on startup, if firefox is not default, it does prompt “do you want to set firefox as default?”. But if I recall correctly, their method just tells you if the current build is default or not, it does not actually give you the path or name of what is the default browser.

Neither the ctypes method nor the built-in method will work from WebExtensions. You’ll have to make an Addon SDK addon, or classic bootstrap. (not ancient overlay, don’t do those).

Okay, that’s not a problem, can select the browser instead of the default one.

So, the method to catch navigation is to track addEventListener… I thought there is something more universal / firefoxy for navigation catching :slight_smile:

It might be a bit too much. You can use nsIWebProgressListener to catch stuff, but that will catch even non-link clicks. Then you’ll have to filter out what the user did not intend to launch and what he did intend to.

Whereas an addEventListener on link is simple, you know for sure he intended to open it.

I just dug up my old code, the code was practically done so I just finished it up and pushed it to a demo repo. Here is the function to get path to the default browser:

I didn’t implement Android support yet.

You can install download that repo and zip up the contents, rename to xpi, and install. On install you’ll see in browser console it will log the default browser path.

Oh, I see it works for Mac too, great. Will try to use the code.

No worries. It should work. The getDefaultBrowserPath function works on gtk based firefox’s (should be all *nix and solaris), windows, and mac. I tested it a few min ago. The function can be run off mainthread (from a ChromeWorker), this is the preferred way, but in that demo addon it runs it on the mainthread.

You’ll need to import the ostypes submodule into your addon. Here is how to do that: https://github.com/Noitidart/ostypes/issues/1#issuecomment-199508893

…And this works for WebExtensions, right? I’m using this, not XUL.

No achieving this in WebExtensions with this much ease is not possible. You’ll have to set up IPC and write executable binaries for each platform (can’t use javascript). In WebExt - Writing them is a headache, get all the platform dependent tools and tool knowledge. Then testing those binaries is even more a headache, gotta set up your platform dependent environments and enthronement knowledge.

You should make this an Addon SDK addon. Copy paste. And you can launch the path with child_process I think. Or if that doesn’t work then launch it with nsIFile -> launch(). If even launch doesn’t work (although it should), let me know and I’ll give you some launching code which is special as it launches it as non-child and other advantages.

I’ve read that XUL is going to be deprecated, that’s why I try to head towards WebExtensions.

And will nsIWebProgressListener work?

The code I gave you above doesn’t use any XUL or XPCOM. It does use ctypes.jsm though, which needs to be imported with Cu. And ideally, if you use that you would also import ChromeWorker and put it off the mainthread.

nsIWebProgressListener will not work from webextensions but there is a suitable (and I think better) replacement for that here:

https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webNavigation

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webNavigation

nsIWebProgressListener listener will work from SDK.

However I really recommend against it, things will get complicated fast, as it will pick up all kinds of navigation events, and then trying to filter that by calculating user intent is not so easy. I would suggest the addEventListener method to links.

…But to open an url in another browser, I still need to use XUL, described here https://developer.mozilla.org/en/docs/XUL_School, right?

No XUL won’t play a role in launching a file at all.

XPCOM is what you might be thinking of, and yes that will be deprecated.

However Addon SDK has a non-XPCOM method called child_process - https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/system_child_process

I think this can launch stuff directly. If it can’t, what we can do is call bash or shell via child_process and execute a launch code.

If that fails we have other options. There is an XPCOM method of nsIFIle -> launch() that we can try, but I really think child_process will do what we need.

The author of the “Open in …” addons emailed me (@Baris) this and it is superb! No need for the ctypes above:

Here is the code:

        var os = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
        var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
        var args;
       
        if (os == "WINNT"){
            file.initWithPath("C:\\Windows\\System32\\cmd.exe");
            args = ["/c", "start", "https://google.com"];
        }
        else if (os == "Darwin"){
            file.initWithPath ("/usr/bin/open");
            args = ["https://google.com"];
        }
        else if (os == "Linux"){
            file.initWithPath ("/usr/bin/xdg-open");
            args = ["https://google.com"];
        }
       
        process.init(file);
        process.run(false, args, args.length);       

I tested on Windows 10 and Mac OS X El Capitan. I could not have test the Linux code yet. It seems xdg-open is more suitable for Ubuntu. I will download latest Ubuntu and install it as Virtual Machine. Hope to report back in a few hours. You can run on Scratchpad.>

This uses XPCOM and it will work.

I think you can easily use child_process in place of the XPCOM here.

Superb. Much thanks to @Baris

1 Like

I’m kind of stuck on: how to addEventListener on clicks?

EDIT: Solved, with page_mod. Everything works nicely!