| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of app; |
| |
| final _allocationProfileRepository = new AllocationProfileRepository(); |
| final _breakpointRepository = new BreakpointRepository(); |
| final _classRepository = new ClassRepository(); |
| final _classSampleProfileRepository = new ClassSampleProfileRepository(); |
| final _contextRepository = new ContextRepository(); |
| final _evalRepository = new EvalRepository(); |
| final _fieldRepository = new FieldRepository(); |
| final _functionRepository = new FunctionRepository(); |
| final _heapSnapshotRepository = new HeapSnapshotRepository(); |
| final _icdataRepository = new ICDataRepository(); |
| final _inboundReferencesRepository = new InboundReferencesRepository(); |
| final _isolateSampleProfileRepository = new IsolateSampleProfileRepository(); |
| final _libraryRepository = new LibraryRepository(); |
| final _megamorphicCacheRepository = new MegamorphicCacheRepository(); |
| final _metricRepository = new MetricRepository(); |
| final _nativeMemorySampleProfileRepository = |
| new NativeMemorySampleProfileRepository(); |
| final _objectPoolRepository = new ObjectPoolRepository(); |
| final _objectRepository = new ObjectRepository(); |
| final _objectstoreRepository = new ObjectStoreRepository(); |
| final _persistentHandlesRepository = new PersistentHandlesRepository(); |
| final _portsRepository = new PortsRepository(); |
| final _scriptRepository = new ScriptRepository(); |
| final _singleTargetCacheRepository = new SingleTargetCacheRepository(); |
| final _stronglyReachangleInstancesRepository = |
| new StronglyReachableInstancesRepository(); |
| final _subtypeTestCacheRepository = new SubtypeTestCacheRepository(); |
| final _timelineRepository = new TimelineRepository(); |
| final _typeArgumentsRepository = new TypeArgumentsRepository(); |
| final _unlinkedCallRepository = new UnlinkedCallRepository(); |
| final _vmrepository = new VMRepository(); |
| |
| class IsolateNotFound implements Exception { |
| String isolateId; |
| IsolateNotFound(this.isolateId); |
| String toString() => "IsolateNotFound: $isolateId"; |
| } |
| |
| RetainedSizeRepository _retainedSizeRepository = new RetainedSizeRepository(); |
| ReachableSizeRepository _reachableSizeRepository = |
| new ReachableSizeRepository(); |
| RetainingPathRepository _retainingPathRepository = |
| new RetainingPathRepository(); |
| |
| /// A [Page] controls the user interface of Observatory. At any given time |
| /// one page will be the current page. Pages are registered at startup. |
| /// When the user navigates within the application, each page is asked if it |
| /// can handle the current location, the first page to say yes, wins. |
| abstract class Page { |
| final ObservatoryApplication app; |
| final Map<String, String> internalArguments = <String, String>{}; |
| HtmlElement element; |
| |
| Page(this.app); |
| |
| /// Called when the page is installed, this callback must initialize |
| /// [element]. |
| void onInstall(); |
| |
| /// Called when the page is uninstalled, this callback must clear |
| /// [element]. |
| void onUninstall() { |
| element = null; |
| } |
| |
| /// Called when the page should update its state based on [uri]. |
| void visit(Uri uri, Map internalArguments) { |
| this.internalArguments.clear(); |
| this.internalArguments.addAll(internalArguments); |
| _visit(uri); |
| } |
| |
| // Overridden by subclasses. |
| void _visit(Uri uri); |
| |
| /// Called to test whether this page can visit [uri]. |
| bool canVisit(Uri uri); |
| } |
| |
| /// A [MatchingPage] matches a single uri path. |
| abstract class MatchingPage extends Page { |
| final String path; |
| MatchingPage(this.path, app) : super(app); |
| |
| void _visit(Uri uri) { |
| assert(uri != null); |
| assert(canVisit(uri)); |
| } |
| |
| Future<Isolate> getIsolate(Uri uri) { |
| var isolateId = uri.queryParameters['isolateId']; |
| return app.vm.getIsolate(isolateId).then((isolate) { |
| if (isolate == null) { |
| throw new IsolateNotFound(isolateId); |
| } |
| return isolate; |
| }); |
| } |
| |
| EditorRepository getEditor(Uri uri) { |
| final editor = uri.queryParameters['editor']; |
| return new EditorRepository(app.vm, editor: editor); |
| return null; |
| } |
| |
| bool canVisit(Uri uri) => uri.path == path; |
| } |
| |
| /// A [SimplePage] matches a single uri path and displays a single element. |
| class SimplePage extends MatchingPage { |
| final String elementTagName; |
| SimplePage(String path, this.elementTagName, app) : super(path, app); |
| |
| void onInstall() { |
| if (element == null) { |
| element = new Element.tag(elementTagName); |
| } |
| } |
| } |
| |
| /// Error page for unrecognized paths. |
| class ErrorPage extends Page { |
| ErrorPage(app) : super(app); |
| |
| void onInstall() { |
| if (element == null) { |
| // Lazily create page. |
| element = |
| new GeneralErrorElement(app.notifications, queue: app.queue).element; |
| } |
| } |
| |
| void _visit(Uri uri) { |
| assert(element != null); |
| assert(canVisit(uri)); |
| |
| (element as GeneralErrorElement).message = "Path '${uri.path}' not found"; |
| } |
| |
| /// Catch all. |
| bool canVisit(Uri uri) => true; |
| } |
| |
| /// Top-level vm info page. |
| class VMPage extends MatchingPage { |
| VMPage(app) : super('vm', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| if (app.vm == null) { |
| Logger.root.severe('VMPage has no VM'); |
| // Reroute to vm-connect. |
| app.locationManager.go(Uris.vmConnect()); |
| return; |
| } |
| app.vm.reload().then((serviceObject) { |
| VM vm = serviceObject; |
| container.children = <Element>[ |
| new VMViewElement( |
| vm, |
| _vmrepository, |
| app.events, |
| app.notifications, |
| new IsolateRepository(app.vm), |
| new IsolateGroupRepository(app.vm), |
| _scriptRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }).catchError((e, stack) { |
| Logger.root.severe('VMPage visit error: $e'); |
| Logger.root.severe('Stack: $stack'); |
| // Reroute to vm-connect. |
| app.locationManager.go(Uris.vmConnect()); |
| }); |
| } |
| } |
| |
| class FlagsPage extends SimplePage { |
| FlagsPage(app) : super('flags', 'flag-list', app); |
| |
| @override |
| onInstall() { |
| element = new FlagListElement( |
| app.vm, app.events, new FlagsRepository(app.vm), app.notifications, |
| queue: app.queue) |
| .element; |
| } |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| } |
| } |
| |
| class NativeMemoryProfilerPage extends SimplePage { |
| NativeMemoryProfilerPage(app) |
| : super('native-memory-profile', 'native-memory-profile', app); |
| @override |
| onInstall() { |
| if (element == null) { |
| element = new NativeMemoryProfileElement(app.vm, app.events, |
| app.notifications, _nativeMemorySampleProfileRepository, |
| queue: app.queue) |
| .element; |
| } |
| assert(element != null); |
| } |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| } |
| } |
| |
| class InspectPage extends MatchingPage { |
| InspectPage(app) : super('inspect', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| var objectId = uri.queryParameters['objectId']; |
| if (objectId == null) { |
| isolate.reload().then(_visitObject); |
| } else { |
| isolate.getObject(objectId).then(_visitObject); |
| } |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| |
| Future _visitObject(obj) async { |
| container.children = <Element>[]; |
| await obj.reload(); |
| if (obj is Class) { |
| container.children = <Element>[ |
| new ClassViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _classRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _fieldRepository, |
| _scriptRepository, |
| _objectRepository, |
| _evalRepository, |
| _stronglyReachangleInstancesRepository, |
| _classSampleProfileRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Code) { |
| await obj.loadScript(); |
| container.children = <Element>[ |
| new CodeViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Context) { |
| container.children = <Element>[ |
| new ContextViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _contextRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is DartError) { |
| container.children = <Element>[ |
| new ErrorViewElement(app.notifications, obj, queue: app.queue).element |
| ]; |
| } else if (obj is Field) { |
| container.children = <Element>[ |
| new FieldViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _fieldRepository, |
| _classRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _scriptRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Instance) { |
| container.children = <Element>[ |
| new InstanceViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _objectRepository, |
| _classRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _scriptRepository, |
| _evalRepository, |
| _typeArgumentsRepository, |
| _breakpointRepository, |
| _functionRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Isolate) { |
| container.children = <Element>[ |
| new IsolateViewElement( |
| app.vm, |
| obj, |
| app.events, |
| app.notifications, |
| new IsolateRepository(app.vm), |
| _scriptRepository, |
| _functionRepository, |
| _libraryRepository, |
| _objectRepository, |
| _evalRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is ServiceFunction) { |
| container.children = <Element>[ |
| new FunctionViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _functionRepository, |
| _classRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _scriptRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is ICData) { |
| container.children = <Element>[ |
| new ICDataViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _icdataRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is SingleTargetCache) { |
| container.children = <Element>[ |
| new SingleTargetCacheViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _singleTargetCacheRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is SubtypeTestCache) { |
| container.children = <Element>[ |
| new SubtypeTestCacheViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _subtypeTestCacheRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is UnlinkedCall) { |
| container.children = <Element>[ |
| new UnlinkedCallViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _unlinkedCallRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Library) { |
| container.children = <Element>[ |
| new LibraryViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _libraryRepository, |
| _fieldRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _scriptRepository, |
| _objectRepository, |
| _evalRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is MegamorphicCache) { |
| container.children = <Element>[ |
| new MegamorphicCacheViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _megamorphicCacheRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is ObjectPool) { |
| container.children = <Element>[ |
| new ObjectPoolViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _objectPoolRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Script) { |
| var pos; |
| if (app.locationManager.internalArguments['pos'] != null) { |
| try { |
| pos = int.parse(app.locationManager.internalArguments['pos']); |
| } catch (_) {} |
| } |
| container.children = <Element>[ |
| new ScriptViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _scriptRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| _objectRepository, |
| pos: pos, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is HeapObject) { |
| container.children = <Element>[ |
| new ObjectViewElement( |
| app.vm, |
| obj.isolate, |
| obj, |
| app.events, |
| app.notifications, |
| _objectRepository, |
| _retainedSizeRepository, |
| _reachableSizeRepository, |
| _inboundReferencesRepository, |
| _retainingPathRepository, |
| queue: app.queue) |
| .element |
| ]; |
| } else if (obj is Sentinel) { |
| container.children = <Element>[ |
| new SentinelViewElement( |
| app.vm, obj.isolate, obj, app.events, app.notifications, |
| queue: app.queue) |
| .element |
| ]; |
| } else { |
| container.children = <Element>[ |
| new JSONViewElement(obj, app.notifications, queue: app.queue).element |
| ]; |
| } |
| } |
| } |
| |
| /// Class tree page. |
| class ClassTreePage extends SimplePage { |
| ClassTreePage(app) : super('class-tree', 'class-tree', app); |
| |
| final DivElement container = new DivElement(); |
| |
| @override |
| void onInstall() { |
| element = container; |
| } |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new ClassTreeElement(app.vm, isolate, app.events, app.notifications, |
| _classRepository) |
| .element |
| ]; |
| }); |
| } |
| } |
| |
| class DebuggerPage extends MatchingPage { |
| DebuggerPage(app) : super('debugger', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) async { |
| container.children = <Element>[ |
| new DebuggerPageElement( |
| isolate, _objectRepository, _scriptRepository, app.events) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| |
| @override |
| void onUninstall() { |
| super.onUninstall(); |
| container.children = const []; |
| } |
| } |
| |
| class ObjectStorePage extends MatchingPage { |
| ObjectStorePage(app) : super('object-store', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) async { |
| container.children = <Element>[ |
| new ObjectStoreViewElement(isolate.vm, isolate, app.events, |
| app.notifications, _objectstoreRepository, _objectRepository) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| } |
| |
| class CpuProfilerPage extends MatchingPage { |
| CpuProfilerPage(app) : super('profiler', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new CpuProfileElement(isolate.vm, isolate, app.events, |
| app.notifications, _isolateSampleProfileRepository) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| } |
| |
| class TableCpuProfilerPage extends MatchingPage { |
| TableCpuProfilerPage(app) : super('profiler-table', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new CpuProfileTableElement(isolate.vm, isolate, app.events, |
| app.notifications, _isolateSampleProfileRepository) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| assert(element != null); |
| } |
| } |
| |
| class AllocationProfilerPage extends MatchingPage { |
| AllocationProfilerPage(app) : super('allocation-profiler', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new AllocationProfileElement(isolate.vm, isolate, app.events, |
| app.notifications, _allocationProfileRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| app.startGCEventListener(); |
| } |
| |
| @override |
| void onUninstall() { |
| super.onUninstall(); |
| app.stopGCEventListener(); |
| container.children = const []; |
| } |
| } |
| |
| class PortsPage extends MatchingPage { |
| PortsPage(app) : super('ports', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new PortsElement(isolate.vm, isolate, app.events, app.notifications, |
| _portsRepository, _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| } |
| |
| class PersistentHandlesPage extends MatchingPage { |
| PersistentHandlesPage(app) : super('persistent-handles', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new PersistentHandlesPageElement( |
| isolate.vm, |
| isolate, |
| app.events, |
| app.notifications, |
| _persistentHandlesRepository, |
| _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| } |
| |
| class HeapMapPage extends MatchingPage { |
| HeapMapPage(app) : super('heap-map', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new HeapMapElement(isolate.vm, isolate, app.events, app.notifications, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| } |
| |
| class HeapSnapshotPage extends MatchingPage { |
| HeapSnapshotPage(app) : super('heap-snapshot', app); |
| |
| final DivElement container = new DivElement(); |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new HeapSnapshotElement(isolate.vm, isolate, app.events, |
| app.notifications, _heapSnapshotRepository, _objectRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| } |
| |
| class LoggingPage extends MatchingPage { |
| LoggingPage(app) : super('logging', app); |
| |
| final DivElement container = new DivElement(); |
| |
| @override |
| void onInstall() { |
| element = container; |
| container.children = const []; |
| app.startLoggingEventListener(); |
| } |
| |
| @override |
| void onUninstall() { |
| super.onUninstall(); |
| container.children = const []; |
| app.stopLoggingEventListener(); |
| } |
| |
| void _visit(Uri uri) { |
| assert(element != null); |
| assert(canVisit(uri)); |
| getIsolate(uri).then((isolate) { |
| container.children = <Element>[ |
| new LoggingPageElement(app.vm, isolate, app.events, app.notifications, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| } |
| |
| class ErrorViewPage extends Page { |
| ErrorViewPage(app) : super(app); |
| |
| void onInstall() { |
| element = new ErrorViewElement( |
| app.notifications, app.lastErrorOrException as DartError, |
| queue: app.queue) |
| .element; |
| } |
| |
| void _visit(Uri uri) { |
| assert(element != null); |
| assert(canVisit(uri)); |
| } |
| |
| // TODO(turnidge): How to test this page? |
| bool canVisit(Uri uri) => uri.path == 'error'; |
| } |
| |
| class VMConnectPage extends Page { |
| VMConnectPage(app) : super(app); |
| |
| void onInstall() { |
| if (element == null) { |
| element = new VMConnectElement(ObservatoryApplication.app.targets, |
| ObservatoryApplication.app.notifications, |
| queue: ObservatoryApplication.app.queue) |
| .element; |
| } |
| assert(element != null); |
| } |
| |
| void _visit(Uri uri) { |
| assert(element != null); |
| assert(canVisit(uri)); |
| } |
| |
| bool canVisit(Uri uri) => uri.path == 'vm-connect'; |
| } |
| |
| class IsolateReconnectPage extends Page { |
| IsolateReconnectPage(app) : super(app); |
| |
| final DivElement container = new DivElement(); |
| |
| void onInstall() { |
| element = container; |
| } |
| |
| void _visit(Uri uri) { |
| app.vm.reload(); |
| container.children = <Element>[ |
| new IsolateReconnectElement( |
| app.vm, |
| app.events, |
| app.notifications, |
| uri.queryParameters['isolateId'], |
| Uri.parse(uri.queryParameters['originalUri'])) |
| .element |
| ]; |
| assert(element != null); |
| assert(canVisit(uri)); |
| } |
| |
| bool canVisit(Uri uri) => uri.path == 'isolate-reconnect'; |
| } |
| |
| class MetricsPage extends MatchingPage { |
| MetricsPage(app) : super('metrics', app); |
| |
| final DivElement container = new DivElement(); |
| |
| Isolate lastIsolate; |
| |
| void _visit(Uri uri) { |
| super._visit(uri); |
| getIsolate(uri).then((isolate) async { |
| lastIsolate = isolate; |
| container.children = const []; |
| await _metricRepository.startSampling(isolate); |
| container.children = <Element>[ |
| new MetricsPageElement(isolate.vm, isolate, app.events, |
| app.notifications, _metricRepository, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| |
| @override |
| void onUninstall() { |
| super.onUninstall(); |
| _metricRepository.stopSampling(lastIsolate); |
| container.children = const []; |
| } |
| } |
| |
| class TimelinePage extends Page { |
| TimelinePage(app) : super(app); |
| |
| void onInstall() { |
| element = new TimelinePageElement( |
| app.vm, _timelineRepository, app.events, app.notifications, |
| queue: app.queue) |
| .element; |
| } |
| |
| void _visit(Uri uri) { |
| assert(canVisit(uri)); |
| } |
| |
| bool canVisit(Uri uri) => uri.path == 'timeline'; |
| } |
| |
| class TimelineDashboardPage extends Page { |
| TimelineDashboardPage(app) : super(app); |
| |
| DivElement container = new DivElement(); |
| |
| void onInstall() { |
| if (element == null) { |
| element = container; |
| } |
| } |
| |
| void _visit(Uri uri) { |
| assert(canVisit(uri)); |
| app.vm.load().then((_) { |
| container.children = <Element>[ |
| new TimelineDashboardElement( |
| app.vm, _timelineRepository, app.notifications, |
| queue: app.queue) |
| .element |
| ]; |
| }); |
| } |
| |
| @override |
| void onUninstall() { |
| super.onUninstall(); |
| container.children = const []; |
| } |
| |
| bool canVisit(Uri uri) => uri.path == 'timeline-dashboard'; |
| } |
| |
| class ProcessSnapshotPage extends Page { |
| ProcessSnapshotPage(app) : super(app); |
| |
| void onInstall() { |
| element = new ProcessSnapshotElement(app.vm, app.events, app.notifications, |
| queue: app.queue) |
| .element; |
| } |
| |
| void _visit(Uri uri) { |
| assert(canVisit(uri)); |
| } |
| |
| bool canVisit(Uri uri) => uri.path == 'process-snapshot'; |
| } |