blob: 6d99a4368da7060fb0be4e2cd53ba8ab2529d83c [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library observatory_sky_shell_service_client;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class ServiceClient {
Completer<dynamic> isolateStartedId;
Completer<dynamic> isolatePausedId;
Completer<dynamic> isolateResumeId;
ServiceClient(this.client, {this.isolateStartedId, this.isolatePausedId,
this.isolateResumeId}) {
client.listen(_onData,
onError: _onError,
cancelOnError: true);
}
Future<Map<String, dynamic>> invokeRPC(String method, [Map<String, dynamic> params]) async {
final String key = _createKey();
final String request = json.encode(<String, dynamic>{
'jsonrpc': '2.0',
'method': method,
'params': params == null ? <String, dynamic>{} : params,
'id': key,
});
client.add(request);
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
_outstandingRequests[key] = completer;
print('-> $key ($method)');
return completer.future;
}
String _createKey() {
final String key = '$_id';
_id++;
return key;
}
void _onData(dynamic message) {
final Map<String, dynamic> response = json.decode(message);
final dynamic key = response['id'];
if (key != null) {
print('<- $key');
final dynamic completer = _outstandingRequests.remove(key);
assert(completer != null);
final dynamic result = response['result'];
final dynamic error = response['error'];
if (error != null) {
assert(result == null);
completer.completeError(error);
} else {
assert(result != null);
completer.complete(result);
}
} else {
if (response['method'] == 'streamNotify') {
_onServiceEvent(response['params']);
}
}
}
void _onServiceEvent(Map<String, dynamic> params) {
if (params == null) {
return;
}
final Map<String, dynamic> event = params['event'];
if (event == null || event['type'] != 'Event') {
return;
}
final dynamic isolateId = event['isolate']['id'];
switch (params['streamId']) {
case 'Isolate':
if (event['kind'] == 'IsolateStart') {
isolateStartedId?.complete(isolateId);
}
break;
case 'Debug':
switch (event['kind']) {
case 'Resume':
isolateResumeId?.complete(isolateId);
break;
case 'PauseStart':
isolatePausedId?.complete(isolateId);
break;
}
break;
}
}
void _onError(dynamic error) {
print('WebSocket error: $error');
}
final WebSocket client;
final Map<String, Completer<dynamic>> _outstandingRequests = <String, Completer<dynamic>>{};
int _id = 1;
}