feat(driver): extract driver into temp folder when running playwright (#74)

This commit is contained in:
Yury Semikhatsky 2020-11-16 22:58:59 -08:00 committed by GitHub
parent eeb8bd16c9
commit 6676cdd5b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 43 deletions

View File

@ -20,27 +20,9 @@ jobs:
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 1.8 java-version: 1.8
- run: mkdir -p driver
- name: Install driver - name: Install driver
working-directory: driver
env:
OS: ${{ matrix.os }}
shell: bash shell: bash
run: | run: scripts/download_driver.sh
FILE_NAME="unkwnown"
if [[ $OS == *"ubuntu"* ]]; then
FILE_NAME=playwright-cli-0.160.0-next.1604357190081-linux.zip
fi
if [[ $OS == *"macos"* ]]; then
FILE_NAME=playwright-cli-0.160.0-next.1604357190081-mac.zip
fi
if [[ $OS == *"windows"* ]]; then
FILE_NAME=playwright-cli-0.160.0-next.1604357190081-win32_x64.zip
fi
echo "Downloading from $FILE_NAME"
curl -O https://playwright.azureedge.net/builds/cli/next/$FILE_NAME
unzip $FILE_NAME -d .
./playwright-cli install
- name: Build with Maven - name: Build with Maven
run: mvn -B package -D skipTests --no-transfer-progress run: mvn -B package -D skipTests --no-transfer-progress
- name: Run tests - name: Run tests

View File

@ -11,17 +11,11 @@ git clone https://github.com/microsoft/playwright-java
cd playwright-java cd playwright-java
``` ```
2. Download playwright-cli binary package into `driver/` directory and run `install` command. It will 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 `playwright/src/main/resources/driver/` directory. It will also install Playwright and download browser binaries for Chromium, Firefox and WebKit.
```bash ```bash
mkdir driver scripts/download_driver.sh
cd driver
FILENAME=playwright-cli-0.160.0-next.1604373941495-linux.zip
curl -O https://playwright.azureedge.net/builds/cli/next/${FILENAME}
unzip ${FILENAME} -d .
./playwright-cli install
``` ```
Replace `-linux.zip` in the file name with `-win32_x64.zip` or `-mac.zip` for other platforms.
Names of published driver archives can be found at https://github.com/microsoft/playwright-cli/actions Names of published driver archives can be found at https://github.com/microsoft/playwright-cli/actions

View File

@ -20,6 +20,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.microsoft.playwright.PlaywrightException; import com.microsoft.playwright.PlaywrightException;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.time.Duration; import java.time.Duration;
@ -68,6 +69,10 @@ public class Connection {
root = new Root(this); root = new Root(this);
} }
void close() throws IOException {
transport.close();
}
public JsonElement sendMessage(String guid, String method, JsonObject params) { public JsonElement sendMessage(String guid, String method, JsonObject params) {
return (JsonElement) root.toDeferred(sendMessageAsync(guid, method, params)).get(); return (JsonElement) root.toDeferred(sendMessageAsync(guid, method, params)).get();
} }

View File

@ -17,34 +17,68 @@
package com.microsoft.playwright.impl; package com.microsoft.playwright.impl;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.microsoft.playwright.*; import com.microsoft.playwright.DeviceDescriptor;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.PlaywrightException;
import com.microsoft.playwright.Selectors;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileSystems; import java.net.URISyntaxException;
import java.util.HashMap; import java.nio.file.Files;
import java.util.Map; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
public class PlaywrightImpl extends ChannelOwner implements Playwright { public class PlaywrightImpl extends ChannelOwner implements Playwright {
private static Path driverTempDir;
public static PlaywrightImpl create() { public static PlaywrightImpl create() {
try { try {
File cwd = FileSystems.getDefault().getPath(".").toFile(); Path driver = ensureDriverExtracted();
File driver = new File(cwd, "../driver/playwright-cli"); ProcessBuilder pb = new ProcessBuilder(driver.toString(), "run-driver");
ProcessBuilder pb = new ProcessBuilder(driver.getCanonicalPath(), "run-driver");
pb.redirectError(ProcessBuilder.Redirect.INHERIT); pb.redirectError(ProcessBuilder.Redirect.INHERIT);
// pb.environment().put("DEBUG", "pw:pro*"); // pb.environment().put("DEBUG", "pw:pro*");
Process p = pb.start(); Process p = pb.start();
Connection connection = new Connection(p.getInputStream(), p.getOutputStream()); Connection connection = new Connection(p.getInputStream(), p.getOutputStream());
PlaywrightImpl playwright = (PlaywrightImpl)connection.waitForObjectWithKnownName("Playwright"); return (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright");
return playwright;
} catch (IOException e) { } catch (IOException e) {
throw new PlaywrightException("Failed to launch driver", e); throw new PlaywrightException("Failed to launch driver", e);
} }
} }
private static Path ensureDriverExtracted() {
if (driverTempDir == null) {
try {
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 RuntimeException("Failed to extract driver from " + path, e);
}
});
} catch (IOException | URISyntaxException e) {
throw new PlaywrightException("Failed to launch driver", e);
}
}
// TODO: remove dir on exit
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 chromium;
private final BrowserTypeImpl firefox; private final BrowserTypeImpl firefox;
private final BrowserTypeImpl webkit; private final BrowserTypeImpl webkit;
@ -91,4 +125,12 @@ public class PlaywrightImpl extends ChannelOwner implements Playwright {
public Selectors selectors() { public Selectors selectors() {
return selectors; return selectors;
} }
public void close() {
try {
connection.close();
} catch (IOException e) {
throw new PlaywrightException("Failed to close", e);
}
}
} }

