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 testOnJsBeforeUnloadIsCalled()201 public void testOnJsBeforeUnloadIsCalled() 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 } 225 testOnJsAlert()226 public void testOnJsAlert() throws Exception { 227 if (!NullWebViewUtils.isWebViewAvailable()) { 228 return; 229 } 230 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 231 mOnUiThread.setWebChromeClient(webChromeClient); 232 233 final WebSettings settings = mOnUiThread.getSettings(); 234 settings.setJavaScriptEnabled(true); 235 settings.setJavaScriptCanOpenWindowsAutomatically(true); 236 237 assertFalse(webChromeClient.hadOnJsAlert()); 238 239 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_ALERT_URL); 240 mOnUiThread.loadUrlAndWaitForCompletion(url); 241 242 new PollingCheck(TEST_TIMEOUT) { 243 @Override 244 protected boolean check() { 245 return webChromeClient.hadOnJsAlert(); 246 } 247 }.run(); 248 assertEquals(webChromeClient.getMessage(), "testOnJsAlert"); 249 } 250 testOnJsConfirm()251 public void testOnJsConfirm() throws Exception { 252 if (!NullWebViewUtils.isWebViewAvailable()) { 253 return; 254 } 255 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 256 mOnUiThread.setWebChromeClient(webChromeClient); 257 258 final WebSettings settings = mOnUiThread.getSettings(); 259 settings.setJavaScriptEnabled(true); 260 settings.setJavaScriptCanOpenWindowsAutomatically(true); 261 262 assertFalse(webChromeClient.hadOnJsConfirm()); 263 264 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_CONFIRM_URL); 265 mOnUiThread.loadUrlAndWaitForCompletion(url); 266 267 new PollingCheck(TEST_TIMEOUT) { 268 @Override 269 protected boolean check() { 270 return webChromeClient.hadOnJsConfirm(); 271 } 272 }.run(); 273 assertEquals(webChromeClient.getMessage(), "testOnJsConfirm"); 274 } 275 testOnJsPrompt()276 public void testOnJsPrompt() throws Exception { 277 if (!NullWebViewUtils.isWebViewAvailable()) { 278 return; 279 } 280 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 281 mOnUiThread.setWebChromeClient(webChromeClient); 282 283 final WebSettings settings = mOnUiThread.getSettings(); 284 settings.setJavaScriptEnabled(true); 285 settings.setJavaScriptCanOpenWindowsAutomatically(true); 286 287 assertFalse(webChromeClient.hadOnJsPrompt()); 288 289 final String promptResult = "CTS"; 290 webChromeClient.setPromptResult(promptResult); 291 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_PROMPT_URL); 292 mOnUiThread.loadUrlAndWaitForCompletion(url); 293 294 new PollingCheck(TEST_TIMEOUT) { 295 @Override 296 protected boolean check() { 297 return webChromeClient.hadOnJsPrompt(); 298 } 299 }.run(); 300 // the result returned by the client gets set as the page title 301 new PollingCheck(TEST_TIMEOUT) { 302 @Override 303 protected boolean check() { 304 return mOnUiThread.getTitle().equals(promptResult); 305 } 306 }.run(); 307 assertEquals(webChromeClient.getMessage(), "testOnJsPrompt"); 308 } 309 310 private class MockWebChromeClient extends WaitForProgressClient { 311 private boolean mHadOnProgressChanged; 312 private boolean mHadOnReceivedTitle; 313 private String mPageTitle; 314 private boolean mHadOnJsAlert; 315 private boolean mHadOnJsConfirm; 316 private boolean mHadOnJsPrompt; 317 private boolean mHadOnJsBeforeUnload; 318 private String mMessage; 319 private String mPromptResult; 320 private boolean mHadOnCloseWindow; 321 private boolean mHadOnCreateWindow; 322 private boolean mHadOnRequestFocus; 323 private boolean mHadOnReceivedIcon; 324 MockWebChromeClient()325 public MockWebChromeClient() { 326 super(mOnUiThread); 327 } 328 setPromptResult(String promptResult)329 public void setPromptResult(String promptResult) { 330 mPromptResult = promptResult; 331 } 332 hadOnProgressChanged()333 public boolean hadOnProgressChanged() { 334 return mHadOnProgressChanged; 335 } 336 hadOnReceivedTitle()337 public boolean hadOnReceivedTitle() { 338 return mHadOnReceivedTitle; 339 } 340 getPageTitle()341 public String getPageTitle() { 342 return mPageTitle; 343 } 344 hadOnJsAlert()345 public boolean hadOnJsAlert() { 346 return mHadOnJsAlert; 347 } 348 hadOnJsConfirm()349 public boolean hadOnJsConfirm() { 350 return mHadOnJsConfirm; 351 } 352 hadOnJsPrompt()353 public boolean hadOnJsPrompt() { 354 return mHadOnJsPrompt; 355 } 356 hadOnJsBeforeUnload()357 public boolean hadOnJsBeforeUnload() { 358 return mHadOnJsBeforeUnload; 359 } 360 hadOnCreateWindow()361 public boolean hadOnCreateWindow() { 362 return mHadOnCreateWindow; 363 } 364 hadOnCloseWindow()365 public boolean hadOnCloseWindow() { 366 return mHadOnCloseWindow; 367 } 368 hadOnRequestFocus()369 public boolean hadOnRequestFocus() { 370 return mHadOnRequestFocus; 371 } 372 hadOnReceivedIcon()373 public boolean hadOnReceivedIcon() { 374 return mHadOnReceivedIcon; 375 } 376 getMessage()377 public String getMessage() { 378 return mMessage; 379 } 380 381 @Override onProgressChanged(WebView view, int newProgress)382 public void onProgressChanged(WebView view, int newProgress) { 383 super.onProgressChanged(view, newProgress); 384 mHadOnProgressChanged = true; 385 } 386 387 @Override onReceivedTitle(WebView view, String title)388 public void onReceivedTitle(WebView view, String title) { 389 super.onReceivedTitle(view, title); 390 mPageTitle = title; 391 mHadOnReceivedTitle = true; 392 } 393 394 @Override onJsAlert(WebView view, String url, String message, JsResult result)395 public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 396 super.onJsAlert(view, url, message, result); 397 mHadOnJsAlert = true; 398 mMessage = message; 399 result.confirm(); 400 return true; 401 } 402 403 @Override onJsConfirm(WebView view, String url, String message, JsResult result)404 public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { 405 super.onJsConfirm(view, url, message, result); 406 mHadOnJsConfirm = true; 407 mMessage = message; 408 result.confirm(); 409 return true; 410 } 411 412 @Override onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)413 public boolean onJsPrompt(WebView view, String url, String message, 414 String defaultValue, JsPromptResult result) { 415 super.onJsPrompt(view, url, message, defaultValue, result); 416 mHadOnJsPrompt = true; 417 mMessage = message; 418 result.confirm(mPromptResult); 419 return true; 420 } 421 422 @Override onJsBeforeUnload(WebView view, String url, String message, JsResult result)423 public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) { 424 super.onJsBeforeUnload(view, url, message, result); 425 mHadOnJsBeforeUnload = true; 426 mMessage = message; 427 result.confirm(); 428 return true; 429 } 430 431 @Override onCloseWindow(WebView window)432 public void onCloseWindow(WebView window) { 433 super.onCloseWindow(window); 434 mHadOnCloseWindow = true; 435 } 436 437 @Override onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg)438 public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, 439 Message resultMsg) { 440 mHadOnCreateWindow = true; 441 if (mBlockWindowCreationSync) { 442 return false; 443 } 444 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; 445 if (mBlockWindowCreationAsync) { 446 transport.setWebView(null); 447 } else { 448 WebView childView = new WebView(getActivity()); 449 final WebSettings settings = childView.getSettings(); 450 settings.setJavaScriptEnabled(true); 451 childView.setWebChromeClient(this); 452 transport.setWebView(childView); 453 getActivity().addContentView(childView, new ViewGroup.LayoutParams( 454 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 455 } 456 resultMsg.sendToTarget(); 457 return true; 458 } 459 460 @Override onRequestFocus(WebView view)461 public void onRequestFocus(WebView view) { 462 mHadOnRequestFocus = true; 463 } 464 465 @Override onReceivedIcon(WebView view, Bitmap icon)466 public void onReceivedIcon(WebView view, Bitmap icon) { 467 mHadOnReceivedIcon = true; 468 } 469 } 470 } 471