Skip to content

Commit 78d767c

Browse files
authored
Merge branch 'SeleniumHQ:trunk' into mypy_annotation_cleanup
2 parents b618655 + 21b07d5 commit 78d767c

File tree

19 files changed

+526
-21
lines changed

19 files changed

+526
-21
lines changed

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ on Github.
6262

6363
This document will guide you through the contribution process.
6464

65-
### Step 1: Fork
65+
### Step 1: Fork & Clone
6666

6767
Fork the project [on Github](https://github.com/seleniumhq/selenium)
68-
and check out your copy locally. Use `--depth 1` for a quick check out.
69-
The repository is ~2GB and checking the whole history takes a while.
68+
and clone the repository locally. Use `--depth 1` for a quick clone.
69+
The repository is over 2GB and cloning the whole history takes a while.
7070

7171
```shell
7272
% git clone git@github.com:username/selenium.git --depth 1
@@ -76,7 +76,7 @@ The repository is ~2GB and checking the whole history takes a while.
7676

7777
#### Dependencies
7878

79-
We bundle dependencies in the _third-party/_ directory that is not
79+
We bundle dependencies in the _third-party/_ directory that are not
8080
part of the proper project. Any changes to files in this directory or
8181
its subdirectories should be sent upstream to the respective projects.
8282
Please don't send your patch to us as we cannot accept it.

java/src/org/openqa/selenium/Keys.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,26 @@
2323

2424
/**
2525
* Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private
26-
* Use Area) code points, 0xE000-0xF8FF.
26+
* Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate
27+
* keyboard input where standard Unicode characters are insufficient, such as modifier and control
28+
* keys.
2729
*
28-
* @see <a
29-
* href="http://www.google.com.au/search?&amp;q=unicode+pua&amp;btnK=Search">http://www.google.com.au/search?&amp;q=unicode+pua&amp;btnK=Search</a>
30+
* <p>The codes follow conventions partially established by the W3C WebDriver specification and the
31+
* Selenium project. Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are
32+
* not currently part of the W3C spec. Others (e.g., OPTION, FN) are symbolic and reserved for
33+
* possible future mapping.
34+
*
35+
* <p>For consistency across platforms and drivers, values should be verified before assuming native
36+
* support.
37+
*
38+
* @see <a href="https://www.w3.org/TR/webdriver/#keyboard-actions">W3C WebDriver Keyboard
39+
* Actions</a>
40+
* @see <a href="http://www.google.com.au/search?&q=unicode+pua&btnK=Search">Unicode PUA
41+
* Overview</a>
3042
*/
3143
@NullMarked
3244
public enum Keys implements CharSequence {
45+
// Basic control characters
3346
NULL('\uE000'),
3447
CANCEL('\uE001'), // ^break
3548
HELP('\uE002'),
@@ -99,6 +112,16 @@ public enum Keys implements CharSequence {
99112
META('\uE03D'),
100113
COMMAND(Keys.META),
101114

115+
// Extended macOS/ChromeDriver keys (based on observed Chrome usage)
116+
RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver usage
117+
RIGHT_CONTROL('\uE051'),
118+
RIGHT_ALT('\uE052'),
119+
RIGHT_COMMAND('\uE053'),
120+
121+
// Symbolic macOS keys not yet standardized
122+
OPTION('\uE050'), // TODO: verify Unicode value with WebDriver spec
123+
FN('\uE051'), // TODO: symbolic only; confirm or remove in future
124+
102125
ZENKAKU_HANKAKU('\uE040');
103126

104127
private final char keyCode;
@@ -122,7 +145,6 @@ public char charAt(int index) {
122145
if (index == 0) {
123146
return keyCode;
124147
}
125-
126148
return 0;
127149
}
128150

@@ -136,7 +158,6 @@ public CharSequence subSequence(int start, int end) {
136158
if (start == 0 && end == 1) {
137159
return String.valueOf(keyCode);
138160
}
139-
140161
throw new IndexOutOfBoundsException();
141162
}
142163

@@ -147,11 +168,9 @@ public String toString() {
147168

148169
/**
149170
* Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings;
150-
* appends each of the values to a string, and adds the chord termination key (Keys.NULL) and
151-
* returns the resultant string.
171+
* appends each to a string, adds the chord termination key (Keys.NULL), and returns it.
152172
*
153-
* <p>Note: When the low-level webdriver key handlers see Keys.NULL, active modifier keys
154-
* (CTRL/ALT/SHIFT/etc) release via a keyup event.
173+
* <p>Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events.
155174
*
156175
* @param value characters to send
157176
* @return String representation of the char sequence
@@ -161,35 +180,32 @@ public static String chord(CharSequence... value) {
161180
}
162181

163182
/**
164-
* @see #chord(CharSequence...)
183+
* Overload of {@link #chord(CharSequence...)} that accepts an iterable.
184+
*
165185
* @param value characters to send
166186
* @return String representation of the char sequence
167187
*/
168188
public static String chord(Iterable<CharSequence> value) {
169189
StringBuilder builder = new StringBuilder();
170-
171190
for (CharSequence seq : value) {
172191
builder.append(seq);
173192
}
174-
175193
builder.append(Keys.NULL);
176194
return builder.toString();
177195
}
178196

179197
/**
180-
* Get the special key representation, {@link Keys}, of the supplied character if there is one. If
181-
* there is no special key tied to this character, null will be returned.
198+
* Retrieves the {@link Keys} enum constant corresponding to the given Unicode character.
182199
*
183200
* @param key unicode character code
184-
* @return special key linked to the character code, or null if character is not a special key
201+
* @return special key linked to the character code, or null if not found
185202
*/
186203
public static @Nullable Keys getKeyFromUnicode(char key) {
187204
for (Keys unicodeKey : values()) {
188205
if (unicodeKey.charAt(0) == key) {
189206
return unicodeKey;
190207
}
191208
}
192-
193209
return null;
194210
}
195211
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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.bidi.browsingcontext;
19+
20+
import static java.util.Collections.unmodifiableMap;
21+
22+
import java.util.Map;
23+
import java.util.TreeMap;
24+
import org.openqa.selenium.json.JsonInput;
25+
26+
public class HistoryUpdated {
27+
28+
private final String browsingContextId;
29+
30+
private final int timestamp;
31+
32+
private final String url;
33+
34+
private HistoryUpdated(String browsingContextId, int timestamp, String url) {
35+
this.browsingContextId = browsingContextId;
36+
this.timestamp = timestamp;
37+
this.url = url;
38+
}
39+
40+
public static HistoryUpdated fromJson(JsonInput input) {
41+
String browsingContextId = null;
42+
int timestamp = 0;
43+
String url = null;
44+
45+
input.beginObject();
46+
while (input.hasNext()) {
47+
switch (input.nextName()) {
48+
case "context":
49+
browsingContextId = input.read(String.class);
50+
break;
51+
52+
case "timestamp":
53+
timestamp = input.read(int.class);
54+
break;
55+
56+
case "url":
57+
url = input.read(String.class);
58+
break;
59+
60+
default:
61+
input.skipValue();
62+
break;
63+
}
64+
}
65+
66+
input.endObject();
67+
68+
return new HistoryUpdated(browsingContextId, timestamp, url);
69+
}
70+
71+
public String getBrowsingContextId() {
72+
return browsingContextId;
73+
}
74+
75+
public int getTimestamp() {
76+
return timestamp;
77+
}
78+
79+
public String getUrl() {
80+
return url;
81+
}
82+
83+
private Map<String, Object> toJson() {
84+
Map<String, Object> toReturn = new TreeMap<>();
85+
86+
toReturn.put("browsingContextId", this.getBrowsingContextId());
87+
toReturn.put("timestamp", this.getTimestamp());
88+
toReturn.put("url", this.getUrl());
89+
90+
return unmodifiableMap(toReturn);
91+
}
92+
}

java/src/org/openqa/selenium/bidi/module/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ java_library(
2525
"//java/src/org/openqa/selenium/bidi/permissions",
2626
"//java/src/org/openqa/selenium/bidi/script",
2727
"//java/src/org/openqa/selenium/bidi/storage",
28+
"//java/src/org/openqa/selenium/bidi/webextension",
2829
"//java/src/org/openqa/selenium/json",
2930
"//java/src/org/openqa/selenium/remote/http",
3031
artifact("com.google.auto.service:auto-service-annotations"),

java/src/org/openqa/selenium/bidi/module/BrowsingContextInspector.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.openqa.selenium.bidi.Event;
3030
import org.openqa.selenium.bidi.HasBiDi;
3131
import org.openqa.selenium.bidi.browsingcontext.BrowsingContextInfo;
32+
import org.openqa.selenium.bidi.browsingcontext.HistoryUpdated;
3233
import org.openqa.selenium.bidi.browsingcontext.NavigationInfo;
3334
import org.openqa.selenium.bidi.browsingcontext.UserPromptClosed;
3435
import org.openqa.selenium.bidi.browsingcontext.UserPromptOpened;
@@ -88,6 +89,16 @@ public class BrowsingContextInspector implements AutoCloseable {
8889
}
8990
});
9091

92+
private final Event<HistoryUpdated> historyUpdated =
93+
new Event<>(
94+
"browsingContext.historyUpdated",
95+
params -> {
96+
try (StringReader reader = new StringReader(JSON.toJson(params));
97+
JsonInput input = JSON.newInput(reader)) {
98+
return input.read(HistoryUpdated.class);
99+
}
100+
});
101+
91102
public BrowsingContextInspector(WebDriver driver) {
92103
this(new HashSet<>(), driver);
93104
}
@@ -172,6 +183,14 @@ public void onUserPromptOpened(Consumer<UserPromptOpened> consumer) {
172183
}
173184
}
174185

186+
public void onHistoryUpdated(Consumer<HistoryUpdated> consumer) {
187+
if (browsingContextIds.isEmpty()) {
188+
this.bidi.addListener(historyUpdated, consumer);
189+
} else {
190+
this.bidi.addListener(browsingContextIds, historyUpdated, consumer);
191+
}
192+
}
193+
175194
private void addNavigationEventListener(String name, Consumer<NavigationInfo> consumer) {
176195
Event<NavigationInfo> navigationEvent = new Event<>(name, navigationInfoMapper);
177196

@@ -190,6 +209,7 @@ public void close() {
190209
this.bidi.clearListener(browsingContextDestroyed);
191210
this.bidi.clearListener(userPromptOpened);
192211
this.bidi.clearListener(userPromptClosed);
212+
this.bidi.clearListener(historyUpdated);
193213

194214
navigationEventSet.forEach(this.bidi::clearListener);
195215
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
load("@rules_jvm_external//:defs.bzl", "artifact")
2+
load("//java:defs.bzl", "java_library")
3+
4+
java_library(
5+
name = "webextension",
6+
srcs = glob(
7+
[
8+
"*.java",
9+
],
10+
),
11+
visibility = [
12+
"//java/src/org/openqa/selenium/bidi:__subpackages__",
13+
"//java/src/org/openqa/selenium/firefox:__subpackages__",
14+
"//java/src/org/openqa/selenium/remote:__pkg__",
15+
"//java/test/org/openqa/selenium/bidi:__subpackages__",
16+
"//java/test/org/openqa/selenium/grid:__subpackages__",
17+
],
18+
deps = [
19+
"//java/src/org/openqa/selenium:core",
20+
"//java/src/org/openqa/selenium/bidi",
21+
"//java/src/org/openqa/selenium/json",
22+
"//java/src/org/openqa/selenium/remote/http",
23+
artifact("com.google.auto.service:auto-service-annotations"),
24+
],
25+
)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.bidi.webextension;
19+
20+
import java.util.Map;
21+
22+
public class ExtensionArchivePath extends ExtensionData {
23+
private final String path;
24+
25+
public ExtensionArchivePath(String path) {
26+
this.path = path;
27+
}
28+
29+
@Override
30+
public Map<String, Object> toMap() {
31+
String type = "archivePath";
32+
return Map.of("extensionData", Map.of("type", type, "path", path));
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.bidi.webextension;
19+
20+
import java.util.Map;
21+
22+
public class ExtensionBase64Encoded extends ExtensionData {
23+
private final String value;
24+
25+
public ExtensionBase64Encoded(String value) {
26+
this.value = value;
27+
}
28+
29+
@Override
30+
public Map<String, Object> toMap() {
31+
String type = "base64";
32+
return Map.of("extensionData", Map.of("type", type, "value", value));
33+
}
34+
}

0 commit comments

Comments
 (0)