Skip to content

Commit ad00dd5

Browse files
committed
Redesigning MarionetteDriver to use the gecko shim
1 parent a660392 commit ad00dd5

File tree

5 files changed

+164
-39
lines changed

5 files changed

+164
-39
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.firefox;
19+
20+
import com.google.common.collect.ImmutableList;
21+
import com.google.common.collect.ImmutableMap;
22+
23+
import org.openqa.selenium.WebDriverException;
24+
import org.openqa.selenium.firefox.internal.Executable;
25+
import org.openqa.selenium.remote.service.DriverService;
26+
27+
import java.io.File;
28+
import java.io.IOException;
29+
30+
/**
31+
* Manages the life and death of an GeckoDriver aka 'wires'.
32+
*/
33+
public class GeckoDriverService extends DriverService {
34+
35+
/**
36+
* System property that defines the location of the GeckoDriver executable
37+
* that will be used by the {@link #createDefaultService() default service}.
38+
*/
39+
public static final String GECKO_DRIVER_EXE_PROPERTY = "webdriver.gecko.driver";
40+
41+
/**
42+
*
43+
* @param executable The GeckoDriver executable.
44+
* @param port Which port to start the GeckoDriver on.
45+
* @param args The arguments to the launched server.
46+
* @param environment The environment for the launched server.
47+
* @throws IOException If an I/O error occurs.
48+
*/
49+
private GeckoDriverService(File executable, int port, ImmutableList<String> args,
50+
ImmutableMap<String, String> environment) throws IOException {
51+
super(executable, port, args, environment);
52+
}
53+
54+
/**
55+
* Configures and returns a new {@link GeckoDriverService} using the default configuration. In
56+
* this configuration, the service will use the GeckoDriver executable identified by the
57+
* {@link #GECKO_DRIVER_EXE_PROPERTY} system property. Each service created by this method will
58+
* be configured to use a free port on the current system.
59+
*
60+
* @return A new GeckoDriverService using the default configuration.
61+
*/
62+
public static GeckoDriverService createDefaultService() {
63+
return new Builder().usingAnyFreePort().build();
64+
}
65+
66+
/**
67+
* Builder used to configure new {@link GeckoDriverService} instances.
68+
*/
69+
public static class Builder extends DriverService.Builder<
70+
GeckoDriverService, GeckoDriverService.Builder> {
71+
72+
@Override
73+
protected File findDefaultExecutable() {
74+
return findExecutable("wires", GECKO_DRIVER_EXE_PROPERTY,
75+
"https://github.com/jgraham/wires",
76+
"https://github.com/jgraham/wires");
77+
}
78+
79+
@Override
80+
protected ImmutableList<String> createArgs() {
81+
ImmutableList.Builder<String> argsBuilder = ImmutableList.builder();
82+
argsBuilder.add(String.format("--webdriver-port=%d", getPort()));
83+
if (getLogFile() != null) {
84+
argsBuilder.add(String.format("--log-file=\"%s\"", getLogFile().getAbsolutePath()));
85+
}
86+
argsBuilder.add("-b");
87+
argsBuilder.add(new Executable(null).getPath());
88+
return argsBuilder.build();
89+
}
90+
91+
@Override
92+
protected GeckoDriverService createDriverService(File exe, int port,
93+
ImmutableList<String> args,
94+
ImmutableMap<String, String> environment) {
95+
try {
96+
return new GeckoDriverService(exe, port, args, environment);
97+
} catch (IOException e) {
98+
throw new WebDriverException(e);
99+
}
100+
}
101+
}
102+
}

java/client/src/org/openqa/selenium/firefox/MarionetteDriver.java

+49-32
Original file line numberDiff line numberDiff line change
@@ -17,64 +17,81 @@
1717

1818
package org.openqa.selenium.firefox;
1919

20+
import com.google.common.base.Throwables;
21+
2022
import org.openqa.selenium.Beta;
2123
import org.openqa.selenium.Capabilities;
2224
import org.openqa.selenium.WebDriverException;
23-
import org.openqa.selenium.firefox.internal.MarionetteConnection;
24-
import org.openqa.selenium.interactions.ActionChainExecutor;
25-
import org.openqa.selenium.interactions.CanPerformActionChain;
26-
import org.openqa.selenium.internal.Lock;
27-
import org.openqa.selenium.remote.RemoteActionChainExecutor;
28-
import org.openqa.selenium.remote.RemoteExecuteMethod;
25+
import org.openqa.selenium.remote.DesiredCapabilities;
26+
import org.openqa.selenium.remote.FileDetector;
27+
import org.openqa.selenium.remote.RemoteWebDriver;
28+
import org.openqa.selenium.remote.service.DriverCommandExecutor;
2929

