blob: 29660211f0556009bedf227c13f3d49d9791a24b [file] [log] [blame]
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.test.ActivityInstrumentationTestCase2;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaResourceApi.OpenForReadResult;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginEntry;
import org.apache.cordova.test.actions.CordovaWebViewTestActivity;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
public class CordovaResourceApiTest extends ActivityInstrumentationTestCase2<CordovaWebViewTestActivity> {
public CordovaResourceApiTest()
{
super(CordovaWebViewTestActivity.class);
}
CordovaWebView cordovaWebView;
CordovaResourceApi resourceApi;
private CordovaWebViewTestActivity activity;
String execPayload;
Integer execStatus;
protected void setUp() throws Exception {
super.setUp();
activity = this.getActivity();
cordovaWebView = activity.cordovaWebView;
resourceApi = cordovaWebView.getResourceApi();
resourceApi.setThreadCheckingEnabled(false);
cordovaWebView.pluginManager.addService(new PluginEntry("CordovaResourceApiTestPlugin1", new CordovaPlugin() {
@Override
public Uri remapUri(Uri uri) {
if (uri.getQuery() != null && uri.getQuery().contains("pluginRewrite")) {
return cordovaWebView.getResourceApi().remapUri(
Uri.parse("data:text/plain;charset=utf-8,pass"));
}
return null;
}
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
synchronized (CordovaResourceApiTest.this) {
execPayload = args.getString(0);
execStatus = args.getInt(1);
CordovaResourceApiTest.this.notify();
}
return true;
}
}));
}
private Uri createTestImageContentUri() {
Bitmap imageBitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.icon);
String stored = MediaStore.Images.Media.insertImage(activity.getContentResolver(),
imageBitmap, "app-icon", "desc");
return Uri.parse(stored);
}
private void performApiTest(Uri uri, String expectedMimeType, File expectedLocalFile,
boolean expectRead, boolean expectWrite) throws IOException {
uri = resourceApi.remapUri(uri);
assertEquals(expectedLocalFile, resourceApi.mapUriToFile(uri));
try {
OpenForReadResult readResult = resourceApi.openForRead(uri);
String mimeType2 = resourceApi.getMimeType(uri);
assertEquals("openForRead mime-type", expectedMimeType, readResult.mimeType);
assertEquals("getMimeType mime-type", expectedMimeType, mimeType2);
readResult.inputStream.read();
if (!expectRead) {
fail("Expected getInputStream to throw.");
}
} catch (IOException e) {
if (expectRead) {
throw e;
}
}
try {
OutputStream outStream = resourceApi.openOutputStream(uri);
outStream.write(123);
if (!expectWrite) {
fail("Expected getOutputStream to throw.");
}
outStream.close();
} catch (IOException e) {
if (expectWrite) {
throw e;
}
}
}
public void testValidContentUri() throws IOException
{
Uri contentUri = createTestImageContentUri();
File localFile = resourceApi.mapUriToFile(contentUri);
assertNotNull(localFile);
performApiTest(contentUri, "image/jpeg", localFile, true, true);
}
public void testInvalidContentUri() throws IOException
{
Uri contentUri = Uri.parse("content://media/external/images/media/999999999");
performApiTest(contentUri, null, null, false, false);
}
public void testValidAssetUri() throws IOException
{
Uri assetUri = Uri.parse("file:///android_asset/www/index.html?foo#bar"); // Also check for stripping off ? and # correctly.
performApiTest(assetUri, "text/html", null, true, false);
}
public void testInvalidAssetUri() throws IOException
{
Uri assetUri = Uri.parse("file:///android_asset/www/missing.html");
performApiTest(assetUri, "text/html", null, false, false);
}
public void testFileUriToExistingFile() throws IOException
{
File f = File.createTempFile("te s t", ".txt"); // Also check for dealing with spaces.
try {
Uri fileUri = Uri.parse(f.toURI().toString() + "?foo#bar"); // Also check for stripping off ? and # correctly.
performApiTest(fileUri, "text/plain", f, true, true);
} finally {
f.delete();
}
}
public void testFileUriToMissingFile() throws IOException
{
File f = new File(Environment.getExternalStorageDirectory() + "/somefilethatdoesntexist");
Uri fileUri = Uri.parse(f.toURI().toString());
try {
performApiTest(fileUri, null, f, false, true);
} finally {
f.delete();
}
}
public void testFileUriToMissingFileWithMissingParent() throws IOException
{
File f = new File(Environment.getExternalStorageDirectory() + "/somedirthatismissing" + System.currentTimeMillis() + "/somefilethatdoesntexist");
Uri fileUri = Uri.parse(f.toURI().toString());
performApiTest(fileUri, null, f, false, true);
}
public void testUnrecognizedUri() throws IOException
{
Uri uri = Uri.parse("somescheme://foo");
performApiTest(uri, null, null, false, false);
}
public void testRelativeUri()
{
try {
resourceApi.openForRead(Uri.parse("/foo"));
fail("Should have thrown for relative URI 1.");
} catch (Throwable t) {
}
try {
resourceApi.openForRead(Uri.parse("//foo/bar"));
fail("Should have thrown for relative URI 2.");
} catch (Throwable t) {
}
try {
resourceApi.openForRead(Uri.parse("foo.png"));
fail("Should have thrown for relative URI 3.");
} catch (Throwable t) {
}
}
public void testPluginOverride() throws IOException
{
Uri uri = Uri.parse("plugin-uri://foohost/android_asset/www/index.html?pluginRewrite=yes");
performApiTest(uri, "text/plain", null, true, false);
}
public void testMainThreadUsage() throws IOException
{
Uri assetUri = Uri.parse("file:///android_asset/www/index.html");
resourceApi.setThreadCheckingEnabled(true);
try {
resourceApi.openForRead(assetUri);
fail("Should have thrown for main thread check.");
} catch (Throwable t) {
}
}
public void testDataUriPlain() throws IOException
{
Uri uri = Uri.parse("data:text/plain;charset=utf-8,pa%20ss");
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("text/plain", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals("pa ss", data);
}
public void testDataUriBase64() throws IOException
{
Uri uri = Uri.parse("data:text/js;charset=utf-8;base64,cGFzcw==");
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("text/js", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals("pass", data);
}
public void testWebViewRequestIntercept() throws IOException
{
cordovaWebView.sendJavascript(
"var x = new XMLHttpRequest;\n" +
"x.open('GET', 'file://foo?pluginRewrite=1', false);\n" +
"x.send();\n" +
"cordova.require('cordova/exec')(null,null,'CordovaResourceApiTestPlugin1', 'foo', [x.responseText, x.status])");
execPayload = null;
execStatus = null;
try {
synchronized (this) {
this.wait(2000);
}
} catch (InterruptedException e) {
}
assertEquals("pass", execPayload);
assertEquals(execStatus.intValue(), 200);
}
public void testWebViewWhiteListRejection() throws IOException
{
cordovaWebView.sendJavascript(
"var x = new XMLHttpRequest;\n" +
"x.open('GET', 'http://foo/bar', false);\n" +
"x.send();\n" +
"cordova.require('cordova/exec')(null,null,'CordovaResourceApiTestPlugin1', 'foo', [x.responseText, x.status])");
execPayload = null;
execStatus = null;
try {
synchronized (this) {
this.wait(2000);
}
} catch (InterruptedException e) {
}
assertEquals("", execPayload);
assertEquals(execStatus.intValue(), 404);
}
}