I have a custom URL protocol handler cgit:[...]
It launches up a background process which configures some stuff on the local machine. The protocol works fine, i'm launching it from JavaScript (currently using document.location = 'cgit:[...]'
), but i actually want JavaScript to wait until the associated program exits.
So basically the steps i want JavaScript to do:
JavaScript does something
JavaScript launches cgit:[...]
Javascript waits until cgit:[...]
exits
JavaScript does something else
Code:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
or:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
Any ideas if this is possible?
As i didn't find a suitable way to solve my problem using ajax requests or anything similar, i finally solved my problem using a kind-of-ugly workarround including XmlHttpRequest
For launching the protocol i'm still using document.location=cgit:[...]
I'm using a server side system including "lock-files" - that's like generic dummy files, with generated names for each request.
Once the user requests to open the custom protocol, such a file is being generated on the server specifically for that one protocol-opening-request.
I created a folder called "$locks" on the server where these files are being placed in. Once the protocol-associated program exits, the appropriate file is being deleted.
The website continuously checks if the file for a request still exists using XmlHttpRequest
and fires a callback if it doesn't (example timout between tests: 1 sec).
The structure of the new files is the following:
lockThisRequest.php
: It creates a file in the $locks directory based on the req
url-parameter.unlockThisRequest.php
: It deletes a file in the $locks directory; again based on the req
url-parameter.The JavaScript part of it goes:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
Ussage is:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
the lockThisRequest.php
-file:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
and unlockThisRequest.php
:
<?php
unlink("../\$locks/".$_GET["req"]); // Delete lock file
?>
The local program / script executed by the protocol can simply call something like:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req=$1"
after it finished.
As i just said this works, but it's anything else than nice (congratulations if you kept track of those instructions)
I'd rather prefered a more simple way and (important) this also may cause security issues with the lockThisRequest.php
and unlockThisRequest.php
files!
I'm fine with this solution, because i'm only using it on a password protected private page. But if you plan to use it on a public or non protected page, you may want to add some security to the php files.
Anyways, the solution works for me now, but if anyone finds a better way to do it - for example by using ajax requests - he/she would be very welcome to add that way to the respective stackoverflow-documentation or the like and post a link to it on this thread. I'd still be interested in alternative solutions :)