diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 209dd791..85f481d6 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -38,6 +38,7 @@ import android.util.Log; import android.view.View; import android.webkit.HttpAuthHandler; import android.webkit.SslErrorHandler; +import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -66,7 +67,7 @@ public class CordovaWebViewClient extends WebViewClient { /** * Constructor. - * + * * @param cordova * @param view */ @@ -77,7 +78,7 @@ public class CordovaWebViewClient extends WebViewClient { /** * Constructor. - * + * * @param view */ public void setWebView(CordovaWebView view) { @@ -101,8 +102,8 @@ public class CordovaWebViewClient extends WebViewClient { String callbackId = url.substring(idx3 + 1, idx4); String jsonArgs = url.substring(idx4 + 1); appView.pluginManager.exec(service, action, callbackId, jsonArgs); - } - + } + /** * Give the host application a chance to take over the control when a new url * is about to be loaded in the current WebView. @@ -210,6 +211,21 @@ public class CordovaWebViewClient extends WebViewClient { return true; } + /** + * Check for intercepting any requests for resources. + * This includes images and scripts and so on, not just top-level pages. + * @param view The WebView. + * @param url The URL to be loaded. + * @return Either null to proceed as normal, or a WebResourceResponse. + */ + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if (this.appView.pluginManager != null) { + return this.appView.pluginManager.shouldInterceptRequest(url); + } + return null; + } + /** * 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 @@ -226,7 +242,7 @@ public class CordovaWebViewClient extends WebViewClient { AuthenticationToken token = this.getAuthenticationToken(host, realm); if (token != null) { handler.proceed(token.getUserName(), token.getPassword()); - } + } else { // Handle 401 like we'd normally do! super.onReceivedHttpAuthRequest(view, handler, host, realm); @@ -234,11 +250,11 @@ public class CordovaWebViewClient extends WebViewClient { } /** - * Notify the host application that a page has started loading. - * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted - * one time for the main frame. This also means that onPageStarted will not be called when the contents of an - * embedded frame changes, i.e. clicking a link whose target is an iframe. - * + * Notify the host application that a page has started loading. + * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted + * one time for the main frame. This also means that onPageStarted will not be called when the contents of an + * embedded frame changes, i.e. clicking a link whose target is an iframe. + * * @param view The webview initiating the callback. * @param url The url of the page. */ @@ -260,7 +276,7 @@ public class CordovaWebViewClient extends WebViewClient { /** * Notify the host application that a page has finished loading. * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. - * + * * * @param view The webview initiating the callback. * @param url The url of the page. @@ -349,11 +365,11 @@ public class CordovaWebViewClient extends WebViewClient { } /** - * Notify the host application that an SSL error occurred while loading a resource. - * The host application must call either handler.cancel() or handler.proceed(). - * Note that the decision may be retained for use in response to future SSL errors. + * Notify the host application that an SSL error occurred while loading a resource. + * The host application must call either handler.cancel() or handler.proceed(). + * Note that the decision may be retained for use in response to future SSL errors. * The default behavior is to cancel the load. - * + * * @param view The WebView that is initiating the callback. * @param handler An SslErrorHandler object that will handle the user's response. * @param error The SSL error object. @@ -385,7 +401,7 @@ public class CordovaWebViewClient extends WebViewClient { /** * Sets the authentication token. - * + * * @param authenticationToken * @param host * @param realm @@ -402,10 +418,10 @@ public class CordovaWebViewClient extends WebViewClient { /** * Removes the authentication token. - * + * * @param host * @param realm - * + * * @return the authentication token or null if did not exist */ public AuthenticationToken removeAuthenticationToken(String host, String realm) { @@ -414,16 +430,16 @@ public class CordovaWebViewClient extends WebViewClient { /** * Gets the authentication token. - * + * * In order it tries: * 1- host + realm * 2- host * 3- realm * 4- no host, no realm - * + * * @param host * @param realm - * + * * @return the authentication token */ public AuthenticationToken getAuthenticationToken(String host, String realm) { diff --git a/framework/src/org/apache/cordova/api/CordovaPlugin.java b/framework/src/org/apache/cordova/api/CordovaPlugin.java index f4c785e1..2b225e64 100644 --- a/framework/src/org/apache/cordova/api/CordovaPlugin.java +++ b/framework/src/org/apache/cordova/api/CordovaPlugin.java @@ -22,7 +22,12 @@ import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaWebView; import org.json.JSONArray; import org.json.JSONException; + +import android.annotation.TargetApi; import android.content.Intent; +import android.os.Build; +import android.util.Log; +import android.webkit.WebResourceResponse; /** * Plugins must extend this class and override one of the execute methods. @@ -150,7 +155,7 @@ public class CordovaPlugin { } /** - * By specifying a in plugins.xml you can map a URL (using startsWith atm) to this method. + * By specifying a in config.xml you can map a URL (using startsWith atm) to this method. * * @param url The URL that is trying to be loaded in the Cordova webview. * @return Return true to prevent the URL from loading. Default is false. @@ -159,6 +164,17 @@ public class CordovaPlugin { return false; } + /** + * By specifying a in config.xml you can map a URL prefix to this method. It applies to all resources loaded in the WebView, not just top-level navigation. + * + * @param url The URL of the resource to be loaded. + * @return Return a WebResourceResponse for the resource, or null to let the WebView handle it normally. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public WebResourceResponse shouldInterceptRequest(String url) { + return null; + } + /** * Called when the WebView does a top-level navigation or refreshes. * diff --git a/framework/src/org/apache/cordova/api/PluginManager.java b/framework/src/org/apache/cordova/api/PluginManager.java index d0e6aef4..337ef129 100755 --- a/framework/src/org/apache/cordova/api/PluginManager.java +++ b/framework/src/org/apache/cordova/api/PluginManager.java @@ -30,6 +30,8 @@ import org.xmlpull.v1.XmlPullParserException; import android.content.Intent; import android.content.res.XmlResourceParser; +import android.webkit.WebResourceResponse; + /** * PluginManager is exposed to JavaScript in the Cordova WebView. * @@ -118,7 +120,7 @@ public class PluginManager { // System.out.println("Plugin: "+name+" => "+value); onload = "true".equals(xml.getAttributeValue(null, "onload")); entry = new PluginEntry(service, pluginClass, onload); - this.addService(entry); + this.addService(entry); } //What is this? else if (strNode.equals("url-filter")) { @@ -366,6 +368,25 @@ public class PluginManager { return false; } + /** + * Called when the WebView is loading any resource, top-level or not. + * + * Uses the same url-filter tag as onOverrideUrlLoading. + * + * @param url The URL of the resource to be loaded. + * @return Return a WebResourceResponse with the resource, or null if the WebView should handle it. + */ + public WebResourceResponse shouldInterceptRequest(String url) { + Iterator> it = this.urlMap.entrySet().iterator(); + while (it.hasNext()) { + HashMap.Entry pairs = it.next(); + if (url.startsWith(pairs.getKey())) { + return this.getPlugin(pairs.getValue()).shouldInterceptRequest(url); + } + } + return null; + } + /** * Called when the app navigates or refreshes. */