Chromium Code Reviews| Index: runtime/bin/vmservice/client/lib/service_html.dart |
| =================================================================== |
| --- runtime/bin/vmservice/client/lib/service_html.dart (revision 38598) |
| +++ runtime/bin/vmservice/client/lib/service_html.dart (working copy) |
| @@ -8,249 +8,43 @@ |
| import 'dart:convert'; |
| import 'dart:html'; |
| -import 'package:logging/logging.dart'; |
| -import 'package:observatory/service.dart'; |
| +import 'package:observatory/service_common.dart'; |
| // Export the service library. |
| -export 'package:observatory/service.dart'; |
| +export 'package:observatory/service_common.dart'; |
| -/// Description of a VM target. |
| -class WebSocketVMTarget { |
| - // Last time this VM has been connected to. |
| - int lastConnectionTime = 0; |
| - bool get hasEverConnected => lastConnectionTime > 0; |
| +class _HtmlWebSocket implements CommonWebSocket { |
| + WebSocket _webSocket; |
| - // Chrome VM or standalone; |
| - bool chrome = false; |
| - bool get standalone => !chrome; |
| - |
| - // User defined name. |
| - String name; |
| - // Network address of VM. |
| - String networkAddress; |
| - |
| - WebSocketVMTarget(this.networkAddress) { |
| - name = networkAddress; |
| + void connect(String address, |
| + void onOpen(), |
| + void onMessage(dynamic data), |
| + void onError(), |
| + void onClose()) { |
| + print("connect"); |
|
Cutch
2014/07/28 20:46:14
remove debug printing before committing
koda
2014/07/28 23:08:30
Done.
|
| + _webSocket = new WebSocket(address); |
| + _webSocket.onClose.listen((CloseEvent) => onClose()); |
| + _webSocket.onError.listen((Event) => onError()); |
| + _webSocket.onOpen.listen((Event) => onOpen()); |
| + _webSocket.onMessage.listen((MessageEvent event) => onMessage(event.data)); |
| } |
| - |
| - WebSocketVMTarget.fromMap(Map json) { |
| - lastConnectionTime = json['lastConnectionTime']; |
| - chrome = json['chrome']; |
| - name = json['name']; |
| - networkAddress = json['networkAddress']; |
| - if (name == null) { |
| - name = networkAddress; |
| - } |
| + |
| + bool get isOpen => _webSocket.readyState == WebSocket.OPEN; |
| + |
| + void send(dynamic data) { |
| + _webSocket.send(data); |
| } |
| - |
| - Map toJson() { |
| - return { |
| - 'lastConnectionTime': lastConnectionTime, |
| - 'chrome': chrome, |
| - 'name': name, |
| - 'networkAddress': networkAddress, |
| - }; |
| + |
| + void close() { |
| + _webSocket.close(); |
| } |
| } |
| -class _WebSocketRequest { |
| - final String id; |
| - final Completer<String> completer; |
| - _WebSocketRequest(this.id) |
| - : completer = new Completer<String>(); |
| -} |
| - |
| /// The [WebSocketVM] communicates with a Dart VM over WebSocket. The Dart VM |
| /// can be embedded in Chromium or standalone. In the case of Chromium, we |
| /// make the service requests via the Chrome Remote Debugging Protocol. |
| -class WebSocketVM extends VM { |
| - final Completer _connected = new Completer(); |
| - final Completer _disconnected = new Completer(); |
| - final WebSocketVMTarget target; |
| - final Map<String, _WebSocketRequest> _delayedRequests = |
| - new Map<String, _WebSocketRequest>(); |
| - final Map<String, _WebSocketRequest> _pendingRequests = |
| - new Map<String, _WebSocketRequest>(); |
| - int _requestSerial = 0; |
| - WebSocket _webSocket; |
| - |
| - WebSocketVM(this.target) { |
| - assert(target != null); |
| - } |
| - |
| - void _notifyConnect() { |
| - if (!_connected.isCompleted) { |
| - Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}'); |
| - _connected.complete(this); |
| - } |
| - } |
| - Future get onConnect => _connected.future; |
| - void _notifyDisconnect() { |
| - if (!_disconnected.isCompleted) { |
| - Logger.root.info('WebSocketVM connection error: ${target.networkAddress}'); |
| - _disconnected.complete(this); |
| - } |
| - } |
| - Future get onDisconnect => _disconnected.future; |
| - |
| - void disconnect() { |
| - if (_webSocket != null) { |
| - _webSocket.close(); |
| - } |
| - _cancelAllRequests(); |
| - _notifyDisconnect(); |
| - } |
| - |
| - Future<String> getString(String id) { |
| - if (_webSocket == null) { |
| - // Create a WebSocket. |
| - _webSocket = new WebSocket(target.networkAddress); |
| - _webSocket.onClose.listen(_onClose); |
| - _webSocket.onError.listen(_onError); |
| - _webSocket.onOpen.listen(_onOpen); |
| - _webSocket.onMessage.listen(_onMessage); |
| - } |
| - return _makeRequest(id); |
| - } |
| - |
| - /// Add a request for [id] to pending requests. |
| - Future<String> _makeRequest(String id) { |
| - assert(_webSocket != null); |
| - // Create request. |
| - String serial = (_requestSerial++).toString(); |
| - var request = new _WebSocketRequest(id); |
| - if (_webSocket.readyState == WebSocket.OPEN) { |
| - // Already connected, send request immediately. |
| - _sendRequest(serial, request); |
| - } else { |
| - // Not connected yet, add to delayed requests. |
| - _delayedRequests[serial] = request; |
| - } |
| - return request.completer.future; |
| - } |
| - |
| - void _onClose(CloseEvent event) { |
| - _cancelAllRequests(); |
| - _notifyDisconnect(); |
| - } |
| - |
| - // WebSocket error event handler. |
| - void _onError(Event) { |
| - _cancelAllRequests(); |
| - _notifyDisconnect(); |
| - } |
| - |
| - // WebSocket open event handler. |
| - void _onOpen(Event) { |
| - target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch; |
| - _sendAllDelayedRequests(); |
| - _notifyConnect(); |
| - } |
| - |
| - // WebSocket message event handler. |
| - void _onMessage(MessageEvent event) { |
| - var map = JSON.decode(event.data); |
| - if (map == null) { |
| - Logger.root.severe('WebSocketVM got empty message'); |
| - return; |
| - } |
| - // Extract serial and response. |
| - var serial; |
| - var response; |
| - if (target.chrome) { |
| - if (map['method'] != 'Dart.observatoryData') { |
| - // ignore devtools protocol spam. |
| - return; |
| - } |
| - serial = map['params']['id'].toString(); |
| - response = map['params']['data']; |
| - } else { |
| - serial = map['seq']; |
| - response = map['response']; |
| - } |
| - if (serial == null) { |
| - // Messages without sequence numbers are asynchronous events |
| - // from the vm. |
| - postEventMessage(response); |
| - return; |
| - } |
| - // Complete request. |
| - var request = _pendingRequests.remove(serial); |
| - if (request == null) { |
| - Logger.root.severe('Received unexpected message: ${map}'); |
| - return; |
| - } |
| - request.completer.complete(response); |
| - } |
| - |
| - String _generateNetworkError(String userMessage) { |
| - return JSON.encode({ |
| - 'type': 'ServiceException', |
| - 'id': '', |
| - 'kind': 'NetworkException', |
| - 'message': userMessage |
| - }); |
| - } |
| - |
| - void _cancelRequests(Map<String, _WebSocketRequest> requests) { |
| - requests.forEach((String serial, _WebSocketRequest request) { |
| - request.completer.complete( |
| - _generateNetworkError('WebSocket disconnected')); |
| - }); |
| - requests.clear(); |
| - } |
| - |
| - /// Cancel all pending and delayed requests by completing them with an error. |
| - void _cancelAllRequests() { |
| - if (_pendingRequests.length > 0) { |
| - Logger.root.info('Cancelling all pending requests.'); |
| - _cancelRequests(_pendingRequests); |
| - } |
| - if (_delayedRequests.length > 0) { |
| - Logger.root.info('Cancelling all delayed requests.'); |
| - _cancelRequests(_delayedRequests); |
| - } |
| - } |
| - |
| - /// Send all delayed requests. |
| - void _sendAllDelayedRequests() { |
| - assert(_webSocket != null); |
| - if (_delayedRequests.length == 0) { |
| - return; |
| - } |
| - Logger.root.info('Sending all delayed requests.'); |
| - // Send all delayed requests. |
| - _delayedRequests.forEach(_sendRequest); |
| - // Clear all delayed requests. |
| - _delayedRequests.clear(); |
| - } |
| - |
| - /// Send the request over WebSocket. |
| - void _sendRequest(String serial, _WebSocketRequest request) { |
| - assert (_webSocket.readyState == WebSocket.OPEN); |
| - if (!request.id.endsWith('/profile/tag')) { |
| - Logger.root.info('GET ${request.id} from ${target.networkAddress}'); |
| - } |
| - // Mark request as pending. |
| - assert(_pendingRequests.containsKey(serial) == false); |
| - _pendingRequests[serial] = request; |
| - var message; |
| - // Encode message. |
| - if (target.chrome) { |
| - message = JSON.encode({ |
| - 'id': int.parse(serial), |
| - 'method': 'Dart.observatoryQuery', |
| - 'params': { |
| - 'id': serial, |
| - 'query': request.id |
| - } |
| - }); |
| - } else { |
| - message = JSON.encode({'seq': serial, 'request': request.id}); |
| - } |
| - // Send message. |
| - _webSocket.send(message); |
| - } |
| +class WebSocketVM extends CommonWebSocketVM { |
| + WebSocketVM(WebSocketVMTarget target) : super(target, new _HtmlWebSocket()); |
| } |
| // A VM that communicates with the service via posting messages from DevTools. |