/* HTML5 Speedtest v4.0 by Federico Dossena https://github.com/adolfintel/speedtest/ GNU LGPLv3 License */ //data reported to main thread var testStatus=0, //0=not started, 1=download test, 2=ping+jitter test, 3=upload test, 4=finished, 5=abort/error dlStatus="", //download speed in megabit/s with 2 decimal digits ulStatus="", //upload speed in megabit/s with 2 decimal digits pingStatus="", //ping in milliseconds with 2 decimal digits jitterStatus="", //jitter in milliseconds with 2 decimal digits clientIp=""; //client's IP address as reported by getIP.php //test settings. can be overridden by sending specific values with the start command var settings={ time_ul:15, //duration of upload test in seconds time_dl:15, //duration of download test in seconds count_ping:35, //number of pings to perform in ping test url_dl:"garbage.php", //path to a large file or garbage.php, used for download test. must be relative to this js file url_ul:"empty.dat", //path to an empty file, used for upload test. must be relative to this js file url_ping:"empty.dat", //path to an empty file, used for ping test. must be relative to this js file url_getIp:"getIP.php", //path to getIP.php relative to this js file, or a similar thing that outputs the client's ip xhr_dlMultistream:10, //number of download streams to use (can be different if enable_quirks is active) xhr_ulMultistream:3, //number of upload streams to use (can be different if enable_quirks is active) xhr_dlUseBlob:false, //if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize and/or high xhr_dlMultistream) garbagePhp_chunkSize:20, //size of chunks sent by garbage.php (can be different if enable_quirks is active) enable_quirks:true, //enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers, unless they are already being overridden with the start command allow_fetchAPI:false, //enables Fetch API. currently disabled because it leaks memory like no tomorrow force_fetchAPI:false //when Fetch API is enabled, it will force usage on every browser that supports it }; var xhr=null, //array of currently active xhr requests interval=null; //timer used in tests /* when set to true (automatically) the download test will use the fetch api instead of xhr. fetch api is used if -allow_fetchAPI is true AND -(we're on chrome that supports fetch api AND enable_quirks is true) OR (we're on any browser that supports fetch api AND force_fetchAPI is true) */ var useFetchAPI=false; /* listener for commands from main thread to this worker. commands: -status: returns the current status as a string of values spearated by a semicolon (;) in this order: testStatus;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus -abort: aborts the current test -start: starts the test. optionally, settings can be passed as JSON. example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"} */ this.addEventListener('message', function(e){ var params=e.data.split(" "); if(params[0]=="status"){ //return status postMessage(testStatus+";"+dlStatus+";"+ulStatus+";"+pingStatus+";"+clientIp+";"+jitterStatus); } if(params[0]=="start"&&testStatus==0){ //start new test testStatus=1; try{ //parse settings, if present var s=JSON.parse(e.data.substring(5)); if(typeof s.url_dl != "undefined") settings.url_dl=s.url_dl; //download url if(typeof s.url_ul != "undefined") settings.url_ul=s.url_ul; //upload url if(typeof s.url_ping != "undefined") settings.url_ping=s.url_ping; //ping url if(typeof s.url_getIp != "undefined") settings.url_getIp=s.url_getIp; //url to getIP.php if(typeof s.time_dl != "undefined") settings.time_dl=s.time_dl; //duration of download test if(typeof s.time_ul != "undefined") settings.time_ul=s.time_ul; //duration of upload test if(typeof s.enable_quirks != "undefined") settings.enable_quirks=s.enable_quirks; //enable quirks or not if(typeof s.allow_fetchAPI != "undefined") settings.allow_fetchAPI=s.allow_fetchAPI; //allows fetch api to be used if supported //quirks for specific browsers. more may be added in future releases if(settings.enable_quirks){ var ua=navigator.userAgent; if(/Firefox.(\d+\.\d+)/i.test(ua)){ //ff more precise with 1 upload stream settings.xhr_ulMultistream=1; } if(/Edge.(\d+\.\d+)/i.test(ua)){ //edge more precise with 3 download streams settings.xhr_dlMultistream=3; } if((/Safari.(\d+)/i.test(ua))&&!(/Chrome.(\d+)/i.test(ua))){ //safari more precise with 10 upload streams and 5mb chunks for download test settings.xhr_ulMultistream=10; settings.garbagePhp_chunkSize=5; } if(/Chrome.(\d+)/i.test(ua)&&(!!self.fetch)){ //chrome can't handle large xhr very well, use fetch api if available and allowed if(settings.allow_fetchAPI) useFetchAPI=true; //chrome more precise with 5 streams settings.xhr_dlMultistream=5; } } if(typeof s.count_ping != "undefined") settings.count_ping=s.count_ping; //number of pings for ping test if(typeof s.xhr_dlMultistream != "undefined") settings.xhr_dlMultistream=s.xhr_dlMultistream; //number of download streams if(typeof s.xhr_ulMultistream != "undefined") settings.xhr_ulMultistream=s.xhr_ulMultistream; //number of upload streams if(typeof s.xhr_dlUseBlob != "undefined") settings.xhr_dlUseBlob=s.xhr_dlUseBlob; //use blob for download test if(typeof s.garbagePhp_chunkSize != "undefined") settings.garbagePhp_chunkSize=s.garbagePhp_chunkSize; //size of garbage.php chunks if(typeof s.force_fetchAPI != "undefined") settings.force_fetchAPI=s.force_fetchAPI; //use fetch api on all browsers that support it if enabled if(settings.allow_fetchAPI&&settings.force_fetchAPI&&(!!self.fetch)) useFetchAPI=true; }catch(e){console.log(e)} //run the tests console.log(settings); console.log("Fetch API: "+useFetchAPI); getIp(function(){dlTest(function(){testStatus=2;pingTest(function(){testStatus=3;ulTest(function(){testStatus=4;});});})}); } if(params[0]=="abort"){ //abort command clearRequests(); //stop all xhr activity if(interval)clearInterval(interval); //clear timer if present testStatus=5;dlStatus="";ulStatus="";pingStatus="";jitterStatus=""; //set test as aborted } }); //stops all XHR activity, aggressively function clearRequests(){ if(xhr){ for(var i=0;ijitter?(jitter*0.2+instjitter*0.8):(jitter*0.9+instjitter*0.1); //update jitter, weighted average. spikes in ping values are given more weight. } prevInstspd=instspd; } pingStatus=ping.toFixed(2); jitterStatus=jitter.toFixed(2); i++; if(i