import base64
from IPython.display import display, Javascript
def open_trace(trace):
"""Executes JavaScript to open a local trace in the Perfetto UI directly in
the browser.
Args:
trace: The trace file object
"""
trace_file_path = trace.trace_file
with open(trace.trace_file, 'rb') as f:
trace_base64 = base64.b64encode(f.read()).decode('utf-8')
js_code = f"""
const trace_base64 = "{trace_base64}";
const trace_title = "{trace_file_path}";
function base64ToArrayBuffer(base64) {{
const binary_string = window.atob(base64);
const len = binary_string.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {{
bytes[i] = binary_string.charCodeAt(i);
}}
return bytes.buffer;
}}
function openPerfettoUI() {{
const perfettoUI = window.open('https://ui.perfetto.dev');
if (!perfettoUI) {{
console.error('Error: Pop-up was blocked. Please allow pop-ups for this page.');
return;
}}
const traceBuffer = base64ToArrayBuffer(trace_base64);
const pingInterval = setInterval(() => {{
try {{
perfettoUI.postMessage('PING', 'https://ui.perfetto.dev');
}} catch (e) {{
console.error("Error sending PING:", e);
clearInterval(pingInterval);
}}
}}, 50);
const messageHandler = (event) => {{
if (event.origin !== 'https://ui.perfetto.dev') {{
return;
}}
if (event.data === 'PONG') {{
clearInterval(pingInterval);
window.removeEventListener('message', messageHandler); // Remove listener after receiving PONG
try {{
perfettoUI.postMessage({{
perfetto: {{
buffer: traceBuffer,
title: trace_title,
fileName: trace_title
}}
}}, 'https://ui.perfetto.dev');
}} catch (e) {{
console.error("Error posting trace data:", e);
}}
}}
}};
window.addEventListener('message', messageHandler);
}}
// Immediately call the function to open the Perfetto UI
openPerfettoUI();
"""
display(Javascript(js_code))