Skip to content

Commit c33b577

Browse files
feat: Support for Appium Chrome Dev Protocol Commands (#1375)
* Client support for Appium : Chrome Dev Protocol * Review Changes - Client support for Appium : Chrome Dev Protocol * Review changes for documentation * CheckStyle Fix
1 parent f27d29d commit c33b577

File tree

4 files changed

+164
-1
lines changed

4 files changed

+164
-1
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client;
18+
19+
import com.google.common.collect.ImmutableMap;
20+
import org.openqa.selenium.remote.Response;
21+
22+
import javax.annotation.Nullable;
23+
import java.util.Collections;
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
27+
import static com.google.common.base.Preconditions.checkNotNull;
28+
import static io.appium.java_client.MobileCommand.EXECUTE_GOOGLE_CDP_COMMAND;
29+
30+
public interface ExecuteCDPCommand extends ExecutesMethod {
31+
32+
/**
33+
* Allows to execute ChromeDevProtocol commands against Android Chrome browser session.
34+
*
35+
* @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/)
36+
* @param params additional parameters required to execute the command
37+
* @return Value (Output of the command execution)
38+
* @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command
39+
* @since Appium 1.18
40+
*/
41+
default Map<String, Object> executeCdpCommand(String command, @Nullable Map<String, Object> params) {
42+
Map<String, Object> data = new HashMap<>();
43+
data.put("cmd", checkNotNull(command));
44+
data.put("params", params == null ? Collections.emptyMap() : params);
45+
Response response = execute(EXECUTE_GOOGLE_CDP_COMMAND, data);
46+
//noinspection unchecked
47+
return ImmutableMap.copyOf((Map<String, Object>) response.getValue());
48+
}
49+
50+
/**
51+
* Allows to execute ChromeDevProtocol commands against Android Chrome browser session without parameters.
52+
*
53+
* @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/)
54+
* @return Value (Output of the command execution)
55+
* @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command
56+
* @since Appium 1.18
57+
*/
58+
default Map<String, Object> executeCdpCommand(String command) {
59+
return executeCdpCommand(command, null);
60+
}
61+
}

src/main/java/io/appium/java_client/MobileCommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ public class MobileCommand {
114114
protected static final String COMPARE_IMAGES;
115115
protected static final String EXECUTE_DRIVER_SCRIPT;
116116
protected static final String GET_ALLSESSION;
117+
protected static final String EXECUTE_GOOGLE_CDP_COMMAND;
117118

118119
public static final Map<String, CommandInfo> commandRepository;
119120

@@ -192,6 +193,7 @@ public class MobileCommand {
192193
COMPARE_IMAGES = "compareImages";
193194
EXECUTE_DRIVER_SCRIPT = "executeDriverScript";
194195
GET_ALLSESSION = "getAllSessions";
196+
EXECUTE_GOOGLE_CDP_COMMAND = "executeCdp";
195197

196198
commandRepository = new HashMap<>();
197199
commandRepository.put(RESET, postC("/session/:sessionId/appium/app/reset"));
@@ -282,6 +284,7 @@ public class MobileCommand {
282284
commandRepository.put(COMPARE_IMAGES, postC("/session/:sessionId/appium/compare_images"));
283285
commandRepository.put(EXECUTE_DRIVER_SCRIPT, postC("/session/:sessionId/appium/execute_driver"));
284286
commandRepository.put(GET_ALLSESSION, getC("/sessions"));
287+
commandRepository.put(EXECUTE_GOOGLE_CDP_COMMAND, postC("/session/:sessionId/goog/cdp/execute"));
285288
}
286289

287290
/**

src/main/java/io/appium/java_client/android/AndroidDriver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import io.appium.java_client.AppiumDriver;
2727
import io.appium.java_client.CommandExecutionHelper;
28+
import io.appium.java_client.ExecuteCDPCommand;
2829
import io.appium.java_client.FindsByAndroidDataMatcher;
2930
import io.appium.java_client.FindsByAndroidViewMatcher;
3031
import io.appium.java_client.FindsByAndroidUIAutomator;
@@ -67,7 +68,7 @@ public class AndroidDriver<T extends WebElement>
6768
HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard,
6869
CanRecordScreen, SupportsSpecialEmulatorCommands,
6970
SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard,
70-
HasBattery<AndroidBatteryInfo> {
71+
HasBattery<AndroidBatteryInfo>, ExecuteCDPCommand {
7172

7273
private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID;
7374

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.android;
18+
19+
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
20+
import io.appium.java_client.remote.MobileBrowserType;
21+
import io.appium.java_client.remote.MobileCapabilityType;
22+
import io.appium.java_client.service.local.AppiumDriverLocalService;
23+
import org.junit.After;
24+
import org.junit.Before;
25+
import org.junit.Test;
26+
import org.openqa.selenium.WebDriver;
27+
import org.openqa.selenium.WebElement;
28+
import org.openqa.selenium.remote.DesiredCapabilities;
29+
import org.openqa.selenium.remote.RemoteWebElement;
30+
import org.openqa.selenium.support.FindBy;
31+
import org.openqa.selenium.support.PageFactory;
32+
33+
import java.util.HashMap;
34+
import java.util.Map;
35+
36+
import static java.time.Duration.ofSeconds;
37+
import static org.junit.Assert.assertNotNull;
38+
39+
public class ExecuteCDPCommandTest {
40+
41+
private WebDriver driver;
42+
43+
private AppiumDriverLocalService service;
44+
45+
@FindBy(name = "q")
46+
private WebElement searchTextField;
47+
48+
49+
/**
50+
* The setting up.
51+
*/
52+
@Before
53+
public void setUp() {
54+
service = AppiumDriverLocalService.buildDefaultService();
55+
service.start();
56+
57+
DesiredCapabilities capabilities = new DesiredCapabilities();
58+
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
59+
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.CHROME);
60+
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");
61+
driver = new AndroidDriver<RemoteWebElement>(service.getUrl(), capabilities);
62+
//This time out is set because test can be run on slow Android SDK emulator
63+
PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this);
64+
}
65+
66+
/**
67+
* finishing.
68+
*/
69+
@After
70+
public void tearDown() {
71+
if (driver != null) {
72+
driver.quit();
73+
}
74+
75+
if (service != null) {
76+
service.stop();
77+
}
78+
}
79+
80+
@Test
81+
public void testExecuteCDPCommandWithoutParam() {
82+
driver.get("https://www.google.com");
83+
searchTextField.sendKeys("Hello");
84+
Map<String, Object> cookies = ((AndroidDriver) driver).executeCdpCommand("Page.getCookies");
85+
assertNotNull(cookies);
86+
}
87+
88+
@Test
89+
public void testExecuteCDPCommandWithParams() {
90+
Map<String, Object> params = new HashMap();
91+
params.put("latitude", 13.0827);
92+
params.put("longitude", 80.2707);
93+
params.put("accuracy", 1);
94+
((AndroidDriver) driver).executeCdpCommand("Emulation.setGeolocationOverride", params);
95+
driver.get("https://www.google.com");
96+
}
97+
98+
}

0 commit comments

Comments
 (0)