Show origin prompt

Change-Id: I807713c71abcbe7e74b88919731e12ca2a6dfafa
diff --git a/ui/src/frontend/trace_url_handler.ts b/ui/src/frontend/trace_url_handler.ts
index 54b3fe5..28d3c5c 100644
--- a/ui/src/frontend/trace_url_handler.ts
+++ b/ui/src/frontend/trace_url_handler.ts
@@ -215,6 +215,13 @@
 }
 
 function loadTraceFromUrl(url: string) {
+  if (url.startsWith('data:')) {
+    // Gate behind a trust prompt: window.open(...?url=data:...) would
+    // otherwise silently load attacker-controlled bytes.
+    promptDataUrlTrust(url);
+    return;
+  }
+
   const isLocalhostTraceUrl = ['127.0.0.1', 'localhost'].includes(
     new URL(url).hostname,
   );
@@ -235,6 +242,29 @@
   }
 }
 
+function promptDataUrlTrust(url: string) {
+  const origin = document.referrer ? new URL(document.referrer).origin : 'null';
+  const originTxt = origin === 'null' ? 'An unknown origin' : origin;
+  showModal({
+    title: 'Open trace?',
+    content: m(
+      'div',
+      m('div', `${originTxt} is trying to open an embedded trace.`),
+      m('div', 'Only continue if you trust this URL.'),
+    ),
+    buttons: [
+      {text: 'No', primary: true},
+      {
+        text: 'Yes',
+        primary: false,
+        action: () => {
+          AppImpl.instance.openTraceFromUrl(url);
+        },
+      },
+    ],
+  });
+}
+
 function openTraceFromAndroidBugTool() {
   const msg = 'Loading trace from ABT extension';
   AppImpl.instance.omnibox.showStatusMessage(msg);