1<!doctype html> 2<html lang="en-us"> 3<head> 4 <meta charset="utf-8"> 5 <title>Perfetto UI</title> 6 <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" /> 7 <link rel="shortcut icon" id="favicon" type="image/png" href="data:image/png;base64,iVBORw0KGgo="> 8</head> 9<body data-perfetto_version='{"filled_by_build_js":"."}'> 10 <!-- 11 Don't add any content here. The whole <body> is replaced by 12 frontend/index.ts when bootstrapping. This is only used for very early 13 error reporting. 14 --> 15 <style> 16 #app_load_failure {opacity:0;transition:opacity 1s ease;position:absolute;overflow:auto;background:#080082;top:0;left:0;width:100%;height:100%;bottom:0;right:0;margin:0;opacity:0;user-select:text} 17 #app_load_failure > pre {color:#fff;position:absolute;margin:auto;white-space:pre-wrap;top:10vh;max-width:90vw;width:880px;left:0;right:0;font-size:16px;line-height:30px;font-weight:700} 18 #app_load_failure > pre span {background:#fff;color:#080082;padding:2px} 19 #app_load_failure_dbg { overflow-wrap: break-word; font-size: 12px; line-height: 1; font-weight: initial;} 20 #app_load_failure a {color:#fff} 21 #app_load { position: absolute; top: 0; left: 0; right:0; bottom: 0; background-color: #2c3e50;} 22 #app_load_spinner { margin: 30vh auto; width: 150px; height: 150px; border: 3px solid rgba(255,255,255,.3); border-radius: 50%; border-top-color: #fff; animation: app_load_spin 1s ease-in-out infinite; } 23 @keyframes app_load_spin { to { transform: rotate(360deg); } } 24 </style> 25 <div id="app_load"><div id="app_load_spinner"></div></div> 26 <div id="app_load_failure"> 27<pre> 28<span>Perfetto UI - An unrecoverable problem occurred</span> 29 30If you are seeing this message, something went wrong while loading the UI. 31In most cases this is due to very slow or flaky network and it goes away by 32disabling and re-enabling WiFi or trying reloading. 33 34If the problem persists try these remediation steps: 35 36* Force-reload the page with Ctrl+Shift+R (Mac: Meta+Shift+R) or 37 Shift + click on the refresh button. 38 39* <a href="javascript:clearAllCaches();">Clear all the site storage and caches</a> and reload the page. 40 41* Clear the site data and caches from devtools, following <a target="_blank" href="https://developers.google.com/web/tools/chrome-devtools/storage/cache#deletecache">these instructions</a>. 42 43If none of this works, file a bug attaching logs and screenshots from devtools. 44 Googlers: <a href="http://go/perfetto-ui-bug" target="_blank">go/perfetto-ui-bug</a> 45 Non-googlers: <a href="https://github.com/google/perfetto/issues/new" target="_blank">github.com/google/perfetto/issues/new</a> 46 47<div id=app_load_failure_err></div> 48Technical Information: 49<div id=app_load_failure_dbg></div> 50</pre> 51 </div> 52 <script type="text/javascript"> 53 'use strict'; 54 (function () { 55 const TIMEOUT_MS = 120000; 56 let errTimerId = undefined; 57 58 function errHandler(err) { 59 // Note: we deliberately don't clearTimeout(), which means that this 60 // handler is called also in the happy case when the UI loads. In that 61 // case, though, the onCssLoaded() in frontend/index.ts will empty the 62 // <body>, so |div| below will be null and this function becomes a 63 // no-op. 64 const div = document.getElementById('app_load_failure'); 65 if (!div) return; 66 div.style.opacity ='1'; 67 const errDom = document.getElementById('app_load_failure_err'); 68 if (!errDom) return; 69 console.error(err); 70 errDom.innerText += `${err}\n`; 71 const storageJson = JSON.stringify(window.localStorage); 72 const dbg = document.getElementById('app_load_failure_dbg'); 73 if (!dbg) return; 74 dbg.innerText = `LocalStorage: ${storageJson}\n`; 75 if (errTimerId !== undefined) clearTimeout(errTimerId); 76 } 77 78 // For the 'Click here to clear all caches'. 79 window.clearAllCaches = async () => { 80 if (window.localStorage) window.localStorage.clear(); 81 if (window.sessionStorage) window.sessionStorage.clear(); 82 const promises = []; 83 if (window.caches) { 84 try { 85 const keys = await window.caches.keys(); 86 keys.forEach(k => promises.push(window.caches.delete(k))); 87 } catch (_) { 88 // TODO(288483453) 89 } 90 } 91 if (navigator.serviceWorker) { 92 const regs = await navigator.serviceWorker.getRegistrations(); 93 regs.forEach(reg => promises.push(reg.unregister())); 94 } 95 try { 96 await Promise.all(promises); 97 } catch (_) { 98 // TODO(288483453) 99 } 100 window.location.reload(); 101 } 102 103 // If the frontend doesn't come up, make the error page above visible. 104 errTimerId = setTimeout(() => errHandler('Timed out'), TIMEOUT_MS); 105 window.onerror = errHandler; 106 window.onunhandledrejection = errHandler; 107 108 const versionStr = document.body.dataset['perfetto_version'] || '{}'; 109 const versionMap = JSON.parse(versionStr); 110 const channel = localStorage.getItem('perfettoUiChannel') || 'stable'; 111 112 // The '.' below is a fallback for the case of opening a pinned version 113 // (e.g., ui.perfetto.dev/v1.2.3./). In that case, the index.html has no 114 // valid version map; we want to load the frontend from the same 115 // sub-directory directory, hence ./frontend_bundle.js. 116 const version = versionMap[channel] || versionMap['stable'] || '.'; 117 118 const script = document.createElement('script'); 119 script.async = true; 120 script.src = version + '/frontend_bundle.js'; 121 script.onerror = () => errHandler(`Failed to load ${script.src}`); 122 123 document.head.append(script); 124 })(); 125 </script> 126</body> 127</html> 128