Skip to content

Commit 626f908

Browse files
authored
Add Print page support in Java (#8991)
1 parent 87db0cb commit 626f908

16 files changed

+545
-1
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ java_export(
2525
"mobile/*.java",
2626
"net/*.java",
2727
"virtualauthenticator/*.java",
28+
"print/*.java",
29+
2830
]),
2931
hides = [
3032
"org.openqa.selenium.interactions.internal",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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;
19+
20+
public class Pdf {
21+
22+
private final String base64EncodedPdf;
23+
24+
public Pdf(String base64EncodedPdf) {
25+
this.base64EncodedPdf = base64EncodedPdf;
26+
}
27+
28+
public String getContent() {
29+
return base64EncodedPdf;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
package org.openqa.selenium;
18+
19+
import org.openqa.selenium.print.PrintOptions;
20+
21+
public interface PrintsPage {
22+
Pdf print(PrintOptions printOptions) throws WebDriverException;
23+
}

java/client/src/org/openqa/selenium/internal/Require.java

+15
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ public static int positive(String argName, Integer number, String message) {
159159
return number;
160160
}
161161

162+
public static double positive(String argName, double number, String message) {
163+
if (number <= 0) {
164+
if (message == null) {
165+
throw new IllegalArgumentException(argName + " must be greater than 0");
166+
} else {
167+
throw new IllegalArgumentException(message);
168+
}
169+
}
170+
return number;
171+
}
172+
173+
public static double positive(String argName, double number) {
174+
return positive(argName, number, null);
175+
}
176+
162177
public static int positive(String argName, Integer number) {
163178
return positive(argName, number, null);
164179
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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.print;
19+
20+
import org.openqa.selenium.internal.Require;
21+
22+
public class PageMargin {
23+
private double top;
24+
private double bottom;
25+
private double left;
26+
private double right;
27+
28+
public PageMargin() {
29+
this.top = 1.0;
30+
this.bottom = 1.0;
31+
this.left = 1.0;
32+
this.right = 1.0;
33+
}
34+
35+
public double getTop() {
36+
return top;
37+
}
38+
39+
public void setTop(double top) {
40+
this.top = Require.positive("top", top);
41+
}
42+
43+
public double getBottom() {
44+
return bottom;
45+
}
46+
47+
public void setBottom(double bottom) {
48+
this.bottom = Require.positive("bottom", bottom);
49+
}
50+
51+
public double getLeft() {
52+
return left;
53+
}
54+
55+
public void setLeft(double left) {
56+
this.left = Require.positive("left", left);
57+
}
58+
59+
public double getRight() {
60+
return right;
61+
}
62+
63+
public void setRight(double right) {
64+
this.right = Require.positive("right", right);
65+
}
66+
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.print;
19+
20+
21+
import org.openqa.selenium.internal.Require;
22+
23+
public class PageSize {
24+
25+
private double height;
26+
private double width;
27+
28+
public PageSize() {
29+
// Initialize with defaults. A4 paper size defaults in cms.
30+
this.height = 21.59;
31+
this.width = 27.94;
32+
}
33+
public double getHeight() {
34+
return height;
35+
}
36+
37+
public double getWidth() {
38+
return width;
39+
}
40+
41+
public void setHeight(double height) {
42+
this.height = Require.positive("height", height);
43+
}
44+
45+
public void setWidth(double width) {
46+
this.width = Require.positive("width", width);
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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.print;
19+
20+
import org.openqa.selenium.internal.Require;
21+
22+
public class PrintOptions {
23+
24+
public enum Orientation {
25+
Portrait,
26+
Landscape
27+
}
28+
private Orientation orientation = Orientation.Portrait;
29+
private double scale = 1.0;
30+
private boolean background = false;
31+
private boolean shrinkToFit = true;
32+
private PageSize pageSize = new PageSize();
33+
private PageMargin pageMargin = new PageMargin();
34+
private String[] pageRanges;
35+
36+
public Orientation getOrientation() {
37+
return this.orientation;
38+
}
39+
40+
public void setOrientation(Orientation orientation) {
41+
this.orientation = Require.nonNull("orientation", orientation);
42+
}
43+
44+
public String[] getPageRanges() {
45+
return this.pageRanges;
46+
}
47+
48+
public void setPageRanges(String firstRange, String ... ranges) {
49+
Require.nonNull("pageRanges", firstRange);
50+
this.pageRanges = new String[ranges.length + 1]; // Need to add all ranges and the initial range too.
51+
52+
this.pageRanges[0] = firstRange;
53+
54+
for (int i = 1; i < ranges.length; i++) {
55+
this.pageRanges[i] = ranges[i - 1];
56+
}
57+
}
58+
59+
public void setBackground(boolean background) {
60+
this.background = Require.nonNull("background", background);
61+
}
62+
63+
public boolean getBackground() {
64+
return this.background;
65+
}
66+
67+
public void setScale(double scale) {
68+
if (scale < 0.1 || scale > 2) {
69+
throw new IllegalArgumentException("Scale value should be between 0.1 and 2");
70+
}
71+
this.scale = scale;
72+
}
73+
74+
public double getScale() {
75+
return this.scale;
76+
}
77+
78+
public boolean getShrinkToFit() {
79+
return this.shrinkToFit;
80+
}
81+
82+
public void setShrinkToFit(boolean value) {
83+
this.shrinkToFit = Require.nonNull("value", value);
84+
}
85+
86+
public void setPageSize(PageSize pageSize) {
87+
this.pageSize = Require.nonNull("pageSize", pageSize);
88+
}
89+
90+
public void setPageMargin(PageMargin margin) {
91+
this.pageMargin = Require.nonNull("margin", margin);
92+
}
93+
94+
public PageSize getPageSize() {
95+
return this.pageSize;
96+
}
97+
98+
public PageMargin getPageMargin() {
99+
return this.pageMargin;
100+
}
101+
}

java/client/src/org/openqa/selenium/remote/DriverCommand.java

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.openqa.selenium.Point;
2626
import org.openqa.selenium.WindowType;
2727
import org.openqa.selenium.interactions.Sequence;
28+
import org.openqa.selenium.print.PrintOptions;
2829

2930
import java.time.Duration;
3031
import java.util.Collection;
@@ -227,6 +228,11 @@ static CommandPayload SET_ALERT_VALUE(String keysToSend) {
227228

228229
String SET_TIMEOUT = "setTimeout";
229230

231+
String PRINT_PAGE = "printPage";
232+
static CommandPayload PRINT_PAGE(PrintOptions options) {
233+
return new CommandPayload(PRINT_PAGE, ImmutableMap.of("options", options));
234+
}
235+
230236
@Deprecated
231237
static CommandPayload SET_IMPLICIT_WAIT_TIMEOUT(long time, TimeUnit unit) {
232238
return new CommandPayload(

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
import org.openqa.selenium.logging.LoggingPreferences;
5555
import org.openqa.selenium.logging.Logs;
5656
import org.openqa.selenium.logging.NeedsLocalLogs;
57+
import org.openqa.selenium.print.PrintOptions;
58+
import org.openqa.selenium.Pdf;
59+
import org.openqa.selenium.PrintsPage;
5760
import org.openqa.selenium.remote.internal.WebElementToJsonConverter;
5861
import org.openqa.selenium.virtualauthenticator.Credential;
5962
import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator;
@@ -87,7 +90,7 @@
8790
@Augmentable
8891
public class RemoteWebDriver implements WebDriver, JavascriptExecutor, HasInputDevices,
8992
HasCapabilities, Interactive, TakesScreenshot,
90-
HasVirtualAuthenticator {
93+
HasVirtualAuthenticator, PrintsPage {
9194

9295
// TODO(dawagner): This static logger should be unified with the per-instance localLogs
9396
private static final Logger logger = Logger.getLogger(RemoteWebDriver.class.getName());
@@ -324,6 +327,14 @@ public <X> X getScreenshotAs(OutputType<X> outputType) throws WebDriverException
324327
}
325328
}
326329

330+
@Override
331+
public Pdf print(PrintOptions printOptions) throws WebDriverException {
332+
Response response = execute(DriverCommand.PRINT_PAGE(printOptions));
333+
334+
Object result = response.getValue();
335+
return new Pdf((String) result);
336+
}
337+
327338
@Override
328339
public WebElement findElement(By locator) {
329340
if (locator instanceof By.StandardLocator) {

java/client/src/org/openqa/selenium/remote/codec/w3c/W3CHttpCommandCodec.java

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import static org.openqa.selenium.remote.DriverCommand.SET_TIMEOUT;
7474
import static org.openqa.selenium.remote.DriverCommand.SUBMIT_ELEMENT;
7575
import static org.openqa.selenium.remote.DriverCommand.UPLOAD_FILE;
76+
import static org.openqa.selenium.remote.DriverCommand.PRINT_PAGE;
7677

7778
import com.google.common.collect.ImmutableList;
7879
import com.google.common.collect.ImmutableMap;
@@ -154,6 +155,8 @@ public W3CHttpCommandCodec() {
154155
defineCommand(GET_ALERT_TEXT, get(alert + "/text"));
155156
defineCommand(SET_ALERT_VALUE, post(alert + "/text"));
156157

158+
defineCommand(PRINT_PAGE, post(sessionId + "/print"));
159+
157160
defineCommand(UPLOAD_FILE, post(sessionId + "/se/file"));
158161

159162
defineCommand(GET_ACTIVE_ELEMENT, get(sessionId + "/element/active"));

java/client/test/org/openqa/selenium/BUILD.bazel

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ SMALL_TESTS = [
1616
"ProxyTest.java",
1717
"RequireTest.java",
1818
"WebDriverExceptionTest.java",
19+
"print/PrintOptionsTest.java",
20+
"print/PageMarginTest.java",
21+
"print/PageSizeTest.java"
1922
]
2023

2124
java_test_suite(

0 commit comments

Comments
 (0)