| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * The global load time data that contains the localized strings that we will | 6 * The global load time data that contains the localized strings that we will |
| 7 * get from the main page when this page first loads. | 7 * get from the main page when this page first loads. |
| 8 */ | 8 */ |
| 9 var loadTimeData = null; | 9 var loadTimeData = null; |
| 10 | 10 |
| 11 /** |
| 12 * A queue of a sequence of closures that will incrementally build the sys info |
| 13 * html table. |
| 14 */ |
| 15 var tableCreationClosuresQueue = []; |
| 16 |
| 17 /** |
| 18 * The time used to post delayed tasks in MS. Currently set to be enough for two |
| 19 * frames. |
| 20 */ |
| 21 var STANDARD_DELAY_MS = 32; |
| 22 |
| 11 function getValueDivForButton(button) { | 23 function getValueDivForButton(button) { |
| 12 return $(button.id.substr(0, button.id.length - 4)); | 24 return $(button.id.substr(0, button.id.length - 4)); |
| 13 } | 25 } |
| 14 | 26 |
| 15 function getButtonForValueDiv(valueDiv) { | 27 function getButtonForValueDiv(valueDiv) { |
| 16 return $(valueDiv.id + '-btn'); | 28 return $(valueDiv.id + '-btn'); |
| 17 } | 29 } |
| 18 | 30 |
| 19 /** | 31 /** |
| 32 * Expands the multiline table cell that contains the given valueDiv. |
| 33 * @param {HTMLElement} button The expand button. |
| 34 * @param {HTMLElement} valueDiv The div that contains the multiline logs. |
| 35 * @param {number} delayFactor A value used for increasing the delay after which |
| 36 * the cell will be expanded. Useful for expandAll() since it expands the |
| 37 * multiline cells one after another with each expension done slightly after |
| 38 * the previous one. |
| 39 */ |
| 40 function expand(button, valueDiv, delayFactor) { |
| 41 button.textContent = loadTimeData.getString('sysinfoPageCollapseBtn'); |
| 42 // Show the spinner container. |
| 43 var valueCell = valueDiv.parentNode; |
| 44 valueCell.firstChild.hidden = false; |
| 45 // Expanding huge logs can take a very long time, so we do it after a delay |
| 46 // to have a chance to render the spinner. |
| 47 setTimeout(function() { |
| 48 valueCell.className = 'number-expanded'; |
| 49 // Hide the spinner container. |
| 50 valueCell.firstChild.hidden = true; |
| 51 }, STANDARD_DELAY_MS * delayFactor); |
| 52 } |
| 53 |
| 54 /** |
| 55 * Collapses the multiline table cell that contains the given valueDiv. |
| 56 * @param {HTMLElement} button The expand button. |
| 57 * @param {HTMLElement} valueDiv The div that contains the multiline logs. |
| 58 */ |
| 59 function collapse(button, valueDiv) { |
| 60 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); |
| 61 valueDiv.parentNode.className = 'number-collapsed'; |
| 62 } |
| 63 |
| 64 /** |
| 20 * Toggles whether an item is collapsed or expanded. | 65 * Toggles whether an item is collapsed or expanded. |
| 21 */ | 66 */ |
| 22 function changeCollapsedStatus() { | 67 function changeCollapsedStatus() { |
| 23 var valueDiv = getValueDivForButton(this); | 68 var valueDiv = getValueDivForButton(this); |
| 24 if (valueDiv.parentNode.className == 'number-collapsed') { | 69 if (valueDiv.parentNode.className == 'number-collapsed') |
| 25 valueDiv.parentNode.className = 'number-expanded'; | 70 expand(this, valueDiv, 1); |
| 26 this.textContent = loadTimeData.getString('sysinfoPageCollapseBtn'); | 71 else |
| 27 } else { | 72 collapse(this, valueDiv); |
| 28 valueDiv.parentNode.className = 'number-collapsed'; | |
| 29 this.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); | |
| 30 } | |
| 31 } | 73 } |
| 32 | 74 |
| 33 /** | 75 /** |
| 34 * Collapses all log items. | 76 * Collapses all log items. |
| 35 */ | 77 */ |
| 36 function collapseAll() { | 78 function collapseAll() { |
| 37 var valueDivs = document.getElementsByClassName('stat-value'); | 79 var valueDivs = document.getElementsByClassName('stat-value'); |
| 38 for (var i = 0; i < valueDivs.length; i++) { | 80 for (var i = 0; i < valueDivs.length; ++i) { |
| 81 if (valueDivs[i].parentNode.className != 'number-expanded') |
| 82 continue; |
| 39 var button = getButtonForValueDiv(valueDivs[i]); | 83 var button = getButtonForValueDiv(valueDivs[i]); |
| 40 if (button && button.className != 'button-hidden') { | 84 if (button) |
| 41 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); | 85 collapse(button, valueDivs[i]); |
| 42 valueDivs[i].parentNode.className = 'number-collapsed'; | |
| 43 } | |
| 44 } | 86 } |
| 45 } | 87 } |
| 46 | 88 |
| 47 /** | 89 /** |
| 48 * Expands all log items. | 90 * Expands all log items. |
| 49 */ | 91 */ |
| 50 function expandAll() { | 92 function expandAll() { |
| 51 var valueDivs = document.getElementsByClassName('stat-value'); | 93 var valueDivs = document.getElementsByClassName('stat-value'); |
| 52 for (var i = 0; i < valueDivs.length; i++) { | 94 for (var i = 0; i < valueDivs.length; ++i) { |
| 95 if (valueDivs[i].parentNode.className != 'number-collapsed') |
| 96 continue; |
| 53 var button = getButtonForValueDiv(valueDivs[i]); | 97 var button = getButtonForValueDiv(valueDivs[i]); |
| 54 if (button && button.className != 'button-hidden') { | 98 if (button) |
| 55 button.textContent = loadTimeData.getString('sysinfoPageCollapseBtn'); | 99 expand(button, valueDivs[i], i + 1); |
| 56 valueDivs[i].parentNode.className = 'number-expanded'; | |
| 57 } | |
| 58 } | 100 } |
| 59 } | 101 } |
| 60 | 102 |
| 61 /** | |
| 62 * Collapse only those log items with multi-line values. | |
| 63 */ | |
| 64 function collapseMultiLineStrings() { | |
| 65 var valueDivs = document.getElementsByClassName('stat-value'); | |
| 66 var nameDivs = document.getElementsByClassName('stat-name'); | |
| 67 for (var i = 0; i < valueDivs.length; i++) { | |
| 68 var button = getButtonForValueDiv(valueDivs[i]); | |
| 69 button.onclick = changeCollapsedStatus; | |
| 70 if (valueDivs[i].scrollHeight > (nameDivs[i].scrollHeight * 2)) { | |
| 71 button.className = ''; | |
| 72 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); | |
| 73 valueDivs[i].parentNode.className = 'number-collapsed'; | |
| 74 } else { | |
| 75 button.className = 'button-hidden'; | |
| 76 valueDivs[i].parentNode.className = 'number'; | |
| 77 } | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 function createNameCell(key) { | 103 function createNameCell(key) { |
| 82 var nameCell = document.createElement('td'); | 104 var nameCell = document.createElement('td'); |
| 83 nameCell.setAttribute('class', 'name'); | 105 nameCell.setAttribute('class', 'name'); |
| 84 var nameDiv = document.createElement('div'); | 106 var nameDiv = document.createElement('div'); |
| 85 nameDiv.setAttribute('class', 'stat-name'); | 107 nameDiv.setAttribute('class', 'stat-name'); |
| 86 nameDiv.appendChild(document.createTextNode(key)); | 108 nameDiv.appendChild(document.createTextNode(key)); |
| 87 nameCell.appendChild(nameDiv); | 109 nameCell.appendChild(nameDiv); |
| 88 return nameCell; | 110 return nameCell; |
| 89 } | 111 } |
| 90 | 112 |
| 91 function createButtonCell(key) { | 113 function createButtonCell(key, isMultiLine) { |
| 92 var buttonCell = document.createElement('td'); | 114 var buttonCell = document.createElement('td'); |
| 93 buttonCell.setAttribute('class', 'button-cell'); | 115 buttonCell.setAttribute('class', 'button-cell'); |
| 94 var button = document.createElement('button'); | 116 |
| 95 button.setAttribute('id', '' + key + '-value-btn'); | 117 if (isMultiLine) { |
| 96 buttonCell.appendChild(button); | 118 var button = document.createElement('button'); |
| 119 button.setAttribute('id', '' + key + '-value-btn'); |
| 120 button.onclick = changeCollapsedStatus; |
| 121 button.textContent = loadTimeData.getString('sysinfoPageExpandBtn'); |
| 122 buttonCell.appendChild(button); |
| 123 } |
| 124 |
| 97 return buttonCell; | 125 return buttonCell; |
| 98 } | 126 } |
| 99 | 127 |
| 100 function createValueCell(key, value) { | 128 function createValueCell(key, value, isMultiLine) { |
| 101 var valueCell = document.createElement('td'); | 129 var valueCell = document.createElement('td'); |
| 102 var valueDiv = document.createElement('div'); | 130 var valueDiv = document.createElement('div'); |
| 103 valueDiv.setAttribute('class', 'stat-value'); | 131 valueDiv.setAttribute('class', 'stat-value'); |
| 104 valueDiv.setAttribute('id', '' + key + '-value'); | 132 valueDiv.setAttribute('id', '' + key + '-value'); |
| 105 valueDiv.appendChild(document.createTextNode(value)); | 133 valueDiv.appendChild(document.createTextNode(value)); |
| 134 |
| 135 if (isMultiLine) { |
| 136 valueCell.className = 'number-collapsed'; |
| 137 var loadingContainer = $('spinner-container').cloneNode(true); |
| 138 loadingContainer.setAttribute('id', '' + key + '-value-loading'); |
| 139 loadingContainer.hidden = true; |
| 140 valueCell.appendChild(loadingContainer); |
| 141 } else { |
| 142 valueCell.className = 'number'; |
| 143 } |
| 144 |
| 106 valueCell.appendChild(valueDiv); | 145 valueCell.appendChild(valueDiv); |
| 107 return valueCell; | 146 return valueCell; |
| 108 } | 147 } |
| 109 | 148 |
| 110 function createTableRow(key, value) { | 149 function createTableRow(key, value) { |
| 111 var row = document.createElement('tr'); | 150 var row = document.createElement('tr'); |
| 151 |
| 152 // Avoid using element.scrollHeight as it's very slow. crbug.com/653968. |
| 153 var isMultiLine = value.split('\n').length > 2 || value.length > 1000; |
| 154 |
| 112 row.appendChild(createNameCell(key)); | 155 row.appendChild(createNameCell(key)); |
| 113 row.appendChild(createButtonCell(key)); | 156 row.appendChild(createButtonCell(key, isMultiLine)); |
| 114 row.appendChild(createValueCell(key, value)); | 157 row.appendChild(createValueCell(key, value, isMultiLine)); |
| 158 |
| 115 return row; | 159 return row; |
| 116 } | 160 } |
| 117 | 161 |
| 118 /** | 162 /** |
| 119 * Builds the system information table row by row. | 163 * Finalize the page after the content has been loaded. |
| 120 * @param {Element} table The DOM table element to which the newly created rows | |
| 121 * will be appended. | |
| 122 * @param {Object} systemInfo The system information that will be used to fill | |
| 123 * the table. | |
| 124 */ | 164 */ |
| 125 function createTable(table, systemInfo) { | 165 function finishPageLoading() { |
| 126 for (var key in systemInfo) { | 166 $('collapseAllBtn').onclick = collapseAll; |
| 127 var item = systemInfo[key]; | 167 $('expandAllBtn').onclick = expandAll; |
| 128 table.appendChild(createTableRow(item['key'], item['value'])); | 168 |
| 169 $('spinner-container').hidden = true; |
| 170 } |
| 171 |
| 172 /** |
| 173 * Pops a closure from the front of the queue and executes it. |
| 174 */ |
| 175 function processQueue() { |
| 176 var closure = tableCreationClosuresQueue.shift(); |
| 177 if (closure) |
| 178 closure(); |
| 179 |
| 180 if (tableCreationClosuresQueue.length > 0) { |
| 181 // Post a task to process the next item in the queue. |
| 182 setTimeout(processQueue, STANDARD_DELAY_MS); |
| 129 } | 183 } |
| 130 } | 184 } |
| 131 | 185 |
| 132 /** | 186 /** |
| 133 * The callback which will be invoked by the parent window, when the system | 187 * Creates a closure that creates a table row for the given key and value. |
| 134 * information is ready. | 188 * @param {string} key The name of the log. |
| 189 * @param {string} value The contents of the log. |
| 190 * @return {function():void} A closure that creates a row for the given log. |
| 191 */ |
| 192 function createTableRowWrapper(key, value) { |
| 193 return function() { |
| 194 $('detailsTable').appendChild(createTableRow(key, value)); |
| 195 }; |
| 196 } |
| 197 |
| 198 /** |
| 199 * Creates closures to build the system information table row by row |
| 200 * incrementally. |
| 135 * @param {Object} systemInfo The system information that will be used to fill | 201 * @param {Object} systemInfo The system information that will be used to fill |
| 136 * the table. | 202 * the table. |
| 137 */ | 203 */ |
| 138 function onSysInfoReady(systemInfo) { | 204 function createTable(systemInfo) { |
| 139 createTable($('detailsTable'), systemInfo); | 205 for (var key in systemInfo) { |
| 206 var item = systemInfo[key]; |
| 207 tableCreationClosuresQueue.push( |
| 208 createTableRowWrapper(item['key'], item['value'])); |
| 209 } |
| 140 | 210 |
| 141 $('collapseAllBtn').onclick = collapseAll; | 211 tableCreationClosuresQueue.push(finishPageLoading); |
| 142 $('expandAllBtn').onclick = expandAll; | |
| 143 | 212 |
| 144 collapseMultiLineStrings(); | 213 processQueue(); |
| 145 | |
| 146 $('status').textContent = ''; | |
| 147 } | 214 } |
| 148 | 215 |
| 149 /** | 216 /** |
| 150 * Initializes the page when the window is loaded. | 217 * Initializes the page when the window is loaded. |
| 151 */ | 218 */ |
| 152 window.onload = function() { | 219 window.onload = function() { |
| 153 loadTimeData = getLoadTimeData(); | 220 loadTimeData = getLoadTimeData(); |
| 154 i18nTemplate.process(document, loadTimeData); | 221 i18nTemplate.process(document, loadTimeData); |
| 155 getFullSystemInfo(onSysInfoReady); | 222 getFullSystemInfo(createTable); |
| 156 }; | 223 }; |
| OLD | NEW |