diff --git a/java/client/src/org/openqa/selenium/HasExtensions.java b/java/client/src/org/openqa/selenium/HasExtensions.java new file mode 100644 index 0000000000000..fae1b7ad14c2f --- /dev/null +++ b/java/client/src/org/openqa/selenium/HasExtensions.java @@ -0,0 +1,41 @@ +// 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; + +import java.nio.file.Path; + +/** + * Used by classes to indicate that they can install and uninstall browser extensions on the fly. + */ +public interface HasExtensions { + + /** + * Installs an extension. + * + * @param path absolute path to the extension file that should be installed. + * @return the unique identifier of the installed extension. + */ + String installExtension(Path path); + + /** + * Uninstall the extension by the given identifier. + * + * @param extensionId The unique extension identifier returned by {{@link #installExtension(Path)}} + */ + void uninstallExtension(String extensionId); +} diff --git a/java/client/src/org/openqa/selenium/firefox/FirefoxDriver.java b/java/client/src/org/openqa/selenium/firefox/FirefoxDriver.java index 1ba8dae572855..9124e05c4f6cb 100644 --- a/java/client/src/org/openqa/selenium/firefox/FirefoxDriver.java +++ b/java/client/src/org/openqa/selenium/firefox/FirefoxDriver.java @@ -17,13 +17,15 @@ package org.openqa.selenium.firefox; -import static org.openqa.selenium.firefox.FirefoxDriver.SystemProperty.DRIVER_USE_MARIONETTE; +import static java.util.Collections.singletonMap; import static org.openqa.selenium.remote.CapabilityType.PROXY; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.HasExtensions; import org.openqa.selenium.ImmutableCapabilities; import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.Proxy; @@ -32,12 +34,15 @@ import org.openqa.selenium.html5.SessionStorage; import org.openqa.selenium.html5.WebStorage; import org.openqa.selenium.remote.CommandExecutor; +import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.FileDetector; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.html5.RemoteWebStorage; +import org.openqa.selenium.remote.http.HttpMethod; import org.openqa.selenium.remote.service.DriverCommandExecutor; import org.openqa.selenium.remote.service.DriverService; +import java.nio.file.Path; import java.util.Objects; import java.util.Set; @@ -53,7 +58,7 @@ *WebDriver driver = new FirefoxDriver(options); * */ -public class FirefoxDriver extends RemoteWebDriver implements WebStorage { +public class FirefoxDriver extends RemoteWebDriver implements WebStorage, HasExtensions { public static final class SystemProperty { @@ -96,6 +101,24 @@ public static final class SystemProperty { public static final String PROFILE = "firefox_profile"; public static final String MARIONETTE = "marionette"; + private static class ExtraCommands { + static String INSTALL_EXTENSION = "installExtension"; + static String UNINSTALL_EXTENSION = "uninstallExtension"; + } + + private static final ImmutableMap EXTRA_COMMANDS = ImmutableMap.of( + ExtraCommands.INSTALL_EXTENSION, + new CommandInfo("/session/:sessionId/moz/addon/install", HttpMethod.POST), + ExtraCommands.UNINSTALL_EXTENSION, + new CommandInfo("/session/:sessionId/moz/addon/uninstall", HttpMethod.POST) + ); + + private static class FirefoxDriverCommandExecutor extends DriverCommandExecutor { + public FirefoxDriverCommandExecutor(DriverService service) { + super(service, EXTRA_COMMANDS); + } + } + protected FirefoxBinary binary; private RemoteWebStorage webStorage; @@ -127,22 +150,22 @@ public FirefoxDriver(FirefoxOptions options) { } public FirefoxDriver(GeckoDriverService service) { - super(new DriverCommandExecutor(service), new FirefoxOptions()); + super(new FirefoxDriverCommandExecutor(service), new FirefoxOptions()); webStorage = new RemoteWebStorage(getExecuteMethod()); } public FirefoxDriver(XpiDriverService service) { - super(new DriverCommandExecutor(service), new FirefoxOptions()); + super(new FirefoxDriverCommandExecutor(service), new FirefoxOptions()); webStorage = new RemoteWebStorage(getExecuteMethod()); } public FirefoxDriver(GeckoDriverService service, FirefoxOptions options) { - super(new DriverCommandExecutor(service), dropCapabilities(options)); + super(new FirefoxDriverCommandExecutor(service), dropCapabilities(options)); webStorage = new RemoteWebStorage(getExecuteMethod()); } public FirefoxDriver(XpiDriverService service, FirefoxOptions options) { - super(new DriverCommandExecutor(service), dropCapabilities(options)); + super(new FirefoxDriverCommandExecutor(service), dropCapabilities(options)); webStorage = new RemoteWebStorage(getExecuteMethod()); } @@ -150,7 +173,7 @@ private static CommandExecutor toExecutor(FirefoxOptions options) { Objects.requireNonNull(options, "No options to construct executor from"); DriverService.Builder builder; - if (! Boolean.parseBoolean(System.getProperty(DRIVER_USE_MARIONETTE, "true")) + if (! Boolean.parseBoolean(System.getProperty(SystemProperty.DRIVER_USE_MARIONETTE, "true")) || options.isLegacy()) { FirefoxProfile profile = options.getProfile(); if (profile == null) { @@ -165,7 +188,7 @@ private static CommandExecutor toExecutor(FirefoxOptions options) { .usingFirefoxBinary(options.getBinary()); } - return new DriverCommandExecutor(builder.build()); + return new FirefoxDriverCommandExecutor(builder.build()); } @Override @@ -194,8 +217,19 @@ private static boolean isLegacy(Capabilities desiredCapabilities) { return marionette instanceof Boolean && ! (Boolean) marionette; } + @Override + public String installExtension(Path path) { + return (String) execute(ExtraCommands.INSTALL_EXTENSION, + singletonMap("path", path.toAbsolutePath().toString())).getValue(); + } + + @Override + public void uninstallExtension(String extensionId) { + execute(ExtraCommands.UNINSTALL_EXTENSION, singletonMap("id", extensionId)); + } + private static Boolean forceMarionetteFromSystemProperty() { - String useMarionette = System.getProperty(DRIVER_USE_MARIONETTE); + String useMarionette = System.getProperty(SystemProperty.DRIVER_USE_MARIONETTE); if (useMarionette == null) { return null; }