Add Android 4.0 workaround for links with params

Android 4.0.x has a known bug [1] while accessing local files with
params:

file://file.html?param=2

This commit adds a workaround for this problem by removing the params
part of the local URI before accessing the file.

[1] http://code.google.com/p/android/issues/detail?id=17535
This commit is contained in:
Juan G. Hurtado 2012-05-16 08:37:40 +02:00 committed by Viafirma
parent fc50a0d954
commit 45680a562e

View File

@ -38,35 +38,35 @@ import android.webkit.WebViewClient;
* This class is the WebViewClient that implements callbacks for our web view. * This class is the WebViewClient that implements callbacks for our web view.
*/ */
public class CordovaWebViewClient extends WebViewClient { public class CordovaWebViewClient extends WebViewClient {
private static final String TAG = "Cordova"; private static final String TAG = "Cordova";
DroidGap ctx; DroidGap ctx;
private boolean doClearHistory = false; private boolean doClearHistory = false;
/** /**
* Constructor. * Constructor.
* *
* @param ctx * @param ctx
*/ */
public CordovaWebViewClient(DroidGap ctx) { public CordovaWebViewClient(DroidGap ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
/** /**
* Give the host application a chance to take over the control when a new url * Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView. * is about to be loaded in the current WebView.
* *
* @param view The WebView that is initiating the callback. * @param view The WebView that is initiating the callback.
* @param url The url to be loaded. * @param url The url to be loaded.
* @return true to override, false for default behavior * @return true to override, false for default behavior
*/ */
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves // First give any plugins the chance to handle the url themselves
if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) { if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) {
} }
// If dialing phone (tel:5551212) // If dialing phone (tel:5551212)
else if (url.startsWith(WebView.SCHEME_TEL)) { else if (url.startsWith(WebView.SCHEME_TEL)) {
try { try {
@ -154,11 +154,11 @@ public class CordovaWebViewClient extends WebViewClient {
} }
return true; return true;
} }
/** /**
* On received http auth request. * On received http auth request.
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
* *
* @param view * @param view
* the view * the view
* @param handler * @param handler
@ -171,27 +171,27 @@ public class CordovaWebViewClient extends WebViewClient {
@Override @Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
String realm) { String realm) {
// get the authentication token // get the authentication token
AuthenticationToken token = ctx.getAuthenticationToken(host,realm); AuthenticationToken token = ctx.getAuthenticationToken(host,realm);
if(token != null) { if(token != null) {
handler.proceed(token.getUserName(), token.getPassword()); handler.proceed(token.getUserName(), token.getPassword());
} }
} }
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
// Clear history so history.back() doesn't do anything. // Clear history so history.back() doesn't do anything.
// So we can reinit() native side CallbackServer & PluginManager. // So we can reinit() native side CallbackServer & PluginManager.
view.clearHistory(); view.clearHistory();
this.doClearHistory = true; this.doClearHistory = true;
} }
/** /**
* Notify the host application that a page has finished loading. * Notify the host application that a page has finished loading.
* *
* @param view The webview initiating the callback. * @param view The webview initiating the callback.
* @param url The url of the page. * @param url The url of the page.
*/ */
@ -200,8 +200,8 @@ public class CordovaWebViewClient extends WebViewClient {
super.onPageFinished(view, url); super.onPageFinished(view, url);
/** /**
* Because of a timing issue we need to clear this history in onPageFinished as well as * Because of a timing issue we need to clear this history in onPageFinished as well as
* onPageStarted. However we only want to do this if the doClearHistory boolean is set to * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
* true. You see when you load a url with a # in it which is common in jQuery applications * true. You see when you load a url with a # in it which is common in jQuery applications
* onPageStared is not called. Clearing the history at that point would break jQuery apps. * onPageStared is not called. Clearing the history at that point would break jQuery apps.
*/ */
@ -252,15 +252,15 @@ public class CordovaWebViewClient extends WebViewClient {
this.ctx.endActivity(); this.ctx.endActivity();
} }
} }
/** /**
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
* The errorCode parameter corresponds to one of the ERROR_* constants. * The errorCode parameter corresponds to one of the ERROR_* constants.
* *
* @param view The WebView that is initiating the callback. * @param view The WebView that is initiating the callback.
* @param errorCode The error code corresponding to an ERROR_* value. * @param errorCode The error code corresponding to an ERROR_* value.
* @param description A String describing the error. * @param description A String describing the error.
* @param failingUrl The url that failed to load. * @param failingUrl The url that failed to load.
*/ */
@Override @Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
@ -275,9 +275,9 @@ public class CordovaWebViewClient extends WebViewClient {
// Handle error // Handle error
this.ctx.onReceivedError(errorCode, description, failingUrl); this.ctx.onReceivedError(errorCode, description, failingUrl);
} }
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.ctx.getPackageName(); final String packageName = this.ctx.getPackageName();
final PackageManager pm = this.ctx.getPackageManager(); final PackageManager pm = this.ctx.getPackageManager();
ApplicationInfo appInfo; ApplicationInfo appInfo;
@ -289,7 +289,7 @@ public class CordovaWebViewClient extends WebViewClient {
return; return;
} else { } else {
// debug = false // debug = false
super.onReceivedSslError(view, handler, error); super.onReceivedSslError(view, handler, error);
} }
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
// When it doubt, lock it out! // When it doubt, lock it out!
@ -299,7 +299,7 @@ public class CordovaWebViewClient extends WebViewClient {
@Override @Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
/* /*
* If you do a document.location.href the url does not get pushed on the stack * If you do a document.location.href the url does not get pushed on the stack
* so we do a check here to see if the url should be pushed. * so we do a check here to see if the url should be pushed.
*/ */
@ -307,4 +307,40 @@ public class CordovaWebViewClient extends WebViewClient {
this.ctx.pushUrl(url); this.ctx.pushUrl(url);
} }
} }
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if(url.contains("?")){
return generateWebResourceResponse(url);
} else {
return super.shouldInterceptRequest(view, url);
}
}
private WebResourceResponse generateWebResourceResponse(String url) {
final String ANDROID_ASSET = "file:///android_asset/";
if (url.startsWith(ANDROID_ASSET)) {
String niceUrl = url;
niceUrl = url.replaceFirst(ANDROID_ASSET, "");
if(niceUrl.contains("?")){
niceUrl = niceUrl.split("\\?")[0];
}
String mimetype = null;
if(niceUrl.endsWith(".html")){
mimetype = "text/html";
}
try {
AssetManager assets = ctx.getAssets();
Uri uri = Uri.parse(niceUrl);
InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING);
WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream);
return response;
} catch (IOException e) {
Log.e("generateWebResourceResponse", e.getMessage(), e);
}
}
return null;
}
} }