Ask Reuben

Browser Close

How can I prevent user closing application by closing a browser tab?

How can I control the dialog that appears when closing a browser tab? 

How can I do a tidy exit when user closes a browser tab?

When running a Genero application through Genero Desktop Client, the GDC is a process running on the front-end operating system and has to respect the rules of that operating system.   When running a Genero application through Genero Browser Client, we are similarly bound by the rules that browsers apply.  A place where you will encounter these rules is what happens when you attempt to close a browser tab by clicking the close button in the browser tab (or File->Close Tab).

Whenever I attempt to explain browser rules, I like to ask the question …

What would a malicious website developer do if they could break the rule you are asking me to break ?

… so when ever someone asks “I want to prevent the user closing a browser tab unless …”, I’ll say “what would a malicious website developer do if they were able to write code that meant you were unable to close a browser tab?”

So what happens when user closes a browser tab?  Why do sometimes you get a dialog …

… and why does sometimes that dialog not appear?

This behaviour is controlled by the onbeforeunload event and like most things web we can learn more about it at the applicable w3schools page. With the try-it-yourself page you can experiment at what text appears and if the dialog appears.  Experiment changing the text “Write something clever here”, and also experiment by replacing the text with null, that is …

return null;

Unless you are using an old browser or Internet Explorer, you should observe that changing the text does not change the text that appears in the dialog.  It used to but this has been removed from most browsers over time.  The Mozilla page is also a good one to read and if you look at the Browser Compatibility (scroll about halfway down) you will see what browsers currently support custom text (currently only Internet Explorer) or what versions used to (for example Chrome upto version 51, Firefox upto version 44).  Hence you are stuck with the text that the browser  dictates.

What you should’ve observed is that when returning null instead of text, then the dialog box does not appear.  Now try this with a Genero application, run your web application and append a URL argument, debugMode=0 and debugMode = 1 e.g.

http://localhost:6394/ua/r/gwc-demo?debugMode=0

http://localhost:6394/ua/r/gwc-demo?debugMode=1

Make a change such as expanding a tree node on the left hand side and now attempt to close the browser tab.  You should find that with debugMode=0 the dialog box did appear, and that with debugMode=1 the dialog box did not appear.  This can also be controlled by use of the –development argument inside your .xcf as detailed here.  We recognise that when developing this dialog box will be annoying and so stop it appearing.  This page in the GBC documentation also details these methods.

If you were observant you will have noticed that I said “Make a change such as expanding a tree node”.  If you didn’t follow this you might not have got the dialog box to appear when it should.  That is because there is one more concept, and that is a browser will only make the dialog appear if it considers the page “dirty”.  That is if you have not made any changes, why inconvenience you with the dialog.  I am not aware of a way we can trick the browser into thinking the page is dirty other than actually doing something on the page.

So hopefully the above gives you some explanation of what controls if the browser dialog appears when the user attempts to close a browser tab, and you recognise that we can’t stop the user closing the browser tab, we can only put a speed bump in there way.  The next question relates to what your program can do once the user closes the browser tab, and the answer is the same as what you can call to cater for case when GDC is shutdown, that is use OPTIONS ON CLOSE APPLICATION.

This is a callback function where you can get your program to do a tidy exit.  That is a ROLLBACK WORK, DISCONNECT from the database, perhaps write to the ERRORLOG, update a whowhatwhen table, and then EXIT PROGRAM thus freeing up a user license.  What you want to avoid is your program continuing to hang around, perhaps locking the database, using up a license  etc until the USER_AGENT timeout occurs.  This callback function should be as concise as possible and it is important that it has no user interface.  If it does display any user interface, the browser tab will have been closed before it can appear or be responded to and you will get a runtime error.

OPTIONS ON CLOSE APPLICATION CALL tidy_exit()
...

FUNCTION tidy_exit()
    ROLLBACK WORK
    DISCONNECT ALL
    CALL errorlog("Front-end terminated")
    EXIT PROGRAM 1
END FUNCTION

So in summary, once the user closes a browser tab, there is little we can do to stop them other than the standard warning dialog.   We can stop the dialog appearing so that it does not inconvenience developers, QA testers etc.   Be aware that the dialog might not appear if the browser considers the page “clean”.  What you should do is make sure your program is considerate to other programs and users and exit as tidily as it can at this point.