Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1539)

Side by Side Diff: runtime/bin/vmservice/client/lib/service_common.dart

Issue 443713004: Rename vmservice/client to vmservice/observatory to match package name. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 library service_common;
6
7 import 'dart:async';
8 import 'dart:convert';
9
10 import 'package:logging/logging.dart';
11 import 'package:observatory/service.dart';
12
13 // Export the service library.
14 export 'package:observatory/service.dart';
15
16 /// Description of a VM target.
17 class WebSocketVMTarget {
18 // Last time this VM has been connected to.
19 int lastConnectionTime = 0;
20 bool get hasEverConnected => lastConnectionTime > 0;
21
22 // Chrome VM or standalone;
23 bool chrome = false;
24 bool get standalone => !chrome;
25
26 // User defined name.
27 String name;
28 // Network address of VM.
29 String networkAddress;
30
31 WebSocketVMTarget(this.networkAddress) {
32 name = networkAddress;
33 }
34
35 WebSocketVMTarget.fromMap(Map json) {
36 lastConnectionTime = json['lastConnectionTime'];
37 chrome = json['chrome'];
38 name = json['name'];
39 networkAddress = json['networkAddress'];
40 if (name == null) {
41 name = networkAddress;
42 }
43 }
44
45 Map toJson() {
46 return {
47 'lastConnectionTime': lastConnectionTime,
48 'chrome': chrome,
49 'name': name,
50 'networkAddress': networkAddress,
51 };
52 }
53 }
54
55 class _WebSocketRequest {
56 final String id;
57 final Completer<String> completer;
58 _WebSocketRequest(this.id)
59 : completer = new Completer<String>();
60 }
61
62 /// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html].
63 abstract class CommonWebSocket {
64 void connect(String address,
65 void onOpen(),
66 void onMessage(dynamic data),
67 void onError(),
68 void onClose());
69 bool get isOpen;
70 void send(dynamic data);
71 void close();
72 }
73
74 /// A [CommonWebSocketVM] communicates with a Dart VM over a CommonWebSocket.
75 /// The Dart VM can be embedded in Chromium or standalone. In the case of
76 /// Chromium, we make the service requests via the Chrome Remote Debugging
77 /// Protocol.
78 abstract class CommonWebSocketVM extends VM {
79 final Completer _connected = new Completer();
80 final Completer _disconnected = new Completer();
81 final WebSocketVMTarget target;
82 final Map<String, _WebSocketRequest> _delayedRequests =
83 new Map<String, _WebSocketRequest>();
84 final Map<String, _WebSocketRequest> _pendingRequests =
85 new Map<String, _WebSocketRequest>();
86 int _requestSerial = 0;
87 bool _hasInitiatedConnect = false;
88
89 CommonWebSocket _webSocket;
90
91 CommonWebSocketVM(this.target, this._webSocket) {
92 assert(target != null);
93 }
94
95 void _notifyConnect() {
96 if (!_connected.isCompleted) {
97 Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}' );
98 _connected.complete(this);
99 }
100 }
101 Future get onConnect => _connected.future;
102 void _notifyDisconnect() {
103 if (!_disconnected.isCompleted) {
104 Logger.root.info('WebSocketVM connection error: ${target.networkAddress}') ;
105 _disconnected.complete(this);
106 }
107 }
108 Future get onDisconnect => _disconnected.future;
109
110 void disconnect() {
111 if (_hasInitiatedConnect) {
112 _webSocket.close();
113 }
114 _cancelAllRequests();
115 _notifyDisconnect();
116 }
117
118 Future<String> getString(String id) {
119 if (!_hasInitiatedConnect) {
120 _hasInitiatedConnect = true;
121 _webSocket.connect(
122 target.networkAddress, _onOpen, _onMessage, _onError, _onClose);
123 }
124 return _makeRequest(id);
125 }
126
127 /// Add a request for [id] to pending requests.
128 Future<String> _makeRequest(String id) {
129 assert(_hasInitiatedConnect);
130 // Create request.
131 String serial = (_requestSerial++).toString();
132 var request = new _WebSocketRequest(id);
133 if (_webSocket.isOpen) {
134 // Already connected, send request immediately.
135 _sendRequest(serial, request);
136 } else {
137 // Not connected yet, add to delayed requests.
138 _delayedRequests[serial] = request;
139 }
140 return request.completer.future;
141 }
142
143 void _onClose() {
144 _cancelAllRequests();
145 _notifyDisconnect();
146 }
147
148 // WebSocket error event handler.
149 void _onError() {
150 _cancelAllRequests();
151 _notifyDisconnect();
152 }
153
154 // WebSocket open event handler.
155 void _onOpen() {
156 target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch;
157 _sendAllDelayedRequests();
158 _notifyConnect();
159 }
160
161 // WebSocket message event handler.
162 void _onMessage(dynamic data) {
163 assert(data is String); // We don't handle binary data, yet.
164 var map = JSON.decode(data);
165 if (map == null) {
166 Logger.root.severe('WebSocketVM got empty message');
167 return;
168 }
169 // Extract serial and response.
170 var serial;
171 var response;
172 if (target.chrome) {
173 if (map['method'] != 'Dart.observatoryData') {
174 // ignore devtools protocol spam.
175 return;
176 }
177 serial = map['params']['id'].toString();
178 response = map['params']['data'];
179 } else {
180 serial = map['seq'];
181 response = map['response'];
182 }
183 if (serial == null) {
184 // Messages without sequence numbers are asynchronous events
185 // from the vm.
186 postEventMessage(response);
187 return;
188 }
189 // Complete request.
190 var request = _pendingRequests.remove(serial);
191 if (request == null) {
192 Logger.root.severe('Received unexpected message: ${map}');
193 return;
194 }
195 request.completer.complete(response);
196 }
197
198 String _generateNetworkError(String userMessage) {
199 return JSON.encode({
200 'type': 'ServiceException',
201 'id': '',
202 'kind': 'NetworkException',
203 'message': userMessage
204 });
205 }
206
207 void _cancelRequests(Map<String, _WebSocketRequest> requests) {
208 requests.forEach((String serial, _WebSocketRequest request) {
209 request.completer.complete(
210 _generateNetworkError('WebSocket disconnected'));
211 });
212 requests.clear();
213 }
214
215 /// Cancel all pending and delayed requests by completing them with an error.
216 void _cancelAllRequests() {
217 if (_pendingRequests.length > 0) {
218 Logger.root.info('Cancelling all pending requests.');
219 _cancelRequests(_pendingRequests);
220 }
221 if (_delayedRequests.length > 0) {
222 Logger.root.info('Cancelling all delayed requests.');
223 _cancelRequests(_delayedRequests);
224 }
225 }
226
227 /// Send all delayed requests.
228 void _sendAllDelayedRequests() {
229 assert(_webSocket.isOpen);
230 if (_delayedRequests.length == 0) {
231 return;
232 }
233 Logger.root.info('Sending all delayed requests.');
234 // Send all delayed requests.
235 _delayedRequests.forEach(_sendRequest);
236 // Clear all delayed requests.
237 _delayedRequests.clear();
238 }
239
240 /// Send the request over WebSocket.
241 void _sendRequest(String serial, _WebSocketRequest request) {
242 assert (_webSocket.isOpen);
243 if (!request.id.endsWith('/profile/tag')) {
244 Logger.root.info('GET ${request.id} from ${target.networkAddress}');
245 }
246 // Mark request as pending.
247 assert(_pendingRequests.containsKey(serial) == false);
248 _pendingRequests[serial] = request;
249 var message;
250 // Encode message.
251 if (target.chrome) {
252 message = JSON.encode({
253 'id': int.parse(serial),
254 'method': 'Dart.observatoryQuery',
255 'params': {
256 'id': serial,
257 'query': request.id
258 }
259 });
260 } else {
261 message = JSON.encode({'seq': serial, 'request': request.id});
262 }
263 // Send message.
264 _webSocket.send(message);
265 }
266 }
OLDNEW
« no previous file with comments | « runtime/bin/vmservice/client/lib/service.dart ('k') | runtime/bin/vmservice/client/lib/service_html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698