- * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * this method will accept a leading slash in the path.
- *
- * @param authority the authority to match
- * @param path the path to match. * may be used as a wild card for
- * any text, and # may be used as a wild card for numbers.
- * @param code the code that is returned when a URI is matched
- * against the given components. Must be positive.
- */
- public void addURI(String scheme, String authority, String path, Object code) {
- if (code == null) {
- throw new IllegalArgumentException("Code can't be null");
- }
-
- String[] tokens = null;
- if (path != null) {
- String newPath = path;
- // Strip leading slash if present.
- if (path.length() > 0 && path.charAt(0) == '/') {
- newPath = path.substring(1);
- }
- tokens = PATH_SPLIT_PATTERN.split(newPath);
- }
-
- int numTokens = tokens != null ? tokens.length : 0;
- UriMatcher node = this;
- for (int i = -2; i < numTokens; i++) {
- String token;
- if (i == -2)
- token = scheme;
- else if (i == -1)
- token = authority;
- else
- token = tokens[i];
- ArrayList
- * This class is intended to be used from within the
- * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, String)} and
- * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView,
- * android.webkit.WebResourceRequest)}
- * methods.
- */
-public class WebViewLocalServer {
- private static String TAG = "WebViewAssetServer";
- private String basePath;
- public final static String httpScheme = "http";
- public final static String httpsScheme = "https";
- public final static String fileStart = "/_app_file_";
- public final static String contentStart = "/_app_content_";
-
- private final UriMatcher uriMatcher;
- private final AndroidProtocolHandler protocolHandler;
- private final String authority;
- private final String customScheme;
- // Whether we're serving local files or proxying (for example, when doing livereload on a
- // non-local endpoint (will be false in that case)
- private boolean isAsset;
- // Whether to route all requests to paths without extensions back to `index.html`
- private final boolean html5mode;
- private ConfigXmlParser parser;
-
- public String getAuthority() { return authority; }
-
- /**
- * A handler that produces responses for paths on the virtual asset server.
- *
- * Methods of this handler will be invoked on a background thread and care must be taken to
- * correctly synchronize access to any shared state.
- *
- * On Android KitKat and above these methods may be called on more than one thread. This thread
- * may be different than the thread on which the shouldInterceptRequest method was invoke.
- * This means that on Android KitKat and above it is possible to block in this method without
- * blocking other resources from loading. The number of threads used to parallelize loading
- * is an internal implementation detail of the WebView and may change between updates which
- * means that the amount of time spend blocking in this method should be kept to an absolute
- * minimum.
- */
- public abstract static class PathHandler {
- protected String mimeType;
- private String encoding;
- private String charset;
- private int statusCode;
- private String reasonPhrase;
- private Maprequest.
- * This method should be invoked from within
- * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView,
- * android.webkit.WebResourceRequest)}.
- *
- * @param uri the request Uri to process.
- * @return a response if the request URL had a matching handler, null if no handler was found.
- */
- public WebResourceResponse shouldInterceptRequest(Uri uri, WebResourceRequest request) {
- PathHandler handler;
- synchronized (uriMatcher) {
- handler = (PathHandler) uriMatcher.match(uri);
- }
- if (handler == null) {
- return null;
- }
-
- if (isLocalFile(uri) || uri.getAuthority().equals(this.authority)) {
- Log.d("SERVER", "Handling local request: " + uri.toString());
- return handleLocalRequest(uri, handler, request);
- } else {
- return handleProxyRequest(uri, handler);
- }
- }
-
- private boolean isLocalFile(Uri uri) {
- String path = uri.getPath();
- if (path.startsWith(contentStart) || path.startsWith(fileStart)) {
- return true;
- }
- return false;
- }
-
-
- private WebResourceResponse handleLocalRequest(Uri uri, PathHandler handler, WebResourceRequest request) {
- String path = uri.getPath();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && request != null && request.getRequestHeaders().get("Range") != null) {
- InputStream responseStream = new LollipopLazyInputStream(handler, uri);
- String mimeType = getMimeType(path, responseStream);
- Mapuri. The handler will be invoked
- * every time the shouldInterceptRequest method of the instance is called with
- * a matching uri.
- *
- * @param uri the uri to use the handler for. The scheme and authority (domain) will be matched
- * exactly. The path may contain a '*' element which will match a single element of
- * a path (so a handler registered for /a/* will be invoked for /a/b and /a/c.html
- * but not for /a/b/b) or the '**' element which will match any number of path
- * elements.
- * @param handler the handler to use for the uri.
- */
- void register(Uri uri, PathHandler handler) {
- synchronized (uriMatcher) {
- uriMatcher.addURI(uri.getScheme(), uri.getAuthority(), uri.getPath(), handler);
- }
- }
-
- /**
- * Hosts the application's assets on an http(s):// URL. Assets from the local path
- * assetPath/... will be available under
- * http(s)://{uuid}.androidplatform.net/assets/....
- *
- * @param assetPath the local path in the application's asset folder which will be made
- * available by the server (for example "/www").
- */
- public void hostAssets(String assetPath) {
- hostAssets(authority, assetPath);
- }
-
-
- /**
- * Hosts the application's assets on an http(s):// URL. Assets from the local path
- * assetPath/... will be available under
- * http(s)://{domain}/{virtualAssetPath}/....
- *
- * @param domain custom domain on which the assets should be hosted (for example "example.com").
- * @param assetPath the local path in the application's asset folder which will be made
- * available by the server (for example "/www").
- * @return prefixes under which the assets are hosted.
- */
- public void hostAssets(final String domain,
- final String assetPath) {
- this.isAsset = true;
- this.basePath = assetPath;
-
- createHostingDetails();
- }
-
- private void createHostingDetails() {
- final String assetPath = this.basePath;
-
- if (assetPath.indexOf('*') != -1) {
- throw new IllegalArgumentException("assetPath cannot contain the '*' character.");
- }
-
- PathHandler handler = new PathHandler() {
- @Override
- public InputStream handle(Uri url) {
- InputStream stream = null;
- String path = url.getPath();
- try {
- if (path.startsWith(contentStart)) {
- stream = protocolHandler.openContentUrl(url);
- } else if (path.startsWith(fileStart) || !isAsset) {
- if (!path.startsWith(fileStart)) {
- path = basePath + url.getPath();
- }
- stream = protocolHandler.openFile(path);
- } else {
- stream = protocolHandler.openAsset(assetPath + path);
- }
- } catch (IOException e) {
- Log.e(TAG, "Unable to open asset URL: " + url);
- return null;
- }
-
- return stream;
- }
- };
-
- registerUriForScheme(httpScheme, handler, authority);
- registerUriForScheme(httpsScheme, handler, authority);
- if (!customScheme.equals(httpScheme) && !customScheme.equals(httpsScheme)) {
- registerUriForScheme(customScheme, handler, authority);
- }
-
- }
-
- private void registerUriForScheme(String scheme, PathHandler handler, String authority) {
- Uri.Builder uriBuilder = new Uri.Builder();
- uriBuilder.scheme(scheme);
- uriBuilder.authority(authority);
- uriBuilder.path("");
- Uri uriPrefix = uriBuilder.build();
-
- register(Uri.withAppendedPath(uriPrefix, "/"), handler);
- register(Uri.withAppendedPath(uriPrefix, "**"), handler);
- }
-
- /**
- * Hosts the application's resources on an http(s):// URL. Resources
- * http(s)://{uuid}.androidplatform.net/res/{resource_type}/{resource_name}.
- *
- * @return prefixes under which the resources are hosted.
- */
- public AssetHostingDetails hostResources() {
- return hostResources(authority, "/res", true, true);
- }
-
- /**
- * Hosts the application's resources on an http(s):// URL. Resources
- * http(s)://{uuid}.androidplatform.net/{virtualResourcesPath}/{resource_type}/{resource_name}.
- *
- * @param virtualResourcesPath the path on the local server under which the resources
- * should be hosted.
- * @param enableHttp whether to enable hosting using the http scheme.
- * @param enableHttps whether to enable hosting using the https scheme.
- * @return prefixes under which the resources are hosted.
- */
- public AssetHostingDetails hostResources(final String virtualResourcesPath, boolean enableHttp,
- boolean enableHttps) {
- return hostResources(authority, virtualResourcesPath, enableHttp, enableHttps);
- }
-
- /**
- * Hosts the application's resources on an http(s):// URL. Resources
- * http(s)://{domain}/{virtualResourcesPath}/{resource_type}/{resource_name}.
- *
- * @param domain custom domain on which the assets should be hosted (for example "example.com").
- * If untrusted content is to be loaded into the WebView it is advised to make
- * this random.
- * @param virtualResourcesPath the path on the local server under which the resources
- * should be hosted.
- * @param enableHttp whether to enable hosting using the http scheme.
- * @param enableHttps whether to enable hosting using the https scheme.
- * @return prefixes under which the resources are hosted.
- */
- public AssetHostingDetails hostResources(final String domain,
- final String virtualResourcesPath, boolean enableHttp,
- boolean enableHttps) {
- if (virtualResourcesPath.indexOf('*') != -1) {
- throw new IllegalArgumentException(
- "virtualResourcesPath cannot contain the '*' character.");
- }
-
- Uri.Builder uriBuilder = new Uri.Builder();
- uriBuilder.scheme(httpScheme);
- uriBuilder.authority(domain);
- uriBuilder.path(virtualResourcesPath);
-
- Uri httpPrefix = null;
- Uri httpsPrefix = null;
-
- PathHandler handler = new PathHandler() {
- @Override
- public InputStream handle(Uri url) {
- InputStream stream = protocolHandler.openResource(url);
- String mimeType = null;
- try {
- mimeType = URLConnection.guessContentTypeFromStream(stream);
- } catch (Exception ex) {
- Log.e(TAG, "Unable to get mime type" + url);
- }
-
- return stream;
- }
- };
-
- if (enableHttp) {
- httpPrefix = uriBuilder.build();
- register(Uri.withAppendedPath(httpPrefix, "**"), handler);
- }
- if (enableHttps) {
- uriBuilder.scheme(httpsScheme);
- httpsPrefix = uriBuilder.build();
- register(Uri.withAppendedPath(httpsPrefix, "**"), handler);
- }
- return new AssetHostingDetails(httpPrefix, httpsPrefix);
- }
-
-
- /**
- * Hosts the application's files on an http(s):// URL. Files from the basePath
- * basePath/... will be available under
- * http(s)://{uuid}.androidplatform.net/....
- *
- * @param basePath the local path in the application's data folder which will be made
- * available by the server (for example "/www").
- */
- public void hostFiles(final String basePath) {
- this.isAsset = false;
- this.basePath = basePath;
- createHostingDetails();
- }
-
- /**
- * The KitKat WebView reads the InputStream on a separate threadpool. We can use that to
- * parallelize loading.
- */
- private static abstract class LazyInputStream extends InputStream {
- protected final PathHandler handler;
- private InputStream is = null;
-
- public LazyInputStream(PathHandler handler) {
- this.handler = handler;
- }
-
- private InputStream getInputStream() {
- if (is == null) {
- is = handle();
- }
- return is;
- }
-
- protected abstract InputStream handle();
-
- @Override
- public int available() throws IOException {
- InputStream is = getInputStream();
- return (is != null) ? is.available() : 0;
- }
-
- @Override
- public int read() throws IOException {
- InputStream is = getInputStream();
- return (is != null) ? is.read() : -1;
- }
-
- @Override
- public int read(byte b[]) throws IOException {
- InputStream is = getInputStream();
- return (is != null) ? is.read(b) : -1;
- }
-
- @Override
- public int read(byte b[], int off, int len) throws IOException {
- InputStream is = getInputStream();
- return (is != null) ? is.read(b, off, len) : -1;
- }
-
- @Override
- public long skip(long n) throws IOException {
- InputStream is = getInputStream();
- return (is != null) ? is.skip(n) : 0;
- }
- }
-
- // For L and above.
- private static class LollipopLazyInputStream extends LazyInputStream {
- private Uri uri;
- private InputStream is;
-
- public LollipopLazyInputStream(PathHandler handler, Uri uri) {
- super(handler);
- this.uri = uri;
- }
-
- @Override
- protected InputStream handle() {
- return handler.handle(uri);
- }
- }
-
- public String getBasePath(){
- return this.basePath;
- }
-}
diff --git a/src/www/util.js b/src/www/util.js
index ba52a8e9..c5f834fc 100644
--- a/src/www/util.js
+++ b/src/www/util.js
@@ -16,14 +16,8 @@ var WebView = {
}
return url;
},
- setServerBasePath: function(path) {
- exec(null, null, 'IonicWebView', 'setServerBasePath', [path]);
- },
getServerBasePath: function(callback) {
exec(callback, null, 'IonicWebView', 'getServerBasePath', []);
- },
- persistServerBasePath: function() {
- exec(null, null, 'IonicWebView', 'persistServerBasePath', []);
}
}