Skip to content

Commit 173391f

Browse files
committed
[java][BiDi] implement browsingContext.downloadEnd
1 parent 0417a8e commit 173391f

File tree

5 files changed

+296
-14
lines changed

5 files changed

+296
-14
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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 org.openqa.selenium.json.JsonInput;
21+
22+
public class DownloadCanceled extends NavigationInfo {
23+
24+
private final String status;
25+
26+
DownloadCanceled(
27+
String browsingContextId, String navigationId, long timestamp, String url, String status) {
28+
super(browsingContextId, navigationId, timestamp, url);
29+
this.status = status != null ? status : "canceled";
30+
}
31+
32+
public static DownloadCanceled fromJson(JsonInput input) {
33+
String browsingContextId = null;
34+
String navigationId = null;
35+
long timestamp = 0;
36+
String url = null;
37+
String status = "canceled";
38+
39+
input.beginObject();
40+
while (input.hasNext()) {
41+
switch (input.nextName()) {
42+
case "context":
43+
browsingContextId = input.read(String.class);
44+
break;
45+
46+
case "navigation":
47+
navigationId = input.read(String.class);
48+
break;
49+
50+
case "timestamp":
51+
timestamp = input.read(Long.class);
52+
break;
53+
54+
case "url":
55+
url = input.read(String.class);
56+
break;
57+
58+
case "status":
59+
status = input.read(String.class);
60+
if (!"canceled".equals(status)) {
61+
throw new IllegalArgumentException("Expected status 'canceled', but got: " + status);
62+
}
63+
break;
64+
65+
default:
66+
input.skipValue();
67+
break;
68+
}
69+
}
70+
71+
input.endObject();
72+
73+
return new DownloadCanceled(browsingContextId, navigationId, timestamp, url, status);
74+
}
75+
76+
public String getStatus() {
77+
return status;
78+
}
79+
}
Lines changed: 95 additions & 0 deletions
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 org.openqa.selenium.json.JsonInput;
21+
22+
public class DownloadCompleted extends NavigationInfo {
23+
24+
private final String status;
25+
private final String filepath;
26+
27+
DownloadCompleted(
28+
String browsingContextId,
29+
String navigationId,
30+
long timestamp,
31+
String url,
32+
String status,
33+
String filepath) {
34+
super(browsingContextId, navigationId, timestamp, url);
35+
this.status = status != null ? status : "complete";
36+
this.filepath = filepath;
37+
}
38+
39+
public static DownloadCompleted fromJson(JsonInput input) {
40+
String browsingContextId = null;
41+
String navigationId = null;
42+
long timestamp = 0;
43+
String url = null;
44+
String status = "complete";
45+
String filepath = null;
46+
47+
input.beginObject();
48+
while (input.hasNext()) {
49+
switch (input.nextName()) {
50+
case "context":
51+
browsingContextId = input.read(String.class);
52+
break;
53+
54+
case "navigation":
55+
navigationId = input.read(String.class);
56+
break;
57+
58+
case "timestamp":
59+
timestamp = input.read(Long.class);
60+
break;
61+
62+
case "url":
63+
url = input.read(String.class);
64+
break;
65+
66+
case "status":
67+
status = input.read(String.class);
68+
if (!"complete".equals(status)) {
69+
throw new IllegalArgumentException("Expected status 'complete', but got: " + status);
70+
}
71+
break;
72+
73+
case "filepath":
74+
filepath = input.read(String.class);
75+
break;
76+
77+
default:
78+
input.skipValue();
79+
break;
80+
}
81+
}
82+
83+
input.endObject();
84+
85+
return new DownloadCompleted(browsingContextId, navigationId, timestamp, url, status, filepath);
86+
}
87+
88+
public String getStatus() {
89+
return status;
90+
}
91+
92+
public String getFilepath() {
93+
return filepath;
94+
}
95+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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 org.openqa.selenium.json.JsonInput;
21+
22+
public class DownloadEnded {
23+
24+
private final NavigationInfo downloadParams;
25+
26+
public DownloadEnded(NavigationInfo downloadParams) {
27+
this.downloadParams = downloadParams;
28+
}
29+
30+
public static DownloadEnded fromJson(JsonInput input) {
31+
String browsingContextId = null;
32+
String navigationId = null;
33+
long timestamp = 0;
34+
String url = null;
35+
String status = null;
36+
String filepath = null;
37+
38+
input.beginObject();
39+
while (input.hasNext()) {
40+
switch (input.nextName()) {
41+
case "context":
42+
browsingContextId = input.read(String.class);
43+
break;
44+
case "navigation":
45+
navigationId = input.read(String.class);
46+
break;
47+
case "timestamp":
48+
timestamp = input.read(Long.class);
49+
break;
50+
case "url":
51+
url = input.read(String.class);
52+
break;
53+
case "status":
54+
status = input.read(String.class);
55+
break;
56+
case "filepath":
57+
filepath = input.read(String.class);
58+
break;
59+
default:
60+
input.skipValue();
61+
break;
62+
}
63+
}
64+
input.endObject();
65+
66+
// Create the appropriate object based on status
67+
if ("canceled".equals(status)) {
68+
DownloadCanceled canceled =
69+
new DownloadCanceled(browsingContextId, navigationId, timestamp, url, status);
70+
return new DownloadEnded(canceled);
71+
} else if ("complete".equals(status)) {
72+
DownloadCompleted completed =
73+
new DownloadCompleted(browsingContextId, navigationId, timestamp, url, status, filepath);
74+
return new DownloadEnded(completed);
75+
} else {
76+
throw new IllegalArgumentException(
77+
"status must be either 'canceled' or 'complete', but got: " + status);
78+
}
79+
}
80+
81+
public NavigationInfo getDownloadParams() {
82+
return downloadParams;
83+
}
84+
85+
public boolean isCanceled() {
86+
return downloadParams instanceof DownloadCanceled;
87+
}
88+
89+
public boolean isCompleted() {
90+
return downloadParams instanceof DownloadCompleted;
91+
}
92+
93+
}

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,7 @@
2828
import org.openqa.selenium.bidi.BiDi;
2929
import org.openqa.selenium.bidi.Event;
3030
import org.openqa.selenium.bidi.HasBiDi;
31-
import org.openqa.selenium.bidi.browsingcontext.BrowsingContextInfo;
32-
import org.openqa.selenium.bidi.browsingcontext.DownloadInfo;
33-
import org.openqa.selenium.bidi.browsingcontext.HistoryUpdated;
34-
import org.openqa.selenium.bidi.browsingcontext.NavigationInfo;
35-
import org.openqa.selenium.bidi.browsingcontext.UserPromptClosed;
36-
import org.openqa.selenium.bidi.browsingcontext.UserPromptOpened;
31+
import org.openqa.selenium.bidi.browsingcontext.*;
3732
import org.openqa.selenium.internal.Require;
3833
import org.openqa.selenium.json.Json;
3934
import org.openqa.selenium.json.JsonInput;
@@ -70,6 +65,14 @@ public class BrowsingContextInspector implements AutoCloseable {
7065
}
7166
};
7267

