Android implementation of UrlRemap.
Project: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/commit/5ab66f57 Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/5ab66f57 Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/5ab66f57 Branch: refs/heads/master Commit: 5ab66f572d071e0ddcc67284202ad3aa9e7ab908 Parents: 06150bc Author: Andrew Grieve <[email protected]> Authored: Wed Oct 23 21:43:29 2013 -0400 Committer: Andrew Grieve <[email protected]> Committed: Wed Oct 23 21:55:18 2013 -0400 ---------------------------------------------------------------------- UrlRemap/src/android/UrlRemap.java | 164 +++++++++++++------------------- 1 file changed, 64 insertions(+), 100 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/5ab66f57/UrlRemap/src/android/UrlRemap.java ---------------------------------------------------------------------- diff --git a/UrlRemap/src/android/UrlRemap.java b/UrlRemap/src/android/UrlRemap.java index deb7f12..fe49b7e 100644 --- a/UrlRemap/src/android/UrlRemap.java +++ b/UrlRemap/src/android/UrlRemap.java @@ -23,127 +23,94 @@ import java.util.List; import java.util.regex.Pattern; import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaPlugin; +import org.json.JSONException; + import android.net.Uri; -import android.net.Uri.Builder; -import android.util.Log; public class UrlRemap extends CordovaPlugin { - private static final String LOG_TAG = "UrlRemap"; - private static final String APP_BUNDLE_REPLACED = "UrlRemapReplaced"; - private static class RouteParams { - public String matchRegex; - public String replaceRegex; - public String replacer; - public boolean redirectToReplacedUrl; - - public RouteParams(String matchRegex, String replaceRegex, String replacer, boolean redirectToReplacedUrl){ - this.matchRegex = matchRegex; - this.replaceRegex = replaceRegex; - this.replacer = replacer; - this.redirectToReplacedUrl = redirectToReplacedUrl; - } + Pattern matchRegex; + Pattern replaceRegex; + String replacer; + boolean redirectToReplacedUrl; + String jsToInject; } - private final String BUNDLE_PATH = "file:///android_asset/www/"; // Have a default replacement path that redirects app-bundle: uri's to the bundle - private final RouteParams appBundleParams = new RouteParams("^app-bundle:///.*", "^app-bundle:///", BUNDLE_PATH, true); + private RouteParams resetUrlParams; private List<RouteParams> rerouteParams = new ArrayList<RouteParams>(); @Override - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - resetMap(); - } - private void resetMap(){ - rerouteParams.clear(); - rerouteParams.add(appBundleParams); - } - - @Override - public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) { + public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { if ("addAlias".equals(action)) { - addAlias(args, callbackContext); - return true; + RouteParams params = new RouteParams(); + params.matchRegex = Pattern.compile(args.getString(0)); + params.replaceRegex = Pattern.compile(args.getString(1)); + params.replacer = args.getString(2); + params.redirectToReplacedUrl = args.getBoolean(3); + rerouteParams.add(params); } else if ("clearAllAliases".equals(action)) { - clearAllAliases(args, callbackContext); - return true; + resetMappings(); + } else if ("injectJs".equals(action)) { + RouteParams params = new RouteParams(); + params.matchRegex = Pattern.compile(args.getString(0)); + params.jsToInject = args.getString(1); + rerouteParams.add(params); + } else if ("setResetUrl".equals(action)) { + resetUrlParams = new RouteParams(); + resetUrlParams.matchRegex = Pattern.compile(args.getString(0)); + } else { + return false; } - return false; + callbackContext.success(); + return true; } - private void addAlias(CordovaArgs args, CallbackContext callbackContext) { - try { - String sourceUrlMatchRegex = args.getString(0).replace("{BUNDLE_WWW}", getRegex(BUNDLE_PATH)); - String sourceUrlReplaceRegex = args.getString(1).replace("{BUNDLE_WWW}", getRegex(BUNDLE_PATH)); - String replaceString = args.getString(2).replace("{BUNDLE_WWW}", BUNDLE_PATH); - boolean redirectToReplacedUrl = args.getBoolean(3); - if(replaceString.matches(sourceUrlMatchRegex)){ - callbackContext.error("The replaceString cannot match the match regex. This would lead to recursive replacements."); - } else { - rerouteParams.add(new RouteParams(sourceUrlMatchRegex, sourceUrlReplaceRegex, replaceString, redirectToReplacedUrl)); - callbackContext.success(); - } - } catch(Exception e) { - callbackContext.error("Could not add alias"); - Log.e(LOG_TAG, "Could not add alias"); - } + private void resetMappings() { + resetUrlParams = null; + rerouteParams.clear(); } - private void clearAllAliases(CordovaArgs args, CallbackContext callbackContext) { - try { - resetMap(); - callbackContext.success(); - } catch(Exception e) { - callbackContext.error("Could not clear aliases"); - Log.e(LOG_TAG, "Could not clear aliases"); + private RouteParams getChosenParams(String url, boolean forInjection) { + for (RouteParams params : rerouteParams) { + if ((params.jsToInject != null) == forInjection && params.matchRegex.matcher(url).find()) { + return params; + } } + return null; } + + @Override + public boolean onOverrideUrlLoading(String url) { + if (resetUrlParams != null && resetUrlParams.matchRegex.matcher(url).find()) { + resetMappings(); + } - private String getRegex(String string){ - return Pattern.quote(string); - } + RouteParams params = getChosenParams(url, false); + // Check if we need to replace the url + if (params != null && params.redirectToReplacedUrl) { + String newUrl = params.replaceRegex.matcher(url).replaceFirst(params.replacer); - private RouteParams getChosenParams(String uri){ - if(uri == null) { - return null; - } else { - uri = Uri.parse(uri).toString(); - } - for(int i = rerouteParams.size() - 1; i >= 0; i--){ - RouteParams param = rerouteParams.get(i); - if(uri.matches(param.matchRegex)){ - return param; + if (resetUrlParams != null && resetUrlParams.matchRegex.matcher(newUrl).find()) { + resetMappings(); } + + webView.loadUrl(newUrl); + return true; } - return null; + return false; } @Override public Object onMessage(String id, Object data) { // Look for top level navigation changes - if("onPageStarted".equals(id)){ - String url = data == null? null: data.toString(); - RouteParams params = getChosenParams(url); - // Check if we need to replace the url - if(params != null && params.redirectToReplacedUrl) { - Uri uri = Uri.parse(url); - // Check that the APP_BUNDLE_REPLACED query param doesn't exist. - // If it exists this means a previous app-bundle uri was rerouted to 'uri'. So we shouldn't reroute further. - if(uri.getQueryParameter(APP_BUNDLE_REPLACED) == null){ - String newPath = url.replaceAll(params.replaceRegex, params.replacer); - //We need to special case app-bundle: uri's to make sure they aren't redirected when we load the modified url - if(params.equals(appBundleParams)){ - // Throw in a APP_BUNDLE_REPLACED query parameter - Builder builder = Uri.parse(newPath).buildUpon(); - builder.appendQueryParameter(APP_BUNDLE_REPLACED, "true"); - newPath = builder.build().toString(); - } - webView.stopLoading(); - webView.loadUrl(newPath); - } + if ("onPageFinished".equals(id) && data != null) { + String url = data.toString(); + RouteParams params = getChosenParams(url, true); + if (params != null) { + webView.sendJavascript(params.jsToInject); } } return null; @@ -152,14 +119,11 @@ public class UrlRemap extends CordovaPlugin { @Override public Uri remapUri(Uri uri) { String uriAsString = uri.toString(); - RouteParams params = getChosenParams(uriAsString); - if (params != null){ - // Just send data as we can't tell if this is top level or not. - // If this is a top level request, it will get trapped in the onPageStarted event handled above. - String newUri = uriAsString.replaceAll(params.replaceRegex, params.replacer); - return webView.getResourceApi().remapUri(Uri.parse(newUri)); - } else { - return uri; + RouteParams params = getChosenParams(uriAsString, false); + if (params != null && !params.redirectToReplacedUrl) { + String newUrl = params.replaceRegex.matcher(uriAsString).replaceFirst(params.replacer); + return Uri.parse(newUrl); } + return null; } }