View File

@ -31,17 +31,21 @@ public class Transport {
private final ReaderThread readerThread; private final ReaderThread readerThread;
private final WriterThread writerThread; private final WriterThread writerThread;
private boolean isClosed;
Transport(InputStream input, OutputStream output) { Transport(InputStream input, OutputStream output) {
DataInputStream in = new DataInputStream(new BufferedInputStream(input)); DataInputStream in = new DataInputStream(new BufferedInputStream(input));
readerThread = new ReaderThread(in, incoming); readerThread = new ReaderThread(in, incoming);
readerThread.start(); readerThread.start();
// TODO: buffer?
DataOutputStream out = new DataOutputStream(output); DataOutputStream out = new DataOutputStream(output);
writerThread = new WriterThread(out, outgoing); writerThread = new WriterThread(out, outgoing);
writerThread.start(); writerThread.start();
} }
public void send(String message) { public void send(String message) {
if (isClosed) {
throw new PlaywrightException("Playwright connection closed");
}
try { try {
outgoing.put(message); outgoing.put(message);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -50,16 +54,30 @@ public class Transport {
} }
public String poll(Duration timeout) { public String poll(Duration timeout) {
if (isClosed) {
throw new PlaywrightException("Playwright connection closed");
}
try { try {
return incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS); return incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new PlaywrightException("Failed to read message", e); throw new PlaywrightException("Failed to read message", e);
} }
} }
void close() throws IOException {
if (isClosed) {
return;
}
isClosed = true;
readerThread.interrupt();
readerThread.in.close();
writerThread.interrupt();
writerThread.out.close();
}
} }
class ReaderThread extends Thread { class ReaderThread extends Thread {
private final DataInputStream in; final DataInputStream in;
private final BlockingQueue<String> queue; private final BlockingQueue<String> queue;
private static int readIntLE(DataInputStream in) throws IOException { private static int readIntLE(DataInputStream in) throws IOException {
@ -85,6 +103,7 @@ class ReaderThread extends Thread {
try { try {
queue.put(readMessage()); queue.put(readMessage());
} catch (IOException e) { } catch (IOException e) {
if (!isInterrupted())
e.printStackTrace(); e.printStackTrace();
break; break;
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -102,7 +121,7 @@ class ReaderThread extends Thread {
} }
class WriterThread extends Thread { class WriterThread extends Thread {
private final DataOutputStream out; final DataOutputStream out;
private final BlockingQueue<String> queue; private final BlockingQueue<String> queue;
private static void writeIntLE(DataOutputStream out, int v) throws IOException { private static void writeIntLE(DataOutputStream out, int v) throws IOException {
@ -125,6 +144,7 @@ class WriterThread extends Thread {
out.flush(); out.flush();
sendMessage(queue.take()); sendMessage(queue.take());
} catch (IOException e) { } catch (IOException e) {
if (!isInterrupted())
e.printStackTrace(); e.printStackTrace();
break; break;
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@ -0,0 +1 @@
driver/

44
scripts/download_driver.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
set -e
set +x
FILE_PREFIX=playwright-cli-0.160.0-next.1604373941495
trap "cd $(pwd -P)" EXIT
cd "$(dirname $0)"
cd ../playwright/src/main/resources
if [[ -d driver ]]; then
echo "$(pwd)/driver already exists, delete it first"
exit 1;
fi
mkdir driver
cd driver
echo "Created directory: $(pwd)"
FILE_NAME="unknown"
case $(uname) in
Darwin)
FILE_NAME=${FILE_PREFIX}-mac.zip
echo "Downloading driver for macOS"
;;
Linux)
FILE_NAME=${FILE_PREFIX}-linux.zip
echo "Downloading driver for Linux"
;;
MINGW*)
FILE_NAME=${FILE_PREFIX}-win32_x64.zip
echo "Downloading driver for Windows"
;;
*)
echo "Unknown platform '$(uname)'"
exit 1;
;;
esac
curl -O https://playwright.azureedge.net/builds/cli/next/${FILE_NAME}
unzip ${FILE_NAME} -d .
rm $FILE_NAME
./playwright-cli install