| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of app; | |
| 6 | |
| 7 /// The observatory application. Instances of this are created and owned | |
| 8 /// by the observatory_application custom element. | |
| 9 class ObservatoryApplication extends Observable { | |
| 10 static ObservatoryApplication app; | |
| 11 final _pageRegistry = new List<Page>(); | |
| 12 @observable Page currentPage; | |
| 13 @observable final LocationManager locationManager; | |
| 14 VM _vm; | |
| 15 VM get vm => _vm; | |
| 16 set vm(VM vm) { | |
| 17 if (_vm == vm) { | |
| 18 // Do nothing. | |
| 19 return; | |
| 20 } | |
| 21 if (_vm != null) { | |
| 22 // Disconnect from current VM. | |
| 23 notifications.clear(); | |
| 24 _vm.disconnect(); | |
| 25 } | |
| 26 if (vm != null) { | |
| 27 Logger.root.info('Registering new VM callbacks'); | |
| 28 vm.onConnect.then(_vmConnected); | |
| 29 vm.onDisconnect.then(_vmDisconnected); | |
| 30 vm.errors.stream.listen(_onError); | |
| 31 vm.events.stream.listen(_onEvent); | |
| 32 vm.exceptions.stream.listen(_onException); | |
| 33 } | |
| 34 _vm = vm; | |
| 35 } | |
| 36 final TargetManager targets; | |
| 37 @reflectable final ObservatoryApplicationElement rootElement; | |
| 38 | |
| 39 TraceViewElement _traceView = null; | |
| 40 | |
| 41 @reflectable ServiceObject lastErrorOrException; | |
| 42 @observable ObservableList<ServiceEvent> notifications = | |
| 43 new ObservableList<ServiceEvent>(); | |
| 44 | |
| 45 void _initOnce(bool chromium) { | |
| 46 assert(app == null); | |
| 47 app = this; | |
| 48 _registerPages(); | |
| 49 locationManager._init(this); | |
| 50 } | |
| 51 | |
| 52 void removePauseEvents(Isolate isolate) { | |
| 53 bool isPauseEvent(var event) { | |
| 54 return (event.eventType == 'IsolateInterrupted' || | |
| 55 event.eventType == 'BreakpointReached' || | |
| 56 event.eventType == 'ExceptionThrown'); | |
| 57 } | |
| 58 | |
| 59 notifications.removeWhere((oldEvent) { | |
| 60 return (oldEvent.isolate == isolate && | |
| 61 isPauseEvent(oldEvent)); | |
| 62 }); | |
| 63 } | |
| 64 | |
| 65 void _onEvent(ServiceEvent event) { | |
| 66 switch(event.eventType) { | |
| 67 case 'IsolateCreated': | |
| 68 // vm.reload(); | |
| 69 break; | |
| 70 | |
| 71 case 'IsolateShutdown': | |
| 72 // TODO(turnidge): Should we show the user isolate shutdown events? | |
| 73 // What if there are hundreds of them? Coalesce multiple | |
| 74 // shutdown events into one notification? | |
| 75 removePauseEvents(event.isolate); | |
| 76 // vm.reload(); | |
| 77 break; | |
| 78 | |
| 79 case 'BreakpointResolved': | |
| 80 event.isolate.reloadBreakpoints(); | |
| 81 break; | |
| 82 | |
| 83 case 'BreakpointReached': | |
| 84 case 'IsolateInterrupted': | |
| 85 case 'ExceptionThrown': | |
| 86 removePauseEvents(event.isolate); | |
| 87 notifications.add(event); | |
| 88 break; | |
| 89 | |
| 90 | |
| 91 case 'GC': | |
| 92 // Ignore GC events for now. | |
| 93 break; | |
| 94 | |
| 95 default: | |
| 96 // Ignore unrecognized events. | |
| 97 Logger.root.severe('Unrecognized event: $event'); | |
| 98 break; | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 void _registerPages() { | |
| 103 _pageRegistry.add(new ClassTreePage(this)); | |
| 104 _pageRegistry.add(new DebuggerPage(this)); | |
| 105 _pageRegistry.add(new VMConnectPage(this)); | |
| 106 _pageRegistry.add(new ErrorViewPage(this)); | |
| 107 _pageRegistry.add(new MetricsPage(this)); | |
| 108 // Note that ServiceObjectPage must be the last entry in the list as it is | |
| 109 // the catch all. | |
| 110 _pageRegistry.add(new ServiceObjectPage(this)); | |
| 111 } | |
| 112 | |
| 113 void _onError(ServiceError error) { | |
| 114 lastErrorOrException = error; | |
| 115 _visit('error/', null); | |
| 116 } | |
| 117 | |
| 118 void _onException(ServiceException exception) { | |
| 119 lastErrorOrException = exception; | |
| 120 if (exception.kind == 'NetworkException') { | |
| 121 // Got a network exception, visit the vm-connect page. | |
| 122 this.vm = null; | |
| 123 locationManager.go(locationManager.makeLink('/vm-connect/')); | |
| 124 } else { | |
| 125 _visit('error/', null); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 void _visit(String url, String args) { | |
| 130 var argsMap; | |
| 131 if (args == null) { | |
| 132 argsMap = {}; | |
| 133 } else { | |
| 134 argsMap = Uri.splitQueryString(args); | |
| 135 } | |
| 136 if (argsMap['trace'] != null) { | |
| 137 var traceArg = argsMap['trace']; | |
| 138 if (traceArg == 'on') { | |
| 139 Tracer.start(); | |
| 140 } else if (traceArg == 'off') { | |
| 141 Tracer.stop(); | |
| 142 } | |
| 143 } | |
| 144 if (Tracer.current != null) { | |
| 145 Tracer.current.reset(); | |
| 146 } | |
| 147 if (_traceView != null) { | |
| 148 _traceView.tracer = Tracer.current; | |
| 149 } | |
| 150 for (var i = 0; i < _pageRegistry.length; i++) { | |
| 151 var page = _pageRegistry[i]; | |
| 152 if (page.canVisit(url)) { | |
| 153 _installPage(page); | |
| 154 page.visit(url, argsMap); | |
| 155 return; | |
| 156 } | |
| 157 } | |
| 158 throw new FallThroughError(); | |
| 159 } | |
| 160 | |
| 161 /// Set the Observatory application page. | |
| 162 void _installPage(Page page) { | |
| 163 assert(page != null); | |
| 164 if (currentPage == page) { | |
| 165 // Already isntalled. | |
| 166 return; | |
| 167 } | |
| 168 if (currentPage != null) { | |
| 169 Logger.root.info('Uninstalling page: $currentPage'); | |
| 170 currentPage.onUninstall(); | |
| 171 // Clear children. | |
| 172 rootElement.children.clear(); | |
| 173 } | |
| 174 Logger.root.info('Installing page: $page'); | |
| 175 try { | |
| 176 page.onInstall(); | |
| 177 } catch (e) { | |
| 178 Logger.root.severe('Failed to install page: $e'); | |
| 179 } | |
| 180 // Add new page. | |
| 181 rootElement.children.add(page.element); | |
| 182 | |
| 183 // Add tracing support. | |
| 184 _traceView = new Element.tag('trace-view'); | |
| 185 _traceView.tracer = Tracer.current; | |
| 186 rootElement.children.add(_traceView); | |
| 187 | |
| 188 // Remember page. | |
| 189 currentPage = page; | |
| 190 } | |
| 191 | |
| 192 ObservatoryApplication.devtools(this.rootElement) : | |
| 193 locationManager = new HashLocationManager(), | |
| 194 targets = null { | |
| 195 vm = new PostMessageVM(); | |
| 196 _initOnce(true); | |
| 197 } | |
| 198 | |
| 199 ObservatoryApplication(this.rootElement) : | |
| 200 locationManager = new HashLocationManager(), | |
| 201 targets = new TargetManager() { | |
| 202 vm = new WebSocketVM(targets.defaultTarget); | |
| 203 _initOnce(false); | |
| 204 } | |
| 205 | |
| 206 void _removeDisconnectEvents() { | |
| 207 notifications.removeWhere((oldEvent) { | |
| 208 return (oldEvent.eventType == 'VMDisconnected'); | |
| 209 }); | |
| 210 } | |
| 211 | |
| 212 _vmConnected(VM vm) { | |
| 213 if (vm is WebSocketVM) { | |
| 214 targets.add(vm.target); | |
| 215 } | |
| 216 _removeDisconnectEvents(); | |
| 217 } | |
| 218 | |
| 219 _vmDisconnected(VM vm) { | |
| 220 if (this.vm != vm) { | |
| 221 // This disconnect event occured *after* a new VM was installed. | |
| 222 return; | |
| 223 } | |
| 224 this.vm = null; | |
| 225 notifications.add(new ServiceEvent.vmDisconencted()); | |
| 226 } | |
| 227 } | |
| OLD | NEW |