Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2009 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 android.webkit.cts;
     18 
     19 import android.cts.util.EvaluateJsResultPollingCheck;
     20 import android.cts.util.PollingCheck;
     21 import android.graphics.Bitmap;
     22 import android.os.Message;
     23 import android.test.ActivityInstrumentationTestCase2;
     24 import android.view.KeyEvent;
     25 import android.view.ViewGroup;
     26 import android.webkit.HttpAuthHandler;
     27 import android.webkit.ValueCallback;
     28 import android.webkit.WebChromeClient;
     29 import android.webkit.WebSettings;
     30 import android.webkit.WebView;
     31 import android.webkit.WebViewClient;
     32 import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
     33 
     34 
     35 public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
     36     private static final long TEST_TIMEOUT = 5000;
     37     private static final String TEST_URL = "http://foo.com/";
     38 
     39     private WebViewOnUiThread mOnUiThread;
     40     private CtsTestServer mWebServer;
     41 
     42     public WebViewClientTest() {
     43         super("com.android.cts.stub", WebViewStubActivity.class);
     44     }
     45 
     46     @Override
     47     protected void setUp() throws Exception {
     48         super.setUp();
     49         final WebViewStubActivity activity = getActivity();
     50         new PollingCheck(TEST_TIMEOUT) {
     51             @Override
     52                 protected boolean check() {
     53                 return activity.hasWindowFocus();
     54             }
     55         }.run();
     56         mOnUiThread = new WebViewOnUiThread(this, activity.getWebView());
     57     }
     58 
     59     @Override
     60     protected void tearDown() throws Exception {
     61         mOnUiThread.cleanUp();
     62         if (mWebServer != null) {
     63             mWebServer.shutdown();
     64         }
     65         super.tearDown();
     66     }
     67 
     68     // Verify that the shouldoverrideurlloading is false by default
     69     public void testShouldOverrideUrlLoadingDefault() {
     70         final WebViewClient webViewClient = new WebViewClient();
     71         assertFalse(webViewClient.shouldOverrideUrlLoading(mOnUiThread.getWebView(), null));
     72     }
     73 
     74     // Verify shouldoverrideurlloading called on top level navigation
     75     public void testShouldOverrideUrlLoading() {
     76         final MockWebViewClient webViewClient = new MockWebViewClient();
     77         mOnUiThread.setWebViewClient(webViewClient);
     78         mOnUiThread.getSettings().setJavaScriptEnabled(true);
     79         String data = "<html><body>" +
     80                 "<a href=\"" + TEST_URL + "\" id=\"link\">new page</a>" +
     81                 "</body></html>";
     82         mOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
     83         clickOnLinkUsingJs("link");
     84         assertEquals(TEST_URL, webViewClient.getLastShouldOverrideUrl());
     85     }
     86 
     87     // Verify shouldoverrideurlloading called on webview called via onCreateWindow
     88     public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception {
     89         mWebServer = new CtsTestServer(getActivity());
     90         // WebViewClient for main window
     91         final MockWebViewClient mainWebViewClient = new MockWebViewClient();
     92         // WebViewClient for child window
     93         final MockWebViewClient childWebViewClient = new MockWebViewClient();
     94         mOnUiThread.setWebViewClient(mainWebViewClient);
     95         mOnUiThread.getSettings().setJavaScriptEnabled(true);
     96         mOnUiThread.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
     97         mOnUiThread.getSettings().setSupportMultipleWindows(true);
     98         mOnUiThread.setWebChromeClient(new WebChromeClient() {
     99             @Override
    100             public boolean onCreateWindow(
    101                 WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
    102                 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
    103                 WebView childWebView = new WebView(view.getContext());
    104                 childWebView.setWebViewClient(childWebViewClient);
    105                 childWebView.getSettings().setJavaScriptEnabled(true);
    106                 transport.setWebView(childWebView);
    107                 getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
    108                             ViewGroup.LayoutParams.FILL_PARENT,
    109                             ViewGroup.LayoutParams.WRAP_CONTENT));
    110                 resultMsg.sendToTarget();
    111                 return true;
    112             }
    113         });
    114         mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL));
    115 
    116         new PollingCheck(TEST_TIMEOUT) {
    117             @Override
    118             protected boolean check() {
    119                 return childWebViewClient.hasOnPageFinishedCalled();
    120             }
    121         }.run();
    122         assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL),
    123                 childWebViewClient.getLastShouldOverrideUrl());
    124     }
    125 
    126     private void clickOnLinkUsingJs(final String linkId) {
    127         EvaluateJsResultPollingCheck jsResult = new EvaluateJsResultPollingCheck("null");
    128         mOnUiThread.evaluateJavascript(
    129                 "document.getElementById('" + linkId + "').click();" +
    130                 "console.log('element with id [" + linkId + "] clicked');", jsResult);
    131         jsResult.run();
    132     }
    133 
    134     public void testLoadPage() throws Exception {
    135         final MockWebViewClient webViewClient = new MockWebViewClient();
    136         mOnUiThread.setWebViewClient(webViewClient);
    137         mWebServer = new CtsTestServer(getActivity());
    138         String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
    139 
    140         assertFalse(webViewClient.hasOnPageStartedCalled());
    141         assertFalse(webViewClient.hasOnLoadResourceCalled());
    142         assertFalse(webViewClient.hasOnPageFinishedCalled());
    143         mOnUiThread.loadUrlAndWaitForCompletion(url);
    144 
    145         new PollingCheck(TEST_TIMEOUT) {
    146             @Override
    147             protected boolean check() {
    148                 return webViewClient.hasOnPageStartedCalled();
    149             }
    150         }.run();
    151 
    152         new PollingCheck(TEST_TIMEOUT) {
    153             @Override
    154             protected boolean check() {
    155                 return webViewClient.hasOnLoadResourceCalled();
    156             }
    157         }.run();
    158 
    159         new PollingCheck(TEST_TIMEOUT) {
    160             @Override
    161             protected boolean check() {
    162                 return webViewClient.hasOnPageFinishedCalled();
    163             }
    164         }.run();
    165     }
    166 
    167     public void testOnReceivedError() throws Exception {
    168         final MockWebViewClient webViewClient = new MockWebViewClient();
    169         mOnUiThread.setWebViewClient(webViewClient);
    170 
    171         String wrongUri = "invalidscheme://some/resource";
    172         assertEquals(0, webViewClient.hasOnReceivedErrorCode());
    173         mOnUiThread.loadUrlAndWaitForCompletion(wrongUri);
    174         assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME,
    175                 webViewClient.hasOnReceivedErrorCode());
    176     }
    177 
    178     public void testOnFormResubmission() throws Exception {
    179         final MockWebViewClient webViewClient = new MockWebViewClient();
    180         mOnUiThread.setWebViewClient(webViewClient);
    181         final WebSettings settings = mOnUiThread.getSettings();
    182         settings.setJavaScriptEnabled(true);
    183         mWebServer = new CtsTestServer(getActivity());
    184 
    185         assertFalse(webViewClient.hasOnFormResubmissionCalled());
    186         String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_FORM_URL);
    187         // this loads a form, which automatically posts itself
    188         mOnUiThread.loadUrlAndWaitForCompletion(url);
    189         // wait for JavaScript to post the form
    190         mOnUiThread.waitForLoadCompletion();
    191         // the URL should have changed when the form was posted
    192         assertFalse(url.equals(mOnUiThread.getUrl()));
    193         // reloading the current URL should trigger the callback
    194         mOnUiThread.reload();
    195         new PollingCheck(TEST_TIMEOUT) {
    196             @Override
    197             protected boolean check() {
    198                 return webViewClient.hasOnFormResubmissionCalled();
    199             }
    200         }.run();
    201     }
    202 
    203     public void testDoUpdateVisitedHistory() throws Exception {
    204         final MockWebViewClient webViewClient = new MockWebViewClient();
    205         mOnUiThread.setWebViewClient(webViewClient);
    206         mWebServer = new CtsTestServer(getActivity());
    207 
    208         assertFalse(webViewClient.hasDoUpdateVisitedHistoryCalled());
    209         String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
    210         String url2 = mWebServer.getAssetUrl(TestHtmlConstants.BR_TAG_URL);
    211         mOnUiThread.loadUrlAndWaitForCompletion(url1);
    212         mOnUiThread.loadUrlAndWaitForCompletion(url2);
    213         new PollingCheck(TEST_TIMEOUT) {
    214             @Override
    215             protected boolean check() {
    216                 return webViewClient.hasDoUpdateVisitedHistoryCalled();
    217             }
    218         }.run();
    219     }
    220 
    221     public void testOnReceivedHttpAuthRequest() throws Exception {
    222         final MockWebViewClient webViewClient = new MockWebViewClient();
    223         mOnUiThread.setWebViewClient(webViewClient);
    224         mWebServer = new CtsTestServer(getActivity());
    225 
    226         assertFalse(webViewClient.hasOnReceivedHttpAuthRequestCalled());
    227         String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.EMBEDDED_IMG_URL);
    228         mOnUiThread.loadUrlAndWaitForCompletion(url);
    229         assertTrue(webViewClient.hasOnReceivedHttpAuthRequestCalled());
    230     }
    231 
    232     public void testShouldOverrideKeyEvent() {
    233         final MockWebViewClient webViewClient = new MockWebViewClient();
    234         mOnUiThread.setWebViewClient(webViewClient);
    235 
    236         assertFalse(webViewClient.shouldOverrideKeyEvent(mOnUiThread.getWebView(), null));
    237     }
    238 
    239     public void testOnUnhandledKeyEvent() throws Throwable {
    240         requireLoadedPage();
    241         final MockWebViewClient webViewClient = new MockWebViewClient();
    242         mOnUiThread.setWebViewClient(webViewClient);
    243 
    244         mOnUiThread.requestFocus();
    245         getInstrumentation().waitForIdleSync();
    246 
    247         assertFalse(webViewClient.hasOnUnhandledKeyEventCalled());
    248         sendKeys(KeyEvent.KEYCODE_1);
    249 
    250         new PollingCheck(TEST_TIMEOUT) {
    251             @Override
    252             protected boolean check() {
    253                 return webViewClient.hasOnUnhandledKeyEventCalled();
    254             }
    255         }.run();
    256     }
    257 
    258     public void testOnScaleChanged() throws Throwable {
    259         final MockWebViewClient webViewClient = new MockWebViewClient();
    260         mOnUiThread.setWebViewClient(webViewClient);
    261         mWebServer = new CtsTestServer(getActivity());
    262 
    263         assertFalse(webViewClient.hasOnScaleChangedCalled());
    264         String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
    265         mOnUiThread.loadUrlAndWaitForCompletion(url1);
    266 
    267         mOnUiThread.zoomIn();
    268         new PollingCheck(TEST_TIMEOUT) {
    269             @Override
    270             protected boolean check() {
    271                 return webViewClient.hasOnScaleChangedCalled();
    272             }
    273         }.run();
    274     }
    275 
    276     private void requireLoadedPage() throws Throwable {
    277         mOnUiThread.loadUrlAndWaitForCompletion("about:blank");
    278     }
    279 
    280     private class MockWebViewClient extends WaitForLoadedClient {
    281         private boolean mOnPageStartedCalled;
    282         private boolean mOnPageFinishedCalled;
    283         private boolean mOnLoadResourceCalled;
    284         private int mOnReceivedErrorCode;
    285         private boolean mOnFormResubmissionCalled;
    286         private boolean mDoUpdateVisitedHistoryCalled;
    287         private boolean mOnReceivedHttpAuthRequestCalled;
    288         private boolean mOnUnhandledKeyEventCalled;
    289         private boolean mOnScaleChangedCalled;
    290         private String mLastShouldOverrideUrl;
    291 
    292         public MockWebViewClient() {
    293             super(mOnUiThread);
    294         }
    295 
    296         public boolean hasOnPageStartedCalled() {
    297             return mOnPageStartedCalled;
    298         }
    299 
    300         public boolean hasOnPageFinishedCalled() {
    301             return mOnPageFinishedCalled;
    302         }
    303 
    304         public boolean hasOnLoadResourceCalled() {
    305             return mOnLoadResourceCalled;
    306         }
    307 
    308         public int hasOnReceivedErrorCode() {
    309             return mOnReceivedErrorCode;
    310         }
    311 
    312         public boolean hasOnFormResubmissionCalled() {
    313             return mOnFormResubmissionCalled;
    314         }
    315 
    316         public boolean hasDoUpdateVisitedHistoryCalled() {
    317             return mDoUpdateVisitedHistoryCalled;
    318         }
    319 
    320         public boolean hasOnReceivedHttpAuthRequestCalled() {
    321             return mOnReceivedHttpAuthRequestCalled;
    322         }
    323 
    324         public boolean hasOnUnhandledKeyEventCalled() {
    325             return mOnUnhandledKeyEventCalled;
    326         }
    327 
    328         public boolean hasOnScaleChangedCalled() {
    329             return mOnScaleChangedCalled;
    330         }
    331 
    332         public String getLastShouldOverrideUrl() {
    333             return mLastShouldOverrideUrl;
    334         }
    335 
    336         @Override
    337         public void onPageStarted(WebView view, String url, Bitmap favicon) {
    338             super.onPageStarted(view, url, favicon);
    339             mOnPageStartedCalled = true;
    340         }
    341 
    342         @Override
    343         public void onPageFinished(WebView view, String url) {
    344             super.onPageFinished(view, url);
    345             assertTrue(mOnPageStartedCalled);
    346             assertTrue(mOnLoadResourceCalled);
    347             mOnPageFinishedCalled = true;
    348         }
    349 
    350         @Override
    351         public void onLoadResource(WebView view, String url) {
    352             super.onLoadResource(view, url);
    353             assertTrue(mOnPageStartedCalled);
    354             mOnLoadResourceCalled = true;
    355         }
    356 
    357         @Override
    358         public void onReceivedError(WebView view, int errorCode,
    359                 String description, String failingUrl) {
    360             super.onReceivedError(view, errorCode, description, failingUrl);
    361             mOnReceivedErrorCode = errorCode;
    362         }
    363 
    364         @Override
    365         public void onFormResubmission(WebView view, Message dontResend, Message resend) {
    366             mOnFormResubmissionCalled = true;
    367             dontResend.sendToTarget();
    368         }
    369 
    370         @Override
    371         public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
    372             super.doUpdateVisitedHistory(view, url, isReload);
    373             mDoUpdateVisitedHistoryCalled = true;
    374         }
    375 
    376         @Override
    377         public void onReceivedHttpAuthRequest(WebView view,
    378                 HttpAuthHandler handler, String host, String realm) {
    379             super.onReceivedHttpAuthRequest(view, handler, host, realm);
    380             mOnReceivedHttpAuthRequestCalled = true;
    381         }
    382 
    383         @Override
    384         public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
    385             super.onUnhandledKeyEvent(view, event);
    386             mOnUnhandledKeyEventCalled = true;
    387         }
    388 
    389         @Override
    390         public void onScaleChanged(WebView view, float oldScale, float newScale) {
    391             super.onScaleChanged(view, oldScale, newScale);
    392             mOnScaleChangedCalled = true;
    393         }
    394 
    395         @Override
    396         public boolean shouldOverrideUrlLoading(WebView view, String url) {
    397             mLastShouldOverrideUrl = url;
    398             return false;
    399         }
    400     }
    401 }
    402