Home | History | Annotate | Download | only in browser
      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.ClientCertRequestHandler;
     27 import android.webkit.JsPromptResult;
     28 import android.webkit.JsResult;
     29 import android.webkit.SslErrorHandler;
     30 import android.webkit.WebView;
     31 
     32 import java.io.File;
     33 import java.io.FileOutputStream;
     34 import java.io.IOException;
     35 import java.io.InputStream;
     36 import java.io.OutputStream;
     37 
     38 /**
     39  * Adds a JavaScript interface to the webview and calls functions on it to verify variables
     40  * are passed from JS to Java correctly.
     41  * To run this test, execute:
     42  * adb shell am instrument -w -e class com.android.browser.JNIBindingsTestApp#testJNIBindings \
     43  *     com.android.browser.tests/android.test.InstrumentationTestRunner
     44  */
     45 public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> {
     46 
     47     private final static String TAG = "JNIBindingsTest";
     48 
     49     private static final String SDCARD_BINDINGS_TEST_HTML = "/sdcard/bindings_test.html";
     50 
     51     private static final int MSG_WEBKIT_DATA_READY = 101;
     52 
     53     private BrowserActivity mActivity = null;
     54     private Controller mController = null;
     55     private Instrumentation mInst = null;
     56 
     57     private boolean mTestDone = false;
     58     private String mWebKitResult;
     59 
     60     private String mExpectedWebKitResult = "Running JNI Bindings test...\n" +
     61             "testPrimitiveTypes passed!\n" +
     62             "testObjectTypes passed!\n" +
     63             "testArray passed!\n" +
     64             "testObjectArray passed!\n" +
     65             "testObjectMembers passed!\n" +
     66             "testJSPrimitivesToStringsInJava passed!\n" +
     67             "testJavaReturnTypes passed!\n" +
     68             "getIfaceProperties passed!\n" +
     69             "testParameterTypeMismatch passed!\n";
     70 
     71 
     72     private class GetWebKitDataThread extends Thread {
     73         private JNIBindingsTestApp mTestApp;
     74         private WebView mWebView;
     75         private Handler mHandler;
     76 
     77         GetWebKitDataThread(JNIBindingsTestApp testApp, WebView webView) {
     78             mTestApp = testApp;
     79             mWebView = webView;
     80         }
     81 
     82         @Override
     83         public void run() {
     84             Looper.prepare();
     85             mHandler = new Handler() {
     86                 @Override
     87                 public void handleMessage(Message msg) {
     88                     switch (msg.what) {
     89                         case MSG_WEBKIT_DATA_READY: {
     90                             mTestApp.setWebKitResult((String)msg.obj);
     91                             Looper.myLooper().quit();
     92                         }
     93                         default: super.handleMessage(msg); break;
     94                     }
     95                 }
     96             };
     97             mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY, 1, 0));
     98             Looper.loop();
     99         }
    100     }
    101 
    102     public synchronized void setWebKitResult(String result) {
    103        mWebKitResult = result;
    104        notify();
    105     }
    106 
    107     public JNIBindingsTestApp() {
    108         super(BrowserActivity.class);
    109     }
    110 
    111     @Override
    112     protected void setUp() throws Exception {
    113         super.setUp();
    114 
    115         mActivity = getActivity();
    116         mController = mActivity.getController();
    117         mInst = getInstrumentation();
    118         mInst.waitForIdleSync();
    119 
    120         extractAsset();
    121     }
    122 
    123     @Override
    124     protected void tearDown() throws Exception {
    125         removeAsset();
    126         super.tearDown();
    127     }
    128 
    129     protected void extractAsset() throws IOException {
    130         InputStream in = getInstrumentation().getContext().getAssets().open("bindings_test.html");
    131         OutputStream out = new FileOutputStream(SDCARD_BINDINGS_TEST_HTML);
    132 
    133         byte[] buf = new byte[2048];
    134         int len;
    135 
    136         while ((len = in.read(buf)) >= 0 ) {
    137             out.write(buf, 0, len);
    138         }
    139         out.close();
    140         in.close();
    141     }
    142 
    143     protected void removeAsset(){
    144         File fileToDelete = new File(SDCARD_BINDINGS_TEST_HTML);
    145         fileToDelete.delete();
    146     }
    147 
    148     /**
    149      * Gets the browser ready for testing by starting the application
    150      * and wrapping the WebView's helper clients.
    151      */
    152     void setUpBrowser() {
    153         Tab tab = mController.getTabControl().getCurrentTab();
    154         WebView webView = tab.getWebView();
    155         webView.addJavascriptInterface(new JNIBindingsTest(this), "JNIBindingsTest");
    156 
    157         webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) {
    158 
    159             /**
    160              * Dismisses and logs Javascript alerts.
    161              */
    162             @Override
    163             public boolean onJsAlert(WebView view, String url, String message,
    164                     JsResult result) {
    165                 String logMsg = String.format("JS Alert '%s' received from %s", message, url);
    166                 Log.w(TAG, logMsg);
    167                 result.confirm();
    168 
    169                 return true;
    170             }
    171 
    172             /**
    173              * Confirms and logs Javascript alerts.
    174              */
    175             @Override
    176             public boolean onJsConfirm(WebView view, String url, String message,
    177                     JsResult result) {
    178                 String logMsg = String.format("JS Confirmation '%s' received from %s",
    179                         message, url);
    180                 Log.w(TAG, logMsg);
    181                 result.confirm();
    182 
    183                 return true;
    184             }
    185 
    186             /**
    187              * Confirms and logs Javascript alerts, providing the default value.
    188              */
    189             @Override
    190             public boolean onJsPrompt(WebView view, String url, String message,
    191                     String defaultValue, JsPromptResult result) {
    192                 String logMsg = String.format("JS Prompt '%s' received from %s; " +
    193                         "Giving default value '%s'", message, url, defaultValue);
    194                 Log.w(TAG, logMsg);
    195                 result.confirm(defaultValue);
    196 
    197                 return true;
    198             }
    199         });
    200 
    201         webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) {
    202 
    203             /**
    204              * Bypasses and logs errors.
    205              */
    206             @Override
    207             public void onReceivedError(WebView view, int errorCode,
    208                     String description, String failingUrl) {
    209                 String message = String.format("Error '%s' (%d) loading url: %s",
    210                         description, errorCode, failingUrl);
    211                 Log.w(TAG, message);
    212             }
    213 
    214             /**
    215              * Ignores and logs SSL errors.
    216              */
    217             @Override
    218             public void onReceivedSslError(WebView view, SslErrorHandler handler,
    219                     SslError error) {
    220                 Log.w(TAG, "SSL error: " + error);
    221                 handler.proceed();
    222             }
    223 
    224             /**
    225              * Ignores and logs SSL client certificate requests.
    226              */
    227             @Override
    228             public void onReceivedClientCertRequest(WebView view, ClientCertRequestHandler handler,
    229                     String host_and_port) {
    230                 Log.w(TAG, "SSL client certificate request: " + host_and_port);
    231                 handler.cancel();
    232             }
    233 
    234         });
    235     }
    236 
    237     public synchronized void notifyComplete() {
    238         mTestDone = true;
    239         notify();
    240     }
    241 
    242     public void testJNIBindings() {
    243         setUpBrowser();
    244 
    245         Tab tab = mController.getTabControl().getCurrentTab();
    246         WebView webView = tab.getWebView();
    247         webView.loadUrl("file://" + SDCARD_BINDINGS_TEST_HTML);
    248         synchronized(this) {
    249             while(!mTestDone) {
    250                 try {
    251                     wait();
    252                 } catch (InterruptedException e) {}
    253             }
    254         }
    255 
    256         // Now the tests are complete grab the DOM content and compare to the reference.
    257         GetWebKitDataThread getWKData = new GetWebKitDataThread(this, webView);
    258         mWebKitResult = null;
    259         getWKData.start();
    260 
    261         synchronized(this) {
    262             while(mWebKitResult == null) {
    263                 try {
    264                     wait();
    265                 } catch (InterruptedException e) {}
    266             }
    267         }
    268 
    269         Log.v(TAG, "WebKit result:");
    270         Log.v(TAG, mWebKitResult);
    271         assertEquals("Bindings test failed! See logcat for more details!", mExpectedWebKitResult,
    272                 mWebKitResult);
    273     }
    274 }
    275