3030
/**
3131
* An implementation of the {#link WebDriver} interface that drives Firefox using Marionette interface.
3232
*/
3333
@Beta
34-
public class MarionetteDriver extends FirefoxDriver implements CanPerformActionChain {
34+
public class MarionetteDriver extends RemoteWebDriver {
35+
36+
/**
37+
* Port which is used by default.
38+
*/
39+
private final static int DEFAULT_PORT = 0;
3540

3641
public MarionetteDriver() {
37-
this(new FirefoxBinary(), null);
42+
this(null, null, DEFAULT_PORT);
3843
}
3944

40-
public MarionetteDriver(FirefoxProfile profile) {
41-
super(profile);
45+
public MarionetteDriver(Capabilities capabilities) {
46+
this(null, capabilities, DEFAULT_PORT);
4247
}
4348

44-
public MarionetteDriver(Capabilities desiredCapabilities) {
45-
super(desiredCapabilities);
49+
public MarionetteDriver(int port) {
50+
this(null, null, port);
4651
}
4752

48-
public MarionetteDriver(Capabilities desiredCapabilities, Capabilities requiredCapabilities) {
49-
super(desiredCapabilities, requiredCapabilities);
53+
public MarionetteDriver(GeckoDriverService service) {
54+
this(service, null, DEFAULT_PORT);
5055
}
5156

52-
public MarionetteDriver(FirefoxBinary binary, FirefoxProfile profile) {
53-
super(binary, profile);
57+
public MarionetteDriver(GeckoDriverService service, Capabilities capabilities) {
58+
this(service, capabilities, DEFAULT_PORT);
5459
}
5560

56-
public MarionetteDriver(FirefoxBinary binary, FirefoxProfile profile, Capabilities capabilities) {
57-
super(binary, profile, capabilities);
61+
public MarionetteDriver(GeckoDriverService service, Capabilities capabilities,
62+
int port) {
63+
if (capabilities == null) {
64+
capabilities = DesiredCapabilities.internetExplorer();
65+
}
66+
67+
if (service == null) {
68+
service = setupService(capabilities, port);
69+
}
70+
run(service, capabilities);
5871
}
5972

60-
public MarionetteDriver(FirefoxBinary binary, FirefoxProfile profile,
61-
Capabilities desiredCapabilities, Capabilities requiredCapabilities) {
62-
super(binary, profile, desiredCapabilities, requiredCapabilities);
73+
private void run(GeckoDriverService service, Capabilities capabilities) {
74+
setCommandExecutor(new DriverCommandExecutor(service));
75+
76+
startSession(capabilities);
6377
}
6478

65-
protected ExtensionConnection connectTo(FirefoxBinary binary, FirefoxProfile profile,
66-
String host) {
67-
Lock lock = obtainLock(profile);
79+
@Override
80+
public void setFileDetector(FileDetector detector) {
81+
throw new WebDriverException(
82+
"Setting the file detector only works on remote webdriver instances obtained " +
83+
"via RemoteWebDriver");
84+
}
85+
86+
private GeckoDriverService setupService(Capabilities caps, int port) {
6887
try {
69-
FirefoxBinary bin = binary == null ? new FirefoxBinary() : binary;
88+
GeckoDriverService.Builder builder = new GeckoDriverService.Builder();
89+
builder.usingPort(port);
7090

71-
return new MarionetteConnection(lock, bin, profile, host);
72-
} catch (Exception e) {
73-
throw new WebDriverException(e);
74-
}
75-
}
91+
return builder.build();
7692

77-
public ActionChainExecutor getActionChainExecutor() {
78-
return new RemoteActionChainExecutor(new RemoteExecuteMethod(this));
93+
} catch (IllegalStateException ex) {
94+
throw Throwables.propagate(ex);
95+
}
7996
}
8097
}

java/client/src/org/openqa/selenium/firefox/build.desc

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ java_library(name = "firefox",
88
"//java/client/src/org/openqa/selenium/net",
99
"//java/client/src/org/openqa/selenium/os",
1010
"//java/client/src/org/openqa/selenium/remote",
11+
"//java/client/src/org/openqa/selenium/remote/service",
1112
"//third_party/java/commons-io",
1213
"//third_party/java/guava-libraries",
1314
"//third_party/java/commons-exec",

java/client/src/org/openqa/selenium/remote/service/DriverService.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ public void start() throws IOException {
163163
process.copyOutputTo(System.err);
164164
process.executeAsync();
165165

166-
URL status = new URL(url.toString() + "/status");
167-
new UrlChecker().waitUntilAvailable(20, SECONDS, status);
168-
} catch (UrlChecker.TimeoutException e) {
169-
process.checkForError();
170-
throw new WebDriverException("Timed out waiting for driver server to start.", e);
166+
//URL status = new URL(url.toString() + "/status");
167+
//new UrlChecker().waitUntilAvailable(20, SECONDS, status);
168+
//} catch (UrlChecker.TimeoutException e) {
169+
// process.checkForError();
170+
// throw new WebDriverException("Timed out waiting for driver server to start.", e);
171171
} finally {
172172
lock.unlock();
173173
}

java/client/test/org/openqa/selenium/testing/drivers/ReflectionBackedDriverSupplier.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,13 @@ public WebDriver get() {
7171
profile.setEnableNativeEvents(enableNativeEvents);
7272
desiredCapsToUse.setCapability(FirefoxDriver.PROFILE, profile);
7373

74-
return driverClass.getConstructor(Capabilities.class,
75-
Capabilities.class).newInstance(desiredCapsToUse, requiredCapabilities);
74+
try {
75+
return driverClass.getConstructor(Capabilities.class,
76+
Capabilities.class)
77+
.newInstance(desiredCapsToUse, requiredCapabilities);
78+
} catch (NoSuchMethodException ex) {
79+
return driverClass.getConstructor(Capabilities.class).newInstance(desiredCapsToUse);
80+
}
7681
}
7782

7883
try {

0 commit comments

Comments
 (0)