1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 'use strict'; 6 7 /** 8 * @fileoverview This file provides a JavaScript helper function that 9 * determines when network quiescence has been reached based on the time since 10 * the last resource was received. 11 */ 12 (function() { 13 14 // Make executing this code idempotent. 15 if (window.__telemetry_testHasReachedNetworkQuiescence) { 16 return; 17 } 18 19 // Some benchmarks patch window.performance to make it deterministic. 20 // Save the original performance object before it is patched. 21 var real_performance = window.performance; 22 23 // Set the Resource Timing interface functions that will be used below 24 // to use whatever version is available currently regardless of vendor 25 // prefix. 26 real_performance.clearResourceTimings = 27 (real_performance.clearResourceTimings || 28 real_performance.mozClearResourceTimings || 29 real_performance.msClearResourceTimings || 30 real_performance.oClearResourceTimings || 31 real_performance.webkitClearResourceTimings); 32 33 real_performance.getEntriesByType = 34 (real_performance.getEntriesByType || 35 real_performance.mozGetEntriesByType || 36 real_performance.msGetEntriesByType || 37 real_performance.oGetEntriesByType || 38 real_performance.webkitGetEntriesByType); 39 40 // This variable will available to the function below and it will be 41 // persistent across different function calls. It stores the last 42 // entry in the list of PerformanceResourceTiming objects returned by 43 // real_performance.getEntriesByType('resource'). 44 // 45 // The reason for doing it this way is because the buffer for 46 // PerformanceResourceTiming objects has a limit, and once it's full, 47 // new entries are not added. We're only interested in the last entry, 48 // so we can clear new entries when they're added. 49 var lastEntry = null; 50 51 // True when no resource has been loaded from the network for 52 //|QUIESCENCE_TIMEOUT_MS| milliseconds. This value is sticky. 53 var hasReachedQuiesence = false; 54 55 // Time to wait before declaring network quiescence in milliseconds. 56 var QUIESCENCE_TIMEOUT_MS = 2000; 57 58 /** 59 * This method uses the Resource Timing interface, which is described at 60 * http://www.w3.org/TR/resource-timing/. It determines whether the time 61 * since lodading any resources such as images and script files (including 62 * resources requested via XMLHttpRequest) has exceeded a threshold defined 63 # by |QUIESCENCE_TIMEOUT_MS|. 64 * 65 * @return {boolean} True if the time since either the load event, or the last 66 * resource was received after the load event exceeds the aforementioned 67 * threshold. This state is sticky, so once this function returns true for a 68 * given page, it will always return true. 69 */ 70 window.__telemetry_testHasReachedNetworkQuiescence = function() { 71 if (hasReachedQuiesence) { 72 return true; 73 } 74 75 if (window.document.readyState !== 'complete') { 76 return false; 77 } 78 79 var resourceTimings = real_performance.getEntriesByType('resource'); 80 if (resourceTimings.length > 0) { 81 lastEntry = resourceTimings.pop(); 82 real_performance.clearResourceTimings(); 83 } 84 85 // The times for performance.now() and in the PerformanceResourceTiming 86 // objects are all in milliseconds since performance.timing.navigationStart, 87 // so we must also get load time in the same terms. 88 var timing = real_performance.timing; 89 var loadTime = timing.loadEventEnd - timing.navigationStart; 90 var lastResponseTimeMs = 0; 91 92 // If there have been no resource timing entries, or the last entry was 93 // before the load event, then use the time since the load event. 94 if (!lastEntry || lastEntry.responseEnd < loadTime) { 95 lastResponseTimeMs = real_performance.now() - loadTime; 96 } else { 97 lastResponseTimeMs = real_performance.now() - lastEntry.responseEnd; 98 } 99 100 if (lastResponseTimeMs >= QUIESCENCE_TIMEOUT_MS) { 101 hasReachedQuiesence = true; 102 } 103 104 return hasReachedQuiesence; 105 } 106 107 })(); 108