| 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:developer' show ServiceProtocolInfo; |
| 10 import 'dart:isolate'; | 11 import 'dart:isolate'; |
| 12 import 'dart:math'; |
| 11 import 'dart:typed_data'; | 13 import 'dart:typed_data'; |
| 12 | 14 |
| 13 part 'asset.dart'; | 15 part 'asset.dart'; |
| 14 part 'client.dart'; | 16 part 'client.dart'; |
| 15 part 'devfs.dart'; | 17 part 'devfs.dart'; |
| 16 part 'constants.dart'; | 18 part 'constants.dart'; |
| 17 part 'running_isolate.dart'; | 19 part 'running_isolate.dart'; |
| 18 part 'running_isolates.dart'; | 20 part 'running_isolates.dart'; |
| 19 part 'message.dart'; | 21 part 'message.dart'; |
| 20 part 'message_router.dart'; | 22 part 'message_router.dart'; |
| 21 | 23 |
| 22 final RawReceivePort isolateLifecyclePort = new RawReceivePort(); | 24 final RawReceivePort isolateControlPort = new RawReceivePort(); |
| 23 final RawReceivePort scriptLoadPort = new RawReceivePort(); | 25 final RawReceivePort scriptLoadPort = new RawReceivePort(); |
| 24 | 26 |
| 25 abstract class IsolateEmbedderData { | 27 abstract class IsolateEmbedderData { |
| 26 void cleanup(); | 28 void cleanup(); |
| 27 } | 29 } |
| 28 | 30 |
| 31 String _makeAuthToken() { |
| 32 final kTokenByteSize = 8; |
| 33 Uint8List bytes = new Uint8List(kTokenByteSize); |
| 34 Random random = new Random.secure(); |
| 35 for (int i = 0; i < kTokenByteSize; i++) { |
| 36 bytes[i] = random.nextInt(256); |
| 37 } |
| 38 return BASE64URL.encode(bytes); |
| 39 } |
| 40 |
| 41 // The randomly generated auth token used to access the VM service. |
| 42 final String serviceAuthToken = _makeAuthToken(); |
| 43 |
| 44 // TODO(johnmccutchan): Enable the auth token and drop the origin check. |
| 45 final bool useAuthToken = false; |
| 46 |
| 29 // This is for use by the embedder. It is a map from the isolateId to | 47 // This is for use by the embedder. It is a map from the isolateId to |
| 30 // anything implementing IsolateEmbedderData. When an isolate goes away, | 48 // anything implementing IsolateEmbedderData. When an isolate goes away, |
| 31 // the cleanup method will be invoked after being removed from the map. | 49 // the cleanup method will be invoked after being removed from the map. |
| 32 final Map<int, IsolateEmbedderData> isolateEmbedderData = | 50 final Map<int, IsolateEmbedderData> isolateEmbedderData = |
| 33 new Map<int, IsolateEmbedderData>(); | 51 new Map<int, IsolateEmbedderData>(); |
| 34 | 52 |
| 35 // These must be kept in sync with the declarations in vm/json_stream.h. | 53 // These must be kept in sync with the declarations in vm/json_stream.h. |
| 36 const kInvalidParams = -32602; | 54 const kInvalidParams = -32602; |
| 37 const kInternalError = -32603; | 55 const kInternalError = -32603; |
| 38 const kFeatureDisabled = 100; | 56 const kFeatureDisabled = 100; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 136 |
| 119 /// Called to write a stream into a file. | 137 /// Called to write a stream into a file. |
| 120 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); | 138 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); |
| 121 | 139 |
| 122 /// Called to read a file. | 140 /// Called to read a file. |
| 123 typedef Future<List<int>> ReadFileCallback(Uri path); | 141 typedef Future<List<int>> ReadFileCallback(Uri path); |
| 124 | 142 |
| 125 /// Called to list all files under some path. | 143 /// Called to list all files under some path. |
| 126 typedef Future<List<Map<String,String>>> ListFilesCallback(Uri path); | 144 typedef Future<List<Map<String,String>>> ListFilesCallback(Uri path); |
| 127 | 145 |
| 146 /// Called when we need information about the server. |
| 147 typedef Future<Uri> ServerInformationCallback(); |
| 148 |
| 149 /// Called when we want to [enable] or disable the web server. |
| 150 typedef Future<Uri> WebServerControlCallback(bool enable); |
| 151 |
| 128 /// Hooks that are setup by the embedder. | 152 /// Hooks that are setup by the embedder. |
| 129 class VMServiceEmbedderHooks { | 153 class VMServiceEmbedderHooks { |
| 130 static ServerStartCallback serverStart; | 154 static ServerStartCallback serverStart; |
| 131 static ServerStopCallback serverStop; | 155 static ServerStopCallback serverStop; |
| 132 static CleanupCallback cleanup; | 156 static CleanupCallback cleanup; |
| 133 static CreateTempDirCallback createTempDir; | 157 static CreateTempDirCallback createTempDir; |
| 134 static DeleteDirCallback deleteDir; | 158 static DeleteDirCallback deleteDir; |
| 135 static WriteFileCallback writeFile; | 159 static WriteFileCallback writeFile; |
| 136 static WriteStreamFileCallback writeStreamFile; | 160 static WriteStreamFileCallback writeStreamFile; |
| 137 static ReadFileCallback readFile; | 161 static ReadFileCallback readFile; |
| 138 static ListFilesCallback listFiles; | 162 static ListFilesCallback listFiles; |
| 163 static ServerInformationCallback serverInformation; |
| 164 static WebServerControlCallback webServerControl; |
| 139 } | 165 } |
| 140 | 166 |
| 141 class VMService extends MessageRouter { | 167 class VMService extends MessageRouter { |
| 142 static VMService _instance; | 168 static VMService _instance; |
| 143 | 169 |
| 144 /// Collection of currently connected clients. | 170 /// Collection of currently connected clients. |
| 145 final Set<Client> clients = new Set<Client>(); | 171 final Set<Client> clients = new Set<Client>(); |
| 146 | 172 |
| 147 /// Collection of currently running isolates. | 173 /// Collection of currently running isolates. |
| 148 RunningIsolates runningIsolates = new RunningIsolates(); | 174 RunningIsolates runningIsolates = new RunningIsolates(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: | 213 case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: |
| 188 runningIsolates.isolateShutdown(portId, sp); | 214 runningIsolates.isolateShutdown(portId, sp); |
| 189 IsolateEmbedderData ied = isolateEmbedderData.remove(portId); | 215 IsolateEmbedderData ied = isolateEmbedderData.remove(portId); |
| 190 if (ied != null) { | 216 if (ied != null) { |
| 191 ied.cleanup(); | 217 ied.cleanup(); |
| 192 } | 218 } |
| 193 break; | 219 break; |
| 194 } | 220 } |
| 195 } | 221 } |
| 196 | 222 |
| 223 Future<Null> _serverMessageHandler(int code, SendPort sp, bool enable) async { |
| 224 switch (code) { |
| 225 case Constants.WEB_SERVER_CONTROL_MESSAGE_ID: |
| 226 if (VMServiceEmbedderHooks.webServerControl == null) { |
| 227 sp.send(null); |
| 228 return; |
| 229 } |
| 230 Uri uri = await VMServiceEmbedderHooks.webServerControl(enable); |
| 231 sp.send(uri); |
| 232 break; |
| 233 case Constants.SERVER_INFO_MESSAGE_ID: |
| 234 if (VMServiceEmbedderHooks.serverInformation == null) { |
| 235 sp.send(null); |
| 236 return; |
| 237 } |
| 238 Uri uri = await VMServiceEmbedderHooks.serverInformation(); |
| 239 sp.send(uri); |
| 240 break; |
| 241 } |
| 242 } |
| 243 |
| 197 Future _exit() async { | 244 Future _exit() async { |
| 198 // Stop the server. | 245 // Stop the server. |
| 199 if (VMServiceEmbedderHooks.serverStop != null) { | 246 if (VMServiceEmbedderHooks.serverStop != null) { |
| 200 await VMServiceEmbedderHooks.serverStop(); | 247 await VMServiceEmbedderHooks.serverStop(); |
| 201 } | 248 } |
| 202 | 249 |
| 203 // Close receive ports. | 250 // Close receive ports. |
| 204 isolateLifecyclePort.close(); | 251 isolateControlPort.close(); |
| 205 scriptLoadPort.close(); | 252 scriptLoadPort.close(); |
| 206 | 253 |
| 207 // Create a copy of the set as a list because client.disconnect() will | 254 // Create a copy of the set as a list because client.disconnect() will |
| 208 // alter the connected clients set. | 255 // alter the connected clients set. |
| 209 var clientsList = clients.toList(); | 256 var clientsList = clients.toList(); |
| 210 for (var client in clientsList) { | 257 for (var client in clientsList) { |
| 211 client.disconnect(); | 258 client.disconnect(); |
| 212 } | 259 } |
| 213 devfs.cleanup(); | 260 devfs.cleanup(); |
| 214 if (VMServiceEmbedderHooks.cleanup != null) { | 261 if (VMServiceEmbedderHooks.cleanup != null) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 226 assert(message[1] is String || message[1] is Uint8List); | 273 assert(message[1] is String || message[1] is Uint8List); |
| 227 _eventMessageHandler(message); | 274 _eventMessageHandler(message); |
| 228 return; | 275 return; |
| 229 } | 276 } |
| 230 if (message.length == 1) { | 277 if (message.length == 1) { |
| 231 // This is a control message directing the vm service to exit. | 278 // This is a control message directing the vm service to exit. |
| 232 assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); | 279 assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); |
| 233 _exit(); | 280 _exit(); |
| 234 return; | 281 return; |
| 235 } | 282 } |
| 283 if (message.length == 3) { |
| 284 // This is a message interacting with the web server. |
| 285 assert((message[0] == Constants.WEB_SERVER_CONTROL_MESSAGE_ID) || |
| 286 (message[0] == Constants.SERVER_INFO_MESSAGE_ID)); |
| 287 _serverMessageHandler(message[0], message[1], message[2]); |
| 288 return; |
| 289 } |
| 236 if (message.length == 4) { | 290 if (message.length == 4) { |
| 237 // This is a message informing us of the birth or death of an | 291 // This is a message informing us of the birth or death of an |
| 238 // isolate. | 292 // isolate. |
| 239 _controlMessageHandler(message[0], message[1], message[2], message[3]); | 293 _controlMessageHandler(message[0], message[1], message[2], message[3]); |
| 240 return; | 294 return; |
| 241 } | 295 } |
| 242 } | 296 } |
| 243 print('Internal vm-service error: ignoring illegal message: $message'); | 297 print('Internal vm-service error: ignoring illegal message: $message'); |
| 244 } | 298 } |
| 245 | 299 |
| 246 VMService._internal() | 300 VMService._internal() |
| 247 : eventPort = isolateLifecyclePort { | 301 : eventPort = isolateControlPort { |
| 248 eventPort.handler = messageHandler; | 302 eventPort.handler = messageHandler; |
| 249 } | 303 } |
| 250 | 304 |
| 251 factory VMService() { | 305 factory VMService() { |
| 252 if (VMService._instance == null) { | 306 if (VMService._instance == null) { |
| 253 VMService._instance = new VMService._internal(); | 307 VMService._instance = new VMService._internal(); |
| 254 _onStart(); | 308 _onStart(); |
| 255 } | 309 } |
| 256 return _instance; | 310 return _instance; |
| 257 } | 311 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 return devfs.handleMessage(message); | 472 return devfs.handleMessage(message); |
| 419 } | 473 } |
| 420 if (message.params['isolateId'] != null) { | 474 if (message.params['isolateId'] != null) { |
| 421 return runningIsolates.route(message); | 475 return runningIsolates.route(message); |
| 422 } | 476 } |
| 423 return message.sendToVM(); | 477 return message.sendToVM(); |
| 424 } | 478 } |
| 425 } | 479 } |
| 426 | 480 |
| 427 RawReceivePort boot() { | 481 RawReceivePort boot() { |
| 428 // Return the port we expect isolate startup and shutdown messages on. | 482 // Return the port we expect isolate control messages on. |
| 429 return isolateLifecyclePort; | 483 return isolateControlPort; |
| 430 } | 484 } |
| 431 | 485 |
| 432 void _registerIsolate(int port_id, SendPort sp, String name) { | 486 void _registerIsolate(int port_id, SendPort sp, String name) { |
| 433 var service = new VMService(); | 487 var service = new VMService(); |
| 434 service.runningIsolates.isolateStartup(port_id, sp, name); | 488 service.runningIsolates.isolateStartup(port_id, sp, name); |
| 435 } | 489 } |
| 436 | 490 |
| 437 /// Notify the VM that the service is running. | 491 /// Notify the VM that the service is running. |
| 438 external void _onStart(); | 492 external void _onStart(); |
| 439 | 493 |
| 440 /// Notify the VM that the service is no longer running. | 494 /// Notify the VM that the service is no longer running. |
| 441 external void _onExit(); | 495 external void _onExit(); |
| 442 | 496 |
| 443 /// Notify the VM that the server's address has changed. | 497 /// Notify the VM that the server's address has changed. |
| 444 external void onServerAddressChange(String address); | 498 external void onServerAddressChange(String address); |
| 445 | 499 |
| 446 /// Subscribe to a service stream. | 500 /// Subscribe to a service stream. |
| 447 external bool _vmListenStream(String streamId); | 501 external bool _vmListenStream(String streamId); |
| 448 | 502 |
| 449 /// Cancel a subscription to a service stream. | 503 /// Cancel a subscription to a service stream. |
| 450 external void _vmCancelStream(String streamId); | 504 external void _vmCancelStream(String streamId); |
| 451 | 505 |
| 452 /// Get the bytes to the tar archive. | 506 /// Get the bytes to the tar archive. |
| 453 external Uint8List _requestAssets(); | 507 external Uint8List _requestAssets(); |
| 454 | 508 |
| 455 /// Notify the vm service that an isolate has been spawned via rpc. | 509 /// Notify the vm service that an isolate has been spawned via rpc. |
| 456 external void _spawnUriNotify(obj, String token); | 510 external void _spawnUriNotify(obj, String token); |
| OLD | NEW |