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>