CB-8702 Add API for plugins to override shouldInterceptRequest with a stream

This commit is contained in:
Andrew Grieve 2015-03-18 11:02:27 -04:00
parent 15530a4820
commit 8d5cb00bec
3 changed files with 84 additions and 3 deletions

View File

@ -28,6 +28,9 @@ import org.json.JSONException;
import android.content.Intent;
import android.net.Uri;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* Plugins must extend this class and override one of the execute methods.
*/
@ -249,11 +252,53 @@ public class CordovaPlugin {
/**
* Hook for redirecting requests. Applies to WebView requests as well as requests made by plugins.
* To handle the request directly, return a URI in the form:
*
* cdvplugin://pluginId/...
*
* And implement handleOpenForRead().
* To make this easier, use the toPluginUri() and fromPluginUri() helpers:
*
* public Uri remapUri(Uri uri) { return toPluginUri(uri); }
*
* public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
* Uri origUri = fromPluginUri(uri);
* ...
* }
*/
public Uri remapUri(Uri uri) {
return null;
}
/**
* Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.
* Should never return null.
* Added in cordova-android@4.0.0
*/
public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
throw new FileNotFoundException("Plugin can't handle uri: " + uri);
}
/**
* Refer to remapUri()
* Added in cordova-android@4.0.0
*/
protected Uri toPluginUri(Uri origUri) {
return new Uri.Builder()
.scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)
.authority(serviceName)
.appendQueryParameter("origUri", origUri.toString())
.build();
}
/**
* Refer to remapUri()
* Added in cordova-android@4.0.0
*/
protected Uri fromPluginUri(Uri pluginUri) {
return Uri.parse(pluginUri.getQueryParameter("origUri"));
}
/**
* Called when the WebView does a top-level navigation or refreshes.
*

View File

@ -72,8 +72,11 @@ public class CordovaResourceApi {
public static final int URI_TYPE_DATA = 4;
public static final int URI_TYPE_HTTP = 5;
public static final int URI_TYPE_HTTPS = 6;
public static final int URI_TYPE_PLUGIN = 7;
public static final int URI_TYPE_UNKNOWN = -1;
public static final String PLUGIN_URI_SCHEME = "cdvplugin";
private static final String[] LOCAL_FILE_PROJECTION = { "_data" };
public static Thread jsThread;
@ -123,6 +126,9 @@ public class CordovaResourceApi {
if ("https".equals(scheme)) {
return URI_TYPE_HTTPS;
}
if (PLUGIN_URI_SCHEME.equals(scheme)) {
return URI_TYPE_PLUGIN;
}
return URI_TYPE_UNKNOWN;
}
@ -282,6 +288,14 @@ public class CordovaResourceApi {
InputStream inputStream = conn.getInputStream();
return new OpenForReadResult(uri, inputStream, mimeType, length, null);
}
case URI_TYPE_PLUGIN: {
String pluginId = uri.getHost();
CordovaPlugin plugin = pluginManager.getPlugin(pluginId);
if (plugin == null) {
throw new FileNotFoundException("Invalid plugin ID in URI: " + uri);
}
return plugin.handleOpenForRead(uri);
}
}
throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
}
@ -431,7 +445,7 @@ public class CordovaResourceApi {
public final long length;
public final AssetFileDescriptor assetFd;
OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
public OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
this.uri = uri;
this.inputStream = inputStream;
this.mimeType = mimeType;

View File

@ -36,9 +36,11 @@ import org.apache.cordova.PluginEntry;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class CordovaResourceApiTest extends BaseCordovaIntegrationTest {
@ -58,8 +60,18 @@ public class CordovaResourceApiTest extends BaseCordovaIntegrationTest {
return cordovaWebView.getResourceApi().remapUri(
Uri.parse("data:text/plain;charset=utf-8,pass"));
}
if (uri.getQuery() != null && uri.getQuery().contains("pluginUri")) {
return toPluginUri(uri);
}
return null;
}
@Override
public OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
Uri orig = fromPluginUri(uri);
ByteArrayInputStream retStream = new ByteArrayInputStream(orig.toString().getBytes(StandardCharsets.UTF_8));
return new OpenForReadResult(uri, retStream, "text/plain", retStream.available(), null);
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
synchronized (CordovaResourceApiTest.this) {
execPayload = args.getString(0);
@ -214,6 +226,16 @@ public class CordovaResourceApiTest extends BaseCordovaIntegrationTest {
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals("pass", data);
}
// testPluginUris
{
String origUri = "http://orig/foo?pluginUri";
Uri uri = resourceApi.remapUri(Uri.parse(origUri));
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("openForRead mime-type", "text/plain", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals(origUri, data);
assertEquals(origUri.length(), readResult.length);
}
}
public void testWebViewRequestIntercept() throws Throwable