diff --git a/.gitignore b/.gitignore index 8973dcce..d7aae7e4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,3 @@ target/ .idea *.iml -/driver/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a6338dd0..72d3a27a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ git clone https://github.com/microsoft/playwright-java cd playwright-java ``` -2. Run the following script to download playwright-cli binary for your platform into `playwright/src/main/resources/driver/` directory. It will also install Playwright and download browser binaries for Chromium, Firefox and WebKit. +2. Run the following script to download playwright-cli binary for your platform into `driver/src/main/resources/driver/` directory. It will also install Playwright and download browser binaries for Chromium, Firefox and WebKit. ```bash scripts/download_driver.sh diff --git a/driver/pom.xml b/driver/pom.xml new file mode 100644 index 00000000..fd254274 --- /dev/null +++ b/driver/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.microsoft.playwright + playwright-java + 0.1-SNAPSHOT + + driver + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + + + + com.microsoft.playwright + playwright + 0.1-SNAPSHOT + compile + + + org.junit.jupiter + junit-jupiter-engine + + + diff --git a/driver/src/main/java/com/microsoft/playwright/impl/DriverJar.java b/driver/src/main/java/com/microsoft/playwright/impl/DriverJar.java new file mode 100644 index 00000000..1365cedc --- /dev/null +++ b/driver/src/main/java/com/microsoft/playwright/impl/DriverJar.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.microsoft.playwright.impl; + +import com.microsoft.playwright.PlaywrightException; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +class DriverJar extends Driver { + private final Path driverTempDir; + + DriverJar() throws IOException, URISyntaxException, InterruptedException { + driverTempDir = Files.createTempDirectory("playwright-java-"); + driverTempDir.toFile().deleteOnExit(); + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + Path path = Paths.get(classloader.getResource("driver").toURI()); + Files.list(path).forEach(filePath -> { + try { + extractResource(filePath, driverTempDir); + } catch (IOException e) { + throw new PlaywrightException("Failed to extract driver from " + path, e); + } + }); + + Path driver = driverTempDir.resolve("playwright-cli"); + ProcessBuilder pb = new ProcessBuilder(driver.toString(), "install"); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); + Process p = pb.start(); + boolean result = p.waitFor(10, TimeUnit.MINUTES); + if (!result) { + System.err.println("Timed out waiting for browsers to install"); + } + } + + private static Path extractResource(Path from, Path toDir) throws IOException { + Path path = toDir.resolve(from.getFileName()); + Files.copy(from, path); + path.toFile().setExecutable(true); + path.toFile().deleteOnExit(); +// System.out.println("extracting: " + from.toString() + " to " + path.toString()); + return path; + } + + @Override + Path driverDir() { + return driverTempDir; + } +} diff --git a/playwright/src/main/resources/.gitignore b/driver/src/main/resources/.gitignore similarity index 100% rename from playwright/src/main/resources/.gitignore rename to driver/src/main/resources/.gitignore diff --git a/driver/src/test/java/com/microsoft/playwright/TestLaunch.java b/driver/src/test/java/com/microsoft/playwright/TestLaunch.java new file mode 100644 index 00000000..e2808e5a --- /dev/null +++ b/driver/src/test/java/com/microsoft/playwright/TestLaunch.java @@ -0,0 +1,51 @@ +package com.microsoft.playwright;/* + * Copyright (c) Microsoft Corporation. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.junit.jupiter.api.Test; + +public class TestLaunch { + @Test + void launchBrowser() throws Exception { + // Clear system property to ensure that the driver is loaded from jar. + System.clearProperty("playwright.cli.dir"); + Playwright playwright = Playwright.create(); + String browserName = System.getenv("BROWSER"); + if (browserName == null) { + browserName = "chromium"; + } + BrowserType browserType; + switch (browserName) { + case "webkit": + browserType = playwright.webkit(); + break; + case "firefox": + browserType = playwright.firefox(); + break; + case "chromium": + browserType = playwright.chromium(); + break; + default: + throw new IllegalArgumentException("Unknown browser: " + browserName); + } + String headfulEnv = System.getenv("HEADFUL"); + boolean headful = headfulEnv != null && !"0".equals(headfulEnv) && !"false".equals(headfulEnv); + BrowserType.LaunchOptions options = new BrowserType.LaunchOptions(); + options.headless = !headful; + Browser browser = browserType.launch(options); + browser.close(); + playwright.close(); + } +} diff --git a/playwright/pom.xml b/playwright/pom.xml index d75c7a3c..734528db 100644 --- a/playwright/pom.xml +++ b/playwright/pom.xml @@ -27,6 +27,11 @@ org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5 + + + ${project.parent.basedir}/driver/src/main/resources/driver + + diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Driver.java b/playwright/src/main/java/com/microsoft/playwright/impl/Driver.java new file mode 100644 index 00000000..2d4103c2 --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Driver.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.microsoft.playwright.impl; + +import com.microsoft.playwright.PlaywrightException; + +import java.nio.file.Path; +import java.nio.file.Paths; + +abstract class Driver { + private static Driver instance; + + private static class PreinstalledDriver extends Driver { + private final Path driverDir; + PreinstalledDriver(Path driverDir) { + this.driverDir = driverDir; + } + @Override + Path driverDir() { + return driverDir; + } + } + + static synchronized Path ensureDriverInstalled() { + if (instance == null) { + try { + instance = createDriver(); + } catch (Exception exception) { + throw new PlaywrightException("Failed to find playwright-cli", exception); + } + } + return instance.driverDir().resolve("playwright-cli"); + } + + private static Driver createDriver() throws Exception { + String pathFromProperty = System.getProperty("playwright.cli.dir"); + if (pathFromProperty != null) { + return new PreinstalledDriver(Paths.get(pathFromProperty)); + } + + Class jarDriver = Class.forName("com.microsoft.playwright.impl.DriverJar"); + return (Driver) jarDriver.getDeclaredConstructor().newInstance(); + } + + abstract Path driverDir(); +} diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/PlaywrightImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/PlaywrightImpl.java index 6ecfc8d5..4a0d91f2 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/PlaywrightImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/PlaywrightImpl.java @@ -25,21 +25,17 @@ import com.microsoft.playwright.PlaywrightException; import com.microsoft.playwright.Selectors; import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class PlaywrightImpl extends ChannelOwner implements Playwright { - private static Path driverTempDir; private Process driverProcess; public static PlaywrightImpl create() { try { - Path driver = ensureDriverInstalled(); + Path driver = Driver.ensureDriverInstalled(); ProcessBuilder pb = new ProcessBuilder(driver.toString(), "run-driver"); pb.redirectError(ProcessBuilder.Redirect.INHERIT); // pb.environment().put("DEBUG", "pw:pro*"); @@ -48,47 +44,11 @@ public class PlaywrightImpl extends ChannelOwner implements Playwright { PlaywrightImpl result = (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright"); result.driverProcess = p; return result; - } catch (IOException | InterruptedException | URISyntaxException e) { + } catch (IOException e) { throw new PlaywrightException("Failed to launch driver", e); } } - private static synchronized Path ensureDriverInstalled() throws IOException, InterruptedException, URISyntaxException { - if (driverTempDir == null) { - driverTempDir = Files.createTempDirectory("playwright-java-"); - driverTempDir.toFile().deleteOnExit(); - ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - Path path = Paths.get(classloader.getResource("driver").toURI()); - Files.list(path).forEach(filePath -> { - try { - extractResource(filePath, driverTempDir); - } catch (IOException e) { - throw new PlaywrightException("Failed to extract driver from " + path, e); - } - }); - - Path driver = driverTempDir.resolve("playwright-cli"); - ProcessBuilder pb = new ProcessBuilder(driver.toString(), "install"); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); - Process p = pb.start(); - boolean result = p.waitFor(10, TimeUnit.MINUTES); - if (!result) { - System.err.println("Timed out waiting for browsers to install"); - } - } - return driverTempDir.resolve("playwright-cli"); - } - - private static Path extractResource(Path from, Path toDir) throws IOException { - Path path = toDir.resolve(from.getFileName()); - Files.copy(from, path); - path.toFile().setExecutable(true); - path.toFile().deleteOnExit(); -// System.out.println("extracting: " + from.toString() + " to " + path.toString()); - return path; - } - private final BrowserTypeImpl chromium; private final BrowserTypeImpl firefox; private final BrowserTypeImpl webkit; diff --git a/pom.xml b/pom.xml index 68b91ce3..f14ceedf 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,9 @@ Playwright Java - playwright - api-generator + playwright + api-generator + driver diff --git a/scripts/download_driver.sh b/scripts/download_driver.sh index e5bad437..854a2504 100755 --- a/scripts/download_driver.sh +++ b/scripts/download_driver.sh @@ -8,7 +8,7 @@ FILE_PREFIX=playwright-cli-0.170.0-next.1605573954344 trap "cd $(pwd -P)" EXIT cd "$(dirname $0)" -cd ../playwright/src/main/resources +cd ../driver/src/main/resources if [[ -d driver ]]; then echo "$(pwd)/driver already exists, delete it first" exit 1;