OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of app; | 5 part of app; |
6 | 6 |
7 /// The observatory application. Instances of this are created and owned | 7 /// The observatory application. Instances of this are created and owned |
8 /// by the observatory_application custom element. | 8 /// by the observatory_application custom element. |
9 class ObservatoryApplication { | 9 class ObservatoryApplication { |
10 static ObservatoryApplication app; | 10 static ObservatoryApplication app; |
11 final RenderingQueue queue = new RenderingQueue(); | 11 final RenderingQueue queue = new RenderingQueue(); |
12 final TargetRepository targets = new TargetRepository(); | 12 final TargetRepository targets = new TargetRepository(); |
13 final EventRepository events = new EventRepository(); | 13 final EventRepository events = new EventRepository(); |
14 final NotificationRepository notifications = new NotificationRepository(); | 14 final NotificationRepository notifications = new NotificationRepository(); |
15 final _pageRegistry = new List<Page>(); | 15 final _pageRegistry = new List<Page>(); |
16 LocationManager _locationManager; | 16 LocationManager _locationManager; |
17 LocationManager get locationManager => _locationManager; | 17 LocationManager get locationManager => _locationManager; |
18 Page currentPage; | 18 Page currentPage; |
| 19 bool _vmConnected = false; |
19 VM _vm; | 20 VM _vm; |
20 VM get vm => _vm; | 21 VM get vm => _vm; |
21 | 22 |
22 _setVM(VM vm) { | 23 bool isConnectedVMTarget(WebSocketVMTarget target) { |
23 if (_vm == vm) { | 24 if (_vm is CommonWebSocketVM) { |
| 25 if ((_vm as CommonWebSocketVM).target == target) { |
| 26 return _vm.isConnected; |
| 27 } |
| 28 } |
| 29 return false; |
| 30 } |
| 31 |
| 32 _switchVM(VM newVM) { |
| 33 final VM oldVM = _vm; |
| 34 |
| 35 Logger.root.info('_switchVM from:${oldVM} to:${newVM}'); |
| 36 |
| 37 if (oldVM == newVM) { |
24 // Do nothing. | 38 // Do nothing. |
25 return; | 39 return; |
26 } | 40 } |
27 if (_vm != null) { | 41 |
28 _gcSubscription = null; | 42 if (oldVM != null) { |
| 43 print('disconnecting from the old VM ${oldVM}--'); |
29 // Disconnect from current VM. | 44 // Disconnect from current VM. |
| 45 stopGCEventListener(); |
30 notifications.deleteAll(); | 46 notifications.deleteAll(); |
31 _vm.disconnect(); | 47 oldVM.disconnect(); |
32 } | 48 } |
33 if (vm != null) { | |
34 Logger.root.info('Registering new VM callbacks'); | |
35 | 49 |
36 vm.onConnect.then((_) { | 50 if (newVM != null) { |
| 51 // Mark that we haven't connected yet. |
| 52 _vmConnected = false; |
| 53 // On connect: |
| 54 newVM.onConnect.then((_) { |
| 55 // We connected. |
| 56 _vmConnected = true; |
37 notifications.deleteDisconnectEvents(); | 57 notifications.deleteDisconnectEvents(); |
38 }); | 58 }); |
39 | 59 // On disconnect: |
40 vm.onDisconnect.then((String reason) { | 60 newVM.onDisconnect.then((String reason) { |
41 if (this.vm != vm) { | 61 if (this.vm != newVM) { |
42 // This disconnect event occured *after* a new VM was installed. | 62 // This disconnect event occured *after* a new VM was installed. |
43 return; | 63 return; |
44 } | 64 } |
45 events.add(new ConnectionClosedEvent(new DateTime.now(), reason)); | 65 // Let anyone looking at the targets know that we have disconnected |
| 66 // from one. |
| 67 targets.emitDisconnectEvent(); |
| 68 if (!_vmConnected) { |
| 69 // Connection error. Navigate back to the connect page. |
| 70 Logger.root.info('Connection failed, navigating to VM connect page.'); |
| 71 // Clear the vm. |
| 72 _vm = null; |
| 73 app.locationManager.go(Uris.vmConnect()); |
| 74 } else { |
| 75 // Disconnect. Stay at the current page and push an a connection |
| 76 // closed event. |
| 77 Logger.root.info('Lost an existing connection to a VM'); |
| 78 events.add(new ConnectionClosedEvent(new DateTime.now(), reason)); |
| 79 } |
46 }); | 80 }); |
| 81 // TODO(cbernaschina) smart connection of streams in the events object. |
| 82 newVM.listenEventStream(VM.kVMStream, _onEvent); |
| 83 newVM.listenEventStream(VM.kIsolateStream, _onEvent); |
| 84 newVM.listenEventStream(VM.kDebugStream, _onEvent); |
| 85 } |
47 | 86 |
48 // TODO(cbernaschina) smart connection of streams in the events object. | 87 _vm = newVM; |
49 vm.listenEventStream(VM.kVMStream, _onEvent); | |
50 vm.listenEventStream(VM.kIsolateStream, _onEvent); | |
51 vm.listenEventStream(VM.kDebugStream, _onEvent); | |
52 } | |
53 _vm = vm; | |
54 } | 88 } |
55 | 89 |
56 StreamSubscription _gcSubscription; | 90 StreamSubscription _gcSubscription; |
57 StreamSubscription _loggingSubscription; | 91 StreamSubscription _loggingSubscription; |
58 | 92 |
59 Future startGCEventListener() async { | 93 Future startGCEventListener() async { |
60 if (_gcSubscription != null || _vm == null) { | 94 if (_gcSubscription != null || _vm == null) { |
61 return; | 95 return; |
62 } | 96 } |
63 _gcSubscription = await _vm.listenEventStream(VM.kGCStream, _onEvent); | 97 _gcSubscription = await _vm.listenEventStream(VM.kGCStream, _onEvent); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 } | 219 } |
186 // Add new page. | 220 // Add new page. |
187 rootElement.children.add(page.element); | 221 rootElement.children.add(page.element); |
188 | 222 |
189 // Remember page. | 223 // Remember page. |
190 currentPage = page; | 224 currentPage = page; |
191 } | 225 } |
192 | 226 |
193 ObservatoryApplication(this.rootElement) { | 227 ObservatoryApplication(this.rootElement) { |
194 _locationManager = new LocationManager(this); | 228 _locationManager = new LocationManager(this); |
195 targets.onChange.listen((e) { | 229 targets.onChange.listen((TargetChangeEvent e) { |
196 if (targets.current == null) return _setVM(null); | 230 if (e.disconnected) { |
197 if ((_vm as WebSocketVM)?.target != targets.current) { | 231 // We don't care about disconnected events. |
198 _setVM(new WebSocketVM(targets.current)); | 232 return; |
| 233 } |
| 234 if (targets.current == null) { |
| 235 _switchVM(null); |
| 236 } |
| 237 final bool currentTarget = |
| 238 (_vm as WebSocketVM)?.target == targets.current; |
| 239 final bool currentTargetConnected = (_vm != null) && !_vm.isDisconnected; |
| 240 if (!currentTarget || !currentTargetConnected) { |
| 241 _switchVM(new WebSocketVM(targets.current)); |
199 } | 242 } |
200 }); | 243 }); |
201 _setVM(new WebSocketVM(targets.current)); | 244 |
| 245 Logger.root.info('Setting initial target to ${targets.current.name}'); |
| 246 _switchVM(new WebSocketVM(targets.current)); |
202 _initOnce(); | 247 _initOnce(); |
203 | 248 |
204 // delete pause events. | 249 // delete pause events. |
205 events.onIsolateExit.listen(_deletePauseEvents); | 250 events.onIsolateExit.listen(_deletePauseEvents); |
206 events.onResume.listen(_deletePauseEvents); | 251 events.onResume.listen(_deletePauseEvents); |
207 events.onPauseStart.listen(_deletePauseEvents); | 252 events.onPauseStart.listen(_deletePauseEvents); |
208 events.onPauseExit.listen(_deletePauseEvents); | 253 events.onPauseExit.listen(_deletePauseEvents); |
209 events.onPauseBreakpoint.listen(_deletePauseEvents); | 254 events.onPauseBreakpoint.listen(_deletePauseEvents); |
210 events.onPauseInterrupted.listen(_deletePauseEvents); | 255 events.onPauseInterrupted.listen(_deletePauseEvents); |
211 events.onPauseException.listen(_deletePauseEvents); | 256 events.onPauseException.listen(_deletePauseEvents); |
212 | 257 |
213 // show notification for an event. | 258 // show notification for an event. |
214 events.onIsolateReload.listen(_addNotification); | 259 events.onIsolateReload.listen(_addNotification); |
215 events.onPauseExit.listen(_addNotification); | 260 events.onPauseExit.listen(_addNotification); |
216 events.onPauseBreakpoint.listen(_addNotification); | 261 events.onPauseBreakpoint.listen(_addNotification); |
217 events.onPauseInterrupted.listen(_addNotification); | 262 events.onPauseInterrupted.listen(_addNotification); |
218 events.onPauseException.listen(_addNotification); | 263 events.onPauseException.listen(_addNotification); |
219 events.onInspect.listen(_addNotification); | 264 events.onInspect.listen(_addNotification); |
| 265 events.onConnectionClosed.listen(_addNotification); |
220 } | 266 } |
221 | 267 |
222 loadCrashDump(Map crashDump) { | 268 loadCrashDump(Map crashDump) { |
223 _setVM(new FakeVM(crashDump['result'])); | 269 _switchVM(new FakeVM(crashDump['result'])); |
224 app.locationManager.go('#/vm'); | 270 app.locationManager.go(Uris.vm()); |
225 } | 271 } |
226 | 272 |
227 void handleException(e, st) { | 273 void handleException(e, st) { |
228 if (e is ServerRpcException) { | 274 if (e is ServerRpcException) { |
229 if (e.code == ServerRpcException.kFeatureDisabled) return; | 275 if (e.code == ServerRpcException.kFeatureDisabled) return; |
230 if (e.code == ServerRpcException.kIsolateMustBePaused) return; | 276 if (e.code == ServerRpcException.kIsolateMustBePaused) return; |
231 if (e.code == ServerRpcException.kCannotAddBreakpoint) return; | 277 if (e.code == ServerRpcException.kCannotAddBreakpoint) return; |
232 Logger.root.fine('Dropping exception: ${e}\n${st}'); | 278 Logger.root.fine('Dropping exception: ${e}\n${st}'); |
233 } | 279 } |
234 | 280 |
235 // TODO(turnidge): Report this failure via analytics. | 281 // TODO(turnidge): Report this failure via analytics. |
236 Logger.root.warning('Caught exception: ${e}\n${st}'); | 282 Logger.root.warning('Caught exception: ${e}\n${st}'); |
237 notifications.add(new ExceptionNotification(e, stacktrace: st)); | 283 notifications.add(new ExceptionNotification(e, stacktrace: st)); |
238 } | 284 } |
239 | 285 |
240 // This map keeps track of which curly-blocks have been expanded by the user. | 286 // This map keeps track of which curly-blocks have been expanded by the user. |
241 Map<String,bool> expansions = {}; | 287 Map<String,bool> expansions = {}; |
242 } | 288 } |
OLD | NEW |