68+
private final Function<Map<String, Object>, DownloadEnded> downloadWillEndMapper =
69+
params -> {
70+
try (StringReader reader = new StringReader(JSON.toJson(params));
71+
JsonInput input = JSON.newInput(reader)) {
72+
return input.read(DownloadEnded.class);
73+
}
74+
};
75+
7376
private final Event<BrowsingContextInfo> browsingContextCreated =
7477
new Event<>("browsingContext.contextCreated", browsingContextInfoMapper);
7578

@@ -91,6 +94,9 @@ public class BrowsingContextInspector implements AutoCloseable {
9194
private final Event<DownloadInfo> downloadWillBeginEvent =
9295
new Event<>("browsingContext.downloadWillBegin", downloadWillBeginMapper);
9396

97+
private final Event<DownloadEnded> downloadWillEndEvent =
98+
new Event<>("browsingContext.downloadEnd", downloadWillEndMapper);
99+
94100
private final Event<UserPromptOpened> userPromptOpened =
95101
new Event<>(
96102
"browsingContext.userPromptOpened",
@@ -171,6 +177,14 @@ public void onDownloadWillBegin(Consumer<DownloadInfo> consumer) {
171177
}
172178
}
173179

180+
public void onDownloadEnd(Consumer<DownloadEnded> consumer) {
181+
if (browsingContextIds.isEmpty()) {
182+
this.bidi.addListener(downloadWillEndEvent, consumer);
183+
} else {
184+
this.bidi.addListener(browsingContextIds, downloadWillEndEvent, consumer);
185+
}
186+
}
187+
174188
public void onNavigationAborted(Consumer<NavigationInfo> consumer) {
175189
addNavigationEventListener("browsingContext.navigationAborted", consumer);
176190
}
@@ -227,6 +241,7 @@ public void close() {
227241
this.bidi.clearListener(userPromptClosed);
228242
this.bidi.clearListener(historyUpdated);
229243
this.bidi.clearListener(downloadWillBeginEvent);
244+
this.bidi.clearListener(downloadWillEndEvent);
230245

231246
navigationEventSet.forEach(this.bidi::clearListener);
232247
}

java/test/org/openqa/selenium/bidi/browsingcontext/BrowsingContextInspectorTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,22 +236,22 @@ void canListenToNavigationCommittedEvent()
236236
@Test
237237
@NeedsFreshDriver
238238
@NotYetImplemented(FIREFOX)
239-
void canListenToDownloadWillBeginEvent()
240-
throws ExecutionException, InterruptedException, TimeoutException {
239+
void canListenToDownloadEnd() throws ExecutionException, InterruptedException, TimeoutException {
241240
try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
242-
CompletableFuture<DownloadInfo> future = new CompletableFuture<>();
241+
CompletableFuture<DownloadEnded> future = new CompletableFuture<>();
243242

244-
inspector.onDownloadWillBegin(future::complete);
243+
inspector.onDownloadEnd(future::complete);
245244

246245
BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
247246
context.navigate(appServer.whereIs("/downloads/download.html"), ReadinessState.COMPLETE);
248247

249248
driver.findElement(By.id("file-1")).click();
250249

251-
DownloadInfo downloadInfo = future.get(5, TimeUnit.SECONDS);
252-
assertThat(downloadInfo.getBrowsingContextId()).isEqualTo(context.getId());
253-
assertThat(downloadInfo.getUrl()).contains("/downloads/file_1.txt");
254-
assertThat(downloadInfo.getSuggestedFilename()).isEqualTo("file_1.txt");
250+
DownloadEnded downloadEnded = future.get(5, TimeUnit.SECONDS);
251+
assertThat(downloadEnded.getDownloadParams().getBrowsingContextId())
252+
.isEqualTo(context.getId());
253+
assertThat(downloadEnded.isCompleted()).isTrue();
254+
assertThat(downloadEnded.getDownloadParams().getUrl()).contains("/downloads/file_1.txt");
255255
}
256256
}
257257

0 commit comments

Comments
 (0)