File size: 4,890 Bytes
f3ce0b0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | <!doctype html>
<html lang="en-us">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
<body>
<style>
pre {
border: 1px solid #eee;
margin: 10px 0;
font-family: monospace;
font-size: 10px;
min-height: 100px;
}
body > * {
margin: 20px;
}
#btn_fetch {
font-size: 14px;
}
</style>
<select id="source" size="4">
<option selected>/trace.json</option>
</select>
<br />
<button type="button" id="btn_fetch">Open Perfetto</button>
<br />
<pre id="logs" cols="80" rows="20"></pre>
<script type="text/javascript">
// const ORIGIN = 'http://localhost:8000/perfetto/';
const ORIGIN = "https://ui.perfetto.dev";
const logs = document.getElementById("logs");
const btnFetch = document.getElementById("btn_fetch");
async function getMtime() {
const mtime_resp = await fetch("/mtime");
const mtime = await mtime_resp.text();
return mtime;
}
async function fetchAndOpen(traceUrl) {
logs.innerText += `Fetching trace from ${traceUrl}...\n`;
const mtime = await getMtime();
const resp = await fetch(traceUrl);
// Error checcking is left as an exercise to the reader.
const blob = await resp.blob();
const arrayBuffer = await blob.arrayBuffer();
logs.innerText += `fetch() complete, now passing to ui.perfetto.dev\n`;
openTrace(arrayBuffer, traceUrl, mtime);
}
async function repoll(win, traceUrl, mtime) {
const newMtime = await getMtime();
console.log(newMtime, mtime);
if (newMtime !== mtime) {
logs.innerText += `Trace updated, fetching new version...\n`;
const resp = await fetch(traceUrl);
const blob = await resp.blob();
const arrayBuffer = await blob.arrayBuffer();
logs.innerText += `New trace fetched, opening...\n`;
sendTrace(win, arrayBuffer, traceUrl);
}
setTimeout(() => repoll(win, traceUrl, newMtime), 500);
}
function sendTrace(win, arrayBuffer, traceUrl) {
const reopenUrl = new URL(location.href);
reopenUrl.hash = `#reopen=${traceUrl}`;
logs.innerText += `Sending trace to UI\n`;
win.postMessage(
{
perfetto: {
buffer: arrayBuffer,
title: "trace.json",
url: reopenUrl.toString(),
keepApiOpen: true,
},
},
ORIGIN,
);
}
function openTrace(arrayBuffer, traceUrl, mtime) {
const win = window.open(ORIGIN);
if (!win) {
btnFetch.style.background = "#f3ca63";
btnFetch.onclick = () => openTrace(arrayBuffer);
logs.innerText += `Popups blocked, you need to manually click the button`;
btnFetch.innerText =
"Popups blocked, click here to open the trace file";
return;
}
const timer = setInterval(
() => win.postMessage("PING", ORIGIN),
50,
);
const onMessageHandler = (evt) => {
if (evt.data !== "PONG") return;
// We got a PONG, the UI is ready.
window.clearInterval(timer);
window.removeEventListener("message", onMessageHandler);
sendTrace(win, arrayBuffer, traceUrl);
setTimeout(() => repoll(win, traceUrl, mtime), 500);
};
window.addEventListener("message", onMessageHandler);
}
// This is triggered when following the link from the Perfetto UI's sidebar.
if (location.hash.startsWith("#reopen=")) {
const traceUrl = location.hash.substr(8);
fetchAndOpen(traceUrl);
}
btnFetch.onclick = () =>
fetchAndOpen(document.getElementById("source").value);
</script>
</body>
</html>
|