Skip to content

Commit a4beba5

Browse files
pujaganidiemol
andauthored
[java][cdp] Use devtools script pinning mechanism by default (#11622)
This helps achieve feature parity in script pinning among different Selenium language bindings. Co-authored-by: Diego Molina <[email protected]>
1 parent 3eab322 commit a4beba5

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

java/src/org/openqa/selenium/UnpinnedScriptKey.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121
import java.util.HashSet;
2222
import java.util.Objects;
2323
import java.util.Set;
24+
import java.util.UUID;
2425
import java.util.WeakHashMap;
2526

26-
class UnpinnedScriptKey extends ScriptKey {
27+
public class UnpinnedScriptKey extends ScriptKey {
2728

2829
private static final WeakHashMap<JavascriptExecutor, Set<UnpinnedScriptKey>> pinnedScripts =
2930
new WeakHashMap<>();
3031
private final String script;
32+
private String scriptId;
33+
private final String scriptHandle;
3134

3235
static UnpinnedScriptKey pin(JavascriptExecutor executor, String script) {
3336
UnpinnedScriptKey toReturn = new UnpinnedScriptKey(script);
@@ -51,16 +54,41 @@ static Set<UnpinnedScriptKey> getPinnedScripts(JavascriptExecutor executor) {
5154
return Collections.unmodifiableSet(toReturn);
5255
}
5356

54-
private UnpinnedScriptKey(String script) {
57+
public UnpinnedScriptKey(String script) {
5558
super(script);
5659

60+
this.scriptHandle = UUID.randomUUID().toString().replace("-", "");
5761
this.script = script;
5862
}
5963

60-
String getScript() {
64+
public void setScriptId(String id) {
65+
this.scriptId = id;
66+
}
67+
68+
public String getScriptId() {
69+
return this.scriptId;
70+
}
71+
72+
public String getScript() {
6173
return script;
6274
}
6375

76+
public String getScriptHandle() {
77+
return scriptHandle;
78+
}
79+
80+
public String creationScript() {
81+
return String.format("function __webdriver_%s(arguments) { %s }", this.scriptHandle, this.script);
82+
}
83+
84+
public String executionScript() {
85+
return String.format("return __webdriver_%s(arguments)", this.scriptHandle);
86+
}
87+
88+
public String removalScript() {
89+
return String.format("__webdriver_%s = undefined", this.scriptHandle);
90+
}
91+
6492
@Override
6593
public boolean equals(Object o) {
6694
if (this == o) {

java/src/org/openqa/selenium/remote/RemoteWebDriver.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.openqa.selenium.Dimension;
5353
import org.openqa.selenium.HasCapabilities;
5454
import org.openqa.selenium.ImmutableCapabilities;
55+
import org.openqa.selenium.JavascriptException;
5556
import org.openqa.selenium.JavascriptExecutor;
5657
import org.openqa.selenium.MutableCapabilities;
5758
import org.openqa.selenium.NoAlertPresentException;
@@ -62,9 +63,11 @@
6263
import org.openqa.selenium.Platform;
6364
import org.openqa.selenium.Point;
6465
import org.openqa.selenium.PrintsPage;
66+
import org.openqa.selenium.ScriptKey;
6567
import org.openqa.selenium.SearchContext;
6668
import org.openqa.selenium.SessionNotCreatedException;
6769
import org.openqa.selenium.TakesScreenshot;
70+
import org.openqa.selenium.UnpinnedScriptKey;
6871
import org.openqa.selenium.WebDriver;
6972
import org.openqa.selenium.WebDriverException;
7073
import org.openqa.selenium.WebElement;
@@ -79,6 +82,7 @@
7982
import org.openqa.selenium.interactions.Sequence;
8083
import org.openqa.selenium.internal.Debug;
8184
import org.openqa.selenium.internal.Require;
85+
import org.openqa.selenium.json.TypeToken;
8286
import org.openqa.selenium.logging.LocalLogs;
8387
import org.openqa.selenium.logging.LoggingHandler;
8488
import org.openqa.selenium.logging.Logs;
@@ -471,6 +475,76 @@ public Object executeAsyncScript(String script, Object... args) {
471475
return execute(DriverCommand.EXECUTE_ASYNC_SCRIPT(script, convertedArgs)).getValue();
472476
}
473477

478+
@Override
479+
public ScriptKey pin(String script) {
480+
UnpinnedScriptKey key = (UnpinnedScriptKey) JavascriptExecutor.super.pin(script);
481+
String browserName = getCapabilities().getBrowserName().toLowerCase();
482+
if ((browserName.equals("chrome") ||
483+
browserName.equals("msedge") ||
484+
browserName.equals("microsoftedge")) && this instanceof HasDevTools) {
485+
486+
((HasDevTools) this).maybeGetDevTools().ifPresent(devTools -> {
487+
devTools.createSessionIfThereIsNotOne();
488+
devTools.send(new org.openqa.selenium.devtools.Command<>("Page.enable",
489+
ImmutableMap.of()));
490+
devTools.send(new org.openqa.selenium.devtools.Command<>("Runtime.evaluate",
491+
ImmutableMap.of("expression",
492+
key.creationScript())));
493+
Map<String, Object> result = devTools.send(new org.openqa.selenium.devtools.Command<>(
494+
"Page.addScriptToEvaluateOnNewDocument",
495+
ImmutableMap.of("source", key.creationScript()),
496+
new TypeToken<Map<String, Object>>() {
497+
}.getType()));
498+
key.setScriptId((String) result.get("identifier"));
499+
});
500+
}
501+
return key;
502+
}
503+
504+
@Override
505+
public void unpin(ScriptKey scriptKey) {
506+
UnpinnedScriptKey key = (UnpinnedScriptKey) scriptKey;
507+
508+
JavascriptExecutor.super.unpin(key);
509+
510+
String browserName = getCapabilities().getBrowserName().toLowerCase();
511+
if ((browserName.equals("chrome") ||
512+
browserName.equals("msedge") ||
513+
browserName.equals("microsoftedge")) && this instanceof HasDevTools) {
514+
((HasDevTools) this).maybeGetDevTools().ifPresent(devTools -> {
515+
devTools.send(new org.openqa.selenium.devtools.Command<>("Page.enable",
516+
ImmutableMap.of()));
517+
devTools.send(new org.openqa.selenium.devtools.Command<>(
518+
"Runtime.evaluate",
519+
ImmutableMap.of("expression", key.removalScript())));
520+
devTools.send(new org.openqa.selenium.devtools.Command<>(
521+
"Page.removeScriptToEvaluateOnLoad",
522+
ImmutableMap.of("identifier", key.getScriptId())));
523+
});
524+
}
525+
}
526+
527+
@Override
528+
public Object executeScript(ScriptKey key, Object... args) {
529+
Require.stateCondition(
530+
key instanceof UnpinnedScriptKey,
531+
"Script key should have been generated by this driver");
532+
533+
if (!getPinnedScripts().contains(key)) {
534+
throw new JavascriptException("Script is unpinned");
535+
}
536+
537+
String browserName = getCapabilities().getBrowserName().toLowerCase();
538+
539+
if ((browserName.equals("chrome") ||
540+
browserName.equals("msedge") ||
541+
browserName.equals("microsoftedge")) && this instanceof HasDevTools) {
542+
return executeScript(((UnpinnedScriptKey) key).executionScript(), args);
543+
}
544+
545+
return executeScript(((UnpinnedScriptKey) key).getScript(), args);
546+
}
547+
474548
@Override
475549
public TargetLocator switchTo() {
476550
return new RemoteTargetLocator();

0 commit comments

Comments
 (0)