Detect user navigating away, don't interpret as ajax error

Whenever a user navigates away, all ajax calls will fail with the same
result like a cross-domain redirect (SSO). To distinguish these cases,
we need to detect whether the error is a result of the user navigating
away. For this, we introduce a new flag that will be set in
"beforeunload".

Additional handling was required for false positives in case "beforeunload" is
used (ex: cancelled upload) and the user cancelled the navigation.
This commit is contained in:
Vincent Petry 2016-03-22 16:54:01 +01:00
parent 9c800f62dd
commit 752e6676e1
1 changed files with 26 additions and 1 deletions

View File

@ -741,7 +741,9 @@ var OC={
*/
_processAjaxError: function(xhr) {
// purposefully aborted request ?
if (xhr.status === 0 && (xhr.statusText === 'abort' || xhr.statusText === 'timeout')) {
// this._userIsNavigatingAway needed to distinguish ajax calls cancelled by navigating away
// from calls cancelled by failed cross-domain ajax due to SSO redirect
if (xhr.status === 0 && (xhr.statusText === 'abort' || xhr.statusText === 'timeout' || this._userIsNavigatingAway)) {
return;
}
@ -1438,6 +1440,29 @@ function initCore() {
$('html').addClass('edge');
}
$(window).on('unload', function() {
OC._unloadCalled = true;
});
$(window).on('beforeunload', function() {
// super-trick thanks to http://stackoverflow.com/a/4651049
// in case another handler displays a confirmation dialog (ex: navigating away
// during an upload), there are two possible outcomes: user clicked "ok" or
// "cancel"
// first timeout handler is called after unload dialog is closed
setTimeout(function() {
OC._userIsNavigatingAway = true;
// second timeout event is only called if user cancelled (Chrome),
// but in other browsers it might still be triggered, so need to
// set a higher delay...
setTimeout(function() {
if (!OC._unloadCalled) {
OC._userIsNavigatingAway = false;
}
}, 10000);
},1);
});
$(document).on('ajaxError.main', function( event, request, settings ) {
if (settings && settings.allowAuthErrors) {
return;