fix error on window closing in Chrome 80+

caused by Chrome 80+ no longer allowing to send a synchronious ajax request from beforeunload handler, using sendBeacon (async request with keepalive=true) instead
This commit is contained in:
Ralf Becker 2020-03-02 10:43:19 +01:00
parent 6263c47070
commit 558354bc44
3 changed files with 18 additions and 8 deletions

View File

@ -285,9 +285,9 @@ etemplate2.prototype.bind_unload = function()
{ {
this.destroy_session = jQuery.proxy(function(ev) this.destroy_session = jQuery.proxy(function(ev)
{ {
var request = egw.json("EGroupware\\Api\\Etemplate::ajax_destroy_session", // need to use async === "keepalive" to run via beforeunload
[this.etemplate_exec_id], null, null, false); egw.json("EGroupware\\Api\\Etemplate::ajax_destroy_session",
request.sendRequest(); [this.etemplate_exec_id], null, null, "keepalive").sendRequest();
}, this); }, this);
if (!window.onbeforeunload) if (!window.onbeforeunload)

View File

@ -7,7 +7,6 @@
* @link http://www.egroupware.org * @link http://www.egroupware.org
* @author Andreas Stöckel (as AT stylite.de) * @author Andreas Stöckel (as AT stylite.de)
* @author Ralf Becker <RalfBecker@outdoor-training.de> * @author Ralf Becker <RalfBecker@outdoor-training.de>
* @version $Id$
*/ */
/*egw:uses /*egw:uses
@ -53,7 +52,8 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
* @param {array} _parameters * @param {array} _parameters
* @param {function} _callback * @param {function} _callback
* @param {object} _context * @param {object} _context
* @param {boolean} _async * @param {boolean|"keepalive"} _async true: asynchronious request, false: synchronious request,
* "keepalive": async. request with keepalive===true / sendBeacon, to be used in boforeunload event
* @param {object} _sender * @param {object} _sender
* @param {egw} _egw * @param {egw} _egw
*/ */
@ -95,11 +95,12 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
/** /**
* Sends the assembled request to the server * Sends the assembled request to the server
* @param {boolean} [async=false] Overrides async provided in constructor to give an easy way to make simple async requests * @param {boolean|"keepalive"} _async Overrides async provided in constructor: true: asynchronious request,
* false: synchronious request, "keepalive": async. request with keepalive===true / sendBeacon, to be used in beforeunload event
* @param {string} method ='POST' allow to eg. use a (cachable) 'GET' request instead of POST * @param {string} method ='POST' allow to eg. use a (cachable) 'GET' request instead of POST
* @param {function} error option error callback(_xmlhttp, _err) used instead our default this.error * @param {function} error option error callback(_xmlhttp, _err) used instead our default this.error
* *
* @return {jqXHR} jQuery jqXHR request object * @return {jqXHR|boolean} jQuery jqXHR request object or for async==="keepalive" boolean is returned
*/ */
json_request.prototype.sendRequest = function(async, method, error) json_request.prototype.sendRequest = function(async, method, error)
{ {
@ -117,6 +118,15 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
} }
}); });
// send with keepalive===true or sendBeacon to be used in beforeunload event
if (this.async === "keepalive" && typeof navigator.sendBeacon !== "undefined")
{
const data = new FormData();
data.append('json_data', request_obj);
//(window.opener||window).console.log("navigator.sendBeacon", this.url, request_obj, data.getAll('json_data'));
return navigator.sendBeacon(this.url, data);
}
// Send the request via AJAX using the jquery ajax function // Send the request via AJAX using the jquery ajax function
// we need to use jQuery of window of egw object, as otherwise the one from main window is used! // we need to use jQuery of window of egw object, as otherwise the one from main window is used!
// (causing eg. apply from server with app.$app.method to run in main window instead of popup) // (causing eg. apply from server with app.$app.method to run in main window instead of popup)

View File

@ -237,7 +237,7 @@ app.classes.calendar = (function(){ "use strict"; return AppJS.extend(
{ {
window.onbeforeunload = function () { window.onbeforeunload = function () {
this.egw.json('calendar.calendar_uiforms.ajax_unlock', this.egw.json('calendar.calendar_uiforms.ajax_unlock',
[content.data.id, content.data.lock_token],null,true,null,null).sendRequest(true); [content.data.id, content.data.lock_token],null,true,"keepalive",null).sendRequest();
}; };
} }
} }