Bug 1459299 - 1. Add evaluateChromeJS for chrome privilege code; r?snorp
Add GeckoSessionTestRule.evaluateChromeJS for JS code that requires
chrome privileges, such as setting prefs.
MozReview-Commit-ID: G7NUKukWTT8
--- 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
@@ -96,17 +96,17 @@ open class BaseSessionTest(noErrorCollec
sessionRule.delegateUntilTestEnd(this, callback)
fun GeckoSession.delegateDuringNextWait(callback: Any) =
sessionRule.delegateDuringNextWait(this, callback)
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? =
if (prop is Int) this.asJSList<Any>()[prop] else this.asJSMap<Any>()[prop]
@Suppress("UNCHECKED_CAST")
fun <T> Any?.asJSMap(): Map<String, T> = this as Map<String, T>
--- 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
@@ -1263,9 +1263,26 @@ class GeckoSessionTestRuleTest : BaseSes
sessionRule.session.evaluateJS("throw Error()")
}
@WithDevToolsAPI
@Test(expected = RuntimeException::class)
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")
+ }
}
--- 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
@@ -198,9 +198,22 @@ public final class RDPConnection impleme
* @return Tab actor.
*/
public Tab getMostRecentTab() {
final JSONObject reply = mRoot.sendPacket("{\"type\":\"getTab\"}", "tab")
.optJSONObject("tab");
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);
+ }
}
--- 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
@@ -602,16 +602,17 @@ public class GeckoSessionTestRule extend
protected long mTimeoutMillis;
protected Point mDisplaySize;
protected SurfaceTexture mDisplayTexture;
protected Surface mDisplaySurface;
protected GeckoDisplay mDisplay;
protected boolean mClosedSession;
protected boolean mWithDevTools;
protected Map<GeckoSession, Tab> mRDPTabs;
+ protected Tab mRDPChromeProcess;
public GeckoSessionTestRule() {
mDefaultSettings = new GeckoSessionSettings();
mDefaultSettings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, env.isMultiprocess());
}
/**
* Set an ErrorCollector for assertion errors, or null to not use one.
@@ -988,16 +989,17 @@ public class GeckoSessionTestRule extend
mNullDelegates = null;
mCallRecords = null;
mWaitScopeDelegates = null;
mTestScopeDelegates = null;
mLastWaitStart = 0;
mLastWaitEnd = 0;
mTimeoutMillis = 0;
mRDPTabs = null;
+ mRDPChromeProcess = null;
}
@Override
public Statement apply(final Statement base, final Description description) {
return super.apply(new Statement() {
@Override
public void evaluate() throws Throwable {
try {
@@ -1623,17 +1625,41 @@ public class GeckoSessionTestRule extend
* Evaluate a JavaScript expression in the context of the target page and return the result.
* RDP must be enabled first using the {@link WithDevToolsAPI} annotation. String, number, and
* boolean results are converted to Java values. Undefined and null results are returned as
* null. Objects are returned as Map instances. Arrays are returned as Object[] instances.
*
* @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);
+ }
}