Chromium Code Reviews| Index: runtime/observatory/lib/src/app/location_manager.dart |
| diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart |
| index 86e71e5ef9ab2f11b911e3df655cb789aeb1dd02..14f8de9eb3fa75064c22ce43a655b7a049da098d 100644 |
| --- a/runtime/observatory/lib/src/app/location_manager.dart |
| +++ b/runtime/observatory/lib/src/app/location_manager.dart |
| @@ -4,11 +4,48 @@ |
| part of app; |
| -abstract class LocationManager extends Observable { |
| - final _initialPath = '/vm'; |
| - ObservatoryApplication _app; |
| +/// Utility class to decode and encode the fragment (starts with '#') portion |
| +/// of a url, including any query parameters. |
| +class FragmentUri { |
|
turnidge
2015/04/07 21:24:31
Do we need to introduce this class? What if we ju
Cutch
2015/04/14 21:45:15
I've redone this part of the CL.
|
| + String _path; |
| + String get path => _path; |
| + final Map<String, String> parameters = new Map<String, String>(); |
| + |
| + FragmentUri(String url) { |
| + // Chop off leading '#'. |
| + if (url.startsWith('#')) { |
| + url = url.substring(1); |
| + } |
| + var queryStringIndex = url.indexOf('?'); |
| + if (queryStringIndex == -1) { |
| + _path = url; |
| + } else { |
| + _path = url.substring(0, queryStringIndex); |
| + parameters.addAll( |
| + Uri.splitQueryString(url.substring(queryStringIndex + 1))); |
| + } |
| + } |
| - String _lastUrl; |
| + FragmentUri.from(FragmentUri other) { |
| + _path = other._path; |
| + parameters.addAll(other.parameters); |
| + } |
| + |
| + String toString() { |
| + if (parameters.isEmpty) { |
| + return '#$_path'; |
| + } |
| + var encodedParameters = new Uri(queryParameters: parameters).query; |
| + return '#${_path}?${encodedParameters}'; |
| + } |
| +} |
| + |
| +class LocationManager extends Observable { |
| + final _defaultPath = '/vm'; |
| + ObservatoryApplication _app; |
| + FragmentUri _fragment; |
| + FragmentUri get fragment => _fragment; |
| + String _url; |
| void _init(ObservatoryApplication app) { |
| // Called once. |
| @@ -16,33 +53,34 @@ abstract class LocationManager extends Observable { |
| _app = app; |
| // Register for history events. |
| window.onPopState.listen(_onLocationChange); |
| - _onStartup(); |
| + |
| + var applicationPath = '${window.location.hash}'; |
| + if ((window.location.hash == '') || (window.location.hash == '#')) { |
| + // Observatory has loaded but no application path has been specified, |
| + // use the default. |
| + applicationPath = '#${_defaultPath}'; |
| + } |
| + // Update current application path. |
| + window.history.replaceState(applicationPath, |
| + document.title, |
| + applicationPath); |
| + _updateCurrent(applicationPath); |
| + _go(applicationPath); |
| } |
| - void _onStartup(); |
| - void _onLocationChange(PopStateEvent event); |
| + void _updateCurrent(String url) { |
| + _url = url; |
| + _fragment = new FragmentUri(url); |
| + } |
| void _pushUrl(String url) { |
| - if (_lastUrl != url) { |
| + if (_url != url) { |
| Logger.root.info('Navigated to ${url}'); |
| window.history.pushState(url, document.title, url); |
| - _lastUrl = url; |
| + _updateCurrent(url); |
| } |
| } |
| - /// Go to a specific url. |
| - void go(String url) { |
| - if ((url != makeLink('/vm-connect/')) && _app.vm == null) { |
| - if (!window.confirm('Connection with VM has been lost. ' |
| - 'Proceeding will lose current page.')) { |
| - return; |
| - } |
| - url = makeLink('/vm-connect/'); |
| - } |
| - _pushUrl(url); |
| - _go(url); |
| - } |
| - |
| void _go(String url) { |
| // Chop off leading '#'. |
| if (url.startsWith('#')) { |
| @@ -65,14 +103,27 @@ abstract class LocationManager extends Observable { |
| _app._visit(url, args); |
| } |
| - /// Go back. |
| - void back() { |
| - window.history.go(-1); |
| + /// Go to a specific url. |
| + void go(String url) { |
| + if ((url != makeLink('/vm-connect/')) && _app.vm == null) { |
| + if (!window.confirm('Connection with VM has been lost. ' |
| + 'Proceeding will lose current page.')) { |
| + return; |
| + } |
| + url = makeLink('/vm-connect/'); |
| + } |
| + _pushUrl(url); |
| + _go(url); |
| } |
| - /// Go forward. |
| - void forward() { |
| - window.history.go(1); |
| + /// Starting with the current url, update all parameters present in |
| + /// [updatedParameters], then generate a new url and navigate to that. |
| + goParameter(Map updatedParameters) { |
| + var fragment = new FragmentUri.from(_fragment); |
| + updatedParameters.forEach((k, v) { |
| + fragment.parameters[k] = v; |
| + }); |
| + go(fragment.toString()); |
| } |
| /// Handle clicking on an application url link. |
| @@ -89,50 +140,12 @@ abstract class LocationManager extends Observable { |
| event.preventDefault(); |
| } |
| - /// Given an application url, generate a link. |
| - String makeLink(String url); |
| -} |
| - |
| -/// Uses location.hash to encode application urls. |
| -class HashLocationManager extends LocationManager { |
| - void _onStartup() { |
| - String initialPath = '${window.location.hash}'; |
| - if ((window.location.hash == '') || (window.location.hash == '#')) { |
| - initialPath = '#${_initialPath}'; |
| - } |
| - window.history.pushState(initialPath, document.title, initialPath); |
| + /// Called whenever the browser changes the location bar (e.g. back button). |
| + void _onLocationChange(PopStateEvent event) { |
| + _updateCurrent(window.location.hash); |
| _go(window.location.hash); |
| } |
| - void _onLocationChange(PopStateEvent _) { |
| - _go(window.location.hash); |
| - } |
| - |
| - /// Given an application url, generate a link for an anchor tag. |
| - String makeLink(String url) { |
| - return '#$url'; |
| - } |
| -} |
| - |
| -/// Uses location.pathname to encode application urls. Requires server side |
| -/// rewriting to support copy and paste linking. pub serve makes this hard. |
| -/// STATUS: Work in progress. |
| -class LinkLocationManager extends LocationManager { |
| - void _onStartup() { |
| - Logger.root.warning('Using untested LinkLocationManager'); |
| - String initialPath = window.location.pathname; |
| - if ((window.location.pathname == '/index.html') || |
| - (window.location.pathname == '/')) { |
| - initialPath = '/vm'; |
| - } |
| - window.history.replaceState(initialPath, document.title, initialPath); |
| - _go(window.location.pathname); |
| - } |
| - |
| - void _onLocationChange(PopStateEvent _) { |
| - _go(window.location.pathname); |
| - } |
| - |
| - /// Given an application url, generate a link for an anchor tag. |
| - String makeLink(String url) => url; |
| + /// Given an application url, generate a link. |
| + String makeLink(String url) => '#$url'; |
| } |