How to forward to browser's home (Google Chrome) - javascript

function goHome() {
if (window.home) { // NS
window.home();
}
else { // IE and Google Chrome
if (navigator.appVersion.split("MSIE")[1] <= 7) { // IE 4-7
window.location = "about:home";
}
else if (window.location.href) { // Google Chrome
window.location.href = "??????????"; // <<-- what is the built-in
} // link for the home button
else { // IE 8, 9
// ...
}
}
}
However, I do not know the built-in link for the home button in Google Chrome. Does anybody has an idea?
PS. The JavaScript code is incomplete and just a snippet!

In Chrome, the home page is either an actual URL, or the New Tab page.
So, it would be chrome://newtab/, except that if you try this on a page, you'll raise this security error:
Not allowed to load local resource:
chrome://newtab/
(see the error in Chrome's Developer Tools)
So, I don't think it's possible. I could be wrong, I'm no expert on Chrome.
chrome://newtab/ does take you to the right place if you paste it into your address bar, but that is obviously useless to you.

Related

How to detect if webkitSpeechRecognition actually works in a browser

Edge claims to support webkitSpeechRecognition, but it doesn't work (discussion here, doesn't work on websites meant for testing, like this mozilla one, with the error "Error occurred in recognition: language-not-supported" despite my US english UI).
How can I detect if webkitSpeechRecognition is actually supported? I tried to filter out Edge by looking at the user agent, but it shows up as Chrome, and I'd prefer to just use feature detection rather than looking at the user agent anyway. I'd like to check this without requesting microphone permission (if I did request microphone permission, I'd have to wait for them to accept, and then see the language-not-supported error). Is there a simple way to check this, similar to just checking the value of window["webkitSpeechRecognition"] (which is defined in Edge, despite not working)?
If you want to check the support for webkitSpeechRecognition then you can refer to the JS code example below.
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)
{
console.log("speech recognition API supported");
}
else
{
console.log("speech recognition API not supported")
}
Output in MS Edge 88.0.705.56:
However, if you directly try to make a test using webkitSpeechRecognition then it will not work.
It looks like this feature is currently under development and to use it we need to enable it by passing the command line arguments.
I suggest you refer to the steps below.
Create a shortcut of the Edge chromium-browser.
Right-click the shortcut file and go to Properties.
Under Shortcut tab, in the Target textbox, add --enable-features=msSpeechRecognition after the msedge.exe path. Make sure to add 1 space between the path and command-line argument.
It should look like below.
Click on the OK button to close the properties window.
Launch the Edge browser via shortcut and visit any sample code example for SpeechRecognition. Here I am making a test with this example.
Output in MS Edge 88.0.705.56:
In addition, it's useful to check for errors (as shown in the above example source code, see below, https://www.google.com/intl/en/chrome/demos/speech.html): for instance audio might be disabled if not on a https website.
recognition.onerror = function(event) {
if (event.error == 'no-speech') {
start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
showInfo('info_no_speech');
ignore_onend = true;
}
if (event.error == 'audio-capture') {
start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
showInfo('info_no_microphone');
ignore_onend = true;
}
if (event.error == 'not-allowed') {
if (event.timeStamp - start_timestamp < 100) {
showInfo('info_blocked');
} else {
showInfo('info_denied');
}
ignore_onend = true;
}
};

How to always prompt for geolocation in browser once blocked? [duplicate]

