OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, 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 /// A [Page] controls the user interface of Observatory. At any given time | |
8 /// one page will be the current page. Pages are registered at startup. | |
9 /// When the user navigates within the application, each page is asked if it | |
10 /// can handle the current location, the first page to say yes, wins. | |
11 abstract class Page extends Observable { | |
12 final ObservatoryApplication app; | |
13 | |
14 @observable ObservatoryElement element; | |
15 @observable ObservableMap args; | |
16 | |
17 Page(this.app); | |
18 | |
19 /// Called when the page is installed, this callback must initialize | |
20 /// [element]. | |
21 void onInstall(); | |
22 | |
23 /// Called when the page is uninstalled, this callback must clear | |
24 /// [element]. | |
25 void onUninstall() { | |
26 element = null; | |
27 } | |
28 | |
29 /// Called when the page should update its state based on [url]. | |
30 /// NOTE: Only called when the page is installed. | |
31 void visit(String url, Map argsMap) { | |
32 args = toObservable(argsMap); | |
33 _visit(url); | |
34 } | |
35 | |
36 // Overridden by subclasses. | |
37 void _visit(String url); | |
38 | |
39 /// Called to test whether this page can visit [url]. | |
40 bool canVisit(String url); | |
41 } | |
42 | |
43 /// A general service object viewer. | |
44 class ServiceObjectPage extends Page { | |
45 ServiceObjectPage(app) : super(app); | |
46 | |
47 void onInstall() { | |
48 if (element == null) { | |
49 /// Lazily create page. | |
50 element = new Element.tag('service-view'); | |
51 } | |
52 } | |
53 | |
54 void _visit(String url) { | |
55 assert(element != null); | |
56 assert(canVisit(url)); | |
57 if (url == '') { | |
58 // Nothing requested. | |
59 return; | |
60 } | |
61 /// Request url from VM and display it. | |
62 app.vm.get(url).then((obj) { | |
63 ServiceObjectViewElement serviceElement = element; | |
64 serviceElement.object = obj; | |
65 }).catchError((e) { | |
66 Logger.root.severe('ServiceObjectPage visit error: $e'); | |
67 }); | |
68 } | |
69 | |
70 /// Catch all. | |
71 bool canVisit(String url) => true; | |
72 } | |
73 | |
74 /// Class tree page. | |
75 class ClassTreePage extends Page { | |
76 static const _urlPrefix = 'class-tree/'; | |
77 | |
78 ClassTreePage(app) : super(app); | |
79 | |
80 void onInstall() { | |
81 if (element == null) { | |
82 element = new Element.tag('class-tree'); | |
83 } | |
84 } | |
85 | |
86 void _visit(String url) { | |
87 assert(element != null); | |
88 assert(canVisit(url)); | |
89 // ClassTree urls are 'class-tree/isolate-id', chop off prefix, leaving | |
90 // isolate url. | |
91 url = url.substring(_urlPrefix.length); | |
92 /// Request the isolate url. | |
93 app.vm.get(url).then((isolate) { | |
94 if (element != null) { | |
95 /// Update the page. | |
96 ClassTreeElement page = element; | |
97 page.isolate = isolate; | |
98 } | |
99 }).catchError((e) { | |
100 Logger.root.severe('ClassTreePage visit error: $e'); | |
101 }); | |
102 } | |
103 | |
104 /// Catch all. | |
105 bool canVisit(String url) => url.startsWith(_urlPrefix); | |
106 } | |
107 | |
108 class DebuggerPage extends Page { | |
109 static const _urlPrefix = 'debugger/'; | |
110 | |
111 DebuggerPage(app) : super(app); | |
112 | |
113 void onInstall() { | |
114 if (element == null) { | |
115 element = new Element.tag('debugger-page'); | |
116 } | |
117 } | |
118 | |
119 void _visit(String url) { | |
120 assert(element != null); | |
121 assert(canVisit(url)); | |
122 // Debugger urls are 'debugger/isolate-id', chop off prefix, leaving | |
123 // isolate url. | |
124 url = url.substring(_urlPrefix.length); | |
125 /// Request the isolate url. | |
126 app.vm.get(url).then((isolate) { | |
127 if (element != null) { | |
128 /// Update the page. | |
129 DebuggerPageElement page = element; | |
130 page.isolate = isolate; | |
131 } | |
132 }).catchError((e) { | |
133 Logger.root.severe('Unexpected debugger error: $e'); | |
134 }); | |
135 } | |
136 | |
137 /// Catch all. | |
138 bool canVisit(String url) => url.startsWith(_urlPrefix); | |
139 } | |
140 | |
141 class ErrorViewPage extends Page { | |
142 ErrorViewPage(app) : super(app); | |
143 | |
144 void onInstall() { | |
145 if (element == null) { | |
146 /// Lazily create page. | |
147 element = new Element.tag('service-view'); | |
148 } | |
149 } | |
150 | |
151 void _visit(String url) { | |
152 assert(element != null); | |
153 assert(canVisit(url)); | |
154 (element as ServiceObjectViewElement).object = app.lastErrorOrException; | |
155 } | |
156 | |
157 bool canVisit(String url) => url.startsWith('error/'); | |
158 } | |
159 | |
160 class VMConnectPage extends Page { | |
161 VMConnectPage(app) : super(app); | |
162 | |
163 void onInstall() { | |
164 if (element == null) { | |
165 element = new Element.tag('vm-connect'); | |
166 } | |
167 assert(element != null); | |
168 } | |
169 | |
170 void _visit(String url) { | |
171 assert(element != null); | |
172 assert(canVisit(url)); | |
173 } | |
174 | |
175 bool canVisit(String url) => url.startsWith('vm-connect/'); | |
176 } | |
177 | |
178 class MetricsPage extends Page { | |
179 static RegExp _matcher = new RegExp(r'isolates/.*/metrics'); | |
180 static RegExp _isolateMatcher = new RegExp(r'isolates/.*/'); | |
181 | |
182 // Page state, retained as long as ObservatoryApplication. | |
183 String selectedMetricId; | |
184 | |
185 final Map<int, MetricPoller> pollers = new Map<int, MetricPoller>(); | |
186 | |
187 // 8 seconds, 4 seconds, 2 seconds, 1 second, and one hundred milliseconds. | |
188 static final List<int> POLL_PERIODS = [8000, | |
189 4000, | |
190 2000, | |
191 1000, | |
192 100]; | |
193 | |
194 MetricsPage(app) : super(app) { | |
195 for (var i = 0; i < POLL_PERIODS.length; i++) { | |
196 pollers[POLL_PERIODS[i]] = new MetricPoller(POLL_PERIODS[i]); | |
197 } | |
198 } | |
199 | |
200 void onInstall() { | |
201 if (element == null) { | |
202 element = new Element.tag('metrics-page'); | |
203 (element as MetricsPageElement).page = this; | |
204 } | |
205 assert(element != null); | |
206 } | |
207 | |
208 void setRefreshPeriod(int refreshPeriod, ServiceMetric metric) { | |
209 if (metric.poller != null) { | |
210 if (metric.poller.pollPeriod.inMilliseconds == refreshPeriod) { | |
211 return; | |
212 } | |
213 // Remove from current poller. | |
214 metric.poller.metrics.remove(metric); | |
215 metric.poller = null; | |
216 } | |
217 if (refreshPeriod == 0) { | |
218 return; | |
219 } | |
220 var poller = pollers[refreshPeriod]; | |
221 if (poller != null) { | |
222 poller.metrics.add(metric); | |
223 metric.poller = poller; | |
224 return; | |
225 } | |
226 throw new FallThroughError(); | |
227 } | |
228 | |
229 String _isolateId(String url) { | |
230 // Grab isolate prefix. | |
231 String isolateId = _isolateMatcher.stringMatch(url); | |
232 // Remove the trailing slash. | |
233 return isolateId.substring(0, isolateId.length - 1); | |
234 } | |
235 | |
236 void _visit(String url) { | |
237 assert(element != null); | |
238 assert(canVisit(url)); | |
239 app.vm.get(_isolateId(url)).then((i) { | |
240 (element as MetricsPageElement).isolate = i; | |
241 }); | |
242 } | |
243 | |
244 bool canVisit(String url) => _matcher.hasMatch(url); | |
245 } | |
OLD | NEW |