1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- 2 * Any copyright is dedicated to the Public Domain. 3 http://creativecommons.org/publicdomain/zero/1.0/ */ 4 5 package org.mozilla.geckoview.test 6 7 import android.graphics.Bitmap 8 import android.os.SystemClock 9 import android.view.KeyEvent 10 import android.util.Base64 11 import androidx.test.ext.junit.runners.AndroidJUnit4 12 import androidx.test.filters.MediumTest 13 import java.io.ByteArrayOutputStream 14 import java.util.concurrent.ThreadLocalRandom 15 import org.hamcrest.Matchers.* 16 import org.json.JSONObject 17 import org.junit.Assume.assumeThat 18 import org.junit.Ignore 19 import org.junit.Test 20 import org.junit.runner.RunWith 21 import org.mozilla.geckoview.* 22 import org.mozilla.geckoview.GeckoSession.* 23 import org.mozilla.geckoview.GeckoSession.NavigationDelegate.LoadRequest 24 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule 25 import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.* 26 import org.mozilla.geckoview.test.util.Callbacks 27 import org.mozilla.geckoview.test.util.UiThreadUtils 28 29 @RunWith(AndroidJUnit4::class) 30 @MediumTest 31 class NavigationDelegateTest : BaseSessionTest() { 32 33 // Provides getters for Loader 34 class TestLoader : Loader() { 35 var mUri: String? = null urinull36 override fun uri(uri: String): TestLoader { 37 mUri = uri 38 super.uri(uri) 39 return this 40 } getUrinull41 fun getUri() : String? { 42 return mUri 43 } flagsnull44 override fun flags(f: Int): TestLoader { 45 super.flags(f) 46 return this 47 } 48 } 49 testLoadErrorWithErrorPagenull50 fun testLoadErrorWithErrorPage(testLoader: TestLoader, expectedCategory: Int, 51 expectedError: Int, 52 errorPageUrl: String?) { 53 sessionRule.delegateDuringNextWait( 54 object : Callbacks.ProgressDelegate, Callbacks.NavigationDelegate, Callbacks.ContentDelegate { 55 @AssertCalled(count = 1, order = [1]) 56 override fun onLoadRequest(session: GeckoSession, 57 request: LoadRequest): 58 GeckoResult<AllowOrDeny>? { 59 assertThat("URI should be " + testLoader.getUri(), request.uri, 60 equalTo(testLoader.getUri())) 61 assertThat("App requested this load", request.isDirectNavigation, 62 equalTo(true)) 63 return null 64 } 65 66 @AssertCalled(count = 1, order = [2]) 67 override fun onPageStart(session: GeckoSession, url: String) { 68 assertThat("URI should be " + testLoader.getUri(), url, 69 equalTo(testLoader.getUri())) 70 } 71 72 @AssertCalled(count = 1, order = [3]) 73 override fun onLoadError(session: GeckoSession, uri: String?, 74 error: WebRequestError): GeckoResult<String>? { 75 assertThat("Error category should match", error.category, 76 equalTo(expectedCategory)) 77 assertThat("Error code should match", error.code, 78 equalTo(expectedError)) 79 return GeckoResult.fromValue(errorPageUrl) 80 } 81 82 @AssertCalled(count = 1, order = [4]) 83 override fun onPageStop(session: GeckoSession, success: Boolean) { 84 assertThat("Load should fail", success, equalTo(false)) 85 } 86 }) 87 88 sessionRule.session.load(testLoader) 89 sessionRule.waitForPageStop() 90 91 if (errorPageUrl != null) { 92 sessionRule.waitUntilCalled(object : Callbacks.ContentDelegate, Callbacks.NavigationDelegate { 93 @AssertCalled(count = 1, order = [1]) 94 override fun onLocationChange(session: GeckoSession, url: String?) { 95 assertThat("URL should match", url, equalTo(testLoader.getUri())) 96 } 97 98 @AssertCalled(count = 1, order = [2]) 99 override fun onTitleChange(session: GeckoSession, title: String?) { 100 assertThat("Title should not be empty", title, not(isEmptyOrNullString())) 101 } 102 }) 103 } 104 } 105 testLoadExpectErrornull106 fun testLoadExpectError(testUri: String, expectedCategory: Int, 107 expectedError: Int) { 108 testLoadExpectError(TestLoader().uri(testUri), expectedCategory, expectedError) 109 } 110 testLoadExpectErrornull111 fun testLoadExpectError(testLoader: TestLoader, expectedCategory: Int, 112 expectedError: Int) { 113 testLoadErrorWithErrorPage(testLoader, expectedCategory, 114 expectedError, createTestUrl(HELLO_HTML_PATH)) 115 testLoadErrorWithErrorPage(testLoader, expectedCategory, 116 expectedError, null) 117 } 118 testLoadEarlyErrorWithErrorPagenull119 fun testLoadEarlyErrorWithErrorPage(testUri: String, expectedCategory: Int, 120 expectedError: Int, 121 errorPageUrl: String?) { 122 sessionRule.delegateDuringNextWait( 123 object : Callbacks.ProgressDelegate, Callbacks.NavigationDelegate, Callbacks.ContentDelegate { 124 125 @AssertCalled(false) 126 override fun onPageStart(session: GeckoSession, url: String) { 127 assertThat("URI should be " + testUri, url, equalTo(testUri)) 128 } 129 130 @AssertCalled(count = 1, order = [1]) 131 override fun onLoadError(session: GeckoSession, uri: String?, 132 error: WebRequestError): GeckoResult<String>? { 133 assertThat("Error category should match", error.category, 134 equalTo(expectedCategory)) 135 assertThat("Error code should match", error.code, 136 equalTo(expectedError)) 137 return GeckoResult.fromValue(errorPageUrl) 138 } 139 140 @AssertCalled(false) 141 override fun onPageStop(session: GeckoSession, success: Boolean) { 142 } 143 }) 144 145 sessionRule.session.loadUri(testUri) 146 sessionRule.waitUntilCalled(Callbacks.NavigationDelegate::class, "onLoadError") 147 148 if (errorPageUrl != null) { 149 sessionRule.waitUntilCalled(object: Callbacks.ContentDelegate { 150 @AssertCalled(count = 1) 151 override fun onTitleChange(session: GeckoSession, title: String?) { 152 assertThat("Title should not be empty", title, not(isEmptyOrNullString())) 153 } 154 }) 155 } 156 } 157 testLoadEarlyErrornull158 fun testLoadEarlyError(testUri: String, expectedCategory: Int, 159 expectedError: Int) { 160 testLoadEarlyErrorWithErrorPage(testUri, expectedCategory, expectedError, createTestUrl(HELLO_HTML_PATH)) 161 testLoadEarlyErrorWithErrorPage(testUri, expectedCategory, expectedError, null) 162 } 163 loadFileNotFoundnull164 @Test fun loadFileNotFound() { 165 // TODO: Bug 1673954 166 assumeThat(sessionRule.env.isFission, equalTo(false)) 167 168 // TODO: bug 1710943 169 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 170 171 testLoadExpectError("file:///test.mozilla", 172 WebRequestError.ERROR_CATEGORY_URI, 173 WebRequestError.ERROR_FILE_NOT_FOUND) 174 175 val promise = mainSession.evaluatePromiseJS("document.addCertException(false)") 176 var exceptionCaught = false 177 try { 178 val result = promise.value as Boolean 179 assertThat("Promise should not resolve", result, equalTo(false)) 180 } catch (e: GeckoSessionTestRule.RejectedPromiseException) { 181 exceptionCaught = true; 182 } 183 assertThat("document.addCertException failed with exception", exceptionCaught, equalTo(true)) 184 } 185 loadUnknownHostnull186 @Test fun loadUnknownHost() { 187 // TODO: Bug 1673954 188 assumeThat(sessionRule.env.isFission, equalTo(false)) 189 190 // TODO: bug 1710943 191 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 192 193 testLoadExpectError(UNKNOWN_HOST_URI, 194 WebRequestError.ERROR_CATEGORY_URI, 195 WebRequestError.ERROR_UNKNOWN_HOST) 196 } 197 198 // External loads should not have access to privileged protocols loadExternalDeniednull199 @Test fun loadExternalDenied() { 200 // TODO: Bug 1673954 201 assumeThat(sessionRule.env.isFission, equalTo(false)) 202 203 // TODO: bug 1710943 204 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 205 206 testLoadExpectError(TestLoader().uri("file:///").flags(LOAD_FLAGS_EXTERNAL), 207 WebRequestError.ERROR_CATEGORY_UNKNOWN, 208 WebRequestError.ERROR_UNKNOWN) 209 testLoadExpectError(TestLoader().uri("resource://gre/").flags(LOAD_FLAGS_EXTERNAL), 210 WebRequestError.ERROR_CATEGORY_UNKNOWN, 211 WebRequestError.ERROR_UNKNOWN) 212 testLoadExpectError(TestLoader().uri("about:about").flags(LOAD_FLAGS_EXTERNAL), 213 WebRequestError.ERROR_CATEGORY_UNKNOWN, 214 WebRequestError.ERROR_UNKNOWN) 215 } 216 loadInvalidUrinull217 @Test fun loadInvalidUri() { 218 // TODO: bug 1710943 219 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 220 221 testLoadEarlyError(INVALID_URI, 222 WebRequestError.ERROR_CATEGORY_URI, 223 WebRequestError.ERROR_MALFORMED_URI) 224 } 225 loadBadPortnull226 @Test fun loadBadPort() { 227 // TODO: bug 1710943 228 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 229 230 testLoadEarlyError("http://localhost:1/", 231 WebRequestError.ERROR_CATEGORY_NETWORK, 232 WebRequestError.ERROR_PORT_BLOCKED) 233 } 234 loadUntrustednull235 @Test fun loadUntrusted() { 236 // TODO: Bug 1673954 237 assumeThat(sessionRule.env.isFission, equalTo(false)) 238 val host = if (sessionRule.env.isAutomation) { 239 "expired.example.com" 240 } else { 241 "expired.badssl.com" 242 } 243 val uri = "https://$host/" 244 testLoadExpectError(uri, 245 WebRequestError.ERROR_CATEGORY_SECURITY, 246 WebRequestError.ERROR_SECURITY_BAD_CERT) 247 248 mainSession.waitForJS("document.addCertException(false)") 249 mainSession.delegateDuringNextWait( 250 object : Callbacks.ProgressDelegate, Callbacks.NavigationDelegate, Callbacks.ContentDelegate { 251 @AssertCalled(count = 1, order = [1]) 252 override fun onPageStart(session: GeckoSession, url: String) { 253 assertThat("URI should be " + uri, url, equalTo(uri)) 254 } 255 256 @AssertCalled(count = 1, order = [2]) 257 override fun onPageStop(session: GeckoSession, success: Boolean) { 258 assertThat("Load should succeed", success, equalTo(true)) 259 sessionRule.removeAllCertOverrides() 260 } 261 }) 262 mainSession.evaluateJS("location.reload()") 263 mainSession.waitForPageStop() 264 } 265 loadDeprecatedTlsnull266 @Test fun loadDeprecatedTls() { 267 // TODO: Bug 1673954 268 assumeThat(sessionRule.env.isFission, equalTo(false)) 269 270 // TODO: bug 1710943 271 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 272 273 // Load an initial generic error page in order to ensure 'allowDeprecatedTls' is false 274 testLoadExpectError(UNKNOWN_HOST_URI, 275 WebRequestError.ERROR_CATEGORY_URI, 276 WebRequestError.ERROR_UNKNOWN_HOST) 277 mainSession.evaluateJS("document.allowDeprecatedTls = false") 278 279 val uri = if (sessionRule.env.isAutomation) { 280 "https://tls1.example.com/" 281 } else { 282 "https://tls-v1-0.badssl.com:1010/" 283 } 284 testLoadExpectError(uri, 285 WebRequestError.ERROR_CATEGORY_SECURITY, 286 WebRequestError.ERROR_SECURITY_SSL) 287 288 mainSession.delegateDuringNextWait(object : Callbacks.ProgressDelegate, Callbacks.NavigationDelegate { 289 @AssertCalled(count = 0) 290 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 291 return null 292 } 293 294 @AssertCalled(count = 1) 295 override fun onPageStop(session: GeckoSession, success: Boolean) { 296 assertThat("Load should be successful", success, equalTo(true)) 297 } 298 }) 299 300 mainSession.evaluateJS("document.allowDeprecatedTls = true") 301 mainSession.reload() 302 mainSession.waitForPageStop() 303 } 304 loadWithHTTPSOnlyModenull305 @Test fun loadWithHTTPSOnlyMode() { 306 sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.HTTPS_ONLY) 307 308 val insecureUri = if (sessionRule.env.isAutomation) { 309 "http://nocert.example.com/" 310 } else { 311 "http://neverssl.com" 312 } 313 314 val secureUri = if (sessionRule.env.isAutomation) { 315 "http://example.com/" 316 } else { 317 "http://neverssl.com" 318 } 319 320 mainSession.loadUri(insecureUri) 321 mainSession.waitForPageStop() 322 323 mainSession.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 324 @AssertCalled(count = 1) 325 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 326 assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_SECURITY)) 327 assertThat("codes should match", error.code, equalTo(WebRequestError.ERROR_SECURITY_BAD_CERT)) 328 return null 329 } 330 }) 331 332 sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.ALLOW_ALL) 333 334 mainSession.loadUri(secureUri) 335 mainSession.waitForPageStop() 336 337 mainSession.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 338 @AssertCalled(count = 0) 339 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 340 return null 341 } 342 343 @AssertCalled(count = 1) 344 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 345 return null 346 } 347 }) 348 349 val privateSession = sessionRule.createOpenSession( 350 GeckoSessionSettings.Builder(mainSession.settings) 351 .usePrivateMode(true) 352 .build()) 353 354 privateSession.loadUri(secureUri) 355 privateSession.waitForPageStop() 356 357 var onLoadCalledCounter = 0 358 privateSession.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 359 @AssertCalled(count = 0) 360 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 361 return null 362 } 363 364 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 365 onLoadCalledCounter++ 366 return null 367 } 368 }) 369 370 val httpsFirstPBMPref = "dom.security.https_first_pbm" 371 val httpsFirstPBMPrefValue = (sessionRule.getPrefs(httpsFirstPBMPref)[0] as Boolean) 372 if (httpsFirstPBMPrefValue) { 373 // if https-first is enabled we get two calls to onLoadRequest 374 // (1) http://example.com/ and (2) https://example.com/ 375 assertThat("Assert count privateSession.onLoadRequest", onLoadCalledCounter, equalTo(2)) 376 } else { 377 assertThat("Assert count privateSession.onLoadRequest", onLoadCalledCounter, equalTo(1)) 378 } 379 380 sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.HTTPS_ONLY_PRIVATE) 381 382 privateSession.loadUri(insecureUri) 383 privateSession.waitForPageStop() 384 385 privateSession.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 386 @AssertCalled(count = 1) 387 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 388 assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_SECURITY)) 389 assertThat("codes should match", error.code, equalTo(WebRequestError.ERROR_SECURITY_BAD_CERT)) 390 return null 391 } 392 }) 393 394 mainSession.loadUri(secureUri) 395 mainSession.waitForPageStop() 396 397 mainSession.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 398 @AssertCalled(count = 0) 399 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 400 return null 401 } 402 403 @AssertCalled(count = 1) 404 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 405 return null 406 } 407 }) 408 409 sessionRule.runtime.settings.setAllowInsecureConnections(GeckoRuntimeSettings.ALLOW_ALL) 410 } 411 412 @Ignore // Disabled for bug 1619344. loadUnknownProtocolnull413 @Test fun loadUnknownProtocol() { 414 testLoadEarlyError(UNKNOWN_PROTOCOL_URI, 415 WebRequestError.ERROR_CATEGORY_URI, 416 WebRequestError.ERROR_UNKNOWN_PROTOCOL) 417 } 418 loadUnknownProtocolIframenull419 @Test fun loadUnknownProtocolIframe() { 420 // TODO: bug 1710943 421 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 422 423 // Should match iframe URI from IFRAME_UNKNOWN_PROTOCOL 424 val iframeUri = "foo://bar" 425 sessionRule.session.loadTestPath(IFRAME_UNKNOWN_PROTOCOL) 426 sessionRule.session.waitForPageStop() 427 428 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 429 @AssertCalled(count = 1) 430 override fun onLoadRequest(session: GeckoSession, request: LoadRequest) : GeckoResult<AllowOrDeny>? { 431 assertThat("URI should not be null", request.uri, notNullValue()) 432 assertThat("URI should match", request.uri, endsWith(IFRAME_UNKNOWN_PROTOCOL)) 433 return null 434 } 435 436 @AssertCalled(count = 1) 437 override fun onSubframeLoadRequest(session: GeckoSession, 438 request: LoadRequest): 439 GeckoResult<AllowOrDeny>? { 440 assertThat("URI should not be null", request.uri, notNullValue()) 441 assertThat("URI should match", request.uri, endsWith(iframeUri)) 442 return null 443 } 444 }) 445 } 446 447 @Setting(key = Setting.Key.USE_TRACKING_PROTECTION, value = "true") 448 @Ignore // TODO: Bug 1564373 trackingProtectionnull449 @Test fun trackingProtection() { 450 val category = ContentBlocking.AntiTracking.TEST 451 sessionRule.runtime.settings.contentBlocking.setAntiTracking(category) 452 sessionRule.session.loadTestPath(TRACKERS_PATH) 453 454 sessionRule.waitUntilCalled( 455 object : Callbacks.ContentBlockingDelegate { 456 @AssertCalled(count = 3) 457 override fun onContentBlocked(session: GeckoSession, 458 event: ContentBlocking.BlockEvent) { 459 assertThat("Category should be set", 460 event.antiTrackingCategory, 461 equalTo(category)) 462 assertThat("URI should not be null", event.uri, notNullValue()) 463 assertThat("URI should match", event.uri, endsWith("tracker.js")) 464 } 465 466 @AssertCalled(false) 467 override fun onContentLoaded(session: GeckoSession, event: ContentBlocking.BlockEvent) { 468 } 469 }) 470 471 sessionRule.session.settings.useTrackingProtection = false 472 473 sessionRule.session.reload() 474 sessionRule.session.waitForPageStop() 475 476 sessionRule.forCallbacksDuringWait( 477 object : Callbacks.ContentBlockingDelegate { 478 @AssertCalled(false) 479 override fun onContentBlocked(session: GeckoSession, 480 event: ContentBlocking.BlockEvent) { 481 } 482 483 @AssertCalled(count = 3) 484 override fun onContentLoaded(session: GeckoSession, event: ContentBlocking.BlockEvent) { 485 assertThat("Category should be set", 486 event.antiTrackingCategory, 487 equalTo(category)) 488 assertThat("URI should not be null", event.uri, notNullValue()) 489 assertThat("URI should match", event.uri, endsWith("tracker.js")) 490 } 491 }) 492 } 493 redirectLoadnull494 @Test fun redirectLoad() { 495 // TODO: bug 1710943 496 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 497 498 val redirectUri = if (sessionRule.env.isAutomation) { 499 "http://example.org/tests/junit/hello.html" 500 } else { 501 "http://jigsaw.w3.org/HTTP/300/Overview.html" 502 } 503 val uri = if (sessionRule.env.isAutomation) { 504 "http://example.org/tests/junit/simple_redirect.sjs?$redirectUri" 505 } else { 506 "http://jigsaw.w3.org/HTTP/300/301.html" 507 } 508 509 sessionRule.session.loadUri(uri) 510 sessionRule.waitForPageStop() 511 512 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 513 @AssertCalled(count = 2, order = [1, 2]) 514 override fun onLoadRequest(session: GeckoSession, 515 request: LoadRequest): 516 GeckoResult<AllowOrDeny>? { 517 assertThat("Session should not be null", session, notNullValue()) 518 assertThat("URI should not be null", request.uri, notNullValue()) 519 assertThat("URL should match", request.uri, 520 equalTo(forEachCall(request.uri, redirectUri))) 521 assertThat("Trigger URL should be null", request.triggerUri, 522 nullValue()) 523 assertThat("From app should be correct", request.isDirectNavigation, 524 equalTo(forEachCall(true, false))) 525 assertThat("Target should not be null", request.target, notNullValue()) 526 assertThat("Target should match", request.target, 527 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT)) 528 assertThat("Redirect flag is set", request.isRedirect, 529 equalTo(forEachCall(false, true))) 530 return null 531 } 532 }) 533 } 534 redirectLoadIframenull535 @Test fun redirectLoadIframe() { 536 // TODO: bug 1710943 537 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 538 539 val path = if (sessionRule.env.isAutomation) { 540 IFRAME_REDIRECT_AUTOMATION 541 } else { 542 IFRAME_REDIRECT_LOCAL 543 } 544 545 sessionRule.session.loadTestPath(path) 546 sessionRule.waitForPageStop() 547 548 // We shouldn't be firing onLoadRequest for iframes, including redirects. 549 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 550 @AssertCalled(count = 1) 551 override fun onLoadRequest(session: GeckoSession, 552 request: LoadRequest): 553 GeckoResult<AllowOrDeny>? { 554 assertThat("Session should not be null", session, notNullValue()) 555 assertThat("App requested this load", request.isDirectNavigation, equalTo(true)) 556 assertThat("URI should not be null", request.uri, notNullValue()) 557 assertThat("URI should match", request.uri, endsWith(path)) 558 assertThat("isRedirect should match", request.isRedirect, equalTo(false)) 559 return null 560 } 561 562 @AssertCalled(count = 2) 563 override fun onSubframeLoadRequest(session: GeckoSession, 564 request: LoadRequest): 565 GeckoResult<AllowOrDeny>? { 566 assertThat("Session should not be null", session, notNullValue()) 567 assertThat("App did not request this load", request.isDirectNavigation, equalTo(false)) 568 assertThat("URI should not be null", request.uri, notNullValue()) 569 assertThat("isRedirect should match", request.isRedirect, 570 equalTo(forEachCall(false, true))) 571 return null 572 } 573 }) 574 } 575 redirectDenyLoadnull576 @Test fun redirectDenyLoad() { 577 // TODO: Bug 1673954 578 assumeThat(sessionRule.env.isFission, equalTo(false)) 579 580 // TODO: bug 1710943 581 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 582 583 val redirectUri = if (sessionRule.env.isAutomation) { 584 "http://example.org/tests/junit/hello.html" 585 } else { 586 "http://jigsaw.w3.org/HTTP/300/Overview.html" 587 } 588 val uri = if (sessionRule.env.isAutomation) { 589 "http://example.org/tests/junit/simple_redirect.sjs?$redirectUri" 590 } else { 591 "http://jigsaw.w3.org/HTTP/300/301.html" 592 } 593 594 sessionRule.delegateDuringNextWait( 595 object : Callbacks.NavigationDelegate { 596 @AssertCalled(count = 2, order = [1, 2]) 597 override fun onLoadRequest(session: GeckoSession, 598 request: LoadRequest): 599 GeckoResult<AllowOrDeny>? { 600 assertThat("Session should not be null", session, notNullValue()) 601 assertThat("URI should not be null", request.uri, notNullValue()) 602 assertThat("URL should match", request.uri, 603 equalTo(forEachCall(request.uri, redirectUri))) 604 assertThat("Trigger URL should be null", request.triggerUri, 605 nullValue()) 606 assertThat("From app should be correct", request.isDirectNavigation, 607 equalTo(forEachCall(true, false))) 608 assertThat("Target should not be null", request.target, notNullValue()) 609 assertThat("Target should match", request.target, 610 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT)) 611 assertThat("Redirect flag is set", request.isRedirect, 612 equalTo(forEachCall(false, true))) 613 614 return forEachCall(GeckoResult.allow(), GeckoResult.deny()) 615 } 616 }) 617 618 sessionRule.session.loadUri(uri) 619 sessionRule.waitForPageStop() 620 621 sessionRule.forCallbacksDuringWait( 622 object : Callbacks.ProgressDelegate { 623 @AssertCalled(count = 1, order = [1]) 624 override fun onPageStart(session: GeckoSession, url: String) { 625 assertThat("URL should match", url, equalTo(uri)) 626 } 627 }) 628 } 629 redirectIntentLoadnull630 @Test fun redirectIntentLoad() { 631 assumeThat(sessionRule.env.isAutomation, equalTo(true)) 632 // TODO: Bug 1673954 633 assumeThat(sessionRule.env.isFission, equalTo(false)) 634 635 // TODO: bug 1710943 636 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 637 638 val redirectUri = "intent://test" 639 val uri = "http://example.org/tests/junit/simple_redirect.sjs?$redirectUri" 640 641 sessionRule.session.loadUri(uri) 642 sessionRule.waitForPageStop() 643 644 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 645 @AssertCalled(count = 2, order = [1, 2]) 646 override fun onLoadRequest(session: GeckoSession, 647 request: LoadRequest): 648 GeckoResult<AllowOrDeny>? { 649 assertThat("URL should match", request.uri, equalTo(forEachCall(uri, redirectUri))) 650 assertThat("From app should be correct", request.isDirectNavigation, 651 equalTo(forEachCall(true, false))) 652 return null 653 } 654 }) 655 } 656 657 bypassClassifiernull658 @Test fun bypassClassifier() { 659 // TODO: bug 1710943 660 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 661 662 val phishingUri = "https://www.itisatrap.org/firefox/its-a-trap.html" 663 val category = ContentBlocking.SafeBrowsing.PHISHING 664 665 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(category) 666 667 sessionRule.session.load(Loader() 668 .uri(phishingUri + "?bypass=true") 669 .flags(GeckoSession.LOAD_FLAGS_BYPASS_CLASSIFIER)) 670 sessionRule.session.waitForPageStop() 671 672 sessionRule.forCallbacksDuringWait( 673 object : Callbacks.NavigationDelegate { 674 @AssertCalled(false) 675 override fun onLoadError(session: GeckoSession, uri: String?, 676 error: WebRequestError): GeckoResult<String>? { 677 return null 678 } 679 }) 680 } 681 safebrowsingPhishingnull682 @Test fun safebrowsingPhishing() { 683 // TODO: Bug 1673954 684 assumeThat(sessionRule.env.isFission, equalTo(false)) 685 686 // TODO: bug 1710943 687 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 688 689 val phishingUri = "https://www.itisatrap.org/firefox/its-a-trap.html" 690 val category = ContentBlocking.SafeBrowsing.PHISHING 691 692 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(category) 693 694 // Add query string to avoid bypassing classifier check because of cache. 695 testLoadExpectError(phishingUri + "?block=true", 696 WebRequestError.ERROR_CATEGORY_SAFEBROWSING, 697 WebRequestError.ERROR_SAFEBROWSING_PHISHING_URI) 698 699 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(ContentBlocking.SafeBrowsing.NONE) 700 701 sessionRule.session.loadUri(phishingUri + "?block=false") 702 sessionRule.session.waitForPageStop() 703 704 sessionRule.forCallbacksDuringWait( 705 object : Callbacks.NavigationDelegate { 706 @AssertCalled(false) 707 override fun onLoadError(session: GeckoSession, uri: String?, 708 error: WebRequestError): GeckoResult<String>? { 709 return null 710 } 711 }) 712 } 713 safebrowsingMalwarenull714 @Test fun safebrowsingMalware() { 715 // TODO: Bug 1673954 716 assumeThat(sessionRule.env.isFission, equalTo(false)) 717 718 // TODO: bug 1710943 719 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 720 721 val malwareUri = "https://www.itisatrap.org/firefox/its-an-attack.html" 722 val category = ContentBlocking.SafeBrowsing.MALWARE 723 724 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(category) 725 726 testLoadExpectError(malwareUri + "?block=true", 727 WebRequestError.ERROR_CATEGORY_SAFEBROWSING, 728 WebRequestError.ERROR_SAFEBROWSING_MALWARE_URI) 729 730 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(ContentBlocking.SafeBrowsing.NONE) 731 732 sessionRule.session.loadUri(malwareUri + "?block=false") 733 sessionRule.session.waitForPageStop() 734 735 sessionRule.forCallbacksDuringWait( 736 object : Callbacks.NavigationDelegate { 737 @AssertCalled(false) 738 override fun onLoadError(session: GeckoSession, uri: String?, 739 error: WebRequestError): GeckoResult<String>? { 740 return null 741 } 742 }) 743 } 744 safebrowsingUnwantednull745 @Test fun safebrowsingUnwanted() { 746 // TODO: Bug 1673954 747 assumeThat(sessionRule.env.isFission, equalTo(false)) 748 val unwantedUri = "https://www.itisatrap.org/firefox/unwanted.html" 749 val category = ContentBlocking.SafeBrowsing.UNWANTED 750 751 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(category) 752 753 testLoadExpectError(unwantedUri + "?block=true", 754 WebRequestError.ERROR_CATEGORY_SAFEBROWSING, 755 WebRequestError.ERROR_SAFEBROWSING_UNWANTED_URI) 756 757 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(ContentBlocking.SafeBrowsing.NONE) 758 759 sessionRule.session.loadUri(unwantedUri + "?block=false") 760 sessionRule.session.waitForPageStop() 761 762 sessionRule.forCallbacksDuringWait( 763 object : Callbacks.NavigationDelegate { 764 @AssertCalled(false) 765 override fun onLoadError(session: GeckoSession, uri: String?, 766 error: WebRequestError): GeckoResult<String>? { 767 return null 768 } 769 }) 770 } 771 safebrowsingHarmfulnull772 @Test fun safebrowsingHarmful() { 773 // TODO: Bug 1673954 774 assumeThat(sessionRule.env.isFission, equalTo(false)) 775 776 // TODO: bug 1710943 777 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 778 779 val harmfulUri = "https://www.itisatrap.org/firefox/harmful.html" 780 val category = ContentBlocking.SafeBrowsing.HARMFUL 781 782 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(category) 783 784 testLoadExpectError(harmfulUri + "?block=true", 785 WebRequestError.ERROR_CATEGORY_SAFEBROWSING, 786 WebRequestError.ERROR_SAFEBROWSING_HARMFUL_URI) 787 788 sessionRule.runtime.settings.contentBlocking.setSafeBrowsing(ContentBlocking.SafeBrowsing.NONE) 789 790 sessionRule.session.loadUri(harmfulUri + "?block=false") 791 sessionRule.session.waitForPageStop() 792 793 sessionRule.forCallbacksDuringWait( 794 object : Callbacks.NavigationDelegate { 795 @AssertCalled(false) 796 override fun onLoadError(session: GeckoSession, uri: String?, 797 error: WebRequestError): GeckoResult<String>? { 798 return null 799 } 800 }) 801 } 802 803 // Checks that the User Agent matches the user agent built in 804 // nsHttpHandler::BuildUserAgent defaultUserAgentMatchesActualUserAgentnull805 @Test fun defaultUserAgentMatchesActualUserAgent() { 806 var userAgent = sessionRule.waitForResult(sessionRule.session.userAgent) 807 assertThat("Mobile user agent should match the default user agent", 808 userAgent, equalTo(GeckoSession.getDefaultUserAgent())) 809 } 810 desktopModenull811 @Test fun desktopMode() { 812 sessionRule.session.loadUri("https://example.com") 813 sessionRule.waitForPageStop() 814 815 val mobileSubStr = "Mobile" 816 val desktopSubStr = "X11" 817 818 assertThat("User agent should be set to mobile", 819 getUserAgent(), 820 containsString(mobileSubStr)) 821 822 var userAgent = sessionRule.waitForResult(sessionRule.session.userAgent) 823 assertThat("User agent should be reported as mobile", 824 userAgent, containsString(mobileSubStr)) 825 826 sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_DESKTOP 827 828 sessionRule.session.reload() 829 sessionRule.session.waitForPageStop() 830 831 assertThat("User agent should be set to desktop", 832 getUserAgent(), 833 containsString(desktopSubStr)) 834 835 userAgent = sessionRule.waitForResult(sessionRule.session.userAgent) 836 assertThat("User agent should be reported as desktop", 837 userAgent, containsString(desktopSubStr)) 838 839 sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_MOBILE 840 841 sessionRule.session.reload() 842 sessionRule.session.waitForPageStop() 843 844 assertThat("User agent should be set to mobile", 845 getUserAgent(), 846 containsString(mobileSubStr)) 847 848 userAgent = sessionRule.waitForResult(sessionRule.session.userAgent) 849 assertThat("User agent should be reported as mobile", 850 userAgent, containsString(mobileSubStr)) 851 852 val vrSubStr = "Mobile VR" 853 sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_VR 854 855 sessionRule.session.reload() 856 sessionRule.session.waitForPageStop() 857 858 assertThat("User agent should be set to VR", 859 getUserAgent(), 860 containsString(vrSubStr)) 861 862 userAgent = sessionRule.waitForResult(sessionRule.session.userAgent) 863 assertThat("User agent should be reported as VR", 864 userAgent, containsString(vrSubStr)) 865 866 } 867 getUserAgentnull868 private fun getUserAgent(session: GeckoSession = sessionRule.session): String { 869 return session.evaluateJS("window.navigator.userAgent") as String 870 } 871 uaOverrideNewSessionnull872 @Test fun uaOverrideNewSession() { 873 // TODO: bug 1710943 874 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 875 876 val newSession = sessionRule.createClosedSession() 877 newSession.settings.userAgentOverride = "Test user agent override" 878 879 newSession.open() 880 newSession.loadUri("https://example.com") 881 newSession.waitForPageStop() 882 883 assertThat("User agent should match override", getUserAgent(newSession), 884 equalTo("Test user agent override")) 885 } 886 uaOverridenull887 @Test fun uaOverride() { 888 // TODO: bug 1710943 889 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 890 891 sessionRule.session.loadUri("https://example.com") 892 sessionRule.waitForPageStop() 893 894 val mobileSubStr = "Mobile" 895 val vrSubStr = "Mobile VR" 896 val overrideUserAgent = "This is the override user agent" 897 898 assertThat("User agent should be reported as mobile", 899 getUserAgent(), containsString(mobileSubStr)) 900 901 sessionRule.session.settings.userAgentOverride = overrideUserAgent 902 903 sessionRule.session.reload() 904 sessionRule.session.waitForPageStop() 905 906 assertThat("User agent should be reported as override", 907 getUserAgent(), equalTo(overrideUserAgent)) 908 909 sessionRule.session.settings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_VR 910 911 sessionRule.session.reload() 912 sessionRule.session.waitForPageStop() 913 914 assertThat("User agent should still be reported as override even when USER_AGENT_MODE is set", 915 getUserAgent(), equalTo(overrideUserAgent)) 916 917 sessionRule.session.settings.userAgentOverride = null 918 919 sessionRule.session.reload() 920 sessionRule.session.waitForPageStop() 921 922 assertThat("User agent should now be reported as VR", 923 getUserAgent(), containsString(vrSubStr)) 924 925 sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 926 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 927 sessionRule.session.settings.userAgentOverride = overrideUserAgent 928 return null 929 } 930 }) 931 932 sessionRule.session.reload() 933 sessionRule.session.waitForPageStop() 934 935 assertThat("User agent should be reported as override after being set in onLoadRequest", 936 getUserAgent(), equalTo(overrideUserAgent)) 937 938 sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 939 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 940 sessionRule.session.settings.userAgentOverride = null 941 return null 942 } 943 }) 944 945 sessionRule.session.reload() 946 sessionRule.session.waitForPageStop() 947 948 assertThat("User agent should again be reported as VR after disabling override in onLoadRequest", 949 getUserAgent(), containsString(vrSubStr)) 950 } 951 952 @WithDisplay(width = 600, height = 200) viewportModenull953 @Test fun viewportMode() { 954 // TODO: bug 1710943 955 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 956 957 sessionRule.session.loadTestPath(VIEWPORT_PATH) 958 sessionRule.waitForPageStop() 959 960 val desktopInnerWidth = 980.0 961 val physicalWidth = 600.0 962 val pixelRatio = sessionRule.session.evaluateJS("window.devicePixelRatio") as Double 963 val mobileInnerWidth = physicalWidth / pixelRatio 964 val innerWidthJs = "window.innerWidth" 965 966 var innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double 967 assertThat("innerWidth should be equal to $mobileInnerWidth", 968 innerWidth, closeTo(mobileInnerWidth, 0.1)) 969 970 sessionRule.session.settings.viewportMode = GeckoSessionSettings.VIEWPORT_MODE_DESKTOP 971 972 sessionRule.session.reload() 973 sessionRule.session.waitForPageStop() 974 975 innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double 976 assertThat("innerWidth should be equal to $desktopInnerWidth", innerWidth, 977 closeTo(desktopInnerWidth, 0.1)) 978 979 sessionRule.session.settings.viewportMode = GeckoSessionSettings.VIEWPORT_MODE_MOBILE 980 981 sessionRule.session.reload() 982 sessionRule.session.waitForPageStop() 983 984 innerWidth = sessionRule.session.evaluateJS(innerWidthJs) as Double 985 assertThat("innerWidth should be equal to $mobileInnerWidth again", 986 innerWidth, closeTo(mobileInnerWidth, 0.1)) 987 } 988 loadnull989 @Test fun load() { 990 // TODO: bug 1710943 991 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 992 993 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 994 sessionRule.waitForPageStop() 995 996 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 997 @AssertCalled(count = 1, order = [1]) 998 override fun onLoadRequest(session: GeckoSession, 999 request: LoadRequest): 1000 GeckoResult<AllowOrDeny>? { 1001 assertThat("Session should not be null", session, notNullValue()) 1002 assertThat("URI should not be null", request.uri, notNullValue()) 1003 assertThat("URI should match", request.uri, endsWith(HELLO_HTML_PATH)) 1004 assertThat("Trigger URL should be null", request.triggerUri, 1005 nullValue()) 1006 assertThat("App requested this load", request.isDirectNavigation, 1007 equalTo(true)) 1008 assertThat("Target should not be null", request.target, notNullValue()) 1009 assertThat("Target should match", request.target, 1010 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT)) 1011 assertThat("Redirect flag is not set", request.isRedirect, equalTo(false)) 1012 assertThat("Should not have a user gesture", request.hasUserGesture, equalTo(false)) 1013 return null 1014 } 1015 1016 @AssertCalled(count = 1, order = [2]) 1017 override fun onLocationChange(session: GeckoSession, url: String?) { 1018 assertThat("Session should not be null", session, notNullValue()) 1019 assertThat("URL should not be null", url, notNullValue()) 1020 assertThat("URL should match", url, endsWith(HELLO_HTML_PATH)) 1021 } 1022 1023 @AssertCalled(count = 1, order = [2]) 1024 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 1025 assertThat("Session should not be null", session, notNullValue()) 1026 assertThat("Cannot go back", canGoBack, equalTo(false)) 1027 } 1028 1029 @AssertCalled(count = 1, order = [2]) 1030 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 1031 assertThat("Session should not be null", session, notNullValue()) 1032 assertThat("Cannot go forward", canGoForward, equalTo(false)) 1033 } 1034 1035 @AssertCalled(false) 1036 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1037 return null 1038 } 1039 }) 1040 } 1041 load_dataUrinull1042 @Test fun load_dataUri() { 1043 // TODO: bug 1710943 1044 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1045 1046 val dataUrl = "data:,Hello%2C%20World!" 1047 sessionRule.session.loadUri(dataUrl) 1048 sessionRule.waitForPageStop() 1049 1050 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate { 1051 @AssertCalled(count = 1) 1052 override fun onLocationChange(session: GeckoSession, url: String?) { 1053 assertThat("URL should match the provided data URL", url, equalTo(dataUrl)) 1054 } 1055 1056 @AssertCalled(count = 1) 1057 override fun onPageStop(session: GeckoSession, success: Boolean) { 1058 assertThat("Page should load successfully", success, equalTo(true)) 1059 } 1060 }) 1061 } 1062 1063 @NullDelegate(GeckoSession.NavigationDelegate::class) load_withoutNavigationDelegatenull1064 @Test fun load_withoutNavigationDelegate() { 1065 // TODO: bug 1710943 1066 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1067 1068 // Test that when navigation delegate is disabled, we can still perform loads. 1069 sessionRule.session.loadTestPath(HELLO_HTML_PATH) 1070 sessionRule.session.waitForPageStop() 1071 1072 sessionRule.session.reload() 1073 sessionRule.session.waitForPageStop() 1074 } 1075 1076 @NullDelegate(GeckoSession.NavigationDelegate::class) load_canUnsetNavigationDelegatenull1077 @Test fun load_canUnsetNavigationDelegate() { 1078 // TODO: bug 1710943 1079 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1080 1081 // Test that if we unset the navigation delegate during a load, the load still proceeds. 1082 var onLocationCount = 0 1083 sessionRule.session.navigationDelegate = object : Callbacks.NavigationDelegate { 1084 override fun onLocationChange(session: GeckoSession, url: String?) { 1085 onLocationCount++ 1086 } 1087 } 1088 sessionRule.session.loadTestPath(HELLO_HTML_PATH) 1089 sessionRule.session.waitForPageStop() 1090 1091 assertThat("Should get callback for first load", 1092 onLocationCount, equalTo(1)) 1093 1094 sessionRule.session.reload() 1095 sessionRule.session.navigationDelegate = null 1096 sessionRule.session.waitForPageStop() 1097 1098 assertThat("Should not get callback for second load", 1099 onLocationCount, equalTo(1)) 1100 } 1101 loadStringnull1102 @Test fun loadString() { 1103 // TODO: bug 1710943 1104 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1105 1106 val dataString = "<html><head><title>TheTitle</title></head><body>TheBody</body></html>" 1107 val mimeType = "text/html" 1108 sessionRule.session.load(Loader().data(dataString, mimeType)) 1109 sessionRule.waitForPageStop() 1110 1111 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate, Callbacks.ContentDelegate { 1112 @AssertCalled 1113 override fun onTitleChange(session: GeckoSession, title: String?) { 1114 assertThat("Title should match", title, equalTo("TheTitle")) 1115 } 1116 1117 @AssertCalled(count = 1) 1118 override fun onLocationChange(session: GeckoSession, url: String?) { 1119 assertThat("URL should be a data URL", url, 1120 equalTo(createDataUri(dataString, mimeType))) 1121 } 1122 1123 @AssertCalled(count = 1) 1124 override fun onPageStop(session: GeckoSession, success: Boolean) { 1125 assertThat("Page should load successfully", success, equalTo(true)) 1126 } 1127 }) 1128 } 1129 loadString_noMimeTypenull1130 @Test fun loadString_noMimeType() { 1131 sessionRule.session.load(Loader().data("Hello, World!", null)) 1132 sessionRule.waitForPageStop() 1133 1134 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate { 1135 @AssertCalled(count = 1) 1136 override fun onLocationChange(session: GeckoSession, url: String?) { 1137 assertThat("URL should be a data URL", url, startsWith("data:")) 1138 } 1139 1140 @AssertCalled(count = 1) 1141 override fun onPageStop(session: GeckoSession, success: Boolean) { 1142 assertThat("Page should load successfully", success, equalTo(true)) 1143 } 1144 }) 1145 } 1146 loadData_htmlnull1147 @Test fun loadData_html() { 1148 // TODO: bug 1710943 1149 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1150 1151 val bytes = getTestBytes(HELLO_HTML_PATH) 1152 assertThat("test html should have data", bytes.size, greaterThan(0)) 1153 1154 sessionRule.session.load(Loader().data(bytes, "text/html")) 1155 sessionRule.waitForPageStop() 1156 1157 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate, Callbacks.ContentDelegate { 1158 @AssertCalled(count = 1) 1159 override fun onTitleChange(session: GeckoSession, title: String?) { 1160 assertThat("Title should match", title, equalTo("Hello, world!")) 1161 } 1162 1163 @AssertCalled(count = 1) 1164 override fun onLocationChange(session: GeckoSession, url: String?) { 1165 assertThat("URL should match", url, equalTo(createDataUri(bytes, "text/html"))) 1166 } 1167 1168 @AssertCalled(count = 1) 1169 override fun onPageStop(session: GeckoSession, success: Boolean) { 1170 assertThat("Page should load successfully", success, equalTo(true)) 1171 } 1172 }) 1173 } 1174 createDataUrinull1175 private fun createDataUri(data: String, 1176 mimeType: String?): String { 1177 return String.format("data:%s,%s", mimeType ?: "", data) 1178 } 1179 createDataUrinull1180 private fun createDataUri(bytes: ByteArray, 1181 mimeType: String?): String { 1182 return String.format("data:%s;base64,%s", mimeType ?: "", 1183 Base64.encodeToString(bytes, Base64.NO_WRAP)) 1184 } 1185 loadDataHelpernull1186 fun loadDataHelper(assetPath: String, mimeType: String? = null) { 1187 val bytes = getTestBytes(assetPath) 1188 assertThat("test data should have bytes", bytes.size, greaterThan(0)) 1189 1190 sessionRule.session.load(Loader().data(bytes, mimeType)) 1191 sessionRule.waitForPageStop() 1192 1193 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate, Callbacks.ProgressDelegate { 1194 @AssertCalled(count = 1) 1195 override fun onLocationChange(session: GeckoSession, url: String?) { 1196 assertThat("URL should match", url, equalTo(createDataUri(bytes, mimeType))) 1197 } 1198 1199 @AssertCalled(count = 1) 1200 override fun onPageStop(session: GeckoSession, success: Boolean) { 1201 assertThat("Page should load successfully", success, equalTo(true)) 1202 } 1203 }) 1204 } 1205 1206 loadDatanull1207 @Test fun loadData() { 1208 loadDataHelper("/assets/www/images/test.gif", "image/gif") 1209 } 1210 loadData_noMimeTypenull1211 @Test fun loadData_noMimeType() { 1212 loadDataHelper("/assets/www/images/test.gif") 1213 } 1214 reloadnull1215 @Test fun reload() { 1216 // TODO: bug 1710943 1217 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1218 1219 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 1220 sessionRule.waitForPageStop() 1221 1222 sessionRule.session.reload() 1223 sessionRule.waitForPageStop() 1224 1225 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 1226 @AssertCalled(count = 1, order = [1]) 1227 override fun onLoadRequest(session: GeckoSession, 1228 request: LoadRequest): 1229 GeckoResult<AllowOrDeny>? { 1230 assertThat("URI should match", request.uri, endsWith(HELLO_HTML_PATH)) 1231 assertThat("Trigger URL should be null", request.triggerUri, 1232 nullValue()) 1233 assertThat("Target should match", request.target, 1234 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT)) 1235 assertThat("Load should not be direct", request.isDirectNavigation, 1236 equalTo(false)) 1237 return null 1238 } 1239 1240 @AssertCalled(count = 1, order = [2]) 1241 override fun onLocationChange(session: GeckoSession, url: String?) { 1242 assertThat("URL should match", url, endsWith(HELLO_HTML_PATH)) 1243 } 1244 1245 @AssertCalled(count = 1, order = [2]) 1246 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 1247 assertThat("Cannot go back", canGoBack, equalTo(false)) 1248 } 1249 1250 @AssertCalled(count = 1, order = [2]) 1251 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 1252 assertThat("Cannot go forward", canGoForward, equalTo(false)) 1253 } 1254 1255 @AssertCalled(false) 1256 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1257 return null 1258 } 1259 }) 1260 } 1261 goBackAndForwardnull1262 @Test fun goBackAndForward() { 1263 // TODO: bug 1710943 1264 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1265 1266 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 1267 sessionRule.waitForPageStop() 1268 1269 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO2_HTML_PATH") 1270 sessionRule.waitForPageStop() 1271 1272 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 1273 @AssertCalled(count = 1) 1274 override fun onLocationChange(session: GeckoSession, url: String?, perms : MutableList<GeckoSession.PermissionDelegate.ContentPermission>) { 1275 assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH)) 1276 } 1277 }) 1278 1279 sessionRule.session.goBack() 1280 sessionRule.waitForPageStop() 1281 1282 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 1283 @AssertCalled(count = 0, order = [1]) 1284 override fun onLoadRequest(session: GeckoSession, 1285 request: LoadRequest): 1286 GeckoResult<AllowOrDeny>? { 1287 assertThat("Load should not be direct", request.isDirectNavigation, 1288 equalTo(false)) 1289 return null 1290 } 1291 1292 @AssertCalled(count = 1, order = [2]) 1293 override fun onLocationChange(session: GeckoSession, url: String?, perms : MutableList<GeckoSession.PermissionDelegate.ContentPermission>) { 1294 assertThat("URL should match", url, endsWith(HELLO_HTML_PATH)) 1295 } 1296 1297 @AssertCalled(count = 1, order = [2]) 1298 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 1299 assertThat("Cannot go back", canGoBack, equalTo(false)) 1300 } 1301 1302 @AssertCalled(count = 1, order = [2]) 1303 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 1304 assertThat("Can go forward", canGoForward, equalTo(true)) 1305 } 1306 1307 @AssertCalled(false) 1308 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1309 return null 1310 } 1311 }) 1312 1313 sessionRule.session.goForward() 1314 sessionRule.waitForPageStop() 1315 1316 sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 1317 @AssertCalled(count = 0, order = [1]) 1318 override fun onLoadRequest(session: GeckoSession, 1319 request: LoadRequest): 1320 GeckoResult<AllowOrDeny>? { 1321 assertThat("Load should not be direct", request.isDirectNavigation, 1322 equalTo(false)) 1323 return null 1324 } 1325 1326 @AssertCalled(count = 1, order = [2]) 1327 override fun onLocationChange(session: GeckoSession, url: String?, perms : MutableList<GeckoSession.PermissionDelegate.ContentPermission>) { 1328 assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH)) 1329 } 1330 1331 @AssertCalled(count = 1, order = [2]) 1332 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 1333 assertThat("Can go back", canGoBack, equalTo(true)) 1334 } 1335 1336 @AssertCalled(count = 1, order = [2]) 1337 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 1338 assertThat("Cannot go forward", canGoForward, equalTo(false)) 1339 } 1340 1341 @AssertCalled(false) 1342 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1343 return null 1344 } 1345 }) 1346 } 1347 onLoadUri_returnTrueCancelsLoadnull1348 @Test fun onLoadUri_returnTrueCancelsLoad() { 1349 // TODO: bug 1710943 1350 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1351 1352 sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 1353 @AssertCalled(count = 2) 1354 override fun onLoadRequest(session: GeckoSession, 1355 request: LoadRequest): 1356 GeckoResult<AllowOrDeny>? { 1357 if (request.uri.endsWith(HELLO_HTML_PATH)) { 1358 return GeckoResult.deny() 1359 } else { 1360 return GeckoResult.allow() 1361 } 1362 } 1363 }) 1364 1365 sessionRule.session.loadTestPath(HELLO_HTML_PATH) 1366 sessionRule.session.loadTestPath(HELLO2_HTML_PATH) 1367 sessionRule.waitForPageStop() 1368 1369 sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { 1370 @AssertCalled(count = 1, order = [1]) 1371 override fun onPageStart(session: GeckoSession, url: String) { 1372 assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH)) 1373 } 1374 1375 @AssertCalled(count = 1, order = [2]) 1376 override fun onPageStop(session: GeckoSession, success: Boolean) { 1377 assertThat("Load should succeed", success, equalTo(true)) 1378 } 1379 }) 1380 } 1381 onNewSession_calledForWindowOpennull1382 @Test fun onNewSession_calledForWindowOpen() { 1383 // TODO: bug 1710943 1384 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1385 1386 // Disable popup blocker. 1387 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1388 1389 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1390 sessionRule.session.waitForPageStop() 1391 1392 sessionRule.session.evaluateJS("window.open('newSession_child.html', '_blank')") 1393 1394 sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate { 1395 @AssertCalled(count = 1, order = [1]) 1396 override fun onLoadRequest(session: GeckoSession, 1397 request: LoadRequest): 1398 GeckoResult<AllowOrDeny>? { 1399 assertThat("URI should be correct", request.uri, endsWith(NEW_SESSION_CHILD_HTML_PATH)) 1400 assertThat("Trigger URL should match", request.triggerUri, 1401 endsWith(NEW_SESSION_HTML_PATH)) 1402 assertThat("Target should be correct", request.target, 1403 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW)) 1404 assertThat("Load should not be direct", request.isDirectNavigation, 1405 equalTo(false)) 1406 return null 1407 } 1408 1409 @AssertCalled(count = 1, order = [2]) 1410 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1411 assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH)) 1412 return null 1413 } 1414 }) 1415 } 1416 1417 @Test(expected = GeckoSessionTestRule.RejectedPromiseException::class) onNewSession_rejectLocalnull1418 fun onNewSession_rejectLocal() { 1419 // TODO: bug 1710943 1420 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1421 1422 // Disable popup blocker. 1423 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1424 1425 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1426 sessionRule.session.waitForPageStop() 1427 1428 sessionRule.session.evaluateJS("window.open('file:///data/local/tmp', '_blank')") 1429 } 1430 onNewSession_calledForTargetBlankLinknull1431 @Test fun onNewSession_calledForTargetBlankLink() { 1432 // Disable popup blocker. 1433 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1434 1435 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1436 sessionRule.session.waitForPageStop() 1437 1438 sessionRule.session.evaluateJS("document.querySelector('#targetBlankLink').click()") 1439 1440 sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate { 1441 // We get two onLoadRequest calls for the link click, 1442 // one when loading the URL and one when opening a new window. 1443 @AssertCalled(count = 1, order = [1]) 1444 override fun onLoadRequest(session: GeckoSession, 1445 request: LoadRequest): 1446 GeckoResult<AllowOrDeny>? { 1447 assertThat("URI should be correct", request.uri, endsWith(NEW_SESSION_CHILD_HTML_PATH)) 1448 assertThat("Trigger URL should be null", request.triggerUri, 1449 endsWith(NEW_SESSION_HTML_PATH)) 1450 assertThat("Target should be correct", request.target, 1451 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW)) 1452 return null 1453 } 1454 1455 @AssertCalled(count = 1, order = [2]) 1456 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1457 assertThat("URI should be correct", uri, endsWith(NEW_SESSION_CHILD_HTML_PATH)) 1458 return null 1459 } 1460 }) 1461 } 1462 delegateNewSessionnull1463 private fun delegateNewSession(settings: GeckoSessionSettings = mainSession.settings): GeckoSession { 1464 val newSession = sessionRule.createClosedSession(settings) 1465 1466 sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 1467 @AssertCalled(count = 1) 1468 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession> { 1469 return GeckoResult.fromValue(newSession) 1470 } 1471 }) 1472 1473 return newSession 1474 } 1475 onNewSession_childShouldLoadnull1476 @Test fun onNewSession_childShouldLoad() { 1477 // TODO: bug 1710943 1478 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1479 1480 // Disable popup blocker. 1481 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1482 1483 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1484 sessionRule.session.waitForPageStop() 1485 1486 val newSession = delegateNewSession() 1487 sessionRule.session.evaluateJS("document.querySelector('#targetBlankLink').click()") 1488 // Initial about:blank 1489 newSession.waitForPageStop() 1490 // NEW_SESSION_CHILD_HTML_PATH 1491 newSession.waitForPageStop() 1492 1493 newSession.forCallbacksDuringWait(object : Callbacks.ProgressDelegate { 1494 @AssertCalled(count = 1) 1495 override fun onPageStart(session: GeckoSession, url: String) { 1496 assertThat("URL should match", url, endsWith(NEW_SESSION_CHILD_HTML_PATH)) 1497 } 1498 1499 @AssertCalled(count = 1) 1500 override fun onPageStop(session: GeckoSession, success: Boolean) { 1501 assertThat("Load should succeed", success, equalTo(true)) 1502 } 1503 }) 1504 } 1505 onNewSession_setWindowOpenernull1506 @Test fun onNewSession_setWindowOpener() { 1507 // TODO: bug 1710943 1508 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1509 1510 // Disable popup blocker. 1511 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1512 1513 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1514 sessionRule.session.waitForPageStop() 1515 1516 val newSession = delegateNewSession() 1517 sessionRule.session.evaluateJS("document.querySelector('#targetBlankLink').click()") 1518 newSession.waitForPageStop() 1519 1520 assertThat("window.opener should be set", 1521 newSession.evaluateJS("window.opener.location.pathname") as String, 1522 equalTo(NEW_SESSION_HTML_PATH)) 1523 } 1524 onNewSession_supportNoOpenernull1525 @Test fun onNewSession_supportNoOpener() { 1526 // TODO: bug 1710943 1527 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1528 1529 // Disable popup blocker. 1530 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1531 1532 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1533 sessionRule.session.waitForPageStop() 1534 1535 val newSession = delegateNewSession() 1536 sessionRule.session.evaluateJS("document.querySelector('#noOpenerLink').click()") 1537 newSession.waitForPageStop() 1538 1539 assertThat("window.opener should not be set", 1540 newSession.evaluateJS("window.opener"), 1541 equalTo(JSONObject.NULL)) 1542 } 1543 onNewSession_notCalledForHandledLoadsnull1544 @Test fun onNewSession_notCalledForHandledLoads() { 1545 // TODO: bug 1710943 1546 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1547 1548 // Disable popup blocker. 1549 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1550 1551 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1552 sessionRule.session.waitForPageStop() 1553 1554 sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 1555 override fun onLoadRequest(session: GeckoSession, 1556 request: LoadRequest): 1557 GeckoResult<AllowOrDeny>? { 1558 // Pretend we handled the target="_blank" link click. 1559 if (request.uri.endsWith(NEW_SESSION_CHILD_HTML_PATH)) { 1560 return GeckoResult.deny() 1561 } else { 1562 return GeckoResult.allow() 1563 } 1564 } 1565 }) 1566 1567 sessionRule.session.evaluateJS("document.querySelector('#targetBlankLink').click()") 1568 1569 sessionRule.session.reload() 1570 sessionRule.session.waitForPageStop() 1571 1572 // Assert that onNewSession was not called for the link click. 1573 sessionRule.session.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { 1574 @AssertCalled(count = 2) 1575 override fun onLoadRequest(session: GeckoSession, 1576 request: LoadRequest): 1577 GeckoResult<AllowOrDeny>? { 1578 assertThat("URI must match", request.uri, 1579 endsWith(forEachCall(NEW_SESSION_CHILD_HTML_PATH, NEW_SESSION_HTML_PATH))) 1580 assertThat("Load should not be direct", request.isDirectNavigation, 1581 equalTo(false)) 1582 return null 1583 } 1584 1585 @AssertCalled(count = 0) 1586 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? { 1587 return null 1588 } 1589 }) 1590 } 1591 onNewSession_submitFormWithTargetBlanknull1592 @Test fun onNewSession_submitFormWithTargetBlank() { 1593 // TODO: bug 1710943 1594 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1595 1596 sessionRule.session.loadTestPath(FORM_BLANK_HTML_PATH) 1597 sessionRule.waitForPageStop() 1598 1599 sessionRule.session.evaluateJS(""" 1600 document.querySelector('input[type=text]').focus() 1601 """) 1602 sessionRule.session.waitUntilCalled(GeckoSession.TextInputDelegate::class, 1603 "restartInput") 1604 1605 val time = SystemClock.uptimeMillis() 1606 val keyEvent = KeyEvent(time, time, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0) 1607 sessionRule.session.textInput.onKeyDown(KeyEvent.KEYCODE_ENTER, keyEvent) 1608 sessionRule.session.textInput.onKeyUp(KeyEvent.KEYCODE_ENTER, 1609 KeyEvent.changeAction(keyEvent, 1610 KeyEvent.ACTION_UP)) 1611 1612 sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate { 1613 @AssertCalled(count = 1, order = [1]) 1614 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): 1615 GeckoResult<AllowOrDeny>? { 1616 assertThat("URL should be correct", request.uri, 1617 endsWith("form_blank.html?")) 1618 assertThat("Trigger URL should match", request.triggerUri, 1619 endsWith("form_blank.html")) 1620 assertThat("Target should be correct", request.target, 1621 equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW)) 1622 return null 1623 } 1624 1625 @AssertCalled(count = 1, order = [2]) 1626 override fun onNewSession(session: GeckoSession, uri: String): 1627 GeckoResult<GeckoSession>? { 1628 assertThat("URL should be correct", uri, endsWith("form_blank.html?")) 1629 return null 1630 } 1631 }) 1632 } 1633 loadUriReferrernull1634 @Test fun loadUriReferrer() { 1635 // TODO: bug 1710943 1636 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1637 1638 val uri = "https://example.com" 1639 val referrer = "https://foo.org/" 1640 1641 sessionRule.session.load(Loader() 1642 .uri(uri) 1643 .referrer(referrer) 1644 .flags(GeckoSession.LOAD_FLAGS_NONE)) 1645 sessionRule.session.waitForPageStop() 1646 1647 assertThat("Referrer should match", 1648 sessionRule.session.evaluateJS("document.referrer") as String, 1649 equalTo(referrer)) 1650 } 1651 loadUriReferrerSessionnull1652 @Test fun loadUriReferrerSession() { 1653 // TODO: bug 1710943 1654 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1655 1656 val uri = "https://example.com/bar" 1657 val referrer = "https://example.org/" 1658 1659 sessionRule.session.loadUri(referrer) 1660 sessionRule.session.waitForPageStop() 1661 1662 val newSession = sessionRule.createOpenSession() 1663 newSession.load(Loader() 1664 .uri(uri) 1665 .referrer(sessionRule.session) 1666 .flags(GeckoSession.LOAD_FLAGS_NONE)) 1667 newSession.waitForPageStop() 1668 1669 assertThat("Referrer should match", 1670 newSession.evaluateJS("document.referrer") as String, 1671 equalTo(referrer)) 1672 } 1673 loadUriReferrerSessionFileUrlnull1674 @Test fun loadUriReferrerSessionFileUrl() { 1675 // TODO: bug 1710943 1676 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1677 1678 val uri = "file:///system/etc/fonts.xml" 1679 val referrer = "https://example.org" 1680 1681 sessionRule.session.loadUri(referrer) 1682 sessionRule.session.waitForPageStop() 1683 1684 val newSession = sessionRule.createOpenSession() 1685 newSession.load(Loader() 1686 .uri(uri) 1687 .referrer(sessionRule.session) 1688 .flags(GeckoSession.LOAD_FLAGS_NONE)) 1689 newSession.waitUntilCalled(object : Callbacks.NavigationDelegate { 1690 @AssertCalled 1691 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 1692 return null 1693 } 1694 }) 1695 } 1696 loadUriHeaderTestnull1697 private fun loadUriHeaderTest(headers: Map<String?,String?>, 1698 additional: Map<String?, String?>, 1699 filter: Int = GeckoSession.HEADER_FILTER_CORS_SAFELISTED) { 1700 // First collect default headers with no override 1701 sessionRule.session.loadUri("$TEST_ENDPOINT/anything") 1702 sessionRule.session.waitForPageStop() 1703 1704 val defaultContent = sessionRule.session.evaluateJS("document.body.children[0].innerHTML") as String 1705 val defaultBody = JSONObject(defaultContent) 1706 val defaultHeaders = defaultBody.getJSONObject("headers").asMap<String>() 1707 1708 val expected = HashMap(additional) 1709 for (key in defaultHeaders.keys) { 1710 expected[key] = defaultHeaders[key] 1711 if (additional.containsKey(key)) { 1712 // TODO: Bug 1671294, headers should be replaced, not appended 1713 expected[key] += ", " + additional[key] 1714 } 1715 } 1716 1717 // Now load the page with the header override 1718 sessionRule.session.load(Loader() 1719 .uri("$TEST_ENDPOINT/anything") 1720 .additionalHeaders(headers) 1721 .headerFilter(filter)) 1722 sessionRule.session.waitForPageStop() 1723 1724 val content = sessionRule.session.evaluateJS("document.body.children[0].innerHTML") as String 1725 val body = JSONObject(content) 1726 val actualHeaders = body.getJSONObject("headers").asMap<String>() 1727 1728 assertThat("Headers should match", expected as Map<String?, String?>, 1729 equalTo(actualHeaders)) 1730 } 1731 testLoaderEqualsnull1732 private fun testLoaderEquals(a: Loader, b: Loader, shouldBeEqual: Boolean) { 1733 assertThat("Equal test", a == b, equalTo(shouldBeEqual)) 1734 assertThat("HashCode test", a.hashCode() == b.hashCode(), 1735 equalTo(shouldBeEqual)) 1736 } 1737 loaderEqualsnull1738 @Test fun loaderEquals() { 1739 testLoaderEquals( 1740 Loader().uri("http://test-uri-equals.com"), 1741 Loader().uri("http://test-uri-equals.com"), 1742 true) 1743 testLoaderEquals( 1744 Loader().uri("http://test-uri-equals.com"), 1745 Loader().uri("http://test-uri-equalsx.com"), 1746 false) 1747 1748 testLoaderEquals( 1749 Loader().uri("http://test-uri-equals.com") 1750 .flags(LOAD_FLAGS_BYPASS_CLASSIFIER) 1751 .headerFilter(HEADER_FILTER_UNRESTRICTED_UNSAFE) 1752 .referrer("test-referrer"), 1753 Loader().uri("http://test-uri-equals.com") 1754 .flags(LOAD_FLAGS_BYPASS_CLASSIFIER) 1755 .headerFilter(HEADER_FILTER_UNRESTRICTED_UNSAFE) 1756 .referrer("test-referrer"), 1757 true) 1758 testLoaderEquals( 1759 Loader().uri("http://test-uri-equals.com") 1760 .flags(LOAD_FLAGS_BYPASS_CLASSIFIER) 1761 .headerFilter(HEADER_FILTER_UNRESTRICTED_UNSAFE) 1762 .referrer(sessionRule.session), 1763 Loader().uri("http://test-uri-equals.com") 1764 .flags(LOAD_FLAGS_BYPASS_CLASSIFIER) 1765 .headerFilter(HEADER_FILTER_UNRESTRICTED_UNSAFE) 1766 .referrer("test-referrer"), 1767 false) 1768 1769 testLoaderEquals( 1770 Loader().referrer(sessionRule.session) 1771 .data("testtest", "text/plain"), 1772 Loader().referrer(sessionRule.session) 1773 .data("testtest", "text/plain"), 1774 true) 1775 testLoaderEquals( 1776 Loader().referrer(sessionRule.session) 1777 .data("testtest", "text/plain"), 1778 Loader().referrer("test-referrer") 1779 .data("testtest", "text/plain"), 1780 false) 1781 } 1782 loadUriHeadernull1783 @Test fun loadUriHeader() { 1784 // Basic test 1785 loadUriHeaderTest( 1786 mapOf("Header1" to "Value", "Header2" to "Value1, Value2"), 1787 mapOf() 1788 ) 1789 loadUriHeaderTest( 1790 mapOf("Header1" to "Value", "Header2" to "Value1, Value2"), 1791 mapOf("Header1" to "Value", "Header2" to "Value1, Value2"), 1792 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1793 ) 1794 1795 // Empty value headers are ignored 1796 loadUriHeaderTest( 1797 mapOf("ValueLess1" to "", "ValueLess2" to null), 1798 mapOf() 1799 ) 1800 1801 // Null key or special headers are ignored 1802 loadUriHeaderTest( 1803 mapOf(null to "BadNull", 1804 "Connection" to "BadConnection", 1805 "Host" to "BadHost"), 1806 mapOf() 1807 ) 1808 1809 // Key or value cannot contain '\r\n' 1810 loadUriHeaderTest( 1811 mapOf("Header1" to "Value", 1812 "Header2" to "Value1, Value2", 1813 "this\r\nis invalid" to "test value", 1814 "test key" to "this\r\n is a no-no", 1815 "what" to "what\r\nhost:amazon.com", 1816 "Header3" to "Value1, Value2, Value3" 1817 ), 1818 mapOf() 1819 ) 1820 loadUriHeaderTest( 1821 mapOf("Header1" to "Value", 1822 "Header2" to "Value1, Value2", 1823 "this\r\nis invalid" to "test value", 1824 "test key" to "this\r\n is a no-no", 1825 "what" to "what\r\nhost:amazon.com", 1826 "Header3" to "Value1, Value2, Value3" 1827 ), 1828 mapOf("Header1" to "Value", 1829 "Header2" to "Value1, Value2", 1830 "Header3" to "Value1, Value2, Value3"), 1831 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1832 ) 1833 1834 loadUriHeaderTest( 1835 mapOf("Header1" to "Value", 1836 "Header2" to "Value1, Value2", 1837 "what" to "what\r\nhost:amazon.com"), 1838 mapOf() 1839 ) 1840 loadUriHeaderTest( 1841 mapOf("Header1" to "Value", 1842 "Header2" to "Value1, Value2", 1843 "what" to "what\r\nhost:amazon.com"), 1844 mapOf("Header1" to "Value", "Header2" to "Value1, Value2"), 1845 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1846 ) 1847 1848 loadUriHeaderTest( 1849 mapOf("what" to "what\r\nhost:amazon.com"), 1850 mapOf() 1851 ) 1852 1853 loadUriHeaderTest( 1854 mapOf("this\r\n" to "yes"), 1855 mapOf() 1856 ) 1857 1858 // Connection and Host cannot be overriden, no matter the case spelling 1859 loadUriHeaderTest( 1860 mapOf("Header1" to "Value1", "ConnEction" to "test", "connection" to "test2"), 1861 mapOf() 1862 ) 1863 loadUriHeaderTest( 1864 mapOf("Header1" to "Value1", "ConnEction" to "test", "connection" to "test2"), 1865 mapOf("Header1" to "Value1"), 1866 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1867 ) 1868 1869 loadUriHeaderTest( 1870 mapOf("Header1" to "Value1", "connection" to "test2"), 1871 mapOf() 1872 ) 1873 loadUriHeaderTest( 1874 mapOf("Header1" to "Value1", "connection" to "test2"), 1875 mapOf("Header1" to "Value1"), 1876 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1877 ) 1878 1879 loadUriHeaderTest( 1880 mapOf("Header1 " to "Value1", "host" to "test2"), 1881 mapOf() 1882 ) 1883 loadUriHeaderTest( 1884 mapOf("Header1 " to "Value1", "host" to "test2"), 1885 mapOf("Header1" to "Value1"), 1886 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1887 ) 1888 1889 loadUriHeaderTest( 1890 mapOf("Header1" to "Value1", "host" to "test2"), 1891 mapOf() 1892 ) 1893 loadUriHeaderTest( 1894 mapOf("Header1" to "Value1", "host" to "test2"), 1895 mapOf("Header1" to "Value1"), 1896 GeckoSession.HEADER_FILTER_UNRESTRICTED_UNSAFE 1897 ) 1898 1899 // Adding white space at the end of a forbidden header still prevents override 1900 loadUriHeaderTest( 1901 mapOf("host" to "amazon.com", 1902 "host " to "amazon.com", 1903 "host\r" to "amazon.com", 1904 "host\r\n" to "amazon.com"), 1905 mapOf() 1906 ) 1907 1908 // '\r' or '\n' are forbidden character even when not following each other 1909 loadUriHeaderTest( 1910 mapOf("abc\ra\n" to "amazon.com"), 1911 mapOf() 1912 ) 1913 1914 // CORS Safelist test 1915 loadUriHeaderTest( 1916 mapOf("Accept-Language" to "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5", 1917 "Accept" to "text/html", 1918 "Content-Language" to "de-DE, en-CA", 1919 "Content-Type" to "multipart/form-data; boundary=something"), 1920 mapOf("Accept-Language" to "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5", 1921 "Accept" to "text/html", 1922 "Content-Language" to "de-DE, en-CA", 1923 "Content-Type" to "multipart/form-data; boundary=something"), 1924 GeckoSession.HEADER_FILTER_CORS_SAFELISTED 1925 ) 1926 1927 // CORS safelist doesn't allow Content-type image/svg 1928 loadUriHeaderTest( 1929 mapOf("Accept-Language" to "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5", 1930 "Accept" to "text/html", 1931 "Content-Language" to "de-DE, en-CA", 1932 "Content-Type" to "image/svg; boundary=something"), 1933 mapOf("Accept-Language" to "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5", 1934 "Accept" to "text/html", 1935 "Content-Language" to "de-DE, en-CA"), 1936 GeckoSession.HEADER_FILTER_CORS_SAFELISTED 1937 ) 1938 } 1939 1940 @Test(expected = GeckoResult.UncaughtException::class) onNewSession_doesNotAllowOpenednull1941 fun onNewSession_doesNotAllowOpened() { 1942 // TODO: bug 1710943 1943 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1944 1945 // Disable popup blocker. 1946 sessionRule.setPrefsUntilTestEnd(mapOf("dom.disable_open_during_load" to false)) 1947 1948 sessionRule.session.loadTestPath(NEW_SESSION_HTML_PATH) 1949 sessionRule.session.waitForPageStop() 1950 1951 sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 1952 @AssertCalled(count = 1) 1953 override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession> { 1954 return GeckoResult.fromValue(sessionRule.createOpenSession()) 1955 } 1956 }) 1957 1958 sessionRule.session.evaluateJS("document.querySelector('#targetBlankLink').click()") 1959 1960 sessionRule.session.waitUntilCalled(GeckoSession.NavigationDelegate::class, 1961 "onNewSession") 1962 UiThreadUtils.loopUntilIdle(sessionRule.env.defaultTimeoutMillis) 1963 } 1964 1965 @Test extensionProcessSwitchingnull1966 fun extensionProcessSwitching() { 1967 // TODO: bug 1710943 1968 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 1969 1970 sessionRule.setPrefsUntilTestEnd(mapOf( 1971 "xpinstall.signatures.required" to false, 1972 "extensions.install.requireBuiltInCerts" to false, 1973 "extensions.update.requireBuiltInCerts" to false 1974 )) 1975 1976 val controller = sessionRule.runtime.webExtensionController 1977 1978 sessionRule.addExternalDelegateUntilTestEnd( 1979 WebExtensionController.PromptDelegate::class, 1980 controller::setPromptDelegate, 1981 { controller.promptDelegate = null }, 1982 object : WebExtensionController.PromptDelegate { 1983 @AssertCalled 1984 override fun onInstallPrompt(extension: WebExtension): GeckoResult<AllowOrDeny> { 1985 return GeckoResult.allow() 1986 } 1987 }) 1988 1989 val extension = sessionRule.waitForResult( 1990 controller.install("https://example.org/tests/junit/page-history.xpi")) 1991 1992 assertThat("baseUrl should be a valid extension URL", 1993 extension.metaData.baseUrl, startsWith("moz-extension://")) 1994 1995 val url = extension.metaData.baseUrl + "page.html" 1996 processSwitchingTest(url) 1997 1998 sessionRule.waitForResult(controller.uninstall(extension)) 1999 } 2000 2001 @Test mainProcessSwitchingnull2002 fun mainProcessSwitching() { 2003 // TODO: bug 1710943 2004 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2005 processSwitchingTest("about:config") 2006 } 2007 processSwitchingTestnull2008 private fun processSwitchingTest(url: String) { 2009 val settings = sessionRule.runtime.settings 2010 val aboutConfigEnabled = settings.aboutConfigEnabled 2011 settings.aboutConfigEnabled = true 2012 2013 var currentUrl: String? = null 2014 mainSession.delegateUntilTestEnd(object: GeckoSession.NavigationDelegate { 2015 override fun onLocationChange(session: GeckoSession, url: String?) { 2016 currentUrl = url 2017 } 2018 2019 override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? { 2020 assertThat("Should not get here", false, equalTo(true)) 2021 return null 2022 } 2023 }) 2024 2025 // This will load a page in the child 2026 mainSession.loadTestPath(HELLO2_HTML_PATH) 2027 sessionRule.waitForPageStop() 2028 2029 assertThat("docShell should start out active", mainSession.active, 2030 equalTo(true)) 2031 2032 // This loads in the parent process 2033 mainSession.loadUri(url) 2034 sessionRule.waitForPageStop() 2035 2036 assertThat("URL should match", currentUrl!!, equalTo(url)) 2037 2038 // This will load a page in the child 2039 mainSession.loadTestPath(HELLO_HTML_PATH) 2040 sessionRule.waitForPageStop() 2041 2042 assertThat("URL should match", currentUrl!!, endsWith(HELLO_HTML_PATH)) 2043 assertThat("docShell should be active after switching process", 2044 mainSession.active, 2045 equalTo(true)) 2046 2047 mainSession.loadUri(url) 2048 sessionRule.waitForPageStop() 2049 2050 assertThat("URL should match", currentUrl!!, equalTo(url)) 2051 2052 sessionRule.session.goBack() 2053 sessionRule.waitForPageStop() 2054 2055 assertThat("URL should match", currentUrl!!, endsWith(HELLO_HTML_PATH)) 2056 assertThat("docShell should be active after switching process", 2057 mainSession.active, 2058 equalTo(true)) 2059 2060 sessionRule.session.goBack() 2061 sessionRule.waitForPageStop() 2062 2063 assertThat("URL should match", currentUrl!!, equalTo(url)) 2064 2065 sessionRule.session.goBack() 2066 sessionRule.waitForPageStop() 2067 2068 assertThat("URL should match", currentUrl!!, endsWith(HELLO2_HTML_PATH)) 2069 assertThat("docShell should be active after switching process", 2070 mainSession.active, 2071 equalTo(true)) 2072 2073 settings.aboutConfigEnabled = aboutConfigEnabled 2074 } 2075 setLocationHashnull2076 @Test fun setLocationHash() { 2077 // TODO: bug 1710943 2078 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2079 2080 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 2081 sessionRule.waitForPageStop() 2082 2083 sessionRule.session.evaluateJS("location.hash = 'test1';") 2084 2085 sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate { 2086 @AssertCalled(count = 0) 2087 override fun onLoadRequest(session: GeckoSession, 2088 request: LoadRequest): 2089 GeckoResult<AllowOrDeny>? { 2090 assertThat("Load should not be direct", request.isDirectNavigation, 2091 equalTo(false)) 2092 return null 2093 } 2094 2095 @AssertCalled(count = 1) 2096 override fun onLocationChange(session: GeckoSession, url: String?, perms : MutableList<GeckoSession.PermissionDelegate.ContentPermission>) { 2097 assertThat("URI should match", url, endsWith("#test1")) 2098 } 2099 }) 2100 2101 sessionRule.session.evaluateJS("location.hash = 'test2';") 2102 2103 sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate { 2104 @AssertCalled(count = 0) 2105 override fun onLoadRequest(session: GeckoSession, 2106 request: LoadRequest): 2107 GeckoResult<AllowOrDeny>? { 2108 return null 2109 } 2110 2111 @AssertCalled(count = 1) 2112 override fun onLocationChange(session: GeckoSession, url: String?, perms : MutableList<GeckoSession.PermissionDelegate.ContentPermission>) { 2113 assertThat("URI should match", url, endsWith("#test2")) 2114 } 2115 }) 2116 } 2117 purgeHistorynull2118 @Test fun purgeHistory() { 2119 // TODO: Bug 1648158 2120 assumeThat(sessionRule.env.isFission, equalTo(false)) 2121 2122 // TODO: bug 1710943 2123 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2124 2125 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 2126 sessionRule.waitUntilCalled(object : Callbacks.NavigationDelegate { 2127 @AssertCalled(count = 1) 2128 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 2129 assertThat("Session should not be null", session, notNullValue()) 2130 assertThat("Cannot go back", canGoBack, equalTo(false)) 2131 } 2132 2133 @AssertCalled(count = 1) 2134 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 2135 assertThat("Session should not be null", session, notNullValue()) 2136 assertThat("Cannot go forward", canGoForward, equalTo(false)) 2137 } 2138 }) 2139 sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO2_HTML_PATH") 2140 sessionRule.waitUntilCalled(object : Callbacks.All { 2141 @AssertCalled(count = 1) 2142 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 2143 assertThat("Session should not be null", session, notNullValue()) 2144 assertThat("Cannot go back", canGoBack, equalTo(true)) 2145 } 2146 @AssertCalled(count = 1) 2147 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 2148 assertThat("Session should not be null", session, notNullValue()) 2149 assertThat("Cannot go forward", canGoForward, equalTo(false)) 2150 } 2151 @AssertCalled(count = 1) 2152 override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) { 2153 assertThat("History should have two entries", state.size, equalTo(2)) 2154 } 2155 }) 2156 sessionRule.session.purgeHistory() 2157 sessionRule.waitUntilCalled(object : Callbacks.All { 2158 @AssertCalled(count = 1) 2159 override fun onHistoryStateChange(session: GeckoSession, state: GeckoSession.HistoryDelegate.HistoryList) { 2160 assertThat("History should have one entry", state.size, equalTo(1)) 2161 } 2162 @AssertCalled(count = 1) 2163 override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) { 2164 assertThat("Session should not be null", session, notNullValue()) 2165 assertThat("Cannot go back", canGoBack, equalTo(false)) 2166 } 2167 2168 @AssertCalled(count = 1) 2169 override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) { 2170 assertThat("Session should not be null", session, notNullValue()) 2171 assertThat("Cannot go forward", canGoForward, equalTo(false)) 2172 } 2173 }) 2174 } 2175 2176 @WithDisplay(width = 100, height = 100) userGesturenull2177 @Test fun userGesture() { 2178 // TODO: bug 1710943 2179 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2180 2181 mainSession.loadUri("$TEST_ENDPOINT$CLICK_TO_RELOAD_HTML_PATH") 2182 mainSession.waitForPageStop() 2183 2184 mainSession.synthesizeTap(50, 50) 2185 2186 sessionRule.waitUntilCalled(object : Callbacks.NavigationDelegate { 2187 @AssertCalled(count = 1) 2188 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2189 assertThat("Should have a user gesture", request.hasUserGesture, equalTo(true)) 2190 assertThat("Load should not be direct", request.isDirectNavigation, 2191 equalTo(false)) 2192 return GeckoResult.allow() 2193 } 2194 }) 2195 } 2196 loadAfterLoadnull2197 @Test fun loadAfterLoad() { 2198 // TODO: Bug 1657028 2199 assumeThat(sessionRule.env.isFission, equalTo(false)) 2200 2201 // TODO: bug 1710943 2202 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2203 2204 sessionRule.session.delegateDuringNextWait(object : Callbacks.NavigationDelegate { 2205 @AssertCalled(count = 2) 2206 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2207 assertThat("URLs should match", request.uri, endsWith(forEachCall(HELLO_HTML_PATH, HELLO2_HTML_PATH))) 2208 return GeckoResult.allow() 2209 } 2210 }) 2211 2212 mainSession.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH") 2213 mainSession.loadUri("$TEST_ENDPOINT$HELLO2_HTML_PATH") 2214 mainSession.waitForPageStop() 2215 } 2216 2217 @Test loadLongDataUriToplevelDirectnull2218 fun loadLongDataUriToplevelDirect() { 2219 val dataBytes = ByteArray(3 * 1024 * 1024) 2220 val expectedUri = createDataUri(dataBytes, "*/*") 2221 val loader = Loader().data(dataBytes, "*/*") 2222 2223 sessionRule.session.delegateUntilTestEnd(object : Callbacks.NavigationDelegate { 2224 @AssertCalled(count = 1, order = [1]) 2225 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2226 assertThat("URLs should match", request.uri, equalTo(expectedUri)) 2227 return GeckoResult.allow() 2228 } 2229 2230 @AssertCalled(count = 1, order = [2]) 2231 override fun onLoadError(session: GeckoSession, uri: String?, 2232 error: WebRequestError): GeckoResult<String>? { 2233 assertThat("Error category should match", error.category, 2234 equalTo(WebRequestError.ERROR_CATEGORY_URI)) 2235 assertThat("Error code should match", error.code, 2236 equalTo(WebRequestError.ERROR_DATA_URI_TOO_LONG)) 2237 assertThat("URLs should match", uri, equalTo(expectedUri)) 2238 return null 2239 } 2240 }) 2241 2242 sessionRule.session.load(loader) 2243 sessionRule.waitUntilCalled(Callbacks.NavigationDelegate::class, "onLoadError") 2244 } 2245 2246 @Test loadLongDataUriToplevelIndirectnull2247 fun loadLongDataUriToplevelIndirect() { 2248 // TODO: bug 1710943 2249 assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) 2250 2251 val dataBytes = ByteArray(3 * 1024 * 1024) 2252 val dataUri = createDataUri(dataBytes, "*/*") 2253 2254 sessionRule.session.loadTestPath(DATA_URI_PATH) 2255 sessionRule.session.waitForPageStop() 2256 2257 sessionRule.session.delegateUntilTestEnd(object : Callbacks.NavigationDelegate { 2258 @AssertCalled(false) 2259 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2260 return GeckoResult.deny() 2261 } 2262 }) 2263 2264 sessionRule.session.evaluateJS("document.querySelector('#largeLink').href = \"$dataUri\"") 2265 sessionRule.session.evaluateJS("document.querySelector('#largeLink').click()") 2266 sessionRule.session.waitForPageStop() 2267 } 2268 2269 @Test loadShortDataUriToplevelIndirectnull2270 fun loadShortDataUriToplevelIndirect() { 2271 sessionRule.session.delegateUntilTestEnd(object : Callbacks.NavigationDelegate { 2272 @AssertCalled(count = 2) 2273 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2274 return GeckoResult.allow() 2275 } 2276 2277 @AssertCalled(false) 2278 override fun onLoadError(session: GeckoSession, uri: String?, 2279 error: WebRequestError): GeckoResult<String>? { 2280 return null 2281 } 2282 }) 2283 2284 val dataBytes = this.getTestBytes("/assets/www/images/test.gif") 2285 val uri = createDataUri(dataBytes, "image/*") 2286 2287 sessionRule.session.loadTestPath(DATA_URI_PATH) 2288 sessionRule.session.waitForPageStop() 2289 2290 sessionRule.session.evaluateJS("document.querySelector('#smallLink').href = \"$uri\"") 2291 sessionRule.session.evaluateJS("document.querySelector('#smallLink').click()") 2292 sessionRule.session.waitForPageStop() 2293 } 2294 createLargeHighEntropyImageDataUrinull2295 fun createLargeHighEntropyImageDataUri() : String { 2296 val desiredMinSize = (2 * 1024 * 1024) + 1 2297 2298 val width = 768; 2299 val height = 768; 2300 2301 val bitmap = Bitmap.createBitmap(ThreadLocalRandom.current().ints(width.toLong() * height.toLong()).toArray(), 2302 width, height, Bitmap.Config.ARGB_8888) 2303 2304 val stream = ByteArrayOutputStream() 2305 if (!bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream)) { 2306 throw Exception("Error compressing PNG") 2307 } 2308 2309 val uri = createDataUri(stream.toByteArray(), "image/png") 2310 2311 if (uri.length < desiredMinSize) { 2312 throw Exception("Test uri is too small, want at least " + desiredMinSize + ", got " + uri.length) 2313 } 2314 2315 return uri 2316 } 2317 2318 @Test loadLongDataUriNonToplevelnull2319 fun loadLongDataUriNonToplevel() { 2320 val dataUri = createLargeHighEntropyImageDataUri() 2321 2322 sessionRule.session.delegateUntilTestEnd(object : Callbacks.NavigationDelegate { 2323 @AssertCalled(count = 1) 2324 override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? { 2325 return GeckoResult.allow() 2326 } 2327 2328 @AssertCalled(false) 2329 override fun onLoadError(session: GeckoSession, uri: String?, 2330 error: WebRequestError): GeckoResult<String>? { 2331 return null 2332 } 2333 }) 2334 2335 sessionRule.session.loadTestPath(DATA_URI_PATH) 2336 sessionRule.session.waitForPageStop() 2337 2338 sessionRule.session.evaluateJS("document.querySelector('#image').onload = () => { imageLoaded = true; }") 2339 sessionRule.session.evaluateJS("document.querySelector('#image').src = \"$dataUri\"") 2340 UiThreadUtils.waitForCondition({ 2341 sessionRule.session.evaluateJS("document.querySelector('#image').complete") as Boolean 2342 }, sessionRule.env.defaultTimeoutMillis) 2343 sessionRule.session.evaluateJS("if (!imageLoaded) throw imageLoaded") 2344 } 2345 } 2346