package jp.vmi.selenium.webdriver;
import java.io.File;
import java.io.IOException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.GeckoDriverService;
import org.openqa.selenium.firefox.internal.ProfilesIni;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import jp.vmi.selenium.selenese.utils.PathUtils;
import static jp.vmi.selenium.webdriver.DriverOptions.DriverOption.*;
/**
* Factory of {@link FirefoxDriver}.
*/
public class FirefoxDriverFactory extends WebDriverFactory {
@SuppressWarnings("javadoc")
public static final String BROWSER_NAME = "firefox";
private static final Logger log = LoggerFactory.getLogger(FirefoxDriverFactory.class);
@Override
public String getBrowserName() {
return BROWSER_NAME;
}
@Override
protected DesiredCapabilities setupProxy(DesiredCapabilities caps, DriverOptions driverOptions) {
if (driverOptions.has(PROXY)) {
String[] p = driverOptions.get(PROXY).split(":", 2);
String proxy = p[0];
int port = p.length == 2 ? Integer.parseInt(p[1]) : 80;
JsonObject json = new JsonObject();
json.addProperty("proxyType", "manual");
json.addProperty("httpProxy", proxy);
json.addProperty("httpProxyPort", port);
json.addProperty("sslProxy", proxy);
json.addProperty("sslProxyPort", port);
if (driverOptions.has(NO_PROXY)) {
// don't work?
json.addProperty("noProxy", driverOptions.get(NO_PROXY));
}
caps.setCapability("proxy", json);
}
return caps;
}
@Override
public WebDriver newInstance(DriverOptions driverOptions) {
if (driverOptions.has(GECKODRIVER)) {
String executable = PathUtils.normalize(driverOptions.get(GECKODRIVER));
if (!new File(executable).canExecute())
throw new IllegalArgumentException("Missing GeckoDriver: " + executable);
System.setProperty(GeckoDriverService.GECKO_DRIVER_EXE_PROPERTY, executable);
}
FirefoxOptions firefoxOptions = new FirefoxOptions();
DesiredCapabilities requiredCaps = new DesiredCapabilities();
setupProxy(requiredCaps, driverOptions);
firefoxOptions.addCapabilities(requiredCaps);
firefoxOptions.addCapabilities(driverOptions.getCapabilities());
String firefoxBin = getFirefoxBinary(driverOptions);
if (firefoxBin != null)
firefoxOptions.setBinary(firefoxBin);
if (driverOptions.has(CLI_ARGS))
firefoxOptions.addArguments(driverOptions.getCliArgs());
FirefoxProfile profile = getFirefoxProfile(driverOptions);
if (profile != null)
firefoxOptions.setProfile(profile);
FirefoxDriver driver = new FirefoxDriver(firefoxOptions);
setInitialWindowSize(driver, driverOptions);
return driver;
}
/**
* set driver specific capabilities for RemoteWebDriver.
*
* @param caps desired capabilities.
* @param driverOptions driver options.
*/
public static void setDriverSpecificCapabilitiesForRemoteWebDriver(DesiredCapabilities caps, DriverOptions driverOptions) {
String firefoxBin = getFirefoxBinary(driverOptions);
if (firefoxBin != null) {
caps.setCapability(FirefoxDriver.BINARY, firefoxBin);
log.info("Firefox binary: {}", firefoxBin);
}
if (driverOptions.has(CLI_ARGS))
log.warn("Ignore --cli-args with RemoteWebDriver.");
FirefoxProfile profile = getFirefoxProfile(driverOptions);
if (driverOptions.has(PROXY)) {
if (profile == null)
profile = new FirefoxProfile();
setProxyConfiguration(profile, driverOptions);
}
if (profile != null) {
String json;
try {
json = profile.toJson();
} catch (IOException e) {
throw new RuntimeException(e);
}
caps.setCapability(FirefoxDriver.PROFILE, json);
log.info("Convert Firefox profile to JSON: {} bytes", json.length());
}
}
private static String getFirefoxBinary(DriverOptions driverOptions) {
if (driverOptions.has(FIREFOX))
return driverOptions.get(FIREFOX);
else
return System.getProperty(FirefoxDriver.SystemProperty.BROWSER_BINARY);
}
private static FirefoxProfile getFirefoxProfile(DriverOptions driverOptions) {
if (!driverOptions.has(PROFILE) && !driverOptions.has(PROFILE_DIR))
return null;
FirefoxProfile profile;
// Create FirefoxProfile and set to DesiredCapabilities.
// (FirefoxProfile object can work with both local and remote FirefoxDriver
// see: https://code.google.com/p/selenium/wiki/DesiredCapabilities#Firefox_specific)
String profileName = driverOptions.get(PROFILE);
String profileDir = driverOptions.get(PROFILE_DIR);
if (profileName != null) {
if (profileDir != null)
throw new IllegalArgumentException("Can't specify both '--profile' and '--profile-dir' at once");
// see http://code.google.com/p/selenium/wiki/TipsAndTricks
ProfilesIni allProfiles = new ProfilesIni();
profile = allProfiles.getProfile(profileName);
if (profile == null)
throw new IllegalArgumentException("Profile '" + profile + "' does not exist.");
log.info("Firefox profile: {}", profileName);
} else {
File dir = new File(profileDir);
if (!dir.isDirectory())
throw new IllegalArgumentException("Missing profile directory: " + profileDir);
profile = new FirefoxProfile(dir);
log.info("Firefox profile directory: {}", profileDir);
}
return profile;
}
private static void setProxyConfiguration(FirefoxProfile profile, DriverOptions driverOptions) {
String proxy = driverOptions.get(PROXY);
String[] ps = proxy.split(":", 2);
String host = ps[0];
int port = ps.length == 2 ? Integer.parseInt(ps[1]) : 80;
String noProxy = driverOptions.has(NO_PROXY) ? driverOptions.get(NO_PROXY) : " ";
// see https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Mozilla_networking_preferences#Proxy
profile.setPreference("network.proxy.type", 1); // 1 = MANUAL
profile.setPreference("network.proxy.http", host);
profile.setPreference("network.proxy.http_port", port);
profile.setPreference("network.proxy.ssl", host);
profile.setPreference("network.proxy.ssl_port", port);
profile.setPreference("network.proxy.ftp", host);
profile.setPreference("network.proxy.ftp_port", port);
profile.setPreference("network.proxy.socks", host);
profile.setPreference("network.proxy.socks_port", port);
profile.setPreference("network.proxy.no_proxies_on", noProxy);
}
}