// Copyright (c) 2013 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. 'use strict'; /** * @fileoverview Displays an analysis of the selection. */ base.requireStylesheet('tracing.analysis.analysis_view'); base.require('base.guid'); base.require('tracing.analysis.analysis_results'); base.require('tracing.analysis.analyze_selection'); base.require('tracing.analysis.default_object_view'); base.require('tracing.analysis.object_instance_view'); base.require('tracing.analysis.object_snapshot_view'); base.require('tracing.analysis.slice_view'); base.require('tracing.analysis.util'); base.require('ui'); base.exportTo('tracing.analysis', function() { var AnalysisView = ui.define('div'); AnalysisView.prototype = { __proto__: HTMLDivElement.prototype, decorate: function() { this.className = 'analysis-view'; this.currentView_ = undefined; this.currentSelection_ = undefined; this.selections_ = []; this.guid_ = base.GUID.allocate(); window.addEventListener('popstate', this.onPopState.bind(this)); }, changeViewType: function(viewType) { if (this.currentView_ instanceof viewType) return; this.textContent = ''; try { this.currentView_ = new viewType(); this.appendChild(this.currentView_); } catch (e) { this.currentView_ = undefined; throw e; } if (this.currentView_ instanceof tracing.analysis. AnalysisResults) this.classList.remove('viewing-object'); else this.classList.add('viewing-object'); }, get currentView() { return this.currentView_; }, get selection() { return this.currentSelection_; }, set selection(selection) { this.selections_.push(selection); var state = { view_guid: this.guid_, selection_guid: selection.guid }; window.history.pushState(state); this.processSelection(selection); }, clearSelectionHistory: function() { this.selections_ = []; }, onPopState: function(event) { if ((event.state === null) || (event.state.view_guid !== this.guid_)) return; var idx; for (idx = 0; idx < this.selections_.length; ++idx) { if (this.selections_[idx].guid === event.state.selection_guid) break; } if (idx >= this.selections_.length) return; this.processSelection(this.selections_[idx]); event.stopPropagation(); }, processSelection: function(selection) { var hitsByType = selection.getHitsOrganizedByType(); if (selection.length == 1 && hitsByType.counterSamples.length == 0) { if (this.tryToProcessSelectionUsingCustomViewer(selection[0])) return; } this.changeViewType(tracing.analysis.AnalysisResults); this.currentView.clear(); this.currentSelection_ = selection; tracing.analysis.analyzeHitsByType(this.currentView, hitsByType); }, tryToProcessSelectionUsingCustomViewer: function(hit) { var obj; var typeName; var viewBaseType; var defaultViewType; var viewProperty; var obj = hit.modelObject; if (hit instanceof tracing.SelectionObjectSnapshotHit) { typeName = obj.objectInstance.typeName; viewBaseType = tracing.analysis.ObjectSnapshotView; defaultViewType = tracing.analysis.DefaultObjectSnapshotView; } else if (hit instanceof tracing.SelectionObjectInstanceHit) { typeName = obj.typeName; viewBaseType = tracing.analysis.ObjectInstanceView; defaultViewType = tracing.analysis.DefaultObjectInstanceView; } else if (hit instanceof tracing.SelectionSliceHit) { typeName = obj.title; viewBaseType = tracing.analysis.SliceView; defaultViewType = undefined; } else { return false; } var customViewInfo = viewBaseType.getViewInfo(typeName); var viewType = customViewInfo ? customViewInfo.constructor : defaultViewType; // Some view types don't have default viewers. In those cases, we fall // back to the standard analysis sytem. if (!viewType) return false; this.changeViewType(viewType); this.currentView.modelObject = obj; return true; } }; return { AnalysisView: AnalysisView }; });