summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt')
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt338
1 files changed, 338 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt
new file mode 100644
index 0000000000..913203e61c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PrintDelegateTest.kt
@@ -0,0 +1,338 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.geckoview.test
+
+import android.accessibilityservice.AccessibilityService
+import android.app.UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Color.rgb
+import android.os.Handler
+import android.os.Looper
+import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import org.hamcrest.CoreMatchers.containsString
+import org.junit.After
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.runner.RunWith
+import org.mozilla.geckoview.Autofill
+import org.mozilla.geckoview.GeckoResult
+import org.mozilla.geckoview.GeckoResult.fromException
+import org.mozilla.geckoview.GeckoSession
+import org.mozilla.geckoview.GeckoSession.GeckoPrintException
+import org.mozilla.geckoview.GeckoSession.PrintDelegate
+import org.mozilla.geckoview.GeckoView.ActivityContextDelegate
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
+import kotlin.math.roundToInt
+
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class PrintDelegateTest : BaseSessionTest() {
+ private val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
+ private var deviceHeight = 0
+ private var deviceWidth = 0
+ private var scaledHeight = 0
+ private var scaledWidth = 12
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val uiAutomation = instrumentation.getUiAutomation(FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES)
+
+ @get:Rule
+ override val rules: RuleChain = RuleChain.outerRule(activityRule).around(sessionRule)
+
+ @Before
+ fun setup() {
+ activityRule.scenario.onActivity {
+ class PrintTestActivityDelegate : ActivityContextDelegate {
+ override fun getActivityContext(): Context {
+ return it
+ }
+ }
+ // An activity delegate is required for printing
+ it.view.activityContextDelegate = PrintTestActivityDelegate()
+ deviceHeight = it.resources.displayMetrics.heightPixels
+ deviceWidth = it.resources.displayMetrics.widthPixels
+ scaledHeight = (scaledWidth * (deviceHeight / deviceWidth.toDouble())).roundToInt()
+ }
+ }
+
+ @After
+ fun cleanup() {
+ activityRule.scenario.onActivity {
+ uiAutomation.setOnAccessibilityEventListener {}
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun printDelegateTest() {
+ activityRule.scenario.onActivity {
+ var delegateCalled = 0
+ sessionRule.delegateUntilTestEnd(object : PrintDelegate {
+ @AssertCalled(count = 1)
+ override fun onPrint(session: GeckoSession) {
+ delegateCalled++
+ }
+ })
+ mainSession.loadTestPath(COLOR_ORANGE_BACKGROUND_HTML_PATH)
+ mainSession.waitForPageStop()
+ mainSession.printPageContent()
+ assertTrue("Android print delegate called once.", delegateCalled == 1)
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun windowDotPrintAvailableTest() {
+ activityRule.scenario.onActivity {
+ mainSession.loadTestPath(COLOR_ORANGE_BACKGROUND_HTML_PATH)
+ mainSession.waitForPageStop()
+ val response = mainSession.waitForJS("window.print();")
+ assertTrue("Window.print(); is available.", response == null)
+ }
+ }
+
+ // Returns the center pixel color of the the print preview's screenshot
+ private fun printCenterPixelColor(): GeckoResult<Int> {
+ val pixelResult = GeckoResult<Int>()
+ // Listening for Android Print Activity
+ uiAutomation.setOnAccessibilityEventListener { event ->
+ if (event.packageName == "com.android.printspooler" &&
+ event.eventType == TYPE_VIEW_SCROLLED
+ ) {
+ uiAutomation.setOnAccessibilityEventListener {}
+ // Delaying the screenshot to give time for preview to load
+ Handler(Looper.getMainLooper()).postDelayed({
+ val bitmap = uiAutomation.takeScreenshot()
+ val scaled = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, false)
+ pixelResult.complete(scaled.getPixel(scaledWidth / 2, scaledHeight / 2))
+ }, 1500)
+ }
+ }
+ return pixelResult
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun printPreviewRendered() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.printPageContent()
+ val orange = rgb(255, 113, 57)
+ val centerPixel = printCenterPixelColor()
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun printSuccessWithStatus() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ val result = mainSession.didPrintPageContent()
+ val orange = rgb(255, 113, 57)
+ val centerPixel = printCenterPixelColor()
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ uiAutomation.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK)
+ assertTrue(
+ "Printing should conclude when back is pressed.",
+ sessionRule.waitForResult(result),
+ )
+ }
+ }
+
+ @Test
+ fun printFailWithStatus() {
+ activityRule.scenario.onActivity {
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ mainSession.printDelegate = null
+ val result = mainSession.didPrintPageContent().accept {
+ assertTrue("Should not be able to print.", false)
+ }.exceptionally(
+ GeckoResult.OnExceptionListener<Throwable> { error: Throwable ->
+ assertTrue("Should receive a missing print delegate exception.", (error as GeckoPrintException).code == GeckoPrintException.ERROR_NO_PRINT_DELEGATE)
+ fromException(error)
+ },
+ )
+ try {
+ sessionRule.waitForResult(result)
+ } catch (e: Exception) {
+ assertTrue("Should have an exception", true)
+ }
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun basicWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.evaluateJS("window.print();")
+ val centerPixel = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun statusWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.evaluateJS("window.print()")
+ val centerPixel = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ var didCatch = false
+ try {
+ mainSession.evaluateJS("window.print();")
+ } catch (e: GeckoSessionTestRule.RejectedPromiseException) {
+ assertThat(
+ "Print status context reported.",
+ e.message,
+ containsString("Window.print: No browsing context"),
+ )
+ didCatch = true
+ }
+ assertTrue("Did show print status.", didCatch)
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun staticContextWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ // Print button removes content after printing to test if it froze a static page for printing
+ mainSession.loadTestPath(PRINT_CONTENT_CHANGE)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.evaluateJS("document.getElementById('print-button').click();")
+ val centerPixel = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ assertTrue(
+ "Android print opened and rendered static page.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun iframeWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // Main frame CSS rules render red on screen and green on print
+ // iframe CSS rules render blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_IFRAME)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ // iframe window.print button
+ mainSession.evaluateJS("document.getElementById('iframe').contentDocument.getElementById('print-button').click();")
+ val centerPixelIframe = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ sessionRule.waitForResult(centerPixelIframe).let { it ->
+ assertTrue("The iframe should not print green. (Printed containing page instead of iframe.)", it != Color.GREEN)
+ assertTrue("Printed the iframe correctly.", it == orange)
+ }
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun contentIframeWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // Main frame CSS rules render red on screen and green on print
+ // iframe CSS rules render blue on screen and orange on print
+ mainSession.loadTestPath(PRINT_IFRAME)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ // Main page window.print button
+ mainSession.evaluateJS("document.getElementById('print-button-page').click();")
+ val centerPixelContent = printCenterPixelColor()
+ assertTrue("Printed the main content correctly.", sessionRule.waitForResult(centerPixelContent) == Color.GREEN)
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun contentPDFWindowDotPrintTest() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(ORANGE_PDF_PATH)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.printPageContent()
+ val centerPixel = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ }
+ }
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun availableCanonicalBrowsingContext() {
+ activityRule.scenario.onActivity { activity ->
+ // CSS rules render this blue on screen and orange on print
+ mainSession.loadTestPath(ORANGE_PDF_PATH)
+ mainSession.waitForPageStop()
+ // Setting to the default delegate (test rules changed it)
+ mainSession.printDelegate = activity.view.printDelegate
+ mainSession.setFocused(false)
+ mainSession.printPageContent()
+ val centerPixel = printCenterPixelColor()
+ val orange = rgb(255, 113, 57)
+ assertTrue(
+ "Android print opened and rendered.",
+ sessionRule.waitForResult(centerPixel) == orange,
+ )
+ }
+ }
+}