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