1 <!DOCTYPE html> 2 <!-- much of this is stolen from omahaproxy.appspot.com/viewer --> 3 <html> 4 <head> 5 <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"> 6 <title>NaCl SDK Manifest Viewer</title> 7 </head> 8 <style type="text/css" media="screen"> 9 body { 10 font-family: monospace; 11 font-size: 10pt; 12 } 13 14 table { 15 border-collapse: collapse; 16 border-color: rgb(100, 100, 100); 17 border-style: solid; 18 border-width: 1px 0px 1px 0px; 19 } 20 21 table td { 22 padding: 3px; 23 border-color: rgb(100, 100, 100); 24 border-style: solid; 25 border-width: 0px 1px 0px 1px; 26 } 27 28 thead { 29 background-color: lightblue; 30 font-weight: bold; 31 border-style: solid; 32 border-color: rgb(100, 100, 100); 33 border-width: 0px 0px 2px 0px; 34 text-align: center; 35 } 36 37 tbody tr:nth-child(odd) { 38 background-color: rgb(230, 230, 230); 39 } 40 41 tbody tr:hover { 42 background-color: orange; 43 } 44 45 td a { 46 padding: 3px; 47 } 48 49 #log > span { 50 display: block; 51 } 52 53 #log > span.highlight { 54 font-weight: bold; 55 } 56 57 #log > span.missing { 58 color: #f00; 59 } 60 </style> 61 <body> 62 <h1>NaCl SDK Manifest Viewer</h1> 63 <table> 64 <thead id="columns"> 65 </thead> 66 <tbody id="rows"> 67 </tbody> 68 </table> 69 <h2>Most recent upload log:</h2> 70 <div id="log"> 71 </div> 72 <script type="application/javascript"> 73 function loadText(url, callback) { 74 var xhr = new XMLHttpRequest(); 75 xhr.open('GET', url, true); 76 xhr.onreadystatechange = function (e) { 77 if (xhr.readyState == 4) { 78 if (xhr.status == 200) { 79 callback(xhr.responseText); 80 } else { 81 console.log("Failed to load "+url+": error " + xhr.status); 82 } 83 } 84 } 85 xhr.send(null); 86 } 87 88 function loadJson(url, callback) { 89 loadText(url, function (text) { 90 callback(JSON.parse(text)); 91 }); 92 } 93 94 function removeAllChildren(elm) { 95 while (elm.childNodes.length) { 96 elm.removeChild(elm.firstChild); 97 } 98 } 99 100 function display(data) { 101 data = data.bundles; 102 103 var columnsElm = document.getElementById('columns'); 104 var rowsElm = document.getElementById('rows'); 105 removeAllChildren(columnsElm); 106 removeAllChildren(rowsElm); 107 108 // Create the column headers. 109 var tr = document.createElement('tr'); 110 var columns = [ 111 'name', 'version', 'revision', 'trunk_revision', 'chrome_version', 'win', 'mac', 'linux', 'all' 112 ]; 113 columns.forEach(function(column) { 114 var td = document.createElement('td'); 115 var text = document.createTextNode(column); 116 td.appendChild(text); 117 tr.appendChild(td); 118 }); 119 columnsElm.appendChild(tr); 120 121 data.forEach(function(row) { 122 var tr = document.createElement('tr'); 123 columns.forEach(function(column) { 124 var td = document.createElement('td'); 125 var node = makeCell(row, column); 126 if (node) { 127 td.appendChild(node); 128 } 129 tr.appendChild(td); 130 }); 131 rowsElm.appendChild(tr); 132 }); 133 } 134 135 function makeCell(row, column) { 136 var platforms = ['win', 'mac', 'linux', 'all']; 137 138 if (platforms.indexOf(column) !== -1) { 139 return makePlatformCell(row, column); 140 } else if (column === 'trunk_revision') { 141 return makeTrunkRevisionCell(row); 142 } else if (column === 'chrome_version') { 143 return makeChromeVersionCell(row); 144 } else { 145 return document.createTextNode(row[column]); 146 } 147 } 148 149 function makePlatformCell(row, column) { 150 var archives = row.archives; 151 for (var k = 0; k < archives.length; ++k) { 152 if (column !== archives[k].host_os) { 153 continue; 154 } 155 156 // Convert the URL to a short name: 157 // https://.../36.0.1974.2/naclsdk_linux.tar.bz2 -> naclsdk_linux 158 var url = archives[k].url; 159 var lastSlash = url.lastIndexOf('/'); 160 var nextDot = url.indexOf('.', lastSlash); 161 var name = url.substr(lastSlash + 1, nextDot - lastSlash - 1); 162 163 var node = document.createElement('a'); 164 node.setAttribute('href', url); 165 node.appendChild(document.createTextNode(name)); 166 return node; 167 } 168 return null; 169 } 170 171 function makeTrunkRevisionCell(row) { 172 var url = row.archives[0].url; 173 var version = versionFromUrl(url); 174 if (version) { 175 var node = document.createTextNode(''); 176 baseTrunkRevisionFromVersion(version, function(node) { 177 return function(revision) { 178 node.textContent = revision; 179 }; 180 }(node)); 181 return node; 182 } 183 return null; 184 } 185 186 function makeChromeVersionCell(row) { 187 var url = row.archives[0].url; 188 var version = versionFromUrl(url); 189 if (version) { 190 return document.createTextNode(version); 191 } 192 return null; 193 } 194 195 function versionFromUrl(url) { 196 // Extract the Chrome version from an archive URL. 197 // It should look something like: 198 // https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/36.0.1974.2/naclsdk_win.tar.bz2 199 var lastSlash = url.lastIndexOf('/'); 200 var penultimateSlash = url.lastIndexOf('/', lastSlash - 1); 201 // The version is between these two slashes. 202 var version = url.substr(penultimateSlash + 1, 203 lastSlash - penultimateSlash - 1); 204 // It is a chrome version if it matches one of these regexes: 205 if (/trunk\.\d+/.test(version)) { 206 // Trunk version. 207 return version; 208 } else if (/\d+\.\d+\.\d+\.\d+/.test(version)) { 209 // Branch version. 210 return version; 211 } else { 212 // Not a version. 213 return null; 214 } 215 } 216 217 function baseTrunkRevisionFromVersion(version, callback) { 218 if (version.indexOf('trunk', 0) === 0) { 219 callback(version.substr(6)); // Skip "trunk." 220 } else { 221 revisionFromVersion(baseTrunkVersionFromVersion(version), callback); 222 } 223 } 224 225 function baseTrunkVersionFromVersion(version) { 226 var lastDot = version.lastIndexOf('.'); 227 return version.substr(0, lastDot) + '.0'; 228 } 229 230 function revisionFromVersion(version, callback) { 231 var url = 'http://omahaproxy.appspot.com/revision.json?version='+version; 232 loadJson(url, function(data) { 233 callback(data.chromium_revision); 234 }); 235 } 236 237 function displayLog(text) { 238 var lines = text.split('\n'); 239 var logEl = document.getElementById('log'); 240 lines.forEach(function (line) { 241 var spanEl = document.createElement('span'); 242 spanEl.textContent = line; 243 if (line.indexOf('>>>', 0) === 0) { 244 spanEl.classList.add('highlight'); 245 } else if (line.indexOf('Missing archives') !== -1) { 246 spanEl.classList.add('missing'); 247 } 248 logEl.appendChild(spanEl); 249 }); 250 } 251 252 loadJson('naclsdk_manifest2.json', display); 253 loadText('naclsdk_manifest2.json.log', displayLog); 254 </script> 255 </body> 256 </html> 257