| OLD | NEW | 
|---|
| 1 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dart._vmservice; | 5 library dart._vmservice; | 
| 6 | 6 | 
| 7 import 'dart:async'; | 7 import 'dart:async'; | 
| 8 import 'dart:collection'; | 8 import 'dart:collection'; | 
| 9 import 'dart:convert'; | 9 import 'dart:convert'; | 
| 10 import 'dart:isolate'; | 10 import 'dart:isolate'; | 
| 11 import 'dart:typed_data'; | 11 import 'dart:typed_data'; | 
| 12 | 12 | 
| 13 part 'asset.dart'; | 13 part 'asset.dart'; | 
| 14 part 'client.dart'; | 14 part 'client.dart'; | 
| 15 part 'constants.dart'; | 15 part 'constants.dart'; | 
| 16 part 'running_isolate.dart'; | 16 part 'running_isolate.dart'; | 
| 17 part 'running_isolates.dart'; | 17 part 'running_isolates.dart'; | 
| 18 part 'message.dart'; | 18 part 'message.dart'; | 
| 19 part 'message_router.dart'; | 19 part 'message_router.dart'; | 
| 20 | 20 | 
| 21 final RawReceivePort isolateLifecyclePort = new RawReceivePort(); | 21 final RawReceivePort isolateLifecyclePort = new RawReceivePort(); | 
| 22 final RawReceivePort scriptLoadPort = new RawReceivePort(); | 22 final RawReceivePort scriptLoadPort = new RawReceivePort(); | 
| 23 | 23 | 
| 24 typedef ShutdownCallback(); |  | 
| 25 |  | 
| 26 // These must be kept in sync with the declarations in vm/json_stream.h. | 24 // These must be kept in sync with the declarations in vm/json_stream.h. | 
| 27 const kInvalidParams = -32602; | 25 const kInvalidParams = -32602; | 
| 28 const kInternalError = -32603; | 26 const kInternalError = -32603; | 
| 29 const kStreamAlreadySubscribed = 103; | 27 const kStreamAlreadySubscribed = 103; | 
| 30 const kStreamNotSubscribed = 104; | 28 const kStreamNotSubscribed = 104; | 
| 31 | 29 | 
| 32 var _errorMessages = { | 30 var _errorMessages = { | 
| 33   kInvalidParams: 'Invalid params', | 31   kInvalidParams: 'Invalid params', | 
| 34   kInternalError: 'Internal error', | 32   kInternalError: 'Internal error', | 
| 35   kStreamAlreadySubscribed: 'Stream already subscribed', | 33   kStreamAlreadySubscribed: 'Stream already subscribed', | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 55 | 53 | 
| 56 String encodeResult(Message message, Map result) { | 54 String encodeResult(Message message, Map result) { | 
| 57   var response = { | 55   var response = { | 
| 58     'jsonrpc': '2.0', | 56     'jsonrpc': '2.0', | 
| 59     'id' : message.serial, | 57     'id' : message.serial, | 
| 60     'result' : result, | 58     'result' : result, | 
| 61   }; | 59   }; | 
| 62   return JSON.encode(response); | 60   return JSON.encode(response); | 
| 63 } | 61 } | 
| 64 | 62 | 
|  | 63 const shortDelay = const Duration(milliseconds: 10); | 
|  | 64 | 
|  | 65 /// Called when the server should be started. | 
|  | 66 typedef Future ServerStartCallback(); | 
|  | 67 | 
|  | 68 /// Called when the server should be stopped. | 
|  | 69 typedef Future ServerStopCallback(); | 
|  | 70 | 
|  | 71 /// Called when the service is exiting. | 
|  | 72 typedef Future CleanupCallback(); | 
|  | 73 | 
|  | 74 /// Hooks that are setup by the embedder. | 
|  | 75 class VMServiceEmbedderHooks { | 
|  | 76   static ServerStartCallback serverStart; | 
|  | 77   static ServerStopCallback serverStop; | 
|  | 78   static CleanupCallback cleanup; | 
|  | 79 } | 
| 65 | 80 | 
| 66 class VMService extends MessageRouter { | 81 class VMService extends MessageRouter { | 
| 67   static VMService _instance; | 82   static VMService _instance; | 
| 68 | 83 | 
| 69   /// Collection of currently connected clients. | 84   /// Collection of currently connected clients. | 
| 70   final Set<Client> clients = new Set<Client>(); | 85   final Set<Client> clients = new Set<Client>(); | 
| 71 | 86 | 
| 72   /// Collection of currently running isolates. | 87   /// Collection of currently running isolates. | 
| 73   RunningIsolates runningIsolates = new RunningIsolates(); | 88   RunningIsolates runningIsolates = new RunningIsolates(); | 
| 74 | 89 | 
| 75   /// A port used to receive events from the VM. | 90   /// A port used to receive events from the VM. | 
| 76   final RawReceivePort eventPort; | 91   final RawReceivePort eventPort; | 
| 77 | 92 | 
| 78   ShutdownCallback onShutdown; |  | 
| 79 |  | 
| 80   void _addClient(Client client) { | 93   void _addClient(Client client) { | 
| 81     assert(client.streams.isEmpty); | 94     assert(client.streams.isEmpty); | 
| 82     clients.add(client); | 95     clients.add(client); | 
| 83   } | 96   } | 
| 84 | 97 | 
| 85   void _removeClient(Client client) { | 98   void _removeClient(Client client) { | 
| 86     clients.remove(client); | 99     clients.remove(client); | 
| 87     for (var streamId in client.streams) { | 100     for (var streamId in client.streams) { | 
| 88       if (!_isAnyClientSubscribed(streamId)) { | 101       if (!_isAnyClientSubscribed(streamId)) { | 
| 89         _vmCancelStream(streamId); | 102         _vmCancelStream(streamId); | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 108     switch (code) { | 121     switch (code) { | 
| 109       case Constants.ISOLATE_STARTUP_MESSAGE_ID: | 122       case Constants.ISOLATE_STARTUP_MESSAGE_ID: | 
| 110         runningIsolates.isolateStartup(portId, sp, name); | 123         runningIsolates.isolateStartup(portId, sp, name); | 
| 111       break; | 124       break; | 
| 112       case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: | 125       case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: | 
| 113         runningIsolates.isolateShutdown(portId, sp); | 126         runningIsolates.isolateShutdown(portId, sp); | 
| 114       break; | 127       break; | 
| 115     } | 128     } | 
| 116   } | 129   } | 
| 117 | 130 | 
| 118   void _exit() { | 131   Future _exit() async { | 
|  | 132     // Stop the server. | 
|  | 133     if (VMServiceEmbedderHooks.serverStop != null) { | 
|  | 134       await VMServiceEmbedderHooks.serverStop(); | 
|  | 135     } | 
|  | 136 | 
|  | 137     // Close receive ports. | 
| 119     isolateLifecyclePort.close(); | 138     isolateLifecyclePort.close(); | 
| 120     scriptLoadPort.close(); | 139     scriptLoadPort.close(); | 
|  | 140 | 
| 121     // Create a copy of the set as a list because client.disconnect() will | 141     // Create a copy of the set as a list because client.disconnect() will | 
| 122     // alter the connected clients set. | 142     // alter the connected clients set. | 
| 123     var clientsList = clients.toList(); | 143     var clientsList = clients.toList(); | 
| 124     for (var client in clientsList) { | 144     for (var client in clientsList) { | 
| 125       client.disconnect(); | 145       client.disconnect(); | 
| 126     } | 146     } | 
| 127     // Call embedder shutdown hook after the internal shutdown. | 147     if (VMServiceEmbedderHooks.cleanup != null) { | 
| 128     if (onShutdown != null) { | 148       await VMServiceEmbedderHooks.cleanup(); | 
| 129       onShutdown(); |  | 
| 130     } | 149     } | 
|  | 150     // Notify the VM that we have exited. | 
| 131     _onExit(); | 151     _onExit(); | 
| 132   } | 152   } | 
| 133 | 153 | 
| 134   void messageHandler(message) { | 154   void messageHandler(message) { | 
| 135     if (message is List) { | 155     if (message is List) { | 
| 136       if (message.length == 2) { | 156       if (message.length == 2) { | 
| 137         // This is an event. | 157         // This is an event. | 
| 138         assert(message[0] is String); | 158         assert(message[0] is String); | 
| 139         assert(message[1] is String || message[1] is Uint8List); | 159         assert(message[1] is String || message[1] is Uint8List); | 
| 140         _eventMessageHandler(message); | 160         _eventMessageHandler(message); | 
| 141         return; | 161         return; | 
| 142       } | 162       } | 
| 143       if (message.length == 1) { | 163       if (message.length == 1) { | 
| 144         // This is a control message directing the vm service to exit. | 164         // This is a control message directing the vm service to exit. | 
| 145         assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); | 165         assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); | 
| 146         _exit(); | 166         _exit(); | 
| 147         return; | 167         return; | 
| 148       } | 168       } | 
| 149       if (message.length == 4) { | 169       if (message.length == 4) { | 
| 150         // This is a message informing us of the birth or death of an | 170         // This is a message informing us of the birth or death of an | 
| 151         // isolate. | 171         // isolate. | 
| 152         _controlMessageHandler(message[0], message[1], message[2], message[3]); | 172         _controlMessageHandler(message[0], message[1], message[2], message[3]); | 
| 153         return; | 173         return; | 
| 154       } | 174       } | 
| 155     } | 175     } | 
| 156     print('Internal vm-service error: ignoring illegal message: $message'); | 176     print('Internal vm-service error: ignoring illegal message: $message'); | 
| 157   } | 177   } | 
| 158 | 178 | 
| 159   void _notSupported(_) { |  | 
| 160     throw new UnimplementedError('Service script loading not supported.'); |  | 
| 161   } |  | 
| 162 |  | 
| 163   VMService._internal() | 179   VMService._internal() | 
| 164       : eventPort = isolateLifecyclePort { | 180       : eventPort = isolateLifecyclePort { | 
| 165     scriptLoadPort.handler = _notSupported; |  | 
| 166     eventPort.handler = messageHandler; | 181     eventPort.handler = messageHandler; | 
| 167   } | 182   } | 
| 168 | 183 | 
| 169   factory VMService() { | 184   factory VMService() { | 
| 170     if (VMService._instance == null) { | 185     if (VMService._instance == null) { | 
| 171       VMService._instance = new VMService._internal(); | 186       VMService._instance = new VMService._internal(); | 
| 172       _onStart(); | 187       _onStart(); | 
| 173     } | 188     } | 
| 174     return _instance; | 189     return _instance; | 
| 175   } | 190   } | 
| 176 | 191 | 
| 177   void _clientCollection(Message message) { |  | 
| 178     var members = []; |  | 
| 179     var result = {}; |  | 
| 180     clients.forEach((client) { |  | 
| 181       members.add(client.toJson()); |  | 
| 182     }); |  | 
| 183     result['type'] = 'ClientList'; |  | 
| 184     result['members'] = members; |  | 
| 185     message.setResponse(JSON.encode(result)); |  | 
| 186   } |  | 
| 187 |  | 
| 188   bool _isAnyClientSubscribed(String streamId) { | 192   bool _isAnyClientSubscribed(String streamId) { | 
| 189     for (var client in clients) { | 193     for (var client in clients) { | 
| 190       if (client.streams.contains(streamId)) { | 194       if (client.streams.contains(streamId)) { | 
| 191         return true; | 195         return true; | 
| 192       } | 196       } | 
| 193     } | 197     } | 
| 194     return false; | 198     return false; | 
| 195   } | 199   } | 
| 196 | 200 | 
| 197   Future<String> _streamListen(Message message) async { | 201   Future<String> _streamListen(Message message) async { | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 286 | 290 | 
| 287     // Encode the entire crash dump. | 291     // Encode the entire crash dump. | 
| 288     return encodeResult(message, responses); | 292     return encodeResult(message, responses); | 
| 289   } | 293   } | 
| 290 | 294 | 
| 291   Future<String> route(Message message) { | 295   Future<String> route(Message message) { | 
| 292     if (message.completed) { | 296     if (message.completed) { | 
| 293       return message.response; | 297       return message.response; | 
| 294     } | 298     } | 
| 295     // TODO(turnidge): Update to json rpc.  BEFORE SUBMIT. | 299     // TODO(turnidge): Update to json rpc.  BEFORE SUBMIT. | 
| 296     if ((message.path.length == 1) && (message.path[0] == 'clients')) { |  | 
| 297       _clientCollection(message); |  | 
| 298       return message.response; |  | 
| 299     } |  | 
| 300     if (message.method == '_getCrashDump') { | 300     if (message.method == '_getCrashDump') { | 
| 301       return _getCrashDump(message); | 301       return _getCrashDump(message); | 
| 302     } | 302     } | 
| 303     if (message.method == 'streamListen') { | 303     if (message.method == 'streamListen') { | 
| 304       return _streamListen(message); | 304       return _streamListen(message); | 
| 305     } | 305     } | 
| 306     if (message.method == 'streamCancel') { | 306     if (message.method == 'streamCancel') { | 
| 307       return _streamCancel(message); | 307       return _streamCancel(message); | 
| 308     } | 308     } | 
| 309     if (message.params['isolateId'] != null) { | 309     if (message.params['isolateId'] != null) { | 
| 310       return runningIsolates.route(message); | 310       return runningIsolates.route(message); | 
| 311     } | 311     } | 
| 312     return message.sendToVM(); | 312     return message.sendToVM(); | 
| 313   } | 313   } | 
| 314 } | 314 } | 
| 315 | 315 | 
| 316 RawReceivePort boot() { | 316 RawReceivePort boot() { | 
| 317   // Return the port we expect isolate startup and shutdown messages on. | 317   // Return the port we expect isolate startup and shutdown messages on. | 
| 318   return isolateLifecyclePort; | 318   return isolateLifecyclePort; | 
| 319 } | 319 } | 
| 320 | 320 | 
| 321 void _registerIsolate(int port_id, SendPort sp, String name) { | 321 void _registerIsolate(int port_id, SendPort sp, String name) { | 
| 322   var service = new VMService(); | 322   var service = new VMService(); | 
| 323   service.runningIsolates.isolateStartup(port_id, sp, name); | 323   service.runningIsolates.isolateStartup(port_id, sp, name); | 
| 324 } | 324 } | 
| 325 | 325 | 
|  | 326 /// Notify the VM that the service is running. | 
| 326 external void _onStart(); | 327 external void _onStart(); | 
| 327 | 328 | 
|  | 329 /// Notify the VM that the service is no longer running. | 
| 328 external void _onExit(); | 330 external void _onExit(); | 
| 329 | 331 | 
|  | 332 /// Notify the VM that the server's address has changed. | 
|  | 333 external void onServerAddressChange(String address); | 
|  | 334 | 
|  | 335 /// Subscribe to a service stream. | 
| 330 external bool _vmListenStream(String streamId); | 336 external bool _vmListenStream(String streamId); | 
| 331 | 337 | 
|  | 338 /// Cancel a subscription to a service stream. | 
| 332 external void _vmCancelStream(String streamId); | 339 external void _vmCancelStream(String streamId); | 
| 333 | 340 | 
|  | 341 /// Get the bytes to the tar archive. | 
| 334 external Uint8List _requestAssets(); | 342 external Uint8List _requestAssets(); | 
| OLD | NEW | 
|---|