├── icon.png ├── versions └── 1-0.zip ├── chrome-webstore ├── icon-128.png ├── promo-440.png ├── promo-920.png ├── promo-1440.png ├── screenshot-01.png └── screenshot-02.png ├── onload-execute.js ├── README.md ├── manifest.json ├── performance.js ├── popup.html ├── LICENSE ├── performance.css └── popup.js /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/icon.png -------------------------------------------------------------------------------- /versions/1-0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/versions/1-0.zip -------------------------------------------------------------------------------- /chrome-webstore/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/icon-128.png -------------------------------------------------------------------------------- /chrome-webstore/promo-440.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/promo-440.png -------------------------------------------------------------------------------- /chrome-webstore/promo-920.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/promo-920.png -------------------------------------------------------------------------------- /chrome-webstore/promo-1440.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/promo-1440.png -------------------------------------------------------------------------------- /chrome-webstore/screenshot-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/screenshot-01.png -------------------------------------------------------------------------------- /chrome-webstore/screenshot-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregM/performance-timing-google-chrome-extension/HEAD/chrome-webstore/screenshot-02.png -------------------------------------------------------------------------------- /onload-execute.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("load", function load(event){ 2 | window.removeEventListener("load", load, false); 3 | //console.log("Web Performance Timing API data ready.") 4 | },false); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | performance-timing-google-chrome-extension 2 | ========================================== 3 | 4 | Web Performance Timing API Google Chrome Extension 5 | 6 | Available here: https://chrome.google.com/webstore/detail/web-performance-timing-ap/nllipdabkglnhmanndddgcihbcmjpfej?hl=en-US&authuser=1 7 | 8 | ![Alt text](chrome-webstore/promo-920.png) 9 | 10 | Available under MIT License -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | 4 | "name": "Web Performance Timing API", 5 | "description": "Graphs common performance timing data from your current website using the performance timing API.", 6 | "version": "1.0", 7 | "browser_action": { 8 | "default_icon": "icon.png", 9 | "default_popup": "popup.html" 10 | }, 11 | "permissions": [ 12 | "tabs", "http://*/*", "https://*/*" 13 | ] 14 | } -------------------------------------------------------------------------------- /performance.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var p = {}; 3 | 4 | p.prerequestTime = performance.timing.requestStart - performance.timing.navigationStart; 5 | p.latencyTime = performance.timing.responseStart - performance.timing.requestStart; 6 | p.serverTime = performance.timing.responseEnd - performance.timing.responseStart; 7 | p.domLoadingTime = performance.timing.domInteractive - performance.timing.responseEnd; 8 | p.domCompleteTime = performance.timing.domComplete - performance.timing.domInteractive; 9 | p.loadTime = performance.timing.loadEventEnd - performance.timing.domComplete; 10 | 11 | // Test to make sure these two variables match. 12 | // p.onloadTime = performance.timing.loadEventEnd - performance.timing.navigationStart; 13 | p.totalTime = p.prerequestTime + p.latencyTime + p.serverTime + p.domLoadingTime + p.domCompleteTime + p.loadTime; 14 | 15 | return p; 16 | })(); -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Web Performance API Timing 5 | 6 | 7 | 8 | Web Performance API Timing 9 | 10 | EVENT 11 |   12 | TIME 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Gregory Mazurek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /performance.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: white; 3 | border: 1px solid #EFEFEF; 4 | margin: 10px; 5 | min-width: 475px; 6 | overflow-x: hidden; 7 | padding: 10px; 8 | } 9 | 10 | .header.label { 11 | font-size: 13px; 12 | font-weight: bold; 13 | width: 150px; 14 | } 15 | 16 | .header.performance-label, .header.performance-time { 17 | border: 0; 18 | margin: 10px 0 10px; 19 | text-decoration: underline; 20 | } 21 | 22 | .performance-label, .performance-time, 23 | .performance-graph, 24 | .performance-graph-pre, .performance-graph-key, .performance-graph-post, 25 | .performance-graph-total { 26 | display: block; 27 | float: left; 28 | height: 20px; 29 | line-height: 20px; 30 | } 31 | 32 | .performance-row:hover { 33 | background-color: #EFEFEF; 34 | } 35 | 36 | .performance-row.key-0 { 37 | border-bottom: 1px solid grey; 38 | padding-bottom: 10px; 39 | } 40 | 41 | .performance-label { 42 | border-right: 1px solid grey; 43 | width: 100px; 44 | } 45 | 46 | .performance-time { 47 | padding: 0 0 0 20px; 48 | text-align: right; 49 | width: 60px; 50 | } 51 | 52 | .performance-graph, .performance-graph-total { 53 | height: 20px; 54 | padding: 0 20px; 55 | width: 250px; 56 | } 57 | 58 | .performance-graph-key.key-0 { 59 | background-color: #511906; 60 | } 61 | .performance-graph-key.key-1 { 62 | background-color: #946250; 63 | } 64 | .performance-graph-key.key-2 { 65 | background-color: #4D9371; 66 | } 67 | .performance-graph-key.key-3 { 68 | background-color: #06436B; 69 | } 70 | .performance-graph-key.key-4 { 71 | background-color: #F2A74C; 72 | } 73 | .performance-graph-key.key-5 { 74 | background-color: #3D85B3; 75 | } 76 | .performance-graph-key.key-6 { 77 | background-color: #3B7559; 78 | } 79 | 80 | .clearfix:before, 81 | .clearfix:after { 82 | content: " "; 83 | display: table; 84 | } 85 | 86 | .clearfix:after { 87 | clear: both; 88 | } 89 | 90 | .footer, .explanation { 91 | margin-top: 10px; 92 | } -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* Key for total loading time of page */ 4 | var PAGE_LOAD_KEY = "totalTime"; 5 | 6 | /* Global mutable variables used throughout */ 7 | var precedingTime = pageLoadTotalTime = counter = 0; 8 | 9 | /* The data that will be displayed to the end user */ 10 | /* At some point, share orderOfEvents and eval() on orderOfEvents.calculation */ 11 | var orderOfEvents = [{ 12 | 'key': 'prerequestTime', 13 | 'label': 'Pre-request', 14 | 'calculation': 'performance.timing.requestStart - performance.timing.navigationStart' 15 | }, { 16 | 'key': 'latencyTime', 17 | 'label': 'Latency', 18 | 'calculation': 'performance.timing.responseStart - performance.timing.requestStart' 19 | }, { 20 | 'key': 'serverTime', 21 | 'label': 'Server', 22 | 'calculation': 'performance.timing.responseEnd - performance.timing.responseStart' 23 | }, { 24 | 'key': 'domLoadingTime', 25 | 'label': 'DOM Loading', 26 | 'calculation': 'performance.timing.domInteractive - performance.timing.responseEnd' 27 | }, { 28 | 'key': 'domCompleteTime', 29 | 'label': 'DOM Complete', 30 | 'calculation': 'performance.timing.domComplete - performance.timing.domInteractive' 31 | }, { 32 | 'key': 'loadTime', 33 | 'label': 'Load', 34 | 'calculation': 'performance.timing.loadEventEnd - performance.timing.domComplete' 35 | }]; 36 | 37 | 38 | chromeExtension = { 39 | 40 | /** 41 | * Generate everything. 42 | * 43 | * @private 44 | */ 45 | generate: function () { 46 | 47 | chrome.tabs.executeScript( 48 | { 49 | file: 'performance.js' 50 | }, 51 | function(result, isException) { 52 | if (isException) { 53 | //console.log("There was an error with counting elements on this page."); 54 | } else { 55 | pageLoadTotalTime = result[0][PAGE_LOAD_KEY]; 56 | var dataParent = document.getElementsByClassName('data')[0]; 57 | 58 | var node = chromeExtension.createRow(PAGE_LOAD_KEY, pageLoadTotalTime, 0, pageLoadTotalTime); 59 | dataParent.appendChild(node); 60 | 61 | chromeExtension.incrementCounter(); 62 | 63 | for (var i in orderOfEvents) { 64 | var key = orderOfEvents[i].key; 65 | var time = result[0][key]; 66 | var displayName = orderOfEvents[i].label; 67 | var dataRow = chromeExtension.createRow(displayName, time); 68 | 69 | dataParent.appendChild(dataRow); 70 | 71 | precedingTime = precedingTime + time; 72 | chromeExtension.incrementCounter(); 73 | } 74 | chromeExtension.createRowMouseOverEvent(); 75 | } 76 | } 77 | ); 78 | }, 79 | 80 | /** 81 | * Increments global counter 82 | * 83 | * @private 84 | */ 85 | incrementCounter: function() { 86 | counter = counter + 1; 87 | }, 88 | 89 | /** 90 | * Create a new row with the data passed through 91 | * 92 | * @param {String} key for performance api metric 93 | * @param {Number} value for performance api metric 94 | * @private 95 | */ 96 | createRow: function (key, value) { 97 | var bar, clearfix, barCopy; 98 | 99 | var d = document.createElement('div'); 100 | d.className = 'performance-row performance-row-' + counter + ' key-' + counter; 101 | 102 | var label = document.createElement('span'); 103 | label.className = 'performance-label'; 104 | label.textContent = key; 105 | 106 | var time = document.createElement('span'); 107 | time.className = 'performance-time'; 108 | time.textContent = value + " ms"; 109 | 110 | bar = (key === PAGE_LOAD_KEY) ? this.createGraphTotal() : this.createGraph(key, value, counter); 111 | if (document.getElementsByClassName('performance-graph-total')[0]) { 112 | barCopy = this.createChartData(value, counter); 113 | document.getElementsByClassName('performance-graph-total')[0].appendChild(barCopy); 114 | } 115 | 116 | d.appendChild(label); 117 | d.appendChild(bar); 118 | d.appendChild(time); 119 | 120 | clearfix = this.createClearfixDOMElement(); 121 | d.appendChild(clearfix); 122 | return d; 123 | }, 124 | 125 | /** 126 | * Create a new graph wrapper so that the totals can be passed through 127 | * 128 | * @private 129 | */ 130 | createGraphTotal: function() { 131 | var g = document.createElement('div'); 132 | g.className = 'performance-graph-total'; 133 | return g; 134 | }, 135 | 136 | /** 137 | * Create a new graph with the data passed through 138 | * 139 | * @param {String} DOM element name 140 | * @param {Number} current tally of milliseconds passed 141 | * @private 142 | */ 143 | createGraph: function(key, value) { 144 | var g = document.createElement('span'); 145 | g.className = 'performance-graph ' + key; 146 | 147 | var preTime = this.createPreChartSpacing(counter); 148 | var thisKeyTime = this.createChartData(value, counter); 149 | var clearfix = this.createClearfixDOMElement(); 150 | 151 | g.appendChild(preTime); 152 | g.appendChild(thisKeyTime); 153 | g.appendChild(clearfix); 154 | 155 | return g; 156 | }, 157 | 158 | /** 159 | * Create an the bar which is a percentage of its parent. 160 | * 161 | * @param {Number} value of the data point 162 | * 163 | * @private 164 | */ 165 | createChartData: function(value) { 166 | var d = document.createElement('span'); 167 | d.className = 'performance-graph-key key-' + counter; 168 | d.style.width = (value / pageLoadTotalTime * 100) + '%'; 169 | return d; 170 | }, 171 | 172 | /** 173 | * Create a pre DOM element and assign it to be a percentage 174 | * equal to everything that has been allocated so far. 175 | * 176 | * @private 177 | */ 178 | createPreChartSpacing: function() { 179 | var d = document.createElement('span'); 180 | d.className = 'performance-graph-pre key-' + counter; 181 | d.style.width = (precedingTime / pageLoadTotalTime * 100) + '%'; 182 | return d; 183 | }, 184 | 185 | /** 186 | * Create a clearfix DOM element 187 | * 188 | * @private 189 | */ 190 | createClearfixDOMElement: function() { 191 | var c = document.createElement('span'); 192 | c.className = 'clearfix'; 193 | return c; 194 | }, 195 | 196 | /** 197 | * Create an onmouseover event on each row 198 | * 199 | * @private 200 | */ 201 | createRowMouseOverEvent: function() { 202 | var explanation = document.getElementsByClassName('explanation')[0]; 203 | var preText = "Calc: "; 204 | for (var i = 1; i < (orderOfEvents.length + 1); i++) { 205 | document.getElementsByClassName('performance-row-' + i)[0].onmouseout= function() { 206 | explanation.innerHTML = ' '; 207 | }; 208 | } 209 | document.getElementsByClassName('performance-row-1')[0].onmouseover = function() { 210 | explanation.innerHTML = preText + orderOfEvents[0].calculation; 211 | }; 212 | document.getElementsByClassName('performance-row-2')[0].onmouseover = function() { 213 | explanation.innerHTML = preText + orderOfEvents[1].calculation; 214 | }; 215 | document.getElementsByClassName('performance-row-3')[0].onmouseover = function() { 216 | explanation.innerHTML = preText + orderOfEvents[2].calculation; 217 | }; 218 | document.getElementsByClassName('performance-row-4')[0].onmouseover = function() { 219 | explanation.innerHTML = preText + orderOfEvents[3].calculation; 220 | }; 221 | document.getElementsByClassName('performance-row-5')[0].onmouseover = function() { 222 | explanation.innerHTML = preText + orderOfEvents[4].calculation; 223 | }; 224 | document.getElementsByClassName('performance-row-6')[0].onmouseover = function() { 225 | explanation.innerHTML = preText + orderOfEvents[5].calculation; 226 | }; 227 | }, 228 | 229 | /** 230 | * Execute 231 | * 232 | */ 233 | init: function () { 234 | chrome.tabs.executeScript( 235 | { 236 | file: 'onload-execute.js' 237 | }, 238 | function(result, isException) { 239 | if (result) { 240 | chromeExtension.generate(); 241 | } else { 242 | //console.log("There was an error retrieving Web Performing API Timing information"); 243 | } 244 | }); 245 | } 246 | 247 | } 248 | 249 | window.addEventListener("load", function load(event){ 250 | window.removeEventListener("load", load, false); 251 | chromeExtension.init(); 252 | },false); 253 | 254 | })(); --------------------------------------------------------------------------------