| <!DOCTYPE html> |
| <!-- |
| Copyright 2015 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| |
| <script type="text/javascript" src="https://apis.google.com/js/api.js"></script> |
| <link rel="import" href="/components/polymer/polymer.html"> |
| <link rel="import" href="/core/timeline_view.html"> |
| <link rel="import" href="/extras/full_config.html"> |
| <link rel="import" href="/extras/drive/drive_comment_provider.html"> |
| |
| <style> |
| body { |
| margin: 0; |
| padding: 0; |
| width: 100%; |
| height: 100%; |
| display: -webkit-flex; |
| -webkit-flex-direction: column; |
| } |
| body > x-timeline-view { |
| -webkit-flex: 1 1 auto; |
| overflow: hidden; |
| position: absolute; |
| top: 0px; |
| bottom: 0; |
| left: 0; |
| right: 0; |
| } |
| nav { |
| display: flex; |
| flex-direction: row; |
| justify-content: flex-end; |
| } |
| #navbar button { |
| height: 24px; |
| padding-bottom: 3px; |
| vertical-align: middle; |
| box-shadow: none; |
| background-color: #4d90fe; |
| background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed); |
| border: 1px solid #3079ed; |
| color: #fff; |
| border-radius: 2px; |
| cursor: default; |
| font-size: 11px; |
| font-weight: bold; |
| text-align: center; |
| white-space: nowrap; |
| line-height: 27px; |
| min-width: 54px; |
| outline: 0px; |
| padding: 0 8px; |
| font: normal 13px arial,sans-serif; |
| margin: 5px; |
| } |
| #collabs { |
| display: flex; |
| flex-direction: row; |
| } |
| .collaborator-div { |
| display: inline-block; |
| vertical-align: middle; |
| min-height: 0; |
| width: 100px; |
| font-size: 11px; |
| font-weight: bold; |
| font: normal 13px arial,sans-serif; |
| margin: 10px; |
| } |
| .collaborator-img { |
| margin: 2px; |
| } |
| .collaborator-tooltip { |
| z-index: 10000; |
| transition: visibility 0,opacity .13s ease-in; |
| background-color: #2a2a2a; |
| border: 1px solid #fff; |
| color: #fff; |
| cursor: default; |
| display: block; |
| font-family: arial, sans-serif; |
| font-size: 11px; |
| font-weight: bold; |
| margin-left: -1px; |
| opacity: 1; |
| padding: 7px 9px; |
| word-break: break-word; |
| position: absolute; |
| } |
| .collaborator-tooltip-content { |
| color: #fff; |
| } |
| .collaborator-tooltip-arrow { |
| position: absolute; |
| top: -6px; |
| } |
| .collaborator-tooltip-arrow-before { |
| border-color: #fff transparent !important; |
| left: -6px; |
| border: 6px solid; |
| border-top-width: 0; |
| content: ''; |
| display: block; |
| height: 0; |
| position: absolute; |
| width: 0; |
| } |
| .collaborator-tooltip-arrow-after { |
| top: 1px; |
| border-color: #2a2a2a transparent !important; |
| left: -5px; |
| border: 5px solid; |
| border-top-width: 0; |
| content: ''; |
| display: block; |
| height: 0; |
| position: absolute; |
| width: 0; |
| } |
| |
| </style> |
| <title>Trace Viewer</title> |
| </head> |
| <body> |
| <nav id="navbar"> |
| <div id="collabs"></div> |
| <button id="x-drive-save-to-disk">Save to disk</button> |
| <button id="x-drive-save-to-drive">Save to Drive</button> |
| <button id="x-drive-load-from-drive">Load from Drive</button> |
| <button id="x-drive-share">Share</button> |
| </nav> |
| <x-timeline-view> |
| </x-timeline-view> |
| |
| <script> |
| 'use strict'; |
| |
| // Needs to be global as it's passed through the Google API as a |
| // GET parameter. |
| var onAPIClientLoaded_ = null; |
| |
| (function() { |
| |
| tv.exportTo('tv.e.drive', function() { |
| var appId = '239864068844'; |
| var constants = { |
| APP_ID: appId, |
| ANCHOR_NAME: appId + '.trace_viewer', |
| DEVELOPER_KEY: 'AIzaSyDR-6_wL9vHg1_oz4JHk8IQAkv2_Y0Y8-M', |
| CLIENT_ID: '239864068844-c7gefbfdcp0j6grltulh2r88tsvl18c1.apps.' + |
| 'googleusercontent.com', |
| SCOPE: [ |
| 'https://www.googleapis.com/auth/drive', |
| 'https://www.googleapis.com/auth/drive.install', |
| 'https://www.googleapis.com/auth/drive.file', |
| 'profile' |
| ] |
| }; |
| |
| return { |
| getDriveFileId: function() { return driveFileId_; }, |
| constants: constants |
| }; |
| }); |
| |
| |
| var pickerApiLoaded_ = false; |
| var oauthToken_ = null; |
| |
| var timelineViewEl_ = null; |
| var driveDocument_ = null; |
| var shareClient_ = null; |
| var fileIdToLoad_ = null; |
| var driveFileId_ = null; |
| |
| function parseGETParameter(val) { |
| var result = null; |
| var tmp = []; |
| location.search.substr(1).split('&').forEach(function(item) { |
| tmp = item.split('='); |
| if (tmp[0] === val) |
| result = decodeURIComponent(tmp[1]); |
| }); |
| return result; |
| } |
| |
| // Use the Google API Loader script to load the google.picker script. |
| onAPIClientLoaded_ = function() { |
| var driveState = parseGETParameter('state'); |
| if (driveState != null) { |
| var driveStateJson = JSON.parse(driveState); |
| fileIdToLoad_ = String(driveStateJson.ids); |
| } |
| |
| gapi.load('picker', {'callback': onPickerApiLoad}); |
| gapi.load('auth', {'callback': function() { |
| onAuthApiLoad(true, onAuthResultSuccess); |
| setTimeout(function onRepeatAuthApiLoad() { |
| onAuthApiLoad(true, function() {}); |
| setTimeout(onRepeatAuthApiLoad, 30000); |
| }, 30000); |
| }}); |
| } |
| |
| function onAuthApiLoad(tryImmediate, resultCallback) { |
| window.gapi.auth.authorize( |
| {'client_id': tv.e.drive.constants.CLIENT_ID, |
| 'scope': tv.e.drive.constants.SCOPE, 'immediate': tryImmediate}, |
| function(authResult) { |
| handleAuthResult(authResult, tryImmediate, resultCallback); |
| }); |
| } |
| |
| function onPickerApiLoad() { |
| pickerApiLoaded_ = true; |
| if (fileIdToLoad_ == null) |
| createPicker(); |
| } |
| |
| function onAuthResultSuccess() { |
| if (fileIdToLoad_ == null) |
| createPicker(); |
| else |
| loadFileFromDrive(fileIdToLoad_); |
| } |
| |
| function handleAuthResult(authResult, wasImmediate, resultCallback) { |
| if (authResult && !authResult.error) { |
| oauthToken_ = authResult.access_token; |
| resultCallback(); |
| } else if (wasImmediate) { |
| onAuthApiLoad(false); |
| } |
| } |
| |
| function createPicker() { |
| if (pickerApiLoaded_ && oauthToken_) { |
| var view = new google.picker.View(google.picker.ViewId.DOCS); |
| view.setMimeTypes('application/json,application/octet-stream'); |
| var picker = new google.picker.PickerBuilder() |
| .enableFeature(google.picker.Feature.NAV_HIDDEN) |
| .enableFeature(google.picker.Feature.MULTISELECT_ENABLED) |
| .setAppId(tv.e.drive.constants.APP_ID) |
| .setOAuthToken(oauthToken_) |
| .addView(view) |
| .addView(new google.picker.DocsUploadView()) |
| .setDeveloperKey(tv.e.drive.constants.DEVELOPER_KEY) |
| .setCallback(pickerCallback) |
| .build(); |
| picker.setVisible(true); |
| } |
| } |
| |
| function pickerCallback(data) { |
| if (data.action == google.picker.Action.PICKED) { |
| loadFileFromDrive(data.docs[0].id); |
| } |
| } |
| |
| function initShareButton() { |
| shareClient_ = new gapi.drive.share.ShareClient( |
| tv.e.drive.constants.APP_ID); |
| shareClient_.setItemIds([driveFileId_]); |
| } |
| |
| function loadFileFromDrive(fileId) { |
| gapi.client.load('drive', 'v2', function() { |
| var request = gapi.client.drive.files.get({'fileId': fileId}); |
| request.execute(function(resp) { downloadFile(resp); }); |
| driveFileId_ = fileId; |
| gapi.load('drive-share', initShareButton); |
| }); |
| } |
| |
| function downloadFile(file) { |
| if (file.downloadUrl) { |
| var downloadingOverlay = tv.b.ui.Overlay(); |
| downloadingOverlay.title = 'Downloading...'; |
| downloadingOverlay.userCanClose = false; |
| downloadingOverlay.msgEl = document.createElement('div'); |
| downloadingOverlay.appendChild(downloadingOverlay.msgEl); |
| downloadingOverlay.msgEl.style.margin = '20px'; |
| downloadingOverlay.update = function(msg) { |
| this.msgEl.textContent = msg; |
| } |
| downloadingOverlay.visible = true; |
| |
| var accessToken = gapi.auth.getToken().access_token; |
| var xhr = new XMLHttpRequest(); |
| xhr.open('GET', file.downloadUrl); |
| xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); |
| xhr.onload = function() { |
| downloadingOverlay.visible = false; |
| onDownloaded(file.title, xhr.responseText); |
| }; |
| xhr.onprogress = function(evt) { |
| downloadingOverlay.update( |
| Math.floor(evt.position * 100 / file.fileSize) + '% complete'); |
| }; |
| xhr.onerror = function() { alert('Failed downloading!'); }; |
| xhr.send(); |
| } else { |
| alert('No URL!'); |
| } |
| } |
| |
| function displayAllCollaborators() { |
| var allCollaborators = driveDocument_.getCollaborators(); |
| var collaboratorCount = allCollaborators.length; |
| var collabspan = document.getElementById('collabs'); |
| collabspan.innerHTML = ''; |
| var imageList = []; |
| for (var i = 0; i < collaboratorCount; i++) { |
| var user = allCollaborators[i]; |
| |
| var img = document.createElement('img'); |
| img.src = user.photoUrl; |
| img.alt = user.displayName; |
| img.height = 30; |
| img.width = 30; |
| img.className = 'collaborator-img'; |
| collabspan.appendChild(img); |
| imageList.push({'image': img, 'name': user.displayName}); |
| } |
| for (i = 0; i < imageList.length; i++) { |
| var collabTooltip = tv.b.ui.createDiv({ |
| className: 'collaborator-tooltip' |
| }); |
| var collabTooltipContent = tv.b.ui.createDiv({ |
| className: 'collaborator-tooltip-content' |
| }); |
| collabTooltipContent.textContent = imageList[i].name; |
| collabTooltip.appendChild(collabTooltipContent); |
| collabspan.appendChild(collabTooltip); |
| var collabTooltipArrow = tv.b.ui.createDiv({ |
| className: 'collaborator-tooltip-arrow'}); |
| collabTooltip.appendChild(collabTooltipArrow); |
| var collabTooltipArrowBefore = tv.b.ui.createDiv({ |
| className: 'collaborator-tooltip-arrow-before'}); |
| collabTooltipArrow.appendChild(collabTooltipArrowBefore); |
| var collabTooltipArrowAfter = tv.b.ui.createDiv({ |
| className: 'collaborator-tooltip-arrow-after'}); |
| collabTooltipArrow.appendChild(collabTooltipArrowAfter); |
| |
| var rect = imageList[i].image.getBoundingClientRect(); |
| collabTooltip.style.top = (rect.bottom - 6) + 'px'; |
| collabTooltip.style.left = |
| (rect.left + 16 - (collabTooltip.offsetWidth / 2)) + 'px'; |
| collabTooltipArrow.style.left = (collabTooltip.offsetWidth / 2) + 'px'; |
| collabTooltip.style.visibility = 'hidden'; |
| function visibilityDelegate(element, visibility) { |
| return function() { |
| element.style.visibility = visibility; |
| } |
| } |
| imageList[i].image.addEventListener( |
| 'mouseover', visibilityDelegate(collabTooltip, 'visible')); |
| imageList[i].image.addEventListener( |
| 'mouseout', visibilityDelegate(collabTooltip, 'hidden')); |
| } |
| } |
| |
| function onRealtimeFileLoaded(doc) { |
| if (driveDocument_) |
| driveDocument_.close(); |
| driveDocument_ = doc; |
| doc.addEventListener(gapi.drive.realtime.EventType.COLLABORATOR_JOINED, |
| displayAllCollaborators); |
| doc.addEventListener(gapi.drive.realtime.EventType.COLLABORATOR_LEFT, |
| displayAllCollaborators); |
| |
| displayAllCollaborators(doc); |
| } |
| |
| function onRealtimeError(e) { |
| alert('Error loading realtime: ' + e); |
| } |
| |
| function onDownloaded(filename, content) { |
| gapi.load('auth:client,drive-realtime,drive-share', function() { |
| gapi.drive.realtime.load(driveFileId_, |
| onRealtimeFileLoaded, |
| null, |
| onRealtimeError); |
| |
| }); |
| |
| var traces = []; |
| var filenames = []; |
| filenames.push(filename); |
| traces.push(content); |
| createViewFromTraces(filenames, traces); |
| } |
| |
| function createViewFromTraces(filenames, traces) { |
| var m = new tv.c.TraceModel(); |
| var p = m.importTracesWithProgressDialog(traces, true); |
| p.then( |
| function() { |
| timelineViewEl_.model = m; |
| timelineViewEl_.updateDocumentFavicon(); |
| timelineViewEl_.tabIndex = 1; |
| if (timelineViewEl_.timeline) |
| timelineViewEl_.timeline.focusElement = timelineViewEl_; |
| timelineViewEl_.viewTitle = ''; |
| }, |
| function(err) { |
| var downloadingOverlay = new tv.b.ui.Overlay(); |
| downloadingOverlay.textContent = |
| tv.b.normalizeException(err).message; |
| downloadingOverlay.title = 'Import error'; |
| downloadingOverlay.visible = true; |
| }); |
| } |
| |
| function onSaveToDiskClicked() { |
| throw new Error('Not implemented'); |
| } |
| |
| function onSaveToDriveClicked() { |
| throw new Error('Not implemented'); |
| } |
| |
| function onLoadFromDriveClicked() { |
| createPicker(); |
| } |
| |
| function onLoad() { |
| timelineViewEl_ = document.querySelector('x-timeline-view'); |
| var navbar = document.getElementById('navbar'); |
| timelineViewEl_.style.top = navbar.offsetHeight + 'px'; |
| tv.b.ui.decorate(timelineViewEl_, tv.c.TimelineView); |
| } |
| |
| window.addEventListener('load', onLoad); |
| |
| document.getElementById('x-drive-save-to-disk').onclick = |
| onSaveToDiskClicked; |
| document.getElementById('x-drive-save-to-drive').onclick = |
| onSaveToDriveClicked; |
| document.getElementById('x-drive-load-from-drive').onclick = |
| onLoadFromDriveClicked; |
| document.getElementById('x-drive-share').onclick = function() { |
| shareClient_.showSettingsDialog(); |
| }; |
| |
| }()); |
| |
| </script> |
| <script type="text/javascript" |
| src="https://apis.google.com/js/client.js?onload=onAPIClientLoaded_"> |
| </script> |
| </body> |