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.NullWebViewUtils; 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.ViewGroup; 25 import android.webkit.JsPromptResult; 26 import android.webkit.JsResult; 27 import android.webkit.WebIconDatabase; 28 import android.webkit.WebSettings; 29 import android.webkit.WebView; 30 import android.webkit.cts.WebViewOnUiThread.WaitForProgressClient; 31 32 public class WebChromeClientTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> { 33 private static final long TEST_TIMEOUT = 5000L; 34 35 private CtsTestServer mWebServer; 36 private WebIconDatabase mIconDb; 37 private WebViewOnUiThread mOnUiThread; 38 private boolean mBlockWindowCreationSync; 39 private boolean mBlockWindowCreationAsync; 40 WebChromeClientTest()41 public WebChromeClientTest() { 42 super(WebViewCtsActivity.class); 43 } 44 45 @Override setUp()46 protected void setUp() throws Exception { 47 super.setUp(); 48 WebView webview = getActivity().getWebView(); 49 if (webview != null) { 50 mOnUiThread = new WebViewOnUiThread(this, webview); 51 } 52 mWebServer = new CtsTestServer(getActivity()); 53 } 54 55 @Override tearDown()56 protected void tearDown() throws Exception { 57 if (mOnUiThread != null) { 58 mOnUiThread.cleanUp(); 59 } 60 if (mWebServer != null) { 61 mWebServer.shutdown(); 62 } 63 if (mIconDb != null) { 64 mIconDb.removeAllIcons(); 65 mIconDb.close(); 66 } 67 super.tearDown(); 68 } 69 testOnProgressChanged()70 public void testOnProgressChanged() { 71 if (!NullWebViewUtils.isWebViewAvailable()) { 72 return; 73 } 74 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 75 mOnUiThread.setWebChromeClient(webChromeClient); 76 77 assertFalse(webChromeClient.hadOnProgressChanged()); 78 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 79 mOnUiThread.loadUrlAndWaitForCompletion(url); 80 81 new PollingCheck(TEST_TIMEOUT) { 82 @Override 83 protected boolean check() { 84 return webChromeClient.hadOnProgressChanged(); 85 } 86 }.run(); 87 } 88 testOnReceivedTitle()89 public void testOnReceivedTitle() throws Exception { 90 if (!NullWebViewUtils.isWebViewAvailable()) { 91 return; 92 } 93 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 94 mOnUiThread.setWebChromeClient(webChromeClient); 95 96 assertFalse(webChromeClient.hadOnReceivedTitle()); 97 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 98 mOnUiThread.loadUrlAndWaitForCompletion(url); 99 100 new PollingCheck(TEST_TIMEOUT) { 101 @Override 102 protected boolean check() { 103 return webChromeClient.hadOnReceivedTitle(); 104 } 105 }.run(); 106 assertTrue(webChromeClient.hadOnReceivedTitle()); 107 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, webChromeClient.getPageTitle()); 108 } 109 testOnReceivedIcon()110 public void testOnReceivedIcon() throws Throwable { 111 if (!NullWebViewUtils.isWebViewAvailable()) { 112 return; 113 } 114 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 115 mOnUiThread.setWebChromeClient(webChromeClient); 116 117 runTestOnUiThread(new Runnable() { 118 @Override 119 public void run() { 120 // getInstance must run on the UI thread 121 mIconDb = WebIconDatabase.getInstance(); 122 String dbPath = getActivity().getFilesDir().toString() + "/icons"; 123 mIconDb.open(dbPath); 124 } 125 }); 126 getInstrumentation().waitForIdleSync(); 127 Thread.sleep(100); // Wait for open to be received on the icon db thread. 128 129 assertFalse(webChromeClient.hadOnReceivedIcon()); 130 assertNull(mOnUiThread.getFavicon()); 131 132 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 133 mOnUiThread.loadUrlAndWaitForCompletion(url); 134 135 new PollingCheck(TEST_TIMEOUT) { 136 @Override 137 protected boolean check() { 138 return webChromeClient.hadOnReceivedIcon(); 139 } 140 }.run(); 141 assertNotNull(mOnUiThread.getFavicon()); 142 } 143 runWindowTest(boolean expectWindowClose)144 public void runWindowTest(boolean expectWindowClose) throws Exception { 145 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 146 mOnUiThread.setWebChromeClient(webChromeClient); 147 148 final WebSettings settings = mOnUiThread.getSettings(); 149 settings.setJavaScriptEnabled(true); 150 settings.setJavaScriptCanOpenWindowsAutomatically(true); 151 settings.setSupportMultipleWindows(true); 152 153 assertFalse(webChromeClient.hadOnCreateWindow()); 154 155 // Load a page that opens a child window and sets a timeout after which the child 156 // will be closed. 157 mOnUiThread.loadUrlAndWaitForCompletion(mWebServer. 158 getAssetUrl(TestHtmlConstants.JS_WINDOW_URL)); 159 160 new PollingCheck(TEST_TIMEOUT) { 161 @Override 162 protected boolean check() { 163 return webChromeClient.hadOnCreateWindow(); 164 } 165 }.run(); 166 167 if (expectWindowClose) { 168 new PollingCheck(TEST_TIMEOUT) { 169 @Override 170 protected boolean check() { 171 return webChromeClient.hadOnCloseWindow(); 172 } 173 }.run(); 174 } else { 175 assertFalse(webChromeClient.hadOnCloseWindow()); 176 } 177 } testWindows()178 public void testWindows() throws Exception { 179 if (!NullWebViewUtils.isWebViewAvailable()) { 180 return; 181 } 182 runWindowTest(true); 183 } 184 testBlockWindowsSync()185 public void testBlockWindowsSync() throws Exception { 186 if (!NullWebViewUtils.isWebViewAvailable()) { 187 return; 188 } 189 mBlockWindowCreationSync = true; 190 runWindowTest(false); 191 } 192 testBlockWindowsAsync()193 public void testBlockWindowsAsync() throws Exception { 194 if (!NullWebViewUtils.isWebViewAvailable()) { 195 return; 196 } 197 mBlockWindowCreationAsync = true; 198 runWindowTest(false); 199 } 200 testOnJsBeforeUnload()201 public void testOnJsBeforeUnload() throws Exception { 202 if (!NullWebViewUtils.isWebViewAvailable()) { 203 return; 204 } 205 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 206 mOnUiThread.setWebChromeClient(webChromeClient); 207 208 final WebSettings settings = mOnUiThread.getSettings(); 209 settings.setJavaScriptEnabled(true); 210 settings.setJavaScriptCanOpenWindowsAutomatically(true); 211 212 assertFalse(webChromeClient.hadOnJsBeforeUnload()); 213 214 mOnUiThread.loadUrlAndWaitForCompletion(mWebServer.getAssetUrl(TestHtmlConstants.JS_UNLOAD_URL)); 215 // unload should trigger when we try to navigate away 216 mOnUiThread.loadUrlAndWaitForCompletion(mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 217 218 new PollingCheck(TEST_TIMEOUT) { 219 @Override 220 protected boolean check() { 221 return webChromeClient.hadOnJsBeforeUnload(); 222 } 223 }.run(); 224 assertEquals(webChromeClient.getMessage(), "testOnJsBeforeUnload"); 225 } 226 testOnJsAlert()227 public void testOnJsAlert() throws Exception { 228 if (!NullWebViewUtils.isWebViewAvailable()) { 229 return; 230 } 231 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 232 mOnUiThread.setWebChromeClient(webChromeClient); 233 234 final WebSettings settings = mOnUiThread.getSettings(); 235 settings.setJavaScriptEnabled(true); 236 settings.setJavaScriptCanOpenWindowsAutomatically(true); 237 238 assertFalse(webChromeClient.hadOnJsAlert()); 239 240 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_ALERT_URL); 241 mOnUiThread.loadUrlAndWaitForCompletion(url); 242 243 new PollingCheck(TEST_TIMEOUT) { 244 @Override 245 protected boolean check() { 246 return webChromeClient.hadOnJsAlert(); 247 } 248 }.run(); 249 assertEquals(webChromeClient.getMessage(), "testOnJsAlert"); 250 } 251 testOnJsConfirm()252 public void testOnJsConfirm() throws Exception { 253 if (!NullWebViewUtils.isWebViewAvailable()) { 254 return; 255 } 256 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 257 mOnUiThread.setWebChromeClient(webChromeClient); 258 259 final WebSettings settings = mOnUiThread.getSettings(); 260 settings.setJavaScriptEnabled(true); 261 settings.setJavaScriptCanOpenWindowsAutomatically(true); 262 263 assertFalse(webChromeClient.hadOnJsConfirm()); 264 265 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_CONFIRM_URL); 266 mOnUiThread.loadUrlAndWaitForCompletion(url); 267 268 new PollingCheck(TEST_TIMEOUT) { 269 @Override 270 protected boolean check() { 271 return webChromeClient.hadOnJsConfirm(); 272 } 273 }.run(); 274 assertEquals(webChromeClient.getMessage(), "testOnJsConfirm"); 275 } 276 testOnJsPrompt()277 public void testOnJsPrompt() throws Exception { 278 if (!NullWebViewUtils.isWebViewAvailable()) { 279 return; 280 } 281 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 282 mOnUiThread.setWebChromeClient(webChromeClient); 283 284 final WebSettings settings = mOnUiThread.getSettings(); 285 settings.setJavaScriptEnabled(true); 286 settings.setJavaScriptCanOpenWindowsAutomatically(true); 287 288 assertFalse(webChromeClient.hadOnJsPrompt()); 289 290 final String promptResult = "CTS"; 291 webChromeClient.setPromptResult(promptResult); 292 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_PROMPT_URL); 293 mOnUiThread.loadUrlAndWaitForCompletion(url); 294 295 new PollingCheck(TEST_TIMEOUT) { 296 @Override 297 protected boolean check() { 298 return webChromeClient.hadOnJsPrompt(); 299 } 300 }.run(); 301 // the result returned by the client gets set as the page title 302 new PollingCheck(TEST_TIMEOUT) { 303 @Override 304 protected boolean check() { 305 return mOnUiThread.getTitle().equals(promptResult); 306 } 307 }.run(); 308 assertEquals(webChromeClient.getMessage(), "testOnJsPrompt"); 309 } 310 311 private class MockWebChromeClient extends WaitForProgressClient { 312 private boolean mHadOnProgressChanged; 313 private boolean mHadOnReceivedTitle; 314 private String mPageTitle; 315 private boolean mHadOnJsAlert; 316 private boolean mHadOnJsConfirm; 317 private boolean mHadOnJsPrompt; 318 private boolean mHadOnJsBeforeUnload; 319 private String mMessage; 320 private String mPromptResult; 321 private boolean mHadOnCloseWindow; 322 private boolean mHadOnCreateWindow; 323 private boolean mHadOnRequestFocus; 324 private boolean mHadOnReceivedIcon; 325 MockWebChromeClient()326 public MockWebChromeClient() { 327 super(mOnUiThread); 328 } 329 setPromptResult(String promptResult)330 public void setPromptResult(String promptResult) { 331 mPromptResult = promptResult; 332 } 333 hadOnProgressChanged()334 public boolean hadOnProgressChanged() { 335 return mHadOnProgressChanged; 336 } 337 hadOnReceivedTitle()338 public boolean hadOnReceivedTitle() { 339 return mHadOnReceivedTitle; 340 } 341 getPageTitle()342 public String getPageTitle() { 343 return mPageTitle; 344 } 345 hadOnJsAlert()346 public boolean hadOnJsAlert() { 347 return mHadOnJsAlert; 348 } 349 hadOnJsConfirm()350 public boolean hadOnJsConfirm() { 351 return mHadOnJsConfirm; 352 } 353 hadOnJsPrompt()354 public boolean hadOnJsPrompt() { 355 return mHadOnJsPrompt; 356 } 357 hadOnJsBeforeUnload()358 public boolean hadOnJsBeforeUnload() { 359 return mHadOnJsBeforeUnload; 360 } 361 hadOnCreateWindow()362 public boolean hadOnCreateWindow() { 363 return mHadOnCreateWindow; 364 } 365 hadOnCloseWindow()366 public boolean hadOnCloseWindow() { 367 return mHadOnCloseWindow; 368 } 369 hadOnRequestFocus()370 public boolean hadOnRequestFocus() { 371 return mHadOnRequestFocus; 372 } 373 hadOnReceivedIcon()374 public boolean hadOnReceivedIcon() { 375 return mHadOnReceivedIcon; 376 } 377 getMessage()378 public String getMessage() { 379 return mMessage; 380 } 381 382 @Override onProgressChanged(WebView view, int newProgress)383 public void onProgressChanged(WebView view, int newProgress) { 384 super.onProgressChanged(view, newProgress); 385 mHadOnProgressChanged = true; 386 } 387 388 @Override onReceivedTitle(WebView view, String title)389 public void onReceivedTitle(WebView view, String title) { 390 super.onReceivedTitle(view, title); 391 mPageTitle = title; 392 mHadOnReceivedTitle = true; 393 } 394 395 @Override onJsAlert(WebView view, String url, String message, JsResult result)396 public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 397 super.onJsAlert(view, url, message, result); 398 mHadOnJsAlert = true; 399 mMessage = message; 400 result.confirm(); 401 return true; 402 } 403 404 @Override onJsConfirm(WebView view, String url, String message, JsResult result)405 public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { 406 super.onJsConfirm(view, url, message, result); 407 mHadOnJsConfirm = true; 408 mMessage = message; 409 result.confirm(); 410 return true; 411 } 412 413 @Override onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)414 public boolean onJsPrompt(WebView view, String url, String message, 415 String defaultValue, JsPromptResult result) { 416 super.onJsPrompt(view, url, message, defaultValue, result); 417 mHadOnJsPrompt = true; 418 mMessage = message; 419 result.confirm(mPromptResult); 420 return true; 421 } 422 423 @Override onJsBeforeUnload(WebView view, String url, String message, JsResult result)424 public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) { 425 super.onJsBeforeUnload(view, url, message, result); 426 mHadOnJsBeforeUnload = true; 427 mMessage = message; 428 result.confirm(); 429 return true; 430 } 431 432 @Override onCloseWindow(WebView window)433 public void onCloseWindow(WebView window) { 434 super.onCloseWindow(window); 435 mHadOnCloseWindow = true; 436 } 437 438 @Override onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg)439 public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, 440 Message resultMsg) { 441 mHadOnCreateWindow = true; 442 if (mBlockWindowCreationSync) { 443 return false; 444 } 445 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; 446 if (mBlockWindowCreationAsync) { 447 transport.setWebView(null); 448 } else { 449 WebView childView = new WebView(getActivity()); 450 final WebSettings settings = childView.getSettings(); 451 settings.setJavaScriptEnabled(true); 452 childView.setWebChromeClient(this); 453 transport.setWebView(childView); 454 getActivity().addContentView(childView, new ViewGroup.LayoutParams( 455 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 456 } 457 resultMsg.sendToTarget(); 458 return true; 459 } 460 461 @Override onRequestFocus(WebView view)462 public void onRequestFocus(WebView view) { 463 mHadOnRequestFocus = true; 464 } 465 466 @Override onReceivedIcon(WebView view, Bitmap icon)467 public void onReceivedIcon(WebView view, Bitmap icon) { 468 mHadOnReceivedIcon = true; 469 } 470 } 471 } 472