17
17
18
18
package org .openqa .selenium .firefox ;
19
19
20
+ import static org .openqa .selenium .remote .CapabilityType .PROXY ;
21
+
20
22
import com .google .common .collect .ImmutableMap ;
21
23
import com .google .common .collect .Maps ;
22
24
import com .google .common .collect .Sets ;
25
+
23
26
import org .openqa .selenium .Beta ;
24
27
import org .openqa .selenium .Capabilities ;
25
28
import org .openqa .selenium .ImmutableCapabilities ;
58
61
import java .util .Set ;
59
62
import java .util .stream .StreamSupport ;
60
63
61
- import static org .openqa .selenium .remote .CapabilityType .PROXY ;
62
-
63
64
/**
64
65
* An implementation of the {#link WebDriver} interface that drives Firefox.
65
66
* <p>
78
79
public class FirefoxDriver extends RemoteWebDriver
79
80
implements WebStorage , HasExtensions , HasFullPageScreenshot , HasContext , HasDevTools {
80
81
81
- public static final class SystemProperty {
82
-
83
- /**
84
- * System property that defines the location of the Firefox executable file.
85
- */
86
- public static final String BROWSER_BINARY = "webdriver.firefox.bin" ;
87
-
88
- /**
89
- * System property that defines the location of the file where Firefox log should be stored.
90
- */
91
- public static final String BROWSER_LOGFILE = "webdriver.firefox.logfile" ;
92
-
93
- /**
94
- * System property that defines the additional library path (Linux only).
95
- */
96
- public static final String BROWSER_LIBRARY_PATH = "webdriver.firefox.library.path" ;
97
-
98
- /**
99
- * System property that defines the profile that should be used as a template.
100
- * When the driver starts, it will make a copy of the profile it is using,
101
- * rather than using that profile directly.
102
- */
103
- public static final String BROWSER_PROFILE = "webdriver.firefox.profile" ;
104
-
105
- /**
106
- * System property that defines the location of the webdriver.xpi browser extension to install
107
- * in the browser. If not set, the prebuilt extension bundled with this class will be used.
108
- */
109
- public static final String DRIVER_XPI_PROPERTY = "webdriver.firefox.driver" ;
110
-
111
- /**
112
- * Boolean system property that instructs FirefoxDriver to use Marionette backend,
113
- * overrides any capabilities specified by the user
114
- */
115
- public static final String DRIVER_USE_MARIONETTE = "webdriver.firefox.marionette" ;
116
- }
117
-
118
82
/**
119
83
* @deprecated Use {@link Capability#BINARY}
120
84
*/
121
85
@ Deprecated
122
86
public static final String BINARY = Capability .BINARY ;
123
-
124
87
/**
125
88
* @deprecated Use {@link Capability#PROFILE}
126
89
*/
127
90
@ Deprecated
128
91
public static final String PROFILE = Capability .PROFILE ;
129
-
130
92
/**
131
93
* @deprecated Use {@link Capability#MARIONETTE}
132
94
*/
133
95
@ Deprecated
134
96
public static final String MARIONETTE = Capability .MARIONETTE ;
135
-
136
- public static final class Capability {
137
- public static final String BINARY = "firefox_binary" ;
138
- public static final String PROFILE = "firefox_profile" ;
139
- public static final String MARIONETTE = "marionette" ;
140
- }
141
-
142
- @ Beta
143
- public static RemoteWebDriverBuilder builder () {
144
- return RemoteWebDriver .builder ().oneOf (new FirefoxOptions ());
145
- }
146
-
147
- private static class FirefoxDriverCommandExecutor extends DriverCommandExecutor {
148
- public FirefoxDriverCommandExecutor (DriverService service ) {
149
- super (service , getExtraCommands ());
150
- }
151
-
152
- private static Map <String , CommandInfo > getExtraCommands () {
153
- return ImmutableMap .<String , CommandInfo >builder ()
154
- .putAll (new AddHasContext ().getAdditionalCommands ())
155
- .putAll (new AddHasExtensions ().getAdditionalCommands ())
156
- .putAll (new AddHasFullPageScreenshot ().getAdditionalCommands ())
157
- .build ();
158
- }
159
- }
160
-
161
97
private final Capabilities capabilities ;
162
- protected FirefoxBinary binary ;
163
98
private final RemoteWebStorage webStorage ;
164
99
private final HasExtensions extensions ;
165
100
private final HasFullPageScreenshot fullPageScreenshot ;
166
101
private final HasContext context ;
167
102
private final Optional <URI > cdpUri ;
103
+ protected FirefoxBinary binary ;
168
104
private DevTools devTools ;
169
-
170
105
public FirefoxDriver () {
171
106
this (new FirefoxOptions ());
172
107
}
173
-
174
108
/**
175
109
* @deprecated Use {@link #FirefoxDriver(FirefoxOptions)}.
176
110
*/
177
111
@ Deprecated
178
112
public FirefoxDriver (Capabilities desiredCapabilities ) {
179
113
this (new FirefoxOptions (Require .nonNull ("Capabilities" , desiredCapabilities )));
180
114
}
181
-
182
115
/**
183
116
* @deprecated Use {@link #FirefoxDriver(FirefoxDriverService, FirefoxOptions)}.
184
117
*/
@@ -188,7 +121,6 @@ public FirefoxDriver(FirefoxDriverService service, Capabilities desiredCapabilit
188
121
Require .nonNull ("Driver service" , service ),
189
122
new FirefoxOptions (desiredCapabilities ));
190
123
}
191
-
192
124
public FirefoxDriver (FirefoxOptions options ) {
193
125
this (toExecutor (options ), options );
194
126
}
@@ -215,30 +147,82 @@ private FirefoxDriver(FirefoxDriverCommandExecutor executor, FirefoxOptions opti
215
147
216
148
this .cdpUri = cdpUri ;
217
149
this .capabilities = cdpUri .map (uri ->
218
- new ImmutableCapabilities (
219
- new PersistentCapabilities (capabilities )
220
- .setCapability ("se:cdp" , uri .toString ())
221
- .setCapability ("se:cdpVersion" , "85" )))
222
- .orElse (new ImmutableCapabilities (capabilities ));
150
+ new ImmutableCapabilities (
151
+ new PersistentCapabilities (capabilities )
152
+ .setCapability ("se:cdp" , uri .toString ())
153
+ .setCapability ("se:cdpVersion" , "85.0" )))
154
+ .orElse (new ImmutableCapabilities (capabilities ));
155
+ }
156
+
157
+ @ Beta
158
+ public static RemoteWebDriverBuilder builder () {
159
+ return RemoteWebDriver .builder ().oneOf (new FirefoxOptions ());
223
160
}
224
161
225
162
private static FirefoxDriverCommandExecutor toExecutor (FirefoxOptions options ) {
226
163
Require .nonNull ("Options to construct executor from" , options );
227
164
228
165
String sysProperty = System .getProperty (SystemProperty .DRIVER_USE_MARIONETTE );
229
- boolean isLegacy = (sysProperty != null && ! Boolean .parseBoolean (sysProperty ))
166
+ boolean isLegacy = (sysProperty != null && !Boolean .parseBoolean (sysProperty ))
230
167
|| options .isLegacy ();
231
168
232
169
FirefoxDriverService .Builder <?, ?> builder =
233
- StreamSupport .stream (ServiceLoader .load (DriverService .Builder .class ).spliterator (), false )
234
- .filter (b -> b instanceof FirefoxDriverService .Builder )
235
- .map (FirefoxDriverService .Builder .class ::cast )
236
- .filter (b -> b .isLegacy () == isLegacy )
237
- .findFirst ().orElseThrow (WebDriverException ::new );
170
+ StreamSupport .stream (ServiceLoader .load (DriverService .Builder .class ).spliterator (), false )
171
+ .filter (b -> b instanceof FirefoxDriverService .Builder )
172
+ .map (FirefoxDriverService .Builder .class ::cast )
173
+ .filter (b -> b .isLegacy () == isLegacy )
174
+ .findFirst ().orElseThrow (WebDriverException ::new );
238
175
239
176
return new FirefoxDriverCommandExecutor (builder .withOptions (options ).build ());
240
177
}
241
178
179
+ private static boolean isLegacy (Capabilities desiredCapabilities ) {
180
+ Boolean forceMarionette = forceMarionetteFromSystemProperty ();
181
+ if (forceMarionette != null ) {
182
+ return !forceMarionette ;
183
+ }
184
+ Object marionette = desiredCapabilities .getCapability (Capability .MARIONETTE );
185
+ return marionette instanceof Boolean && !(Boolean ) marionette ;
186
+ }
187
+
188
+ private static Boolean forceMarionetteFromSystemProperty () {
189
+ String useMarionette = System .getProperty (SystemProperty .DRIVER_USE_MARIONETTE );
190
+ if (useMarionette == null ) {
191
+ return null ;
192
+ }
193
+ return Boolean .valueOf (useMarionette );
194
+ }
195
+
196
+ /**
197
+ * Drops capabilities that we shouldn't send over the wire.
198
+ *
199
+ * Used for capabilities which aren't BeanToJson-convertable, and are only used by the local
200
+ * launcher.
201
+ */
202
+ private static Capabilities dropCapabilities (Capabilities capabilities ) {
203
+ if (capabilities == null ) {
204
+ return new ImmutableCapabilities ();
205
+ }
206
+
207
+ MutableCapabilities caps ;
208
+
209
+ if (isLegacy (capabilities )) {
210
+ final Set <String > toRemove = Sets .newHashSet (Capability .BINARY , Capability .PROFILE );
211
+ caps = new MutableCapabilities (
212
+ Maps .filterKeys (capabilities .asMap (), key -> !toRemove .contains (key )));
213
+ } else {
214
+ caps = new MutableCapabilities (capabilities );
215
+ }
216
+
217
+ // Ensure that the proxy is in a state fit to be sent to the extension
218
+ Proxy proxy = Proxy .extractFrom (capabilities );
219
+ if (proxy != null ) {
220
+ caps .setCapability (PROXY , proxy );
221
+ }
222
+
223
+ return caps ;
224
+ }
225
+
242
226
@ Override
243
227
public Capabilities getCapabilities () {
244
228
return capabilities ;
@@ -247,8 +231,8 @@ public Capabilities getCapabilities() {
247
231
@ Override
248
232
public void setFileDetector (FileDetector detector ) {
249
233
throw new WebDriverException (
250
- "Setting the file detector only works on remote webdriver instances obtained " +
251
- "via RemoteWebDriver" );
234
+ "Setting the file detector only works on remote webdriver instances obtained " +
235
+ "via RemoteWebDriver" );
252
236
}
253
237
254
238
@ Override
@@ -261,15 +245,6 @@ public SessionStorage getSessionStorage() {
261
245
return webStorage .getSessionStorage ();
262
246
}
263
247
264
- private static boolean isLegacy (Capabilities desiredCapabilities ) {
265
- Boolean forceMarionette = forceMarionetteFromSystemProperty ();
266
- if (forceMarionette != null ) {
267
- return !forceMarionette ;
268
- }
269
- Object marionette = desiredCapabilities .getCapability (Capability .MARIONETTE );
270
- return marionette instanceof Boolean && ! (Boolean ) marionette ;
271
- }
272
-
273
248
@ Override
274
249
public String installExtension (Path path ) {
275
250
Require .nonNull ("Path" , path );
@@ -304,53 +279,15 @@ public <X> X getFullPageScreenshotAs(OutputType<X> outputType) throws WebDriverE
304
279
return fullPageScreenshot .getFullPageScreenshotAs (outputType );
305
280
}
306
281
307
- @ Override
308
- public void setContext (FirefoxCommandContext commandContext ) {
309
- Require .nonNull ("Firefox Command Context" , commandContext );
310
- context .setContext (commandContext );
311
- }
312
-
313
282
@ Override
314
283
public FirefoxCommandContext getContext () {
315
284
return context .getContext ();
316
285
}
317
286
318
- private static Boolean forceMarionetteFromSystemProperty () {
319
- String useMarionette = System .getProperty (SystemProperty .DRIVER_USE_MARIONETTE );
320
- if (useMarionette == null ) {
321
- return null ;
322
- }
323
- return Boolean .valueOf (useMarionette );
324
- }
325
-
326
- /**
327
- * Drops capabilities that we shouldn't send over the wire.
328
- *
329
- * Used for capabilities which aren't BeanToJson-convertable, and are only used by the local
330
- * launcher.
331
- */
332
- private static Capabilities dropCapabilities (Capabilities capabilities ) {
333
- if (capabilities == null ) {
334
- return new ImmutableCapabilities ();
335
- }
336
-
337
- MutableCapabilities caps ;
338
-
339
- if (isLegacy (capabilities )) {
340
- final Set <String > toRemove = Sets .newHashSet (Capability .BINARY , Capability .PROFILE );
341
- caps = new MutableCapabilities (
342
- Maps .filterKeys (capabilities .asMap (), key -> !toRemove .contains (key )));
343
- } else {
344
- caps = new MutableCapabilities (capabilities );
345
- }
346
-
347
- // Ensure that the proxy is in a state fit to be sent to the extension
348
- Proxy proxy = Proxy .extractFrom (capabilities );
349
- if (proxy != null ) {
350
- caps .setCapability (PROXY , proxy );
351
- }
352
-
353
- return caps ;
287
+ @ Override
288
+ public void setContext (FirefoxCommandContext commandContext ) {
289
+ Require .nonNull ("Firefox Command Context" , commandContext );
290
+ context .setContext (commandContext );
354
291
}
355
292
356
293
@ Override
@@ -383,6 +320,66 @@ public DevTools getDevTools() {
383
320
throw new DevToolsException ("This version of Firefox or geckodriver does not support CDP" );
384
321
}
385
322
386
- return maybeGetDevTools ().orElseThrow (() -> new DevToolsException ("Unable to initialize CDP connection" ));
323
+ return maybeGetDevTools ()
324
+ .orElseThrow (() -> new DevToolsException ("Unable to initialize CDP connection" ));
325
+ }
326
+
327
+ public static final class SystemProperty {
328
+
329
+ /**
330
+ * System property that defines the location of the Firefox executable file.
331
+ */
332
+ public static final String BROWSER_BINARY = "webdriver.firefox.bin" ;
333
+
334
+ /**
335
+ * System property that defines the location of the file where Firefox log should be stored.
336
+ */
337
+ public static final String BROWSER_LOGFILE = "webdriver.firefox.logfile" ;
338
+
339
+ /**
340
+ * System property that defines the additional library path (Linux only).
341
+ */
342
+ public static final String BROWSER_LIBRARY_PATH = "webdriver.firefox.library.path" ;
343
+
344
+ /**
345
+ * System property that defines the profile that should be used as a template.
346
+ * When the driver starts, it will make a copy of the profile it is using,
347
+ * rather than using that profile directly.
348
+ */
349
+ public static final String BROWSER_PROFILE = "webdriver.firefox.profile" ;
350
+
351
+ /**
352
+ * System property that defines the location of the webdriver.xpi browser extension to install
353
+ * in the browser. If not set, the prebuilt extension bundled with this class will be used.
354
+ */
355
+ public static final String DRIVER_XPI_PROPERTY = "webdriver.firefox.driver" ;
356
+
357
+ /**
358
+ * Boolean system property that instructs FirefoxDriver to use Marionette backend,
359
+ * overrides any capabilities specified by the user
360
+ */
361
+ public static final String DRIVER_USE_MARIONETTE = "webdriver.firefox.marionette" ;
362
+ }
363
+
364
+ public static final class Capability {
365
+
366
+ public static final String BINARY = "firefox_binary" ;
367
+ public static final String PROFILE = "firefox_profile" ;
368
+ public static final String MARIONETTE = "marionette" ;
369
+ }
370
+
371
+ private static class FirefoxDriverCommandExecutor extends DriverCommandExecutor {
372
+
373
+ public FirefoxDriverCommandExecutor (DriverService service ) {
374
+ super (service , getExtraCommands ());
375
+ }
376
+
377
+ private static Map <String , CommandInfo > getExtraCommands () {
378
+ return ImmutableMap .<String , CommandInfo >builder ()
379
+ .putAll (new AddHasContext ().getAdditionalCommands ())
380
+ .putAll (new AddHasExtensions ().getAdditionalCommands ())
381
+ .putAll (new AddHasFullPageScreenshot ().getAdditionalCommands ())
382
+ .build ();
383
+ }
387
384
}
388
385
}
0 commit comments