| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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 library service_common; | 5 library service_common; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:typed_data'; |
| 9 | 10 |
| 10 import 'package:logging/logging.dart'; | 11 import 'package:logging/logging.dart'; |
| 11 import 'package:observatory/service.dart'; | 12 import 'package:observatory/service.dart'; |
| 12 | 13 |
| 13 // Export the service library. | 14 // Export the service library. |
| 14 export 'package:observatory/service.dart'; | 15 export 'package:observatory/service.dart'; |
| 15 | 16 |
| 16 /// Description of a VM target. | 17 /// Description of a VM target. |
| 17 class WebSocketVMTarget { | 18 class WebSocketVMTarget { |
| 18 // Last time this VM has been connected to. | 19 // Last time this VM has been connected to. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 /// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html]. | 63 /// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html]. |
| 63 abstract class CommonWebSocket { | 64 abstract class CommonWebSocket { |
| 64 void connect(String address, | 65 void connect(String address, |
| 65 void onOpen(), | 66 void onOpen(), |
| 66 void onMessage(dynamic data), | 67 void onMessage(dynamic data), |
| 67 void onError(), | 68 void onError(), |
| 68 void onClose()); | 69 void onClose()); |
| 69 bool get isOpen; | 70 bool get isOpen; |
| 70 void send(dynamic data); | 71 void send(dynamic data); |
| 71 void close(); | 72 void close(); |
| 73 Future<ByteData> nonStringToByteData(dynamic data); |
| 72 } | 74 } |
| 73 | 75 |
| 74 /// A [CommonWebSocketVM] communicates with a Dart VM over a CommonWebSocket. | 76 /// 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 | 77 /// 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 | 78 /// Chromium, we make the service requests via the Chrome Remote Debugging |
| 77 /// Protocol. | 79 /// Protocol. |
| 78 abstract class CommonWebSocketVM extends VM { | 80 abstract class CommonWebSocketVM extends VM { |
| 79 final Completer _connected = new Completer(); | 81 final Completer _connected = new Completer(); |
| 80 final Completer _disconnected = new Completer(); | 82 final Completer _disconnected = new Completer(); |
| 81 final WebSocketVMTarget target; | 83 final WebSocketVMTarget target; |
| 82 final Map<String, _WebSocketRequest> _delayedRequests = | 84 final Map<String, _WebSocketRequest> _delayedRequests = |
| 83 new Map<String, _WebSocketRequest>(); | 85 new Map<String, _WebSocketRequest>(); |
| 84 final Map<String, _WebSocketRequest> _pendingRequests = | 86 final Map<String, _WebSocketRequest> _pendingRequests = |
| 85 new Map<String, _WebSocketRequest>(); | 87 new Map<String, _WebSocketRequest>(); |
| 86 int _requestSerial = 0; | 88 int _requestSerial = 0; |
| 87 bool _hasInitiatedConnect = false; | 89 bool _hasInitiatedConnect = false; |
| 90 Utf8Decoder _utf8Decoder = new Utf8Decoder(); |
| 88 | 91 |
| 89 CommonWebSocket _webSocket; | 92 CommonWebSocket _webSocket; |
| 90 | 93 |
| 91 CommonWebSocketVM(this.target, this._webSocket) { | 94 CommonWebSocketVM(this.target, this._webSocket) { |
| 92 assert(target != null); | 95 assert(target != null); |
| 93 } | 96 } |
| 94 | 97 |
| 95 void _notifyConnect() { | 98 void _notifyConnect() { |
| 96 if (!_connected.isCompleted) { | 99 if (!_connected.isCompleted) { |
| 97 Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}'
); | 100 Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}'
); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 | 156 |
| 154 // WebSocket open event handler. | 157 // WebSocket open event handler. |
| 155 void _onOpen() { | 158 void _onOpen() { |
| 156 target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch; | 159 target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch; |
| 157 _sendAllDelayedRequests(); | 160 _sendAllDelayedRequests(); |
| 158 _notifyConnect(); | 161 _notifyConnect(); |
| 159 } | 162 } |
| 160 | 163 |
| 161 // WebSocket message event handler. | 164 // WebSocket message event handler. |
| 162 void _onMessage(dynamic data) { | 165 void _onMessage(dynamic data) { |
| 163 assert(data is String); // We don't handle binary data, yet. | 166 if (data is! String) { |
| 167 _webSocket.nonStringToByteData(data).then((ByteData bytes) { |
| 168 // See format spec. in VMs Service::SendEvent. |
| 169 int offset = 0; |
| 170 int metaSize = bytes.getUint64(offset, Endianness.BIG_ENDIAN); |
| 171 offset += 8; |
| 172 var meta = _utf8Decoder.convert(new Uint8List.view( |
| 173 bytes.buffer, bytes.offsetInBytes + offset, metaSize)); |
| 174 offset += metaSize; |
| 175 var data = new ByteData.view( |
| 176 bytes.buffer, |
| 177 bytes.offsetInBytes + offset, |
| 178 bytes.lengthInBytes - offset); |
| 179 postEventMessage(meta, data); |
| 180 }); |
| 181 return; |
| 182 } |
| 164 var map = JSON.decode(data); | 183 var map = JSON.decode(data); |
| 165 if (map == null) { | 184 if (map == null) { |
| 166 Logger.root.severe('WebSocketVM got empty message'); | 185 Logger.root.severe('WebSocketVM got empty message'); |
| 167 return; | 186 return; |
| 168 } | 187 } |
| 169 // Extract serial and response. | 188 // Extract serial and response. |
| 170 var serial; | 189 var serial; |
| 171 var response; | 190 var response; |
| 172 if (target.chrome) { | 191 if (target.chrome) { |
| 173 if (map['method'] != 'Dart.observatoryData') { | 192 if (map['method'] != 'Dart.observatoryData') { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 'query': request.id | 276 'query': request.id |
| 258 } | 277 } |
| 259 }); | 278 }); |
| 260 } else { | 279 } else { |
| 261 message = JSON.encode({'seq': serial, 'request': request.id}); | 280 message = JSON.encode({'seq': serial, 'request': request.id}); |
| 262 } | 281 } |
| 263 // Send message. | 282 // Send message. |
| 264 _webSocket.send(message); | 283 _webSocket.send(message); |
| 265 } | 284 } |
| 266 } | 285 } |
| OLD | NEW |