blob: b4f487cf6564b521b5a31fcefd0201b4f8cefb3c [file] [log] [blame]
// Copyright (c) 2013, 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.
part of observatory;
/// The LocationManager class observes and parses the hash ('#') portion of the
/// URL in window.location. The text after the '#' is used as the request
/// string for the VM service.
class LocationManager extends Observable {
static const int InvalidIsolateId = 0;
static const String defaultHash = '#/isolates/';
static final RegExp currentIsolateMatcher = new RegExp(r"#/isolates/\d+/");
ObservatoryApplication _application;
ObservatoryApplication get application => _application;
@observable String currentHash = '';
@observable Uri currentHashUri;
void init() {
window.onHashChange.listen((event) {
if (setDefaultHash()) {
// We just triggered another onHashChange event.
return;
}
// Request the current anchor.
requestCurrentHash();
});
if (!setDefaultHash()) {
// An anchor was already present, trigger a request.
requestCurrentHash();
}
}
/// Returns the current isolate prefix, i.e. '#/isolates/XX/' if one
/// is present and null otherwise.
String currentIsolateAnchorPrefix() {
Match m = currentIsolateMatcher.matchAsPrefix(currentHash);
if (m == null) {
return null;
}
return m.input.substring(m.start, m.end);
}
/// Predicate, does the current URL have a current isolate ID in it?
bool get hasCurrentIsolate {
return currentIsolateAnchorPrefix() != null;
}
bool get isScriptLink {
String type = currentHashUri.queryParameters['type'];
return type == 'Script';
}
String get scriptName {
return Uri.decodeQueryComponent(currentHashUri.queryParameters['name']);
}
/// Extract the current isolate id as an integer. Returns [InvalidIsolateId]
/// if none is present in window.location.
int currentIsolateId() {
String isolatePrefix = currentIsolateAnchorPrefix();
if (isolatePrefix == null) {
return InvalidIsolateId;
}
String id = isolatePrefix.split("/")[2];
return int.parse(id);
}
/// If no anchor is set, set the default anchor and return true.
/// Return false otherwise.
bool setDefaultHash() {
currentHash = window.location.hash;
if (currentHash == '' || currentHash == '#') {
window.location.hash = defaultHash;
return true;
}
return false;
}
/// Take the current request string from window.location and submit the
/// request to the request manager.
void requestCurrentHash() {
currentHash = window.location.hash;
// Chomp off the #
String requestUrl = currentHash.substring(1);
currentHashUri = Uri.parse(requestUrl);
application.requestManager.get(requestUrl);
}
/// Create a request for [l] on the current isolate.
@observable
String currentIsolateRelativeLink(String l) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return relativeLink(isolateId, l);
}
/// Create a request for [objectId] on the current isolate.
@observable
String currentIsolateObjectLink(int objectId) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return objectLink(isolateId, objectId);
}
/// Create a request for [cid] on the current isolate.
@observable
String currentIsolateClassLink(int cid) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return classLink(isolateId, cid);
}
/// Create a request for the script [objectId] with script [name].
@observable
String currentIsolateScriptLink(int objectId, String name) {
var isolateId = currentIsolateId();
if (isolateId == LocationManager.InvalidIsolateId) {
return defaultHash;
}
return scriptLink(isolateId, objectId, name);
}
/// Create a request for [l] on [isolateId].
@observable
String relativeLink(int isolateId, String l) {
return '#/isolates/$isolateId/$l';
}
/// Create a request for [objectId] on [isolateId].
@observable
String objectLink(int isolateId, int objectId) {
return '#/isolates/$isolateId/objects/$objectId';
}
/// Create a request for [cid] on [isolateId].
@observable
String classLink(int isolateId, int cid) {
return '#/isolates/$isolateId/classes/$cid';
}
@observable
/// Create a request for the script [objectId] with script [url].
String scriptLink(int isolateId, int objectId, String name) {
String encodedName = Uri.encodeQueryComponent(name);
return '#/isolates/$isolateId/objects/$objectId'
'?type=Script&name=$encodedName';
}
}