1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-06 19:02:30 +01:00

fix #2526: better handle timeout conditions

This commit is contained in:
gorhill 2017-04-23 09:00:15 -04:00
parent de3d99ed13
commit 733917d176
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2

View File

@ -71,9 +71,25 @@ api.fetchText = function(url, onLoad, onError) {
onError = onLoad; onError = onLoad;
} }
var contentLoaded = 0,
timeoutAfter = µBlock.hiddenSettings.assetFetchTimeout * 1000 || 30000,
timeoutTimer,
xhr = new XMLHttpRequest();
var cleanup = function() {
xhr.removeEventListener('load', onLoadEvent);
xhr.removeEventListener('error', onErrorEvent);
xhr.removeEventListener('abort', onErrorEvent);
xhr.removeEventListener('progress', onProgressEvent);
if ( timeoutTimer !== undefined ) {
clearTimeout(timeoutTimer);
timeoutTimer = undefined;
}
};
// https://github.com/gorhill/uMatrix/issues/15 // https://github.com/gorhill/uMatrix/issues/15
var onResponseReceived = function() { var onLoadEvent = function() {
this.onload = this.onerror = this.ontimeout = null; cleanup();
// xhr for local files gives status 0, but actually succeeds // xhr for local files gives status 0, but actually succeeds
var details = { var details = {
url: url, url: url,
@ -96,29 +112,44 @@ api.fetchText = function(url, onLoad, onError) {
return onError.call(null, details); return onError.call(null, details);
} }
details.content = this.responseText; details.content = this.responseText;
return onLoad.call(null, details); onLoad(details);
}; };
var onErrorReceived = function() { var onErrorEvent = function() {
this.onload = this.onerror = this.ontimeout = null; cleanup();
µBlock.logger.writeOne('', 'error', errorCantConnectTo.replace('{{msg}}', actualUrl)); µBlock.logger.writeOne('', 'error', errorCantConnectTo.replace('{{msg}}', actualUrl));
onError.call(null, { url: url, content: '' }); onError({ url: url, content: '' });
};
var onTimeout = function() {
xhr.abort();
};
// https://github.com/gorhill/uBlock/issues/2526
// - Timeout only when there is no progress.
var onProgressEvent = function(ev) {
if ( ev.loaded === contentLoaded ) { return; }
contentLoaded = ev.loaded;
if ( timeoutTimer !== undefined ) {
clearTimeout(timeoutTimer);
}
timeoutTimer = vAPI.setTimeout(onTimeout, timeoutAfter);
}; };
// Be ready for thrown exceptions: // Be ready for thrown exceptions:
// I am pretty sure it used to work, but now using a URL such as // I am pretty sure it used to work, but now using a URL such as
// `file:///` on Chromium 40 results in an exception being thrown. // `file:///` on Chromium 40 results in an exception being thrown.
var xhr = new XMLHttpRequest();
try { try {
xhr.open('get', actualUrl, true); xhr.open('get', actualUrl, true);
xhr.timeout = µBlock.hiddenSettings.assetFetchTimeout * 1000 || 30000; xhr.addEventListener('load', onLoadEvent);
xhr.onload = onResponseReceived; xhr.addEventListener('error', onErrorEvent);
xhr.onerror = onErrorReceived; xhr.addEventListener('abort', onErrorEvent);
xhr.ontimeout = onErrorReceived; xhr.addEventListener('progress', onProgressEvent);
xhr.responseType = 'text'; xhr.responseType = 'text';
xhr.send(); xhr.send();
timeoutTimer = vAPI.setTimeout(onTimeout, timeoutAfter);
} catch (e) { } catch (e) {
onErrorReceived.call(xhr); onErrorEvent.call(xhr);
} }
}; };