im building an app through phonegap, with a geolocation button.
if a user denies permission for geolocation the first time, how can i ask for permission again when they click the geolocation button again?
my code structure at the moment is:
function getLocation() {
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, positionError);
} else {
hideLoadingDiv()
showError('Geolocation is not supported by this device')
}
}
function positionError() {
hideLoadingDiv()
showError('Geolocation is not enabled. Please enable to use this feature')
}
You can't.
The only thing you can do is to display the instructions to reactivate the location sharing in his browser's settings (https://support.google.com/chrome/answer/142065?hl=en).
Two ways of doing this:
If you have a version of Chrome bigger than 83.0.4103.97 then use the lock icon in the URL
For older versions of Chrome the bellow code will work fine:
The bellow code only works on Chrome.
Steps:
Open Chrome
Open the console
Copy in the console
var allowGeoRecall = true;
var countLocationAttempts = 0;
Copy in the console the functions
function getLocation() {
console.log('getLocation was called')
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition,
positionError);
} else {
hideLoadingDiv()
console.log('Geolocation is not supported by this device')
}
}
function positionError() {
console.log('Geolocation is not enabled. Please enable to use this feature')
if(allowGeoRecall && countLocationAttempts < 5) {
countLocationAttempts += 1;
getLocation();
}
}
function showPosition(){
console.log('posititon accepted')
allowGeoRecall = false;
}
Run the function in the console
getLocation();
After running this you will be asked to allow to share your position. If your response is negative you will be asked again until you agree.
HINT: If your user has a negative response, let him know why you need the coordinates. Is vital for him to understand that this step is vital for the good run of the web app.
This can be reset in Page Info which can be accessed by clicking the lock icon next to the URL and allowing Location

Skype URIs not working under HTTPS on Chrome, iPad, iPhone

I'm attempting to use the Skype javascript API and noticing some craziness: If my page is HTTP, everything works fine (all the skype buttons, and skype: protocol hrefs) but once I move it to HTTPS it breaks in Chrome, iPad, and iPhone. Case and point:
Call buttons work here:
http://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator
Call buttons DO NOT work here:
https://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator
This is on their own site and it's no workie...
Can anyone suggest some series of rain dances I should do to fix this? Praying to the Skype gods? I'm only a mere mortal.
On click script is creating iframe and adding src="skype:echo123;+16505550123?call" and then as mb21 said bug occurs or "restrictive security policy" happens.
function a(s, v, t) {
var u = true;
window.onblur = function () {
u = false
};
var r = document.getElementById(v);
if (r !== null) {
r.src = s //here error happens....
}
setTimeout(function () {
if (u) {
alert(Skype.installSkypeMsg);
Skype.tryAnalyzeSkypeUri("redirect", t);
window.location = Skype.SkypeClientDownloadUrl
}
}, 2000)
}
How about just using:
<a onclick="window.location='skype:echo123;+16505550123?call';return false;" href="">link</a>
I think this is a bug (or a quite restrictive security policy) in Chrome (and other browsers). In the Chrome developer console I get:
[blocked] The page at https://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator ran insecure content from skype:echo123;+16505550123?call.
It treats skype:echo123;+16505550123?call as a URL and finds it not to be secure (i.e. not https) so the browser refuses to load it. Probably, the JavaScript in the Skype SDK uses window.open or something similar, so digging around in their code might bring up a solution.
Maybe you can adapt this ugly workaround?

How to check if a custom protocol supported

We are using software that registers its own protocol. We can run application from browser then by link like:
customprotocol://do_this.
but is there a way to check is such custom protocol supported by user`s system? If not we would like to ask user to install software first.
E.g:
if (canHandle ('customprotocol')) {
// run software
}
else {
// ask to install
}
Edit
I know about protocolLong property but it works only in IE.
Unfortunately, there's no easy way of achieving this. There's certainly no method of pre-determining whether or not the protocol handler is installed.
Internet Explorer, as you mentioned, has the protocolLong property but I'm having trouble getting it to return anything other than "Unknown Protocol" for all custom protocol handlers -- if anyone knows how to get IE to return the correct value please let me know so I can update this section. The best solution I've found with IE is to append to the user agent string or install a browser extension along with your app that exposes a Javascript accessible property.
Firefox is by far the easiest of the major browsers, as it will allow you to try and catch a navigation attempt that fails. The error object returned contains a name property whose value is NS_ERROR_UNKNOWN_PROTOCOL:
try {
iframe.contentWindow.location.href = "randomprotocolstring://test/";
} catch(e) {
if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL")
window.location = "/download/";
}
Firefox will pop up with its own alert box:
Firefox doesn't know how to open this address, because the protocol (randomprotocolstring) isn't associated with any program.
Once you close this box, the catch block will execute and you have a working fallback.
Second is Opera, which allows you to employ the laws of predictability to detect success of a custom protocol link clicked. If a custom protocol click works, the page will remain the same location. If there is no handler installed, Opera will navigate to an error page. This makes it rather easy to detect with an iframe:
iframe.contentWindow.location = "randomprotocolstring://test/";
window.setTimeout(function () {
try {
alert(ifr.contentWindow.location);
} catch (e) { window.location = "/download/"; }
}, 0);
The setTimeout here is to make sure we check the location after navigation. It's important to note that if you try and access the page, Opera throws a ReferenceException (cross-domain security error). That doesn't matter, because all we need to know is that the location changed from about:blank, so a try...catch works just fine.
Chrome officially sucks with this regard. If a custom protocol handler fails, it does absolutely zip. If the handler works... you guessed it... it does absolutely zip. No way of differentiating between the two, I'm afraid.
I haven't tested Safari but I fear it would be the same as Chrome.
You're welcome to try the test code I wrote whilst investigating this (I had a vested interest in it myself). It's Opera and Firefox cross compatible but currently does nothing in IE and Chrome.
Here's an off-the-wall answer: Install an unusual font at the time you register your custom protocol. Then use javascript to check whether that font exists, using something like this.
Sure it's a hack, but unlike the other answers it would work across browsers and operating systems.
Just to chime in with our own experience, we used FireBreath to create a simple cross-platform plugin. Once installed this plugin registers a mime type which can be detected from the browser javascript after a page refresh. Detection of the mime type indicates that the protocol handler is installed.
if(IE) { //This bastard always needs special treatment
try {
var flash = new ActiveXObject("Plugin.Name");
} catch (e) {
//not installed
}
else { //firefox,chrome,opera
navigator.plugins.refresh(true);
var mimeTypes = navigator.mimeTypes;
var mime = navigator.mimeTypes['application/x-plugin-name'];
if(mime) {
//installed
} else {
//not installed
}
}
Internet Explorer 10 on Windows 8 introduced the very useful navigator.msLaunchUri method for launching a custom protocol URL and detecting the success or failure. For example:
if (typeof (navigator.msLaunchUri) == typeof (Function)) {
navigator.msLaunchUri(witchUrl,
function () { /* Success */ },
function () { /* Failure */ showError(); });
return;
}
Windows 7 / IE 9 and below support conditional comments as suggested by #mark-kahn.
For Internet Explorer, the best solution I've found is to use Conditionl comments & Version Vector (application must write something to registry while installing protocol, see http://msdn.microsoft.com/en-us/library/ms537512.aspx#Version_Vectors). protocolLong doesn't work for custom protocol.
On mobile you can use an embedded iframe to auto switch between the custom protocol and a known one (web or app store), see https://gist.github.com/2662899
I just want to explain more previous Mark's answer (some people did not understand for example user7892745).
1) When you launch you web-page or web-application it checks for an unusual font (something like Chinese Konfuciuz font http://www.fontspace.com/apostrophic-lab/konfuciuz).
Below is the code of sample web-page with function which checks the font (called isFontAvailable):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
/**
* Checks if a font is available to be used on a web page.
*
* #param {String} fontName The name of the font to check
* #return {Boolean}
* #license MIT
* #copyright Sam Clarke 2013
* #author Sam Clarke <sam#samclarke.com>
*/
(function (document) {
var width;
var body = document.body;
var container = document.createElement('span');
container.innerHTML = Array(100).join('wi');
container.style.cssText = [
'position:absolute',
'width:auto',
'font-size:128px',
'left:-99999px'
].join(' !important;');
var getWidth = function (fontFamily) {
container.style.fontFamily = fontFamily;
body.appendChild(container);
width = container.clientWidth;
body.removeChild(container);
return width;
};
// Pre compute the widths of monospace, serif & sans-serif
// to improve performance.
var monoWidth = getWidth('monospace');
var serifWidth = getWidth('serif');
var sansWidth = getWidth('sans-serif');
window.isFontAvailable = function (font) {
return monoWidth !== getWidth(font + ',monospace') ||
sansWidth !== getWidth(font + ',sans-serif') ||
serifWidth !== getWidth(font + ',serif');
};
})(document);
function isProtocolAvailable()
{
if (isFontAvailable('Konfuciuz'))
{
return true;
}
else
{
return false;
}
}
function checkProtocolAvail()
{
if (isProtocolAvailable())
{
alert('Custom protocol is available!');
}
else
{
alert('Please run executable to install protocol!');
}
}
</script>
<h3>Check if custom protocol was installed or not</h3>
<pre>
<input type="button" value="Check if custom protocol was installed!" onclick="checkProtocolAvail()">
</body>
</html>
2) First time when user opens this page, font will not be installed so he will get a message saying "Please run executable to install custom protocol...".
3) He will run executable which will install the font. Your exe can just copy the font file (in my case it is KONFUC__.ttf) into C:\Windows directory or using a code like this (example on Delphi):
// Adding the font ..
AddFontResource(PChar('XXXFont.TTF'));
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
4) After that, when user runs web app again, he gets "Custom protocol is available!" message because font was installed this time.
Tested on Google Chrome, Internet Explorer and Firefox - working great!
For Firefox, most of articles I googled, including Andy E 's answer here, and this gist Cross-browser implementation of navigator.msLaunchUri or https://github.com/ismailhabib/custom-protocol-detection using
iframe.contentWindow.location.href = uri
But it has stopped working since Firefox 64, e.g here https://github.com/ismailhabib/custom-protocol-detection/issues/37 also confirmed that.
So FF 64+ I found I can either using Chrome's method, blurHandler or using the post there https://github.com/ismailhabib/custom-protocol-detection/issues/37#issuecomment-617962659
try {
iframe.contentWindow.location.href = uri;
setTimeout(function () {
try {
if (iframe.contentWindow.location.protocol === "about:") {
successCb();
} else {
failCb();
}
} catch (e) {
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL" ||
e.name === "NS_ERROR_FAILURE" || e.name === "SecurityError") {
failCb();
}
}
}, 500);
} catch (e) {
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL" || e.name === "NS_ERROR_FAILURE"
|| e.name === "SecurityError") {
failCb();
}
}
For Chrome 86+ it also fails to work, check my answer for details Detect Custom Protocol handler in chrome 86
BTW, I find most of answers/articles are outdated in some cases.

How to detect browser's protocol handlers?

I have created a custom URL protocol handler.
http://
mailto://
custom://
I have registered a WinForms application to respond accordingly. This all works great.
But I would like to be able to gracefully handle the case where the user doesn't have the custom URL protocol handler installed, yet.
In order to be able to do this I need to be able to detect the browser's registered protocol handlers, I would assume from JavaScript. But I have been unable to find a way to poll for the information. I am hoping to find a solution to this problem.
Thanks for any ideas you might be able to share.
This would be a very, very hacky way to do this... but would this work?
Put the link in as normal...
But attach an onclick handler to it, that sets a timer and adds an onblur handler for the window
(in theory) if the browser handles the link (application X) will load stealing the focus from the window...
If the onblur event fires, clear the timer...
Otherwise in 3-5seconds let your timeout fire... and notify the user "Hmm, looks like you don't have the Mega Uber Cool Application installed... would you like to install it now? (Ok) (Cancel)"
Far from bulletproof... but it might help?
There's no great cross-browser way to do this. In IE10+ on Win8+, a new msLaunchUri api enables you to launch a protocol, like so:
navigator.msLaunchUri('skype:123456',
function()
{
alert('success');
},
function()
{
alert('failed');
}
);
If the protocol is not installed, the failure callback will fire. Otherwise, the protocol will launch and the success callback will fire.
I discuss this topic a bit further here:
https://web.archive.org/web/20180308105244/https://blogs.msdn.microsoft.com/ieinternals/2011/07/13/understanding-protocols/
This topic is of recent (2021) interest; see https://github.com/fingerprintjs/external-protocol-flooding for discussion.
HTML5 defines Custom scheme and content handlers (to my knowledge Firefox is the only implementor so far), but unfortunately there is currently no way to check if a handler already exists—it has been proposed, but there was no follow-up. This seems like a critical feature to use custom handlers effectively and we as developers should bring attention to this issue in order to get it implemented.
There seems to be no straightforward way via javascript to detect the presence of an installed app that has registered a protocol handler.
In the iTunes model, Apple provides urls to their servers, which then provide pages that run some javascript:
http://ax.itunes.apple.com/detection/itmsCheck.js
So the iTunes installer apparently deploys plugins for the major browsers, whose presence can then be detected.
If your plugin is installed, then you can be reasonably sure that redirecting to your app-specific url will succeed.
What seams the most easy solution is to ask the user the first time.
Using a Javascript confirm dialog per example:
You need this software to be able to read this link. Did you install it ?
if yes: create a cookie to not ask next time; return false and the link applies
if false: window.location.href = '/downloadpage/'
If you have control of the program you're trying to run (the code), one way to see if the user was successful in running the application would be to:
Before trying to open the custom protocol, make an AJAX request to a server script that saves the user's intent in a database (for example, save the userid and what he wanted to do).
Try to open the program, and pass on the intent data.
Have the program make a request to the server to remove the database entry (using the intent data to find the correct row).
Make the javascript poll the server for a while to see if the database entry is gone. If the entry is gone, you'll know the user was successful in opening the application, otherwise the entry will remain (you can remove it later with cronjob).
I have not tried this method, just thought it.
I was able to finally get a cross-browser (Chrome 32, Firefox 27, IE 11, Safari 6) solution working with a combination of this and a super-simple Safari extension. Much of this solution has been mentioned in one way or another in this and this other question.
Here's the script:
function launchCustomProtocol(elem, url, callback) {
var iframe, myWindow, success = false;
if (Browser.name === "Internet Explorer") {
myWindow = window.open('', '', 'width=0,height=0');
myWindow.document.write("<iframe src='" + url + "'></iframe>");
setTimeout(function () {
try {
myWindow.location.href;
success = true;
} catch (ex) {
console.log(ex);
}
if (success) {
myWindow.setTimeout('window.close()', 100);
} else {
myWindow.close();
}
callback(success);
}, 100);
} else if (Browser.name === "Firefox") {
try {
iframe = $("<iframe />");
iframe.css({"display": "none"});
iframe.appendTo("body");
iframe[0].contentWindow.location.href = url;
success = true;
} catch (ex) {
success = false;
}
iframe.remove();
callback(success);
} else if (Browser.name === "Chrome") {
elem.css({"outline": 0});
elem.attr("tabindex", "1");
elem.focus();
elem.blur(function () {
success = true;
callback(true); // true
});
location.href = url;
setTimeout(function () {
elem.off('blur');
elem.removeAttr("tabindex");
if (!success) {
callback(false); // false
}
}, 1000);
} else if (Browser.name === "Safari") {
if (myappinstalledflag) {
location.href = url;
success = true;
} else {
success = false;
}
callback(success);
}
}
The Safari extension was easy to implement. It consisted of a single line of injection script:
myinject.js:
window.postMessage("myappinstalled", window.location.origin);
Then in the web page JavaScript, you need to first register the message event and set a flag if the message is received:
window.addEventListener('message', function (msg) {
if (msg.data === "myappinstalled") {
myappinstalledflag = true;
}
}, false);
This assumes the application which is associated with the custom protocol will manage the installation of the Safari extension.
In all cases, if the callback returns false, you know to inform the user that the application (i.e., it's custom protocol) is not installed.
You say you need to detect the browser's protocol handlers - do you really?
What if you did something like what happens when you download a file from sourceforge? Let's say you want to open myapp://something. Instead of simply creating a link to it, create a link to another HTML page accessed via HTTP. Then, on that page, say that you're attempting to open the application for them. If it doesn't work, they need to install your application, which they can do by clicking on the link you'll provide. If it does work, then you're all set.
This was a recommended approach for IE by Microsoft support
http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx#related_topics
"If you have some control over the binaries being installed on a user’s machine, checking the UA in script seems like a relevant approach:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform
" -- By M$ support
Every web page has access to the userAgent string and if you drop a custom post platform value, detecting this in javascript using navigator.userAgent is quite simple.
Fortunately, other major browsers like Firefox and Chrome (barring Safari :( ), do not throw "page not found" errors when a link with a custom protocol is clicked and the protocol is not installed on the users machine. IE is very unforgiving here, any trick to click in a invisible frame or trap javascript errors does not work and ends up with ugly "webpage cannot be displayed" error. The trick we use in our case is to inform users with browser specific images that clicking on the custom protocol link will open an application. And if they do not find the app opening up, they can click on an "install" page. In terms of XD this wprks way better than the ActiveX approach for IE.
For FF and Chrome, just go ahead and launch the custom protocol without any detection. Let the user tell you what he sees.
For Safari, :( no answers yet
I'm trying to do something similar and I just discovered a trick that works with Firefox. If you combine it with the trick for IE you can have one that works on both main browsers (I'm not sure if it works in Safari and I know it doesn't work in Chrome)
if (navigator.appName=="Microsoft Internet Explorer" && document.getElementById("testprotocollink").protocolLong=="Unknown Protocol") {
alert("No handler registered");
} else {
try {
window.location = "custom://stuff";
} catch(err) {
if (err.toString().search("NS_ERROR_UNKNOWN_PROTOCOL") != -1) {
alert("No handler registered");
}
}
}
In order for this to work you also need to have a hidden link somewhere on the page, like this:
<a id="testprotocollink" href="custom://testprotocol" style="display: none;">testprotocollink</a>
It's a bit hacky but it works. The Firefox version unfortunately still pops up the default alert that comes up when you try to visit a link with an unknown protocol, but it will run your code after the alert is dismissed.
You can try something like this:
function OpenCustomLink(link) {
var w = window.open(link, 'xyz', 'status=0,toolbar=0,menubar=0,height=0,width=0,top=-10,left=-10');
if(w == null) {
//Work Fine
}
else {
w.close();
if (confirm('You Need a Custom Program. Do you want to install?')) {
window.location = 'SetupCustomProtocol.exe'; //URL for installer
}
}
}
This is not a trivial task; one option might be to use signed code, which you could leverage to access the registry and/or filesystem (please note that this is a very expensive option). There is also no unified API or specification for code signing, so you would be required to generate specific code for each target browser. A support nightmare.
Also, I know that Steam, the gaming content delivery system, doesn't seem to have this problem solved either.
Here's another hacky answer that would require (hopefully light) modification to your application to 'phone home' on launch.
User clicks link, which attempts to launch the application. A unique
identifier is put in the link, so that it's passed to the
application when it launches. Web app shows a spinner or something of that nature.
Web page then starts checking for a
'application phone home' event from an app with this same unique ID.
When launched, your application does an HTTP post to your web app
with the unique identifier, to indicate presence.
Either the web page sees that the application launched, eventually, or moves on with a 'please download' page.

Categories