diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt index 328304d09c81..4cc4e6b2261c 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt @@ -101,7 +101,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { fun GeckoSession.synthesizeTap(x: Int, y: Int) = sessionRule.synthesizeTap(this, x, y) - fun GeckoSession.evaluateJS(js: String) = + fun GeckoSession.evaluateJS(js: String): Any? = sessionRule.evaluateJS(this, js) infix fun Any?.dot(prop: Any): Any? = diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt index e3fcc433ec7a..cc9b00efe167 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt @@ -1268,4 +1268,21 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) { fun evaluateJS_throwOnSyntaxError() { sessionRule.session.evaluateJS("<{[") } + + @WithDevToolsAPI + @Test(expected = RuntimeException::class) + fun evaluateJS_throwOnChromeAccess() { + sessionRule.session.evaluateJS("ChromeUtils") + } + + @WithDevToolsAPI + @Test fun evaluateChromeJS() { + assertThat("Should be able to access ChromeUtils", + sessionRule.evaluateChromeJS("ChromeUtils"), notNullValue()) + } + + @Test(expected = AssertionError::class) + fun evaluateChromeJS_throwOnNotWithDevTools() { + sessionRule.evaluateChromeJS("0") + } } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rdp/RDPConnection.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rdp/RDPConnection.java index 9ff67391ebfc..4ba36358aef2 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rdp/RDPConnection.java +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rdp/RDPConnection.java @@ -203,4 +203,17 @@ public final class RDPConnection implements Closeable { final Actor actor = getActor(reply); return (actor != null) ? (Tab) actor : new Tab(this, reply); } + + /** + * Get the actor for the chrome process. The returned Tab object acts like a tab but has + * chrome privileges. + * + * @return Tab actor representing the process. + */ + public Tab getChromeProcess() { + final JSONObject reply = mRoot.sendPacket("{\"type\":\"getProcess\"}", "form") + .optJSONObject("form"); + final Actor actor = getActor(reply); + return (actor != null) ? (Tab) actor : new Tab(this, reply); + } } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java index 3b2d6610ede1..3918d1707a1b 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java @@ -607,6 +607,7 @@ public class GeckoSessionTestRule extends UiThreadTestRule { protected boolean mClosedSession; protected boolean mWithDevTools; protected Map mRDPTabs; + protected Tab mRDPChromeProcess; public GeckoSessionTestRule() { mDefaultSettings = new GeckoSessionSettings(); @@ -996,6 +997,7 @@ public class GeckoSessionTestRule extends UiThreadTestRule { mLastWaitEnd = 0; mTimeoutMillis = 0; mRDPTabs = null; + mRDPChromeProcess = null; } @Override @@ -1631,12 +1633,36 @@ public class GeckoSessionTestRule extends UiThreadTestRule { * @param session Session containing the target page. * @param js JavaScript expression. * @return Result of evaluating the expression. + * @see #evaluateChromeJS */ public Object evaluateJS(final @NonNull GeckoSession session, final @NonNull String js) { - assertThat("Must enable RDP using @WithDevToolsAPI", mRDPTabs, notNullValue()); + assertThat("Must enable RDP using @WithDevToolsAPI", + mWithDevTools, equalTo(true)); final Tab tab = mRDPTabs.get(session); assertThat("Session should have tab object", tab, notNullValue()); return tab.getConsole().evaluateJS(js); } + + /** + * Evaluate a JavaScript expression in the context of a chrome window and return the result. + * RDP must be enabled first using the {@link WithDevToolsAPI} annotation. Results are + * converted the same way as {@link #evaluateJS}. + * + * @param js JavaScript expression. + * @return Result of evaluating the expression. + * @see #evaluateJS + */ + public Object evaluateChromeJS(final @NonNull String js) { + assertThat("Must enable RDP using @WithDevToolsAPI", + mWithDevTools, equalTo(true)); + + if (mRDPChromeProcess == null) { + mRDPChromeProcess = sRDPConnection.getChromeProcess(); + assertThat("Should have chrome process object", + mRDPChromeProcess, notNullValue()); + mRDPChromeProcess.attach(); + } + return mRDPChromeProcess.getConsole().evaluateJS(js); + } }