diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-17 16:49:04 +0300 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-17 16:49:04 +0300 |
commit | 7af7d18cfa2f1fab239e9a21e989bd8061cf23bb (patch) | |
tree | f11a35340c168a2a866fcf5c82c9d21d847206aa /core | |
parent | add696b057fa40696c251d4a52ed9d2a997c7aa0 (diff) | |
parent | b99c6f1f67a207984b8b5355703cabd89d1e7c73 (diff) |
Merge pull request #16783 from owncloud/handle-redirects-global
Adding global error handler for ajax calls which run into redirection…
Diffstat (limited to 'core')
-rw-r--r-- | core/js/files/client.js | 2 | ||||
-rw-r--r-- | core/js/js.js | 64 | ||||
-rw-r--r-- | core/js/setupchecks.js | 9 | ||||
-rw-r--r-- | core/js/tests/specHelper.js | 7 | ||||
-rw-r--r-- | core/js/tests/specs/coreSpec.js | 42 |
5 files changed, 120 insertions, 4 deletions
diff --git a/core/js/files/client.js b/core/js/files/client.js index 627630e8b03..a7f393d325f 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -137,6 +137,8 @@ }); return result; }; + + OC.registerXHRForErrorProcessing(xhr); return xhr; }, diff --git a/core/js/js.js b/core/js/js.js index 83658a537b8..fac9c45f668 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -235,6 +235,13 @@ var OC={ }, /** + * Reloads the current page + */ + reload: function() { + window.location.reload(); + }, + + /** * Protocol that is used to access this ownCloud instance * @return {string} Used protocol */ @@ -727,6 +734,56 @@ var OC={ isUserAdmin: function() { return oc_isadmin; }, + + /** + * Process ajax error, redirects to main page + * if an error/auth error status was returned. + */ + _processAjaxError: function(xhr) { + // purposefully aborted request ? + if (xhr.status === 0 && (xhr.statusText === 'abort' || xhr.statusText === 'timeout')) { + return; + } + + if (_.contains([0, 302, 307, 401], xhr.status)) { + OC.reload(); + } + }, + + /** + * Registers XmlHttpRequest object for global error processing. + * + * This means that if this XHR object returns 401 or session timeout errors, + * the current page will automatically be reloaded. + * + * @param {XMLHttpRequest} xhr + */ + registerXHRForErrorProcessing: function(xhr) { + var loadCallback = function() { + if (xhr.readyState !== 4) { + return; + } + + if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) { + return; + } + + // fire jquery global ajax error handler + $(document).trigger(new $.Event('ajaxError'), xhr); + }; + + var errorCallback = function() { + // fire jquery global ajax error handler + $(document).trigger(new $.Event('ajaxError'), xhr); + }; + + // FIXME: also needs an IE8 way + if (xhr.addEventListener) { + xhr.addEventListener('load', loadCallback); + xhr.addEventListener('error', errorCallback); + } + + } }; /** @@ -1311,6 +1368,13 @@ function initCore() { $('html').addClass('edge'); } + $(document).on('ajaxError.main', function( event, request, settings ) { + if (settings && settings.allowAuthErrors) { + return; + } + OC._processAjaxError(request); + }); + /** * Calls the server periodically to ensure that session doesn't * time out diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index de41b66ec32..1819b5a9c1e 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -40,7 +40,8 @@ '<d:propfind xmlns:d="DAV:">' + '<d:prop><d:resourcetype/></d:prop>' + '</d:propfind>', - complete: afterCall + complete: afterCall, + allowAuthErrors: true }); return deferred.promise(); }, @@ -157,7 +158,8 @@ $.ajax({ type: 'GET', - url: OC.generateUrl('settings/ajax/checksetup') + url: OC.generateUrl('settings/ajax/checksetup'), + allowAuthErrors: true }).then(afterCall, afterCall); return deferred.promise(); }, @@ -181,7 +183,8 @@ $.ajax({ type: 'GET', - url: OC.generateUrl('heartbeat') + url: OC.generateUrl('heartbeat'), + allowAuthErrors: true }).then(afterCall, afterCall); return deferred.promise(); diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js index d13691845a7..f9bdeae0d64 100644 --- a/core/js/tests/specHelper.js +++ b/core/js/tests/specHelper.js @@ -116,7 +116,8 @@ window.isPhantom = /phantom/i.test(navigator.userAgent); // global setup for all tests (function setupTests() { var fakeServer = null, - $testArea = null; + $testArea = null, + ajaxErrorStub = null; /** * Utility functions for testing @@ -162,6 +163,8 @@ window.isPhantom = /phantom/i.test(navigator.userAgent); // dummy select2 (which isn't loaded during the tests) $.fn.select2 = function() { return this; }; + + ajaxErrorStub = sinon.stub(OC, '_processAjaxError'); }); afterEach(function() { @@ -172,6 +175,8 @@ window.isPhantom = /phantom/i.test(navigator.userAgent); $testArea.remove(); delete($.fn.select2); + + ajaxErrorStub.restore(); }); })(); diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index 2e970f7e707..32eb8df32d1 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -302,6 +302,7 @@ describe('Core base tests', function() { /* jshint camelcase: false */ window.oc_config = oldConfig; routeStub.restore(); + $(document).off('ajaxError'); }); it('sends heartbeat half the session lifetime when heartbeat enabled', function() { /* jshint camelcase: false */ @@ -473,6 +474,7 @@ describe('Core base tests', function() { }); afterEach(function() { clock.restore(); + $(document).off('ajaxError'); }); it('Sets up menu toggle', function() { window.initCore(); @@ -841,5 +843,45 @@ describe('Core base tests', function() { // verification is done in afterEach }); }); + describe('global ajax errors', function() { + var reloadStub, ajaxErrorStub; + + beforeEach(function() { + reloadStub = sinon.stub(OC, 'reload'); + // unstub the error processing method + ajaxErrorStub = OC._processAjaxError; + ajaxErrorStub.restore(); + window.initCore(); + }); + afterEach(function() { + reloadStub.restore(); + $(document).off('ajaxError'); + }); + + it('reloads current page in case of auth error', function () { + var dataProvider = [ + [200, false], + [400, false], + [401, true], + [302, true], + [307, true] + ]; + + for (var i = 0; i < dataProvider.length; i++) { + var xhr = { status: dataProvider[i][0] }; + var expectedCall = dataProvider[i][1]; + + reloadStub.reset(); + + $(document).trigger(new $.Event('ajaxError'), xhr); + + if (expectedCall) { + expect(reloadStub.calledOnce).toEqual(true); + } else { + expect(reloadStub.notCalled).toEqual(true); + } + } + }); + }) }); |