blob: 1a892aa4d9b8860123f9d17c62223c7d57952a72 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library service_html;
import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'package:logging/logging.dart';
import 'package:observatory/service.dart';
// Export the service library.
export 'package:observatory/service.dart';
class HttpVM extends VM {
String host;
bool runningInJavaScript() => identical(1.0, 1);
HttpVM() : super() {
if (runningInJavaScript()) {
// When we are running as JavaScript use the same hostname:port
// that the Observatory is loaded from.
host = 'http://${window.location.host}/';
} else {
// Otherwise, assume we are running from the Dart Editor and
// want to connect on the default port.
host = 'http://127.0.0.1:8181/';
}
}
Future<String> getString(String id) {
Logger.root.info('Fetching $id from $host');
return HttpRequest.getString(host + id).catchError((error) {
// If we get an error here, the network request has failed.
Logger.root.severe('HttpRequest.getString failed.');
var request = error.target;
return JSON.encode({
'type': 'ServiceException',
'id': '',
'response': error.target.responseText,
'kind': 'NetworkException',
'message': 'Could not connect to service. Check that you started the'
' VM with the following flags:\n --enable-vm-service'
' --pause-isolates-on-exit'
});
});
}
}
class WebSocketVM extends VM {
final Map<int, Completer> _pendingRequests =
new Map<int, Completer>();
int _requestSerial = 0;
String _host;
Future<WebSocket> _socketFuture;
bool runningInJavaScript() => identical(1.0, 1);
WebSocketVM() : super() {
if (runningInJavaScript()) {
// When we are running as JavaScript use the same hostname:port
// that the Observatory is loaded from.
_host = 'ws://${window.location.host}/ws';
} else {
// Otherwise, assume we are running from the Dart Editor and
// want to connect on the default port.
_host = 'ws://127.0.0.1:8181/ws';
}
var completer = new Completer<WebSocket>();
_socketFuture = completer.future;
var socket = new WebSocket(_host);
socket.onOpen.first.then((_) {
socket.onMessage.listen(_handleMessage);
socket.onClose.first.then((_) {
_socketFuture = null;
});
completer.complete(socket);
});
socket.onError.first.then((_) {
_socketFuture = null;
});
}
void _handleMessage(MessageEvent event) {
var map = JSON.decode(event.data);
int seq = map['seq'];
var response = map['response'];
var completer = _pendingRequests.remove(seq);
if (completer == null) {
Logger.root.severe('Received unexpected message: ${map}');
} else {
completer.complete(response);
}
}
Future<String> getString(String id) {
if (_socketFuture == null) {
var errorResponse = JSON.encode({
'type': 'ServiceException',
'id': '',
'response': '',
'kind': 'NetworkException',
'message': 'Could not connect to service. Check that you started the'
' VM with the following flags:\n --enable-vm-service'
' --pause-isolates-on-exit'
});
return new Future.value(errorResponse);
}
return _socketFuture.then((socket) {
int seq = _requestSerial++;
if (!id.endsWith('/profile/tag')) {
Logger.root.info('Fetching $id from $_host');
}
var completer = new Completer<String>();
_pendingRequests[seq] = completer;
var message = JSON.encode({'seq': seq, 'request': id});
socket.send(message);
return completer.future;
});
}
}
class DartiumVM extends VM {
final Map<String, Completer> _pendingRequests =
new Map<String, Completer>();
int _requestSerial = 0;
DartiumVM() : super() {
window.onMessage.listen(_messageHandler);
Logger.root.info('Connected to DartiumVM');
}
void _messageHandler(msg) {
var id = msg.data['id'];
var name = msg.data['name'];
var data = msg.data['data'];
if (name != 'observatoryData') {
return;
}
var completer = _pendingRequests[id];
assert(completer != null);
_pendingRequests.remove(id);
completer.complete(data);
}
Future<String> getString(String path) {
var idString = '$_requestSerial';
Map message = {};
message['id'] = idString;
message['method'] = 'observatoryQuery';
message['query'] = '/$path';
_requestSerial++;
var completer = new Completer();
_pendingRequests[idString] = completer;
window.parent.postMessage(JSON.encode(message), '*');
return completer.future;
}
}