diff --git a/java/src/org/openqa/selenium/chromium/AddHasPermissions.java b/java/src/org/openqa/selenium/chromium/AddHasPermissions.java new file mode 100644 index 00000000000000..31a1d0b967755c --- /dev/null +++ b/java/src/org/openqa/selenium/chromium/AddHasPermissions.java @@ -0,0 +1,71 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.chromium; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.internal.Require; +import org.openqa.selenium.remote.AdditionalHttpCommands; +import org.openqa.selenium.remote.AugmenterProvider; +import org.openqa.selenium.remote.CommandInfo; +import org.openqa.selenium.remote.ExecuteMethod; +import org.openqa.selenium.remote.http.HttpMethod; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Predicate; + +import static org.openqa.selenium.remote.BrowserType.CHROME; +import static org.openqa.selenium.remote.BrowserType.EDGE; + +@AutoService({AdditionalHttpCommands.class, AugmenterProvider.class}) +public class AddHasPermissions implements AugmenterProvider, AdditionalHttpCommands { + + public static final String SET_PERMISSION = "setPermission"; + + private static final Map COMMANDS = ImmutableMap.of( + SET_PERMISSION, new CommandInfo("/session/:sessionId/permissions", HttpMethod.POST)); + + @Override + public Map getAdditionalCommands() { + return COMMANDS; + } + + @Override public Predicate isApplicable() { + String[] validBrowsers = new String[] { EDGE, CHROME, "msedge" }; + return caps -> new ArrayList<>(Arrays.asList(validBrowsers)).contains(caps.getBrowserName()); + } + + @Override public Class getDescribedInterface() { + return HasPermissions.class; + } + + @Override public HasPermissions getImplementation(Capabilities capabilities, ExecuteMethod executeMethod) { + return new HasPermissions() { + @Override + public void setPermission(String name, String value) { + Require.nonNull("Permission name", name); + Require.nonNull("Permission value", value); + + executeMethod.execute(SET_PERMISSION, ImmutableMap.of("descriptor", ImmutableMap.of("name", name), "state", value)); + } + }; + } +} diff --git a/java/src/org/openqa/selenium/chromium/ChromiumDriver.java b/java/src/org/openqa/selenium/chromium/ChromiumDriver.java index 47b24aeaf20e91..43978db5c38494 100644 --- a/java/src/org/openqa/selenium/chromium/ChromiumDriver.java +++ b/java/src/org/openqa/selenium/chromium/ChromiumDriver.java @@ -76,7 +76,8 @@ public class ChromiumDriver extends RemoteWebDriver implements WebStorage, HasNetworkConditions, HasCasting, - HasCdp { + HasCdp, + HasPermissions { private static final Logger LOG = Logger.getLogger(ChromiumDriver.class.getName()); @@ -86,6 +87,7 @@ public class ChromiumDriver extends RemoteWebDriver implements private final TouchScreen touchScreen; private final RemoteNetworkConnection networkConnection; private final HasNetworkConditions networkConditions; + private final HasPermissions permissions; protected HasCasting casting; protected HasCdp cdp; private final Optional connection; @@ -95,6 +97,7 @@ protected ChromiumDriver(CommandExecutor commandExecutor, Capabilities capabilit super(commandExecutor, capabilities); locationContext = new RemoteLocationContext(getExecuteMethod()); webStorage = new RemoteWebStorage(getExecuteMethod()); + permissions = new AddHasPermissions().getImplementation(getCapabilities(), getExecuteMethod()); touchScreen = new RemoteTouchScreen(getExecuteMethod()); networkConnection = new RemoteNetworkConnection(getExecuteMethod()); networkConditions = new AddHasNetworkConditions().getImplementation(getCapabilities(), getExecuteMethod()); @@ -235,8 +238,7 @@ public void stopCasting(String deviceName) { } public void setPermission(String name, String value) { - getExecuteMethod().execute(ChromiumDriverCommand.SET_PERMISSION, - ImmutableMap.of("descriptor", ImmutableMap.of("name", name), "state", value)); + permissions.setPermission(name, value); } @Override public ChromiumNetworkConditions getNetworkConditions() { diff --git a/java/src/org/openqa/selenium/chromium/ChromiumDriverCommandExecutor.java b/java/src/org/openqa/selenium/chromium/ChromiumDriverCommandExecutor.java index ec024aa3b3743e..249f2914fbe1a4 100644 --- a/java/src/org/openqa/selenium/chromium/ChromiumDriverCommandExecutor.java +++ b/java/src/org/openqa/selenium/chromium/ChromiumDriverCommandExecutor.java @@ -43,8 +43,8 @@ private static Map getExtraCommands(Mapbuilder() .putAll(commands) .putAll(new AddHasNetworkConditions().getAdditionalCommands()) + .putAll(new AddHasPermissions().getAdditionalCommands()) .put(ChromiumDriverCommand.LAUNCH_APP, new CommandInfo("/session/:sessionId/chromium/launch_app", HttpMethod.POST)) - .put(ChromiumDriverCommand.SET_PERMISSION, new CommandInfo("/session/:sessionId/permissions", HttpMethod.POST)) .build(); } } diff --git a/java/src/org/openqa/selenium/chromium/HasPermissions.java b/java/src/org/openqa/selenium/chromium/HasPermissions.java new file mode 100644 index 00000000000000..8aed19a15427e5 --- /dev/null +++ b/java/src/org/openqa/selenium/chromium/HasPermissions.java @@ -0,0 +1,33 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.chromium; + +import org.openqa.selenium.Beta; + +import java.util.Map; + +@Beta +public interface HasPermissions { + + /** + * + * @param name what permission to set. + * @param value what to set the permission to. + */ + public void setPermission(String name, String value); +} diff --git a/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java b/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java index 50012fe92afc60..31a62d0fd47a94 100644 --- a/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java +++ b/java/test/org/openqa/selenium/chrome/ChromeDriverFunctionalTest.java @@ -18,6 +18,7 @@ package org.openqa.selenium.chrome; import org.junit.Test; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.chromium.ChromiumDriver; @@ -25,6 +26,7 @@ import org.openqa.selenium.chromium.HasCasting; import org.openqa.selenium.chromium.HasCdp; import org.openqa.selenium.chromium.HasNetworkConditions; +import org.openqa.selenium.chromium.HasPermissions; import org.openqa.selenium.remote.Augmenter; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.testing.JUnit4TestBase; @@ -61,6 +63,26 @@ public void canSetPermission() { assertThat(checkPermission(driver, CLIPBOARD_WRITE)).isEqualTo("prompt"); } + @Test + public void shouldAllowRemoteWebDriverToAugmentHasPermissions() throws MalformedURLException { + WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/"), new ChromeOptions()); + WebDriver augmentedDriver = new Augmenter().augment(driver); + + try { + driver.get(pages.clicksPage); + assertThat(checkPermission(driver, CLIPBOARD_READ)).isEqualTo("prompt"); + assertThat(checkPermission(driver, CLIPBOARD_WRITE)).isEqualTo("granted"); + + ((HasPermissions) augmentedDriver).setPermission(CLIPBOARD_READ, "denied"); + ((HasPermissions) augmentedDriver).setPermission(CLIPBOARD_WRITE, "prompt"); + + assertThat(checkPermission(driver, CLIPBOARD_READ)).isEqualTo("denied"); + assertThat(checkPermission(driver, CLIPBOARD_WRITE)).isEqualTo("prompt"); + } finally { + driver.quit(); + } + } + @Test public void canSetPermissionHeadless() { ChromeOptions options = new ChromeOptions(); @@ -80,9 +102,9 @@ public void canSetPermissionHeadless() { assertThat(checkPermission(driver, CLIPBOARD_WRITE)).isEqualTo("granted"); } - public String checkPermission(ChromiumDriver driver, String permission){ + public String checkPermission(WebDriver driver, String permission){ @SuppressWarnings("unchecked") - Map result = (Map) driver.executeAsyncScript( + Map result = (Map) ((JavascriptExecutor) driver).executeAsyncScript( "callback = arguments[arguments.length - 1];" + "callback(navigator.permissions.query({" + "name: arguments[0]"