Merge "add launch performance test for browser" into froyo
diff --git a/res/drawable/title_text.xml b/res/drawable/title_text.xml
index 6a214d9..b435e4d 100644
--- a/res/drawable/title_text.xml
+++ b/res/drawable/title_text.xml
@@ -18,7 +18,7 @@
pressed state even without window focus -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
- android:drawable="@*android:drawable/textfield_pressed" />
+ android:drawable="@*android:drawable/textfield_search_empty_pressed" />
<item android:state_pressed="false"
- android:drawable="@*android:drawable/textfield_default" />
+ android:drawable="@*android:drawable/textfield_search_empty_default" />
</selector>
diff --git a/res/layout/title_bar.xml b/res/layout/title_bar.xml
index c251250..9f0cb51 100644
--- a/res/layout/title_bar.xml
+++ b/res/layout/title_bar.xml
@@ -44,6 +44,7 @@
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
+ android:layout_marginBottom="4dip"
android:gravity="center_vertical"
android:orientation="horizontal"
>
@@ -63,8 +64,7 @@
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1.0"
- android:paddingLeft="8dip"
- android:paddingRight="6dip"
+ android:layout_marginLeft="3dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black"
android:gravity="center_vertical"
@@ -76,6 +76,7 @@
android:background="@drawable/stop_background"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginBottom="4dip"
android:src="@drawable/ic_btn_stop_v2"
android:visibility="gone"
/>
diff --git a/src/com/android/browser/TitleBar.java b/src/com/android/browser/TitleBar.java
index 0f19864..2c25534 100644
--- a/src/com/android/browser/TitleBar.java
+++ b/src/com/android/browser/TitleBar.java
@@ -44,7 +44,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -79,7 +78,8 @@
private Drawable mNormalBackground;
private Drawable mLoadingBackground;
private ImageSpan mArcsSpan;
- private int mExtraMargin;
+ private int mLeftMargin;
+ private int mRightMargin;
private static int LONG_PRESS = 1;
@@ -103,8 +103,10 @@
mCircularProgress = (Drawable) resources.getDrawable(
com.android.internal.R.drawable.search_spinner);
DisplayMetrics metrics = resources.getDisplayMetrics();
- mExtraMargin = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, 6.5f, metrics);
+ mLeftMargin = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 8f, metrics);
+ mRightMargin = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 6f, metrics);
mIconDimension = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 20f, metrics);
mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
@@ -115,6 +117,11 @@
mVoiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
mVoiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
+ // This extra tells voice search not to send the application id in its
+ // results intent - http://b/2546173
+ //
+ // TODO: Make a constant for this extra.
+ mVoiceSearchIntent.putExtra("android.speech.extras.SEND_APPLICATION_ID_EXTRA", false);
PackageManager pm = context.getPackageManager();
ResolveInfo ri = pm.resolveActivity(mVoiceSearchIntent,
PackageManager.MATCH_DEFAULT_ONLY);
@@ -267,44 +274,28 @@
if (mInVoiceMode == inVoiceMode) return;
mInVoiceMode = inVoiceMode && mVoiceSearchIntent != null;
Drawable titleDrawable;
- ViewGroup.MarginLayoutParams params
- = (ViewGroup.MarginLayoutParams) mTitleBg.getLayoutParams();
if (mInVoiceMode) {
mRtButton.setImageDrawable(mVoiceDrawable);
titleDrawable = mVoiceModeBackground;
mTitle.setEllipsize(null);
mRtButton.setVisibility(View.VISIBLE);
mStopButton.setVisibility(View.GONE);
- if (params != null) {
- params.setMargins(0, 0, 0, 0);
- }
} else {
if (mInLoad) {
titleDrawable = mLoadingBackground;
mRtButton.setVisibility(View.GONE);
mStopButton.setVisibility(View.VISIBLE);
- ViewGroup.MarginLayoutParams stopParams
- = (ViewGroup.MarginLayoutParams)
- mStopButton.getLayoutParams();
- if (stopParams != null) {
- stopParams.setMargins(0,0,0, mExtraMargin);
- }
- if (params != null) {
- params.setMargins(0, 0, 0, mExtraMargin);
- }
} else {
titleDrawable = mNormalBackground;
mRtButton.setVisibility(View.VISIBLE);
mStopButton.setVisibility(View.GONE);
mRtButton.setImageDrawable(mBookmarkDrawable);
- if (params != null) {
- params.setMargins(0, 0, 0, 0);
- }
}
mTitle.setEllipsize(TextUtils.TruncateAt.END);
}
mTitle.setSingleLine(!mInVoiceMode);
mTitleBg.setBackgroundDrawable(titleDrawable);
+ mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
}
/**
@@ -323,8 +314,6 @@
* Update the progress, from 0 to 100.
*/
/* package */ void setProgress(int newProgress) {
- ViewGroup.MarginLayoutParams params
- = (ViewGroup.MarginLayoutParams) mTitleBg.getLayoutParams();
if (newProgress >= mHorizontalProgress.getMax()) {
mTitle.setCompoundDrawables(null, null, null, null);
((Animatable) mCircularProgress).stop();
@@ -334,11 +323,7 @@
mRtButton.setVisibility(View.VISIBLE);
mStopButton.setVisibility(View.GONE);
mTitleBg.setBackgroundDrawable(mNormalBackground);
- // Set the margin for the textfield to 0, which is appropriate
- // for the normal background
- if (params != null) {
- params.setMargins(0, 0, 0, 0);
- }
+ mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
}
mInLoad = false;
} else {
@@ -354,20 +339,9 @@
mHorizontalProgress.setVisibility(View.VISIBLE);
if (!mInVoiceMode) {
mTitleBg.setBackgroundDrawable(mLoadingBackground);
+ mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
mRtButton.setVisibility(View.GONE);
mStopButton.setVisibility(View.VISIBLE);
- // Set a margin for the bottom of the textfield and the stop
- // button so that the total height matches that of the
- // title bar when the normal background is showing.
- if (params != null) {
- params.setMargins(0,0,0, mExtraMargin);
- }
- ViewGroup.MarginLayoutParams stopParams
- = (ViewGroup.MarginLayoutParams)
- mStopButton.getLayoutParams();
- if (stopParams != null) {
- stopParams.setMargins(0,0,0, mExtraMargin);
- }
}
mInLoad = true;
}
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html
new file mode 100755
index 0000000..c20ccec
--- /dev/null
+++ b/tests/assets/bindings_test.html
@@ -0,0 +1,241 @@
+<html>
+<head>
+<script type="text/javascript">
+
+function testPrimitiveTypes() {
+ return JNIBindingsTest.testPrimitiveTypes(100, 'c', 123.34567890, 456.789, 1234567, 1234567890, 6000, true);
+}
+
+function testObjectTypes() {
+ return JNIBindingsTest.testObjectTypes("Foo", "", {"foo":"bar"}, {});
+}
+
+function testArray() {
+ return JNIBindingsTest.testArray([1,2,3], ['d', 'o', 'g'], [1.2, 2.3, 3.4], [4.5,5.6,6.7], [1,2,3], [4,5,6], [7,8,9], [true, false]);
+}
+
+function testObjectArray() {
+ return JNIBindingsTest.testObjectArray(['Hello', 'World', '!'], [], [{"foo":"bar"}]);
+}
+
+function testObjectMembers() {
+ var foo = {"bool":true,
+ "byte":101,
+ "char":'d',
+ "double":123.456,
+ "float":456.789,
+ "int":102,
+ "long":103,
+ "short":104,
+ "string":"Hello World",
+ "array": [1,2,3],
+ "objArray":["foo", "bar", "baz"],
+ "object": {"foo":1}
+ };
+ return JNIBindingsTest.testObjectMembers(foo.bool, foo.byte, foo.char, foo.double, foo.float, foo.int, foo.long, foo.short, foo.string, foo.array, foo.objArray, foo.object);
+}
+
+function testJSPrimitivesToStringsInJava() {
+ return JNIBindingsTest.testJSPrimitivesToStringsInJava(123, null, 456.789, true, 'd', undefined);
+}
+
+function testJavaReturnTypes() {
+ var expectedBoolReturn = true;
+ var expectedByteReturn = 1;
+ var expectedCharReturn = 98; // 'b'; Currently bindings in JSC and V8 return chars as their ASCII equivalent.
+ var expectedDoubleReturn = 123.456;
+ var expectedFloatReturn = 456.789;
+ var expectedIntReturn = 123;
+ var expectedLongReturn = 1234;
+ var expectedShortReturn = 12345;
+ var expectedStringReturn = "Hello World!";
+
+ var returned = JNIBindingsTest.returnBool();
+ if (returned != expectedBoolReturn) {
+ appendLog("returnBool() failed: expected "+ expectedBoolReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnByte();
+ if (returned != expectedByteReturn) {
+ appendLog("returnByte() failed: expected "+ expectedByteReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnChar();
+ if (returned != expectedCharReturn) {
+ appendLog("returnChar() failed: expected "+ expectedCharReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnDouble();
+ if (returned != expectedDoubleReturn) {
+ appendLog("returnDouble() failed: expected "+ expectedDoubleReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnFloat();
+ if (Math.abs(returned - expectedFloatReturn) > 0.001) {
+ appendLog("returnFloat() failed: expected "+ expectedFloatReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnInt();
+ if (returned != expectedIntReturn) {
+ appendLog("returnInt() failed: expected "+ expectedIntReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnLong();
+ if (returned != expectedLongReturn) {
+ appendLog("returnLong() failed: expected "+ expectedLongReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnShort();
+ if (returned != expectedShortReturn) {
+ appendLog("returnShort() failed: expected "+ expectedShortReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnString();
+ if (returned != expectedStringReturn) {
+ appendLog("returnString() failed: expected "+ expectedStringReturn +", got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnObject();
+ if (returned == null) {
+ appendLog("returnObject() failed: expected non-null, got " + returned);
+ return false;
+ } else if (returned.x != 0) {
+ // EMULATE_JSC_BINDINGS
+ // Note: the Java sets the x property to 123. JSC and V8 do not support object
+ // members in the bindings though.
+ appendLog("returnObject() failed: expected 'x' property 0, got " + returned.x)
+ return false;
+ } else if (returned.s != undefined) {
+ // EMULATE_JSC_BINDINGS
+ // Note that the java class returned has s set to Hello World. JSC and V8 do not support
+ // getting properties.
+ appendLog("returnObject() failed: expected 's' property undefined, got " + returned.s);
+ return false;
+ } else if (!returned.aMethod()) {
+ appendLog("returnObject() failed: expected 'aMethod' method to return true, got " + returned.aMethod());
+ return false;
+ } else if (returned.anotherMethod() != "Hello World") {
+ appendLog("returnObject() failed: expected 'anotherMethod' to return 'Hello World' got "+ returned.anotherMethod());
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnArray();
+ if (returned != null) {
+ appendLog("returnArray() failed: expected null, got " + returned);
+ return false;
+ }
+
+ returned = JNIBindingsTest.returnVoid();
+ if (returned != null) {
+ appendLog("returnVoid() failed: expected null, got " + returned);
+ return false;
+ }
+
+ return true;
+}
+
+function getIfaceProperties() {
+ if (JNIBindingsTest.mInt != 0) {
+ // EMULATE_JSC_BINDINGS
+ // Note: the Java sets the mInt property to 123. JSC and V8 do not support object
+ // members in the bindings though.
+ appendLog("getIfaceProperties() failed: expected mInt = 0, got " + JNIBindingsTest.mInt);
+ return false;
+ }
+
+ if (JNIBindingsTest.mString != undefined) {
+ // EMULATE_JSC_BINDINGS
+ // Note that the java class returned has s set to Hello World. JSC and V8 do not support
+ // getting properties.
+ appendLog("getIfaceProperties() failed: expected mString = 'Hello World', got " + JNIBindingsTest.mString);
+ return false;
+ }
+
+ return true;
+}
+
+function testParameterTypeMismatch() {
+ return JNIBindingsTest.testParameterTypeMismatch("dog");
+}
+
+function appendLog(msg) {
+ var log = document.getElementById("status");
+ log.innerHTML += "<br/>" + msg;
+}
+
+function runTests() {
+
+ // Assume that if the test isn't done after 10s that we failed.
+ window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000);
+
+ if (testPrimitiveTypes()) {
+ appendLog("testPrimitiveTypes passed!");
+ } else {
+ appendLog("testPrimtiveTypes failed!");
+ }
+
+ if (testObjectTypes()) {
+ appendLog("testObjectTypes passed!");
+ } else {
+ appendLog("testObjectTypes failed!");
+ }
+
+ if (testArray()) {
+ appendLog("testArray passed!");
+ } else {
+ appendLog("testArray failed!");
+ }
+
+ if (testObjectArray()) {
+ appendLog("testObjectArray passed!");
+ } else {
+ appendLog("testObjectArray failed!");
+ }
+
+ if (testObjectMembers()) {
+ appendLog("testObjectMembers passed!");
+ } else {
+ appendLog("<br/>testObjectMembers failed!");
+ }
+
+ if (testJSPrimitivesToStringsInJava()) {
+ appendLog("testJSPrimitivesToStringsInJava passed!");
+ } else {
+ appendLog("testJSPrimitivesToStringsInJava failed!");
+ }
+
+ if (testJavaReturnTypes()) {
+ appendLog("testJavaReturnTypes passed!");
+ } else {
+ appendLog("testJavaReturnTypes failed!");
+ }
+
+ if (getIfaceProperties()) {
+ appendLog("getIfaceProperties passed!");
+ } else {
+ appendLog("getIfaceProperties failed!");
+ }
+
+ if (testParameterTypeMismatch()) {
+ appendLog("testParameterTypeMismatch passed!");
+ } else {
+ appendLog("testParameterTypeMismatch failed!");
+ }
+
+ JNIBindingsTest.testComplete();
+}
+</script>
+
+<body onload="runTests();">
+<p id="status">Running JNI Bindings test...</p>
+</body>
+</html>
diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java
new file mode 100644
index 0000000..bfa3ac1
--- /dev/null
+++ b/tests/src/com/android/browser/JNIBindingsTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package com.android.browser;
+
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.Arrays;
+import junit.framework.AssertionFailedError;
+
+public class JNIBindingsTest extends AndroidTestCase {
+
+ private final static String LOGTAG = "JNIBindingsTest";
+ private JNIBindingsTestApp mTestApp;
+
+ public int mInt = 123;
+ public String mString = "Hello World";
+
+ public JNIBindingsTest(JNIBindingsTestApp testApp) {
+ mTestApp = testApp;
+ }
+
+ public void testComplete() {
+ Log.v(LOGTAG, "Completing the test.");
+ mTestApp.testComplete();
+ }
+
+ public void printAssertionFailed(AssertionFailedError e) {
+ Log.e(LOGTAG, "");
+ Log.e(LOGTAG, "*** ASSERTION FAILED: " + e.getMessage());
+ Log.e(LOGTAG, "*** Stack trace:");
+ StackTraceElement[] trace = e.getStackTrace();
+ for(StackTraceElement elem : trace) {
+ Log.e(LOGTAG, "***\t" + elem.toString());
+ }
+ Log.e(LOGTAG, "");
+ }
+
+ public boolean testPrimitiveTypes(byte byteParam, char charParam, double doubleParam,
+ float floatParam, int intParam, long longParam, short shortParam,
+ boolean booleanParam) {
+ byte expectedByteParam = 100;
+ char expectedCharParam = 'c';
+ double expectedDoubleParam = 123.34567890;
+ float expectedFloatParam = 456.789f;
+ int expectedIntParam = 1234567;
+ long expectedLongParam = 1234567890L;
+ short expectedShortParam = 6000;
+ boolean expectedBooleanParam = true;
+
+ try {
+ assertEquals(expectedByteParam, byteParam);
+
+ // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly
+ // assertEquals(expectedCharParam, charParam);
+
+ assertEquals(expectedDoubleParam, doubleParam);
+ assertEquals(expectedFloatParam, floatParam);
+ assertEquals(expectedIntParam, intParam);
+ assertEquals(expectedLongParam, longParam);
+ assertEquals(expectedShortParam, shortParam);
+ assertEquals(expectedBooleanParam, booleanParam);
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testObjectTypes(String stringParam, String emptyString, Object objectParam,
+ Object emptyObject) {
+ String expectedString = "Foo";
+ String expectedEmptyString = "";
+
+ try {
+ assertNotNull(stringParam);
+ assertNotNull(emptyString);
+ assertEquals(expectedString, stringParam);
+ assertEquals(expectedEmptyString, emptyString);
+ assertNull(objectParam);
+ assertNull(emptyObject);
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testArray(byte[] byteArray, char[] charArray, double[] doubleArray,
+ float[] floatArray, int[] intArray, long[] longArray, short[] shortArray,
+ boolean[] booleanArray) {
+ byte[] expectedByteArray = { 1,2,3};
+ char[] expectedCharArray = {'d', 'o', 'g'};
+ double[] expectedDoubleArray = {1.2,2.3,3.4};
+ float[] expectedFloatArray = {4.5F,5.6F,6.7F};
+ int[] expectedIntArray = {1,2,3};
+ long[] expectedLongArray = {4L,5L,6L};
+ short[] expectedShortArray = {7,8,9};
+ boolean[] expectedBooleanArray = {true, false};
+
+ try {
+ assertNotNull(byteArray);
+ assertNotNull(charArray);
+ assertNotNull(doubleArray);
+ assertNotNull(floatArray);
+ assertNotNull(intArray);
+ assertNotNull(longArray);
+ assertNotNull(shortArray);
+ assertNotNull(booleanArray);
+ assertEquals(Arrays.toString(expectedByteArray), Arrays.toString(byteArray));
+ assertEquals(Arrays.toString(expectedCharArray), Arrays.toString(charArray));
+ assertEquals(Arrays.toString(expectedDoubleArray), Arrays.toString(doubleArray));
+ assertEquals(Arrays.toString(expectedFloatArray), Arrays.toString(floatArray));
+ assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArray));
+ assertEquals(Arrays.toString(expectedLongArray), Arrays.toString(longArray));
+ assertEquals(Arrays.toString(expectedShortArray), Arrays.toString(shortArray));
+ assertEquals(Arrays.toString(expectedBooleanArray), Arrays.toString(booleanArray));
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testObjectArray(String[] stringArray, Object[] emptyArray,
+ Object[] objectArray) {
+ String[] expectedStringArray = {"Hello", "World", "!"};
+ String expectedStringArrayClassName = "[Ljava.lang.String;";
+ Object[] expectedObjectArray = {};
+
+ try {
+ assertNotNull(stringArray);
+
+ // EMULATE_JSC_BINDINGS JSC pass null for object arrays that are not strings.
+ // Should be an empty array?
+ assertNull(emptyArray);
+ assertNull(objectArray);
+
+ assertEquals(Arrays.toString(expectedStringArray), Arrays.toString(stringArray));
+ assertEquals(expectedStringArrayClassName, stringArray.getClass().getName());
+
+ // EMULATE_JSC_BINDINGS
+ // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(emptyArray));
+ // assertEquals(expectedObjectArrayClassName, emptyArray.getClass().getName());
+ // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(objectArray));
+ // assertEquals(expectedStringObjectClassName, objectArray.getClass().getName());
+
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testObjectMembers(boolean boolParam, byte byteParam, char charParam,
+ double doubleParam, float floatParam, int intParam, long longParam, short shortParam,
+ String stringParam, int[] intArrayParam, String[] stringArrayParam,
+ Object objectParam) {
+ boolean expectedBoolParam = true;
+ byte expectedByteParam = 101;
+ char expectedCharParam = 'd';
+ double expectedDoubleParam = 123.456;
+ float expectedFloatParam = 456.789F;
+ int expectedIntParam = 102;
+ long expectedLongParam = 103L;
+ short expectedShortParam = 104;
+ String expectedStringParam = "Hello World";
+ int[] expectedIntArray = {1,2,3};
+ String[] expectedStringArrayParam = {"foo", "bar", "baz"};
+ String expectedStringArrayClassName = "[Ljava.lang.String;";
+
+ try {
+ assertEquals(expectedBoolParam, boolParam);
+ assertEquals(expectedByteParam, byteParam);
+
+ // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly. (chars are strings in JS)
+ // assertEquals(expectedCharParam, charParam);
+
+ assertEquals(expectedDoubleParam, doubleParam);
+ assertEquals(expectedFloatParam, floatParam);
+ assertEquals(expectedIntParam, intParam);
+ assertEquals(expectedLongParam, longParam);
+ assertEquals(expectedShortParam, shortParam);
+ assertEquals(expectedStringParam, stringParam);
+ assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArrayParam));
+ assertEquals(Arrays.toString(expectedStringArrayParam),
+ Arrays.toString(stringArrayParam));
+ assertEquals(expectedStringArrayClassName, stringArrayParam.getClass().getName());
+ assertNull(objectParam);
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testJSPrimitivesToStringsInJava(String intParam, String nullParam,
+ String doubleParam, String booleanParam, String charParam,
+ String undefinedParam) {
+ String expectedIntParam = "123";
+ String expectedDoubleParam = "456.789";
+ String expectedBooleanParam = "true";
+ String expectedCharParam = "d";
+
+ // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types. Should be null?
+ String expectedUndefinedParam = "undefined";
+
+ try {
+ assertNotNull(intParam);
+ assertNull(nullParam);
+ assertNotNull(doubleParam);
+ assertNotNull(booleanParam);
+ assertNotNull(charParam);
+
+ // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types.
+ assertNotNull(undefinedParam);
+
+ assertEquals(expectedIntParam, intParam);
+ assertEquals(expectedDoubleParam, doubleParam);
+ assertEquals(expectedBooleanParam, booleanParam);
+ assertEquals(expectedCharParam, charParam);;
+
+ // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types.
+ assertEquals(expectedUndefinedParam, undefinedParam);
+
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean testParameterTypeMismatch(String[] stringArrayParam) {
+ // The JS test will pass a string, not an array to this test.
+ try {
+ assertNull(stringArrayParam);
+ } catch (AssertionFailedError e) {
+ printAssertionFailed(e);
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean returnBool() { return true; }
+ public byte returnByte() { return 1; }
+ public char returnChar() { return 'b'; }
+ public double returnDouble() { return 123.456; }
+ public float returnFloat() { return 456.789F; }
+ public int returnInt() { return 123; }
+ public long returnLong() { return 1234L; }
+ public short returnShort() { return 12345; }
+ public String returnString() { return "Hello World!"; }
+
+ public class TestObject {
+ public int x = 123;
+ public String s = "Hello World!";
+
+ public boolean aMethod() { return true; }
+ public String anotherMethod() { return "Hello World"; }
+ }
+
+ public TestObject returnObject() { return new TestObject(); }
+
+ public int[] returnArray() {
+ int[] array = {1,2,3,4,5};
+ return array;
+ }
+
+ public void returnVoid() { }
+}
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
new file mode 100644
index 0000000..e01aca2
--- /dev/null
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package com.android.browser;
+
+import android.app.Instrumentation;
+import android.net.http.SslError;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+
+/**
+ * Adds a JavaScript interface to the webview and calls functions on it to verify variables
+ * are passed from JS to Java correctly.
+ */
+public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> {
+
+ private final static String TAG = "JNIBindingsTest";
+
+ private static final int MSG_WEBKIT_DATA_READY = 101;
+
+ private BrowserActivity mActivity = null;
+ private Instrumentation mInst = null;
+
+ private boolean mTestDone = false;
+ private String mWebKitResult;
+
+ private String mExpectedWebKitResult = "Running JNI Bindings test...\n" +
+ "testPrimitiveTypes passed!\n" +
+ "testObjectTypes passed!\n" +
+ "testArray passed!\n" +
+ "testObjectArray passed!\n" +
+ "testObjectMembers passed!\n" +
+ "testJSPrimitivesToStringsInJava passed!\n" +
+ "testJavaReturnTypes passed!\n" +
+ "getIfaceProperties passed!\n" +
+ "testParameterTypeMismatch passed!\n";
+
+
+ private class GetWebKitDataThread extends Thread {
+ private JNIBindingsTestApp mTestApp;
+ private WebView mWebView;
+ private Handler mHandler;
+
+ GetWebKitDataThread(JNIBindingsTestApp testApp, WebView webView) {
+ mTestApp = testApp;
+ mWebView = webView;
+ }
+
+ public void run() {
+ Looper.prepare();
+ mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_WEBKIT_DATA_READY: {
+ mTestApp.setWebKitResult((String)msg.obj);
+ Looper.myLooper().quit();
+ }
+ default: super.handleMessage(msg); break;
+ }
+ }
+ };
+ mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY));
+ Looper.loop();
+ }
+ }
+
+ public synchronized void setWebKitResult(String result) {
+ mWebKitResult = result;
+ notify();
+ }
+
+ public JNIBindingsTestApp() {
+ super(BrowserActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mActivity = getActivity();
+ mInst = getInstrumentation();
+ mInst.waitForIdleSync();
+
+ }
+
+ /**
+ * Gets the browser ready for testing by starting the application
+ * and wrapping the WebView's helper clients.
+ */
+ void setUpBrowser() {
+ Tab tab = mActivity.getTabControl().getCurrentTab();
+ WebView webView = tab.getWebView();
+ webView.addJavascriptInterface(new JNIBindingsTest(this), "JNIBindingsTest");
+
+ webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) {
+
+ /**
+ * Dismisses and logs Javascript alerts.
+ */
+ @Override
+ public boolean onJsAlert(WebView view, String url, String message,
+ JsResult result) {
+ String logMsg = String.format("JS Alert '%s' received from %s", message, url);
+ Log.w(TAG, logMsg);
+ result.confirm();
+
+ return true;
+ }
+
+ /**
+ * Confirms and logs Javascript alerts.
+ */
+ @Override
+ public boolean onJsConfirm(WebView view, String url, String message,
+ JsResult result) {
+ String logMsg = String.format("JS Confirmation '%s' received from %s",
+ message, url);
+ Log.w(TAG, logMsg);
+ result.confirm();
+
+ return true;
+ }
+
+ /**
+ * Confirms and logs Javascript alerts, providing the default value.
+ */
+ @Override
+ public boolean onJsPrompt(WebView view, String url, String message,
+ String defaultValue, JsPromptResult result) {
+ String logMsg = String.format("JS Prompt '%s' received from %s; " +
+ "Giving default value '%s'", message, url, defaultValue);
+ Log.w(TAG, logMsg);
+ result.confirm(defaultValue);
+
+ return true;
+ }
+ });
+
+ webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) {
+
+ /**
+ * Bypasses and logs errors.
+ */
+ @Override
+ public void onReceivedError(WebView view, int errorCode,
+ String description, String failingUrl) {
+ String message = String.format("Error '%s' (%d) loading url: %s",
+ description, errorCode, failingUrl);
+ Log.w(TAG, message);
+ }
+
+ /**
+ * Ignores and logs SSL errors.
+ */
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler,
+ SslError error) {
+ Log.w(TAG, "SSL error: " + error);
+ handler.proceed();
+ }
+
+ });
+ }
+
+ public synchronized void testComplete() {
+ mTestDone = true;
+ notify();
+ }
+
+ public void testJNIBindings() {
+ setUpBrowser();
+
+ Tab tab = mActivity.getTabControl().getCurrentTab();
+ WebView webView = tab.getWebView();
+ webView.loadUrl("file:///sdcard/bindings_test.html");
+ synchronized(this) {
+ while(!mTestDone) {
+ try {
+ wait();
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ // Now the tests are complete grab the DOM content and compare to the reference.
+ GetWebKitDataThread getWKData = new GetWebKitDataThread(this, webView);
+ mWebKitResult = null;
+ getWKData.start();
+
+ synchronized(this) {
+ while(mWebKitResult == null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ Log.v(TAG, "WebKit result:");
+ Log.v(TAG, mWebKitResult);
+ assertEquals("Bindings test failed! See logcat for more details!", mExpectedWebKitResult,
+ mWebKitResult);
+ }
+}