1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.browser; 18 19 import android.app.Instrumentation; 20 import android.net.http.SslError; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Message; 24 import android.test.ActivityInstrumentationTestCase2; 25 import android.util.Log; 26 import android.webkit.JsPromptResult; 27 import android.webkit.JsResult; 28 import android.webkit.SslErrorHandler; 29 import android.webkit.WebView; 30 31 import java.io.File; 32 import java.io.FileOutputStream; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 37 /** 38 * Adds a JavaScript interface to the webview and calls functions on it to verify variables 39 * are passed from JS to Java correctly. 40 */ 41 public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> { 42 43 private final static String TAG = "JNIBindingsTest"; 44 45 private static final String SDCARD_BINDINGS_TEST_HTML = "/sdcard/bindings_test.html"; 46 47 private static final int MSG_WEBKIT_DATA_READY = 101; 48 49 private BrowserActivity mActivity = null; 50 private Instrumentation mInst = null; 51 52 private boolean mTestDone = false; 53 private String mWebKitResult; 54 55 private String mExpectedWebKitResult = "Running JNI Bindings test...\n" + 56 "testPrimitiveTypes passed!\n" + 57 "testObjectTypes passed!\n" + 58 "testArray passed!\n" + 59 "testObjectArray passed!\n" + 60 "testObjectMembers passed!\n" + 61 "testJSPrimitivesToStringsInJava passed!\n" + 62 "testJavaReturnTypes passed!\n" + 63 "getIfaceProperties passed!\n" + 64 "testParameterTypeMismatch passed!\n"; 65 66 67 private class GetWebKitDataThread extends Thread { 68 private JNIBindingsTestApp mTestApp; 69 private WebView mWebView; 70 private Handler mHandler; 71 72 GetWebKitDataThread(JNIBindingsTestApp testApp, WebView webView) { 73 mTestApp = testApp; 74 mWebView = webView; 75 } 76 77 @Override 78 public void run() { 79 Looper.prepare(); 80 mHandler = new Handler() { 81 @Override 82 public void handleMessage(Message msg) { 83 switch (msg.what) { 84 case MSG_WEBKIT_DATA_READY: { 85 mTestApp.setWebKitResult((String)msg.obj); 86 Looper.myLooper().quit(); 87 } 88 default: super.handleMessage(msg); break; 89 } 90 } 91 }; 92 mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY)); 93 Looper.loop(); 94 } 95 } 96 97 public synchronized void setWebKitResult(String result) { 98 mWebKitResult = result; 99 notify(); 100 } 101 102 public JNIBindingsTestApp() { 103 super(BrowserActivity.class); 104 } 105 106 @Override 107 protected void setUp() throws Exception { 108 super.setUp(); 109 110 mActivity = getActivity(); 111 mInst = getInstrumentation(); 112 mInst.waitForIdleSync(); 113 114 extractAsset(); 115 } 116 117 @Override 118 protected void tearDown() throws Exception { 119 removeAsset(); 120 super.tearDown(); 121 } 122 123 protected void extractAsset() throws IOException { 124 InputStream in = getInstrumentation().getContext().getAssets().open("bindings_test.html"); 125 OutputStream out = new FileOutputStream(SDCARD_BINDINGS_TEST_HTML); 126 127 byte[] buf = new byte[2048]; 128 int len; 129 130 while ((len = in.read(buf)) >= 0 ) { 131 out.write(buf, 0, len); 132 } 133 out.close(); 134 in.close(); 135 } 136 137 protected void removeAsset(){ 138 File fileToDelete = new File(SDCARD_BINDINGS_TEST_HTML); 139 fileToDelete.delete(); 140 } 141 142 /** 143 * Gets the browser ready for testing by starting the application 144 * and wrapping the WebView's helper clients. 145 */ 146 void setUpBrowser() { 147 Tab tab = mActivity.getTabControl().getCurrentTab(); 148 WebView webView = tab.getWebView(); 149 webView.addJavascriptInterface(new JNIBindingsTest(this), "JNIBindingsTest"); 150 151 webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) { 152 153 /** 154 * Dismisses and logs Javascript alerts. 155 */ 156 @Override 157 public boolean onJsAlert(WebView view, String url, String message, 158 JsResult result) { 159 String logMsg = String.format("JS Alert '%s' received from %s", message, url); 160 Log.w(TAG, logMsg); 161 result.confirm(); 162 163 return true; 164 } 165 166 /** 167 * Confirms and logs Javascript alerts. 168 */ 169 @Override 170 public boolean onJsConfirm(WebView view, String url, String message, 171 JsResult result) { 172 String logMsg = String.format("JS Confirmation '%s' received from %s", 173 message, url); 174 Log.w(TAG, logMsg); 175 result.confirm(); 176 177 return true; 178 } 179 180 /** 181 * Confirms and logs Javascript alerts, providing the default value. 182 */ 183 @Override 184 public boolean onJsPrompt(WebView view, String url, String message, 185 String defaultValue, JsPromptResult result) { 186 String logMsg = String.format("JS Prompt '%s' received from %s; " + 187 "Giving default value '%s'", message, url, defaultValue); 188 Log.w(TAG, logMsg); 189 result.confirm(defaultValue); 190 191 return true; 192 } 193 }); 194 195 webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) { 196 197 /** 198 * Bypasses and logs errors. 199 */ 200 @Override 201 public void onReceivedError(WebView view, int errorCode, 202 String description, String failingUrl) { 203 String message = String.format("Error '%s' (%d) loading url: %s", 204 description, errorCode, failingUrl); 205 Log.w(TAG, message); 206 } 207 208 /** 209 * Ignores and logs SSL errors. 210 */ 211 @Override 212 public void onReceivedSslError(WebView view, SslErrorHandler handler, 213 SslError error) { 214 Log.w(TAG, "SSL error: " + error); 215 handler.proceed(); 216 } 217 218 }); 219 } 220 221 public synchronized void notifyComplete() { 222 mTestDone = true; 223 notify(); 224 } 225 226 public void testJNIBindings() { 227 setUpBrowser(); 228 229 Tab tab = mActivity.getTabControl().getCurrentTab(); 230 WebView webView = tab.getWebView(); 231 webView.loadUrl("file://" + SDCARD_BINDINGS_TEST_HTML); 232 synchronized(this) { 233 while(!mTestDone) { 234 try { 235 wait(); 236 } catch (InterruptedException e) {} 237 } 238 } 239 240 // Now the tests are complete grab the DOM content and compare to the reference. 241 GetWebKitDataThread getWKData = new GetWebKitDataThread(this, webView); 242 mWebKitResult = null; 243 getWKData.start(); 244 245 synchronized(this) { 246 while(mWebKitResult == null) { 247 try { 248 wait(); 249 } catch (InterruptedException e) {} 250 } 251 } 252 253 Log.v(TAG, "WebKit result:"); 254 Log.v(TAG, mWebKitResult); 255 assertEquals("Bindings test failed! See logcat for more details!", mExpectedWebKitResult, 256 mWebKitResult); 257 } 258 } 259