Skip to content

Commit 3832787

Browse files
authored
[java][bidi] Add BrowsingContext module commands
1 parent a6313cf commit 3832787

File tree

7 files changed

+657
-0
lines changed

7 files changed

+657
-0
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ java_library(
66
srcs = glob([
77
"*.java",
88
"log/*.java",
9+
"browsingcontext/*.java"
910
]),
1011
visibility = [
1112
"//java/src/org/openqa/selenium/bidi:__subpackages__",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
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 com.google.common.collect.ImmutableMap;
21+
22+
import org.openqa.selenium.WebDriver;
23+
import org.openqa.selenium.WindowType;
24+
import org.openqa.selenium.bidi.BiDi;
25+
import org.openqa.selenium.bidi.Command;
26+
import org.openqa.selenium.bidi.HasBiDi;
27+
import org.openqa.selenium.internal.Require;
28+
import org.openqa.selenium.json.Json;
29+
import org.openqa.selenium.json.JsonInput;
30+
import org.openqa.selenium.json.TypeToken;
31+
32+
import java.lang.reflect.Type;
33+
import java.util.ArrayList;
34+
import java.util.HashMap;
35+
import java.util.List;
36+
import java.util.Map;
37+
import java.util.function.Function;
38+
39+
public class BrowsingContext {
40+
41+
private final String id;
42+
private final BiDi bidi;
43+
private static final String CONTEXT = "context";
44+
private static final String RELOAD = "browsingContext.reload";
45+
private static final String HANDLE_USER_PROMPT = "browsingContext.handleUserPrompt";
46+
47+
protected static final Type LIST_OF_BROWSING_CONTEXT_INFO =
48+
new TypeToken<List<BrowsingContextInfo>>() {}.getType();
49+
50+
private final Function<JsonInput, String> browsingContextIdMapper = jsonInput -> {
51+
Map<String, Object> result = jsonInput.read(Map.class);
52+
return result.getOrDefault(CONTEXT, "").toString();
53+
};
54+
55+
private final Function<JsonInput, NavigationResult> navigationInfoMapper =
56+
jsonInput -> (NavigationResult) jsonInput.read(NavigationResult.class);
57+
58+
private final Function<JsonInput, List<BrowsingContextInfo>> browsingContextInfoListMapper =
59+
jsonInput -> {
60+
Map<String, Object> result = jsonInput.read(Map.class);
61+
List<Object> contexts = (List<Object>) result.getOrDefault("contexts", new ArrayList<>());
62+
63+
if (contexts.isEmpty()) {
64+
return new ArrayList<>();
65+
}
66+
67+
Json json = new Json();
68+
String dtr = json.toJson(contexts);
69+
70+
return json.toType(dtr, LIST_OF_BROWSING_CONTEXT_INFO);
71+
};
72+
73+
public BrowsingContext(WebDriver driver, String id) {
74+
Require.nonNull("WebDriver", driver);
75+
Require.nonNull("Browsing Context id", id);
76+
77+
if (!(driver instanceof HasBiDi)) {
78+
throw new IllegalArgumentException("WebDriver instance must support BiDi protocol");
79+
}
80+
81+
this.bidi = ((HasBiDi) driver).getBiDi();
82+
this.id = id;
83+
}
84+
85+
public BrowsingContext(WebDriver driver, WindowType type) {
86+
Require.nonNull("WebDriver", driver);
87+
88+
if (!(driver instanceof HasBiDi)) {
89+
throw new IllegalArgumentException("WebDriver instance must support BiDi protocol");
90+
}
91+
92+
this.bidi = ((HasBiDi) driver).getBiDi();
93+
this.id = this.create(type);
94+
}
95+
96+
public BrowsingContext(WebDriver driver, WindowType type, String referenceContextId) {
97+
Require.nonNull("WebDriver", driver);
98+
Require.nonNull("Reference browsing context id", referenceContextId);
99+
if (!(driver instanceof HasBiDi)) {
100+
throw new IllegalArgumentException("WebDriver instance must support BiDi protocol");
101+
}
102+
103+
this.bidi = ((HasBiDi) driver).getBiDi();
104+
this.id = this.create(type, referenceContextId);
105+
}
106+
107+
public String getId() {
108+
return this.id;
109+
}
110+
111+
private String create(WindowType type) {
112+
return this.bidi.send(
113+
new Command<>("browsingContext.create",
114+
ImmutableMap.of("type", type.toString()),
115+
browsingContextIdMapper));
116+
}
117+
118+
private String create(WindowType type, String referenceContext) {
119+
return this.bidi.send(
120+
new Command<>("browsingContext.create",
121+
ImmutableMap.of("type", type.toString(),
122+
"referenceContext", referenceContext),
123+
browsingContextIdMapper));
124+
}
125+
126+
public NavigationResult navigate(String url) {
127+
return this.bidi.send(
128+
new Command<>("browsingContext.navigate",
129+
ImmutableMap.of(CONTEXT, id,
130+
"url", url),
131+
navigationInfoMapper));
132+
}
133+
134+
public NavigationResult navigate(String url, ReadinessState readinessState) {
135+
return this.bidi.send(
136+
new Command<>("browsingContext.navigate",
137+
ImmutableMap.of(CONTEXT, id,
138+
"url", url,
139+
"wait", readinessState.toString()),
140+
navigationInfoMapper));
141+
}
142+
143+
public List<BrowsingContextInfo> getTree() {
144+
return this.bidi.send(
145+
new Command<>("browsingContext.getTree",
146+
ImmutableMap.of("root", id),
147+
browsingContextInfoListMapper));
148+
}
149+
150+
public List<BrowsingContextInfo> getTree(int maxDepth) {
151+
return this.bidi.send(
152+
new Command<>("browsingContext.getTree",
153+
ImmutableMap.of("root", id,
154+
"maxDepth", maxDepth),
155+
browsingContextInfoListMapper));
156+
}
157+
158+
public List<BrowsingContextInfo> getTopLevelContexts() {
159+
return this.bidi.send(
160+
new Command<>("browsingContext.getTree",
161+
new HashMap<>(),
162+
browsingContextInfoListMapper));
163+
}
164+
165+
// Yet to be implemented by browser vendors
166+
private void reload() {
167+
this.bidi.send(new Command<>(RELOAD, ImmutableMap.of(CONTEXT, id)));
168+
}
169+
170+
// Yet to be implemented by browser vendors
171+
private void reload(boolean ignoreCache) {
172+
this.bidi.send(new Command<>(
173+
RELOAD,
174+
ImmutableMap.of(CONTEXT, id,
175+
"ignoreCache", ignoreCache)));
176+
}
177+
178+
// Yet to be implemented by browser vendors
179+
private void reload(ReadinessState readinessState) {
180+
this.bidi.send(new Command<>(
181+
RELOAD,
182+
ImmutableMap.of(CONTEXT, id,
183+
"wait", readinessState.toString())));
184+
}
185+
186+
// Yet to be implemented by browser vendors
187+
private void reload(boolean ignoreCache, ReadinessState readinessState) {
188+
this.bidi.send(new Command<>(
189+
RELOAD,
190+
ImmutableMap.of(CONTEXT, id,
191+
"ignoreCache", ignoreCache,
192+
"wait", readinessState.toString())));
193+
}
194+
195+
// Yet to be implemented by browser vendors
196+
private void handleUserPrompt() {
197+
this.bidi.send(new Command<>(
198+
HANDLE_USER_PROMPT,
199+
ImmutableMap.of(CONTEXT, id)));
200+
}
201+
202+
// Yet to be implemented by browser vendors
203+
private void handleUserPrompt(String userText) {
204+
this.bidi.send(new Command<>(
205+
HANDLE_USER_PROMPT,
206+
ImmutableMap.of(CONTEXT, id,
207+
"userText", userText)));
208+
209+
}
210+
211+
// Yet to be implemented by browser vendors
212+
private void handleUserPrompt(boolean accept, String userText) {
213+
this.bidi.send(new Command<>(
214+
HANDLE_USER_PROMPT,
215+
ImmutableMap.of(CONTEXT, id,
216+
"accept", accept,
217+
"userText", userText)));
218+
219+
}
220+
221+
// Yet to be implemented by browser vendors
222+
private String captureScreenshot() {
223+
return this.bidi.send(new Command<>(
224+
HANDLE_USER_PROMPT,
225+
ImmutableMap.of(CONTEXT, id),
226+
jsonInput -> {
227+
Map<String, Object> result = jsonInput.read(Map.class);
228+
return (String) result.get("data");
229+
}
230+
));
231+
}
232+
233+
public void close() {
234+
// This might need more clean up actions once the behavior is defined.
235+
// Specially when last tab or window is closed.
236+
// Refer: https://github.com./w3c/webdriver-bidi/issues/187
237+
this.bidi.send(new Command<>(
238+
"browsingContext.close",
239+
ImmutableMap.of(CONTEXT, id)));
240+
}
241+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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 org.openqa.selenium.bidi.browsingcontext.BrowsingContext.LIST_OF_BROWSING_CONTEXT_INFO;
21+
22+
import org.openqa.selenium.json.JsonInput;
23+
24+
import java.util.List;
25+
26+
public class BrowsingContextInfo {
27+
28+
private final String id;
29+
30+
private final String url;
31+
32+
private final List<BrowsingContextInfo> children;
33+
34+
private final String parentBrowsingContext;
35+
36+
public String getId() {
37+
return id;
38+
}
39+
40+
public String getUrl() {
41+
return url;
42+
}
43+
44+
public List<BrowsingContextInfo> getChildren() {
45+
return children;
46+
}
47+
48+
public String getParentBrowsingContext() {
49+
return parentBrowsingContext;
50+
}
51+
52+
public BrowsingContextInfo(
53+
String id, String url, List<BrowsingContextInfo> children, String parentBrowsingContext) {
54+
this.id = id;
55+
this.url = url;
56+
this.children = children;
57+
this.parentBrowsingContext = parentBrowsingContext;
58+
}
59+
60+
public static BrowsingContextInfo fromJson(JsonInput input) {
61+
String id = null;
62+
String url = null;
63+
List<BrowsingContextInfo> children = null;
64+
String parentBrowsingContext = null;
65+
66+
input.beginObject();
67+
while (input.hasNext()) {
68+
switch (input.nextName()) {
69+
case "context":
70+
id = input.read(String.class);
71+
break;
72+
73+
case "url":
74+
url = input.read(String.class);
75+
break;
76+
77+
case "children":
78+
children = input.read(LIST_OF_BROWSING_CONTEXT_INFO);
79+
break;
80+
81+
case "parent":
82+
parentBrowsingContext = input.read(String.class);
83+
break;
84+
85+
default:
86+
input.skipValue();
87+
break;
88+
}
89+
}
90+
91+
input.endObject();
92+
93+
return new BrowsingContextInfo(id, url, children, parentBrowsingContext);
94+
}
95+
}

0 commit comments

Comments
 (0)