1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {assertTrue} from '../base/logging'; 16import {globals} from './globals'; 17 18export function isLegacyTrace(fileName: string): boolean { 19 fileName = fileName.toLowerCase(); 20 return ( 21 fileName.endsWith('.json') || fileName.endsWith('.json.gz') || 22 fileName.endsWith('.zip') || fileName.endsWith('.ctrace')); 23} 24 25export function openFileWithLegacyTraceViewer(file: File) { 26 const reader = new FileReader(); 27 reader.onload = () => { 28 if (reader.result instanceof ArrayBuffer) { 29 return openBufferWithLegacyTraceViewer( 30 file.name, reader.result, reader.result.byteLength); 31 } else { 32 const str = reader.result as string; 33 return openBufferWithLegacyTraceViewer(file.name, str, str.length); 34 } 35 }; 36 reader.onerror = err => { 37 console.error(err); 38 }; 39 if (file.name.endsWith('.gz') || file.name.endsWith('.zip')) { 40 reader.readAsArrayBuffer(file); 41 } else { 42 reader.readAsText(file); 43 } 44} 45 46export function openBufferWithLegacyTraceViewer( 47 name: string, data: ArrayBuffer|string, size: number) { 48 if (data instanceof ArrayBuffer) { 49 assertTrue(size <= data.byteLength); 50 if (size !== data.byteLength) { 51 data = data.slice(0, size); 52 } 53 } 54 document.body.style.transition = 55 'filter 1s ease, transform 1s cubic-bezier(0.985, 0.005, 1.000, 0.225)'; 56 document.body.style.filter = 'grayscale(1) blur(10px) opacity(0)'; 57 document.body.style.transform = 'scale(0)'; 58 const transitionPromise = new Promise(resolve => { 59 document.body.addEventListener('transitionend', (e: TransitionEvent) => { 60 if (e.propertyName === 'transform') { 61 resolve(); 62 } 63 }); 64 }); 65 66 const loadPromise = new Promise(resolve => { 67 fetch('/assets/catapult_trace_viewer.html').then(resp => { 68 resp.text().then(content => { 69 resolve(content); 70 }); 71 }); 72 }); 73 74 Promise.all([loadPromise, transitionPromise]).then(args => { 75 const fetchResult = args[0] as string; 76 replaceWindowWithTraceViewer(name, data, fetchResult); 77 }); 78} 79 80// Replaces the contents of the current window with the Catapult's legacy 81// trace viewer HTML, passed in |htmlContent|. 82// This is in its own function to avoid leaking variables from the current 83// document we are about to destroy. 84function replaceWindowWithTraceViewer( 85 name: string, data: ArrayBuffer|string, htmlContent: string) { 86 globals.shutdown(); 87 const newWin = window.open('', '_self') as Window; 88 newWin.document.open('text/html', 'replace'); 89 newWin.document.addEventListener('readystatechange', () => { 90 const doc = newWin.document; 91 if (doc.readyState !== 'complete') return; 92 const ctl = doc.querySelector('x-profiling-view') as TraceViewerAPI; 93 ctl.setActiveTrace(name, data); 94 }); 95 newWin.document.write(htmlContent); 96 newWin.document.close(); 97} 98 99// TraceViewer method that we wire up to trigger the file load. 100interface TraceViewerAPI extends Element { 101 setActiveTrace(name: string, data: ArrayBuffer|string): void; 102} 103