michael@0: // target for window.open() michael@0: const KID_URL = "child-window.html"; michael@0: michael@0: // formats final results michael@0: const SERVER_URL = "http://jrgm.mcom.com/cgi-bin/window-open-2.0/openreport.pl"; michael@0: michael@0: // let system settle between each window.open michael@0: const OPENER_DELAY = 1000; michael@0: michael@0: // three phases: single open/close; overlapped open/close; open-all/close-all michael@0: var PHASE_ONE = 10; michael@0: var PHASE_TWO = 0; michael@0: var PHASE_THREE = 0; michael@0: michael@0: // keep this many windows concurrently open during overlapped phase michael@0: var OVERLAP_COUNT = 3; michael@0: michael@0: // repeat three phases CYCLES times michael@0: var CYCLES = 1; michael@0: michael@0: // autoclose flag michael@0: var AUTOCLOSE = 1; michael@0: michael@0: // Chrome url for child windows. michael@0: var KID_CHROME = null; michael@0: var SAVED_CHROME = null; michael@0: michael@0: // URL options and correspnding vars. michael@0: const options = [ [ "phase1", "PHASE_ONE", false ], michael@0: [ "phase2", "PHASE_TWO", false ], michael@0: [ "phase3", "PHASE_THREE", false ], michael@0: [ "overlap", "OVERLAP_COUNT", false ], michael@0: [ "cycles", "CYCLES", false ], michael@0: [ "chrome", "KID_CHROME", true ], michael@0: [ "close", "AUTOCLOSE", false ] ]; michael@0: michael@0: // Note: You can attach search options to the url for this file to control michael@0: // any of the options in the array above. E.g., specifying michael@0: // mozilla -chrome "file:///D|/mozilla/xpfe/test/winopen.xul?phase1=16&close=0" michael@0: // will run this script with PHASE_ONE=16 and AUTOCLOSE=0. michael@0: // michael@0: // On Win32, you must enclose the -chrome option in quotes in order pass funny Win32 shell michael@0: // characters such as '&' or '|'! michael@0: michael@0: var opts = window.location.search.substring(1).split( '&' ); michael@0: for ( opt in opts ) { michael@0: for ( var i in options ) { michael@0: if ( opts[opt].indexOf( options[i][0]+"=" ) == 0 ) { michael@0: var newVal = opts[opt].split( '=' )[ 1 ]; michael@0: // wrap with quotes, if required. michael@0: if ( options[i][2] ) { michael@0: newVal = '"' + newVal + '"'; michael@0: } michael@0: eval( options[i][1] + "=" + newVal + ";" ); michael@0: } michael@0: } michael@0: } michael@0: michael@0: var prefs = null; michael@0: michael@0: if ( KID_CHROME ) { michael@0: // Reset browser.chromeURL so it points to KID_CHROME. michael@0: // This will cause window.open in openWindow to open that chrome. michael@0: netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); michael@0: prefs = Components.classes["@mozilla.org/preferences-service;1"] michael@0: .getService( Components.interfaces.nsIPrefBranch ); michael@0: SAVED_CHROME = prefs.getCharPref( "browser.chromeURL" ); michael@0: prefs.setCharPref( "browser.chromeURL", KID_CHROME ); michael@0: } michael@0: michael@0: const CYCLE_SIZE = PHASE_ONE + PHASE_TWO + PHASE_THREE; michael@0: const MAX_INDEX = CYCLE_SIZE * CYCLES; // total number of windows to open michael@0: michael@0: var windowList = []; // handles to opened windows michael@0: var startingTimes = []; // time that window.open is called michael@0: var openingTimes = []; // time that child window took to fire onload michael@0: var closingTimes = []; // collect stats for case of closing >1 windows michael@0: var currentIndex = 0; michael@0: michael@0: michael@0: function childIsOpen(aTime) { michael@0: openingTimes[currentIndex] = aTime - startingTimes[currentIndex]; michael@0: updateDisplay(currentIndex, openingTimes[currentIndex]); michael@0: reapWindows(currentIndex); michael@0: currentIndex++; michael@0: if (currentIndex < MAX_INDEX) michael@0: scheduleNextWindow(); michael@0: else michael@0: window.setTimeout(reportResults, OPENER_DELAY); michael@0: } michael@0: michael@0: michael@0: function updateDisplay(index, time) { michael@0: var formIndex = document.getElementById("formIndex"); michael@0: if (formIndex) michael@0: formIndex.setAttribute("value", index+1); michael@0: var formTime = document.getElementById("formTime"); michael@0: if (formTime) michael@0: formTime.setAttribute("value", time); michael@0: } michael@0: michael@0: michael@0: function scheduleNextWindow() { michael@0: window.setTimeout(openWindow, OPENER_DELAY); michael@0: } michael@0: michael@0: michael@0: function closeOneWindow(aIndex) { michael@0: var win = windowList[aIndex]; michael@0: // no-op if window is already closed michael@0: if (win && !win.closed) { michael@0: win.close(); michael@0: windowList[aIndex] = null; michael@0: } michael@0: } michael@0: michael@0: michael@0: function closeAllWindows(aRecordTimeToClose) { michael@0: var timeToClose = (new Date()).getTime(); michael@0: var count = 0; michael@0: for (var i = 0; i < windowList.length; i++) { michael@0: if (windowList[i]) michael@0: count++; michael@0: closeOneWindow(i); michael@0: } michael@0: if (aRecordTimeToClose && count > 0) { michael@0: timeToClose = (new Date()).getTime() - timeToClose; michael@0: closingTimes.push(parseInt(timeToClose/count)); michael@0: } michael@0: } michael@0: michael@0: michael@0: // close some, none, or all open windows in the list michael@0: function reapWindows() { michael@0: var modIndex = currentIndex % CYCLE_SIZE; michael@0: if (modIndex < PHASE_ONE-1) { michael@0: // first phase in each "cycle", are single open/close sequences michael@0: closeOneWindow(currentIndex); michael@0: } michael@0: else if (PHASE_ONE-1 <= modIndex && modIndex < PHASE_ONE+PHASE_TWO-1) { michael@0: // next phase in each "cycle", keep N windows concurrently open michael@0: closeOneWindow(currentIndex - OVERLAP_COUNT); michael@0: } michael@0: else if (modIndex == PHASE_ONE+PHASE_TWO-1) { michael@0: // end overlapping windows cycle; close all windows michael@0: closeAllWindows(false); michael@0: } michael@0: else if (PHASE_ONE+PHASE_TWO <= modIndex && modIndex < CYCLE_SIZE-1) { michael@0: // do nothing; keep adding windows michael@0: } michael@0: else if (modIndex == CYCLE_SIZE-1) { michael@0: // end open-all/close-all phase; close windows, recording time to close michael@0: closeAllWindows(true); michael@0: } michael@0: } michael@0: michael@0: function calcMedian( numbers ) { michael@0: if ( numbers.length == 0 ) { michael@0: return 0; michael@0: } else if ( numbers.length == 1 ) { michael@0: return numbers[0]; michael@0: } else if ( numbers.length == 2 ) { michael@0: return ( numbers[0] + numbers[1] ) / 2; michael@0: } else { michael@0: numbers.sort( function (a,b){ return a-b; } ); michael@0: var n = Math.floor( numbers.length / 2 ); michael@0: return numbers.length % 2 ? numbers[n] : ( numbers[n-1] + numbers[n] ) / 2; michael@0: } michael@0: } michael@0: michael@0: function reportResults() { michael@0: //XXX need to create a client-side method to do this? michael@0: var opening = openingTimes.join(':'); // times for each window open michael@0: var closing = closingTimes.join(':'); // these are for >1 url, as a group michael@0: //var ua = escape(navigator.userAgent).replace(/\+/g, "%2B"); // + == ' ', on servers michael@0: //var reportURL = SERVER_URL + michael@0: // "?opening=" + opening + michael@0: // "&closing=" + closing + michael@0: // "&maxIndex=" + MAX_INDEX + michael@0: // "&cycleSize=" + CYCLE_SIZE + michael@0: //"&ua=" + ua; michael@0: //window.open(reportURL, "test-results"); michael@0: var avgOpenTime = 0; michael@0: var minOpenTime = 99999; michael@0: var maxOpenTime = 0; michael@0: var medOpenTime = calcMedian( openingTimes.slice(1) ); michael@0: // ignore first open michael@0: for (i = 1; i < MAX_INDEX; i++) { michael@0: avgOpenTime += openingTimes[i]; michael@0: if ( minOpenTime > openingTimes[i] ) { michael@0: minOpenTime = openingTimes[i]; michael@0: } michael@0: if ( maxOpenTime < openingTimes[i] ) { michael@0: maxOpenTime = openingTimes[i]; michael@0: } michael@0: } michael@0: avgOpenTime = Math.round(avgOpenTime / (MAX_INDEX - 1)); michael@0: dump("openingTimes="+openingTimes.slice(1)+"\n"); michael@0: dump("avgOpenTime:" + avgOpenTime + "\n" ); michael@0: dump("minOpenTime:" + minOpenTime + "\n" ); michael@0: dump("maxOpenTime:" + maxOpenTime + "\n" ); michael@0: dump("medOpenTime:" + medOpenTime + "\n" ); michael@0: dump("__xulWinOpenTime:" + medOpenTime + "\n"); michael@0: // Close the root window, if required. michael@0: if ( AUTOCLOSE ) { michael@0: window.close(); michael@0: } else { michael@0: document.getElementById("formTimes").value = openingTimes.slice(1); michael@0: document.getElementById("formAvg").value = avgOpenTime; michael@0: document.getElementById("formMin").value = minOpenTime; michael@0: document.getElementById("formMax").value = maxOpenTime; michael@0: document.getElementById("formMed").value = medOpenTime; michael@0: document.getElementById("formAgain").setAttribute( "disabled", "false" ); michael@0: } michael@0: } michael@0: michael@0: function tryAgain() { michael@0: document.getElementById("formAgain").setAttribute( "disabled", "true" ); michael@0: windowList = []; michael@0: startingTimes = []; michael@0: openingTimes = []; michael@0: closingTimes = []; michael@0: currentIndex = 0; michael@0: openWindow(); michael@0: } michael@0: michael@0: function restoreChromeURL() { michael@0: // Restore browser.chromeURL pref. michael@0: if ( KID_CHROME && SAVED_CHROME.length ) { michael@0: netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); michael@0: prefs.setCharPref( "browser.chromeURL", SAVED_CHROME ); michael@0: } michael@0: } michael@0: michael@0: function openWindow() { michael@0: startingTimes[currentIndex] = (new Date()).getTime(); michael@0: var path = window.location.pathname.substring( 0, window.location.pathname.lastIndexOf('/') ); michael@0: var url = window.location.protocol + "//" + michael@0: window.location.hostname + path + "/" + michael@0: KID_URL; michael@0: windowList[currentIndex] = window.open(url, currentIndex); michael@0: } michael@0: michael@0: