Chromium Code Reviews| 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 /// A [Pane] controls the user interface of Observatory. At any given time | |
| 8 /// one pane will be the current pane. Panes are registered at startup. | |
| 9 /// When the user navigates within the application, each pane is asked if it | |
| 10 /// can handle the current location, the first pane to say yes, wins. | |
| 11 abstract class Pane extends Observable { | |
| 12 final ObservatoryApplication app; | |
| 13 | |
| 14 @observable ObservatoryElement element; | |
| 15 | |
| 16 Pane(this.app); | |
| 17 | |
| 18 /// Called when the pane is installed, this callback must initialize | |
| 19 /// [element]. | |
| 20 void onInstall(); | |
| 21 | |
| 22 /// Called when the pane is uninstalled, this callback must clear | |
| 23 /// [element]. | |
| 24 void onUninstall() { | |
| 25 element = null; | |
| 26 } | |
| 27 | |
| 28 /// Called when the pane should update its state based on [url]. | |
| 29 /// NOTE: Only called when the pane is installed. | |
| 30 void visit(String url); | |
| 31 | |
| 32 /// Called to test whether this pane can visit [url]. | |
| 33 bool canVisit(String url); | |
| 34 } | |
| 35 | |
| 36 /// A general service object viewer. | |
| 37 class ServiceObjectPane extends Pane { | |
| 38 ServiceObjectPane(app) : super(app); | |
| 39 | |
| 40 void onInstall() { | |
| 41 if (element == null) { | |
| 42 /// Lazily create pane. | |
| 43 element = new Element.tag('service-view'); | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 void visit(String url) { | |
| 48 assert(element != null); | |
| 49 assert(canVisit(url)); | |
| 50 if (url == '') { | |
| 51 // Nothing requested. | |
| 52 return; | |
| 53 } | |
| 54 /// Request url from VM and display it. | |
| 55 app.vm.get(url).then((obj) { | |
| 56 ServiceObjectViewElement pane = element; | |
| 57 pane.object = obj; | |
| 58 }); | |
| 59 } | |
| 60 | |
| 61 /// Catch all. | |
| 62 bool canVisit(String url) => true; | |
| 63 } | |
| 64 | |
| 65 /// Class tree pane. | |
| 66 class ClassTreePane extends Pane { | |
| 67 static const _urlPrefix = 'class-tree/'; | |
| 68 | |
| 69 ClassTreePane(app) : super(app); | |
| 70 | |
| 71 void onInstall() { | |
| 72 if (element == null) { | |
| 73 element = new Element.tag('class-tree'); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 void visit(String url) { | |
| 78 assert(element != null); | |
| 79 assert(canVisit(url)); | |
| 80 // ClassTree urls are 'class-tree/isolate-id', chop off prefix, leaving | |
| 81 // isolate url. | |
| 82 url = url.substring(_urlPrefix.length); | |
| 83 /// Request the isolate url. | |
| 84 app.vm.get(url).then((i) { | |
| 85 if (element != null) { | |
| 86 /// Update the pane. | |
| 87 ClassTreeElement pane = element; | |
| 88 pane.isolate = i; | |
| 89 } | |
| 90 }); | |
| 91 } | |
| 92 | |
| 93 /// Catch all. | |
| 94 bool canVisit(String url) => url.startsWith(_urlPrefix); | |
| 95 } | |
| 96 | |
| 97 class ErrorViewPane extends Pane { | |
| 98 ErrorViewPane(app) : super(app); | |
| 99 | |
| 100 void onInstall() { | |
| 101 if (element == null) { | |
| 102 /// Lazily create pane. | |
| 103 element = new Element.tag('service-view'); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 void visit(String url) { | |
| 108 assert(element != null); | |
| 109 assert(canVisit(url)); | |
| 110 (element as ServiceObjectViewElement).object = app.lastErrorOrException; | |
| 111 } | |
| 112 | |
| 113 bool canVisit(String url) => url.startsWith('error/'); | |
| 114 } | |
| 115 | |
| 116 /// The observatory application. Instances of this are created and owned | 7 /// The observatory application. Instances of this are created and owned |
| 117 /// by the observatory_application custom element. | 8 /// by the observatory_application custom element. |
| 118 class ObservatoryApplication extends Observable { | 9 class ObservatoryApplication extends Observable { |
| 10 static ObservatoryApplication app; | |
| 119 final _paneRegistry = new List<Pane>(); | 11 final _paneRegistry = new List<Pane>(); |
| 120 ServiceObjectPane _serviceObjectPane; | |
| 121 Pane _currentPane; | 12 Pane _currentPane; |
| 122 @observable final LocationManager locationManager; | 13 @observable final LocationManager locationManager; |
| 123 @observable final VM vm; | 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 _vm.disconnect(); | |
| 24 } | |
| 25 if (vm != null) { | |
| 26 Logger.root.info('Registering new VM callbacks'); | |
| 27 vm.onConnect.then(_vmConnected); | |
| 28 vm.onDisconnect.then(_vmDisconnected); | |
| 29 vm.errors.stream.listen(_onError); | |
| 30 vm.exceptions.stream.listen(_onException); | |
| 31 } | |
| 32 _vm = vm; | |
| 33 } | |
| 34 final TargetManager targets; | |
| 124 @observable Isolate isolate; | 35 @observable Isolate isolate; |
| 125 @reflectable final ObservatoryApplicationElement rootElement; | 36 @reflectable final ObservatoryApplicationElement rootElement; |
| 126 | 37 |
| 127 @reflectable ServiceObject lastErrorOrException; | 38 @reflectable ServiceObject lastErrorOrException; |
| 128 | 39 |
| 129 void _initOnce() { | 40 void _initOnce(bool chromium) { |
| 41 assert(app == null); | |
| 42 app = this; | |
| 43 _vm.errors.stream.listen(_onError); | |
| 44 _vm.exceptions.stream.listen(_onException); | |
|
turnidge
2014/07/01 00:27:47
Are the two above lines necessary now that these h
Cutch
2014/07/01 17:14:51
Done.
| |
| 130 _registerPanes(); | 45 _registerPanes(); |
| 131 vm.errors.stream.listen(_onError); | |
| 132 vm.exceptions.stream.listen(_onException); | |
| 133 location = locationManager; | |
| 134 locationManager._init(this); | 46 locationManager._init(this); |
| 135 } | 47 } |
| 136 | 48 |
| 137 void _registerPanes() { | 49 void _registerPanes() { |
| 138 if (_serviceObjectPane != null) { | |
| 139 // Already done. | |
| 140 return; | |
| 141 } | |
| 142 // Register ClassTreePane. | 50 // Register ClassTreePane. |
| 143 _paneRegistry.add(new ClassTreePane(this)); | 51 _paneRegistry.add(new ClassTreePane(this)); |
| 52 _paneRegistry.add(new VMConnectPane(this)); | |
| 144 _paneRegistry.add(new ErrorViewPane(this)); | 53 _paneRegistry.add(new ErrorViewPane(this)); |
| 145 // Note that ServiceObjectPane must be the last entry in the list as it is | 54 // Note that ServiceObjectPane must be the last entry in the list as it is |
| 146 // the catch all. | 55 // the catch all. |
| 147 _serviceObjectPane = new ServiceObjectPane(this); | 56 _paneRegistry.add(new ServiceObjectPane(this)); |
| 148 _paneRegistry.add(_serviceObjectPane); | |
| 149 } | 57 } |
| 150 | 58 |
| 151 void _onError(ServiceError error) { | 59 void _onError(ServiceError error) { |
| 152 lastErrorOrException = error; | 60 lastErrorOrException = error; |
| 153 _visit('error/', null); | 61 _visit('error/', null); |
| 154 } | 62 } |
| 155 | 63 |
| 156 void _onException(ServiceException exception) { | 64 void _onException(ServiceException exception) { |
| 157 lastErrorOrException = exception; | 65 lastErrorOrException = exception; |
| 158 _visit('error/', null); | 66 if (exception.kind == 'NetworkException') { |
| 67 // Got a network exception, visit the vm-connect pane. | |
| 68 locationManager.go(locationManager.makeLink('/vm-connect/')); | |
| 69 } else { | |
| 70 _visit('error/', null); | |
| 71 } | |
| 159 } | 72 } |
| 160 | 73 |
| 161 void _visit(String url, String args) { | 74 void _visit(String url, String args) { |
| 162 // TODO(johnmccutchan): Pass [args] to pane. | 75 // TODO(johnmccutchan): Pass [args] to pane. |
| 163 for (var i = 0; i < _paneRegistry.length; i++) { | 76 for (var i = 0; i < _paneRegistry.length; i++) { |
| 164 var pane = _paneRegistry[i]; | 77 var pane = _paneRegistry[i]; |
| 165 if (pane.canVisit(url)) { | 78 if (pane.canVisit(url)) { |
| 166 _installPane(pane); | 79 _installPane(pane); |
| 167 pane.visit(url); | 80 pane.visit(url); |
| 168 return; | 81 return; |
| 169 } | 82 } |
| 170 } | 83 } |
| 171 throw new FallThroughError(); | 84 throw new FallThroughError(); |
| 172 } | 85 } |
| 173 | 86 |
| 174 /// Set the Observatory application pane. | 87 /// Set the Observatory application pane. |
| 175 void _installPane(Pane pane) { | 88 void _installPane(Pane pane) { |
| 176 assert(pane != null); | 89 assert(pane != null); |
| 177 print('Installing $pane'); | |
| 178 if (_currentPane == pane) { | 90 if (_currentPane == pane) { |
| 179 // Already isntalled. | 91 // Already isntalled. |
| 180 return; | 92 return; |
| 181 } | 93 } |
| 182 if (_currentPane != null) { | 94 if (_currentPane != null) { |
| 95 Logger.root.info('Uninstalling pane: $_currentPane'); | |
|
turnidge
2014/07/01 00:27:47
Are we keeping this logging in long-term?
Cutch
2014/07/01 17:14:51
Not sure. I like having info on pane switches. Sho
| |
| 183 _currentPane.onUninstall(); | 96 _currentPane.onUninstall(); |
| 97 // Clear children. | |
| 98 rootElement.children.clear(); | |
| 184 } | 99 } |
| 185 pane.onInstall(); | 100 Logger.root.info('Installing pane: $pane'); |
| 186 // Clear children. | 101 try { |
| 187 rootElement.children.clear(); | 102 pane.onInstall(); |
| 103 } catch (e) { | |
| 104 Logger.root.severe('Failed to install pane: $e'); | |
| 105 } | |
| 188 // Add new pane. | 106 // Add new pane. |
| 189 rootElement.children.add(pane.element); | 107 rootElement.children.add(pane.element); |
| 190 // Remember pane. | 108 // Remember pane. |
| 191 _currentPane = pane; | 109 _currentPane = pane; |
| 192 } | 110 } |
| 193 | 111 |
| 194 ObservatoryApplication.devtools(this.rootElement) : | 112 ObservatoryApplication.devtools(this.rootElement) : |
| 195 locationManager = new HashLocationManager(), | 113 locationManager = new HashLocationManager(), |
| 196 vm = new DartiumVM() { | 114 targets = null { |
| 197 _initOnce(); | 115 vm = new PostMessageVM(); |
| 116 _initOnce(true); | |
| 198 } | 117 } |
| 199 | 118 |
| 200 ObservatoryApplication(this.rootElement) : | 119 ObservatoryApplication(this.rootElement) : |
| 201 locationManager = new HashLocationManager(), | 120 locationManager = new HashLocationManager(), |
| 202 vm = new HttpVM() { | 121 targets = new TargetManager() { |
| 203 _initOnce(); | 122 vm = new NetworkVM(targets.defaultTarget); |
| 123 _initOnce(false); | |
| 124 } | |
| 125 | |
| 126 _vmConnected(VM vm) { | |
| 127 if (vm is NetworkVM) { | |
| 128 targets.add(vm.target); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 _vmDisconnected(VM vm) { | |
| 133 if (this.vm != vm) { | |
| 134 // This disconnect event occured *after* a new VM was installed. | |
| 135 return; | |
| 136 } | |
| 137 this.vm = null; | |
| 138 locationManager.go(locationManager.makeLink('/vm-connect/')); | |
| 204 } | 139 } |
| 205 } | 140 } |
| 206 | |
| 207 LocationManager location; | |
| OLD | NEW |