Add java sources and projects
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
*.zip
|
||||
*.tar.gz
|
||||
|
||||
# Maven output dir
|
||||
target/
|
||||
|
||||
.DS_Store
|
||||
*.swp
|
||||
.vscode
|
||||
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
Generated
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="api-generator" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+14
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.microsoft</groupId>
|
||||
<artifactId>api-generator</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* 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.tools;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ApiGenerator {
|
||||
private List<String> output;
|
||||
private Set<String> innerTypes;
|
||||
|
||||
private static Map<String, String> tsToJavaMethodName = new HashMap<>();
|
||||
static {
|
||||
tsToJavaMethodName.put("continue", "continue_");
|
||||
tsToJavaMethodName.put("$eval", "evalOnSelector");
|
||||
tsToJavaMethodName.put("$$eval", "evalOnSelectorAll");
|
||||
tsToJavaMethodName.put("$", "querySelector");
|
||||
tsToJavaMethodName.put("$$", "querySelectorAll");
|
||||
tsToJavaMethodName.put("goto", "navigate");
|
||||
}
|
||||
|
||||
private static String header = "/**\n" +
|
||||
" * Copyright (c) Microsoft Corporation.\n" +
|
||||
" *\n" +
|
||||
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
|
||||
" * you may not use this file except in compliance with the License.\n" +
|
||||
" * You may obtain a copy of the License at\n" +
|
||||
" *\n" +
|
||||
" * http://www.apache.org/licenses/LICENSE-2.0\n" +
|
||||
" *\n" +
|
||||
" * Unless required by applicable law or agreed to in writing, software\n" +
|
||||
" * distributed under the License is distributed on an \"AS IS\" BASIS,\n" +
|
||||
" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
|
||||
" * See the License for the specific language governing permissions and\n" +
|
||||
" * limitations under the License.\n" +
|
||||
" */\n" +
|
||||
"\n" +
|
||||
"package com.microsoft.playwright;\n";
|
||||
|
||||
ApiGenerator(Reader reader) throws IOException {
|
||||
JsonObject api = new Gson().fromJson(reader, JsonObject.class);
|
||||
File cwd = FileSystems.getDefault().getPath(".").toFile();
|
||||
File dir = new File(cwd, "../lib/src/main/java/com/microsoft/playwright");
|
||||
System.out.println("Writing files to: " + dir.getCanonicalPath());
|
||||
dir.mkdirs();
|
||||
for (Map.Entry<String, JsonElement> entry: api.entrySet()) {
|
||||
innerTypes = new HashSet<>();
|
||||
output = new ArrayList<>();
|
||||
String name = entry.getKey();
|
||||
output.add(header);
|
||||
output.add("import java.util.*;");
|
||||
output.add("import java.util.function.BiConsumer;");
|
||||
output.add("");
|
||||
output.add("interface " + name + "{");
|
||||
generateInterface(entry.getValue().getAsJsonObject(), " ");
|
||||
output.add("}");
|
||||
output.add("\n");
|
||||
|
||||
String text = String.join("\n", output);
|
||||
FileWriter writer = new FileWriter(new File(dir, name + ".java"));
|
||||
writer.write(text);
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInterface(JsonObject docClass, String offset) {
|
||||
JsonObject members = docClass.get("members").getAsJsonObject();
|
||||
for (Map.Entry<String, JsonElement> m : members.entrySet())
|
||||
generateMember(m.getValue().getAsJsonObject(), offset);
|
||||
}
|
||||
|
||||
private void generateMember(JsonObject docMember, String offset) {
|
||||
String kind = docMember.get("kind").getAsString();
|
||||
String name = docMember.get("name").getAsString();
|
||||
if ("method".equals(kind)) {
|
||||
String type = convertReturnType(docMember.get("type"));
|
||||
|
||||
StringBuilder args = new StringBuilder();
|
||||
if (docMember.get("args") != null) {
|
||||
for (Map.Entry<String, JsonElement> arg : docMember.get("args").getAsJsonObject().entrySet()) {
|
||||
String argName = arg.getKey();
|
||||
String argType = arg.getValue().getAsJsonObject().get("type").getAsJsonObject().get("name").getAsString();
|
||||
argType = convertBuiltinType(argType);
|
||||
if (argType.equals("Object")) {
|
||||
argType = generateParamClass(name, argName, arg.getValue().getAsJsonObject().get("type").getAsJsonObject(), offset);
|
||||
}
|
||||
|
||||
if (argType.equals("function(Route, Request)")) {
|
||||
argType = "BiConsumer<Route, Request>";
|
||||
} else if (argType.equals("EvaluationArgument")) {
|
||||
argType = "Object";
|
||||
} else if (argType.equals("number")) {
|
||||
argType = "int";
|
||||
} else if (argType.contains("|\"")) {
|
||||
String enumName = enumName(name, argName);
|
||||
generateEnum(enumName, argType, "", offset);
|
||||
argType = enumName;
|
||||
} else if (argType.contains("|")) {
|
||||
argType = "String";
|
||||
} else if (argType.contains("function")) {
|
||||
// js functions are always passed as text in java.
|
||||
if (argName.startsWith("playwright") || argName.startsWith("page")) {
|
||||
argType = "String";
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length() > 0) {
|
||||
args.append(", ");
|
||||
}
|
||||
args.append(argType).append(" ").append(argName);
|
||||
}
|
||||
}
|
||||
|
||||
if (tsToJavaMethodName.containsKey(name))
|
||||
name = tsToJavaMethodName.get(name);
|
||||
output.add(offset + type + " " + name + "(" + args + ");");
|
||||
}
|
||||
}
|
||||
|
||||
private String generateParamClass(String methodName, String argName, JsonObject json, String offset) {
|
||||
String className = toTitle(methodName) + toTitle(argName);
|
||||
output.add("");
|
||||
output.add(offset + "class " + className + " {");
|
||||
String memberOffset = offset + " ";
|
||||
for (Map.Entry<String, JsonElement> e : json.get("properties").getAsJsonObject().entrySet()) {
|
||||
String name = e.getKey();
|
||||
String type = e.getValue().getAsJsonObject().get("type").getAsJsonObject().get("name").getAsString();
|
||||
if ("modifiers".equals(name)) {
|
||||
if (!type.equals("Array<\"Alt\"|\"Control\"|\"Meta\"|\"Shift\">"))
|
||||
throw new RuntimeException("Unexpected type of modifiers: " + type);
|
||||
generateEnum("Modifier", "\"Alt\"|\"Control\"|\"Meta\"|\"Shift\"", className, memberOffset);
|
||||
type = "Set<Modifier>";
|
||||
}
|
||||
if ("media".equals(name)) {
|
||||
if (!type.equals("null|\"print\"|\"screen\""))
|
||||
throw new RuntimeException("Unexpected type of media: " + type);
|
||||
type = "Media";
|
||||
generateEnum(type, "\"print\"|\"screen\"", className, memberOffset);
|
||||
}
|
||||
if ("pdf".equals(methodName) && (name.equals("width") || name.equals("height"))) {
|
||||
if (!type.equals("string|number"))
|
||||
throw new RuntimeException("Unexpected type of pdf dimensions: " + type);
|
||||
type = "String";
|
||||
}
|
||||
if ("continue".equals(methodName) && name.equals("postData")) {
|
||||
if (!type.equals("string|Buffer"))
|
||||
throw new RuntimeException("Unexpected type of pdf dimensions: " + type);
|
||||
type = "String";
|
||||
}
|
||||
if ("fulfill".equals(methodName) && name.equals("body")) {
|
||||
if (!type.equals("string|Buffer"))
|
||||
throw new RuntimeException("Unexpected type of pdf dimensions: " + type);
|
||||
type = "String";
|
||||
}
|
||||
if ("waitForNavigation".equals(methodName) && argName.equals("options") && name.equals("url")) {
|
||||
if (!type.equals("string|RegExp|Function"))
|
||||
throw new RuntimeException("Unexpected type of pdf dimensions: " + type);
|
||||
type = "String";
|
||||
}
|
||||
if (type.contains("|\"") && type.endsWith("\"")) {
|
||||
type = type.replace("null|", "");
|
||||
String enumName = toTitle(name);
|
||||
generateEnum(enumName, type, className, memberOffset);
|
||||
type = enumName;
|
||||
}
|
||||
if ("ignoreDefaultArgs".equals(name)) {
|
||||
type = "Boolean";
|
||||
}
|
||||
type = convertBuiltinType(type);
|
||||
type = replacePrimitiveWithBoxedType(type);
|
||||
output.add(memberOffset + type + " " + name + ";");
|
||||
}
|
||||
output.add(offset + "}");
|
||||
return className;
|
||||
}
|
||||
|
||||
private static String toTitle(String name) {
|
||||
return Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||
}
|
||||
|
||||
private static String enumName(String methodName, String argName) {
|
||||
if (methodName.startsWith("waitFor")) {
|
||||
return methodName.substring("waitFor".length());
|
||||
}
|
||||
return toTitle(argName);
|
||||
}
|
||||
|
||||
private void generateEnum(String name, String values, String scope, String offset) {
|
||||
if (!innerTypes.add(scope + values)) {
|
||||
return;
|
||||
}
|
||||
String[] split = values.split("\\|");
|
||||
List<String> enumValues = Arrays.stream(split).map(s -> s.substring(1, s.length() - 1).replace("-", "_").toUpperCase()).collect(Collectors.toList());
|
||||
output.add(offset + "enum " + name + " { " + String.join(", ", enumValues) + " }");
|
||||
}
|
||||
|
||||
private static String convertReturnType(JsonElement jsonType) {
|
||||
String type = jsonType.isJsonNull() ? "void" : jsonType.getAsJsonObject().get("name").getAsString();
|
||||
if ("Promise".equals(type)) {
|
||||
type = "void";
|
||||
}
|
||||
// Java API is sync just strip Promise<>
|
||||
if (type.startsWith("Promise<")) {
|
||||
type = type.substring("Promise<".length(), type.length() - 1);
|
||||
}
|
||||
return convertBuiltinType(type);
|
||||
}
|
||||
|
||||
private static String replacePrimitiveWithBoxedType(String type) {
|
||||
return type.replace("int", "Integer")
|
||||
.replace("boolean", "Boolean")
|
||||
.replace("double", "Double");
|
||||
}
|
||||
|
||||
private static String convertBuiltinType(String type) {
|
||||
return type.replace("string|number|boolean", "String")
|
||||
.replace("Array<", "List<")
|
||||
.replace("string", "String")
|
||||
.replace("number", "int")
|
||||
.replace("Serializable", "Object")
|
||||
.replace("Buffer", "byte[]")
|
||||
.replace("ChildProcess", "Object")
|
||||
.replace("Object<", "Map<")
|
||||
.replace("null|", "");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File cwd = FileSystems.getDefault().getPath(".").toFile();
|
||||
System.out.println(cwd.getCanonicalPath());
|
||||
File file = new File(cwd, "src/main/resources/api.json");
|
||||
System.out.println("Reading from: " + file.getCanonicalPath());
|
||||
new ApiGenerator(new FileReader(file));
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
/node_modules/
|
||||
.DS_Store
|
||||
*.swp
|
||||
.vscode
|
||||
package-lock.json
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
require('playwright/lib/server');
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "driver",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "^1.4.2"
|
||||
}
|
||||
}
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
Generated
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="lib" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+14
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4" />
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.microsoft</groupId>
|
||||
<artifactId>playwright</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class Browser extends ChannelOwner {
|
||||
Browser(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
BrowserContext newContext() {
|
||||
return newContext(new BrowserNewContextOptions());
|
||||
}
|
||||
|
||||
BrowserContext newContext(BrowserNewContextOptions options) {
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
JsonElement result = sendMessage("newContext", params);
|
||||
return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("context").get("guid").getAsString());
|
||||
}
|
||||
|
||||
void close() {
|
||||
sendMessage("close", new JsonObject());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BrowserContext extends ChannelOwner {
|
||||
protected BrowserContext(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
Page newPage() {
|
||||
JsonObject params = new JsonObject();
|
||||
JsonElement result = sendMessage("newPage", params);
|
||||
return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("page").get("guid").getAsString());
|
||||
}
|
||||
|
||||
public Supplier<Page> waitForPage() {
|
||||
Supplier<JsonObject> pageSupplier = waitForEvent("page");
|
||||
return () -> {
|
||||
JsonObject params = pageSupplier.get();
|
||||
String guid = params.getAsJsonObject("page").get("guid").getAsString();
|
||||
return connection.getExistingObject(guid);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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 java.util.LinkedHashMap;
|
||||
|
||||
public class BrowserNewContextOptions {
|
||||
Boolean noDefaultViewport;
|
||||
public static class Viewport {
|
||||
// TODO: int is preferred here
|
||||
int width;
|
||||
int height;
|
||||
}
|
||||
Viewport viewport;
|
||||
Boolean ignoreHTTPSErrors;
|
||||
Boolean javaScriptEnabled;
|
||||
Boolean bypassCSP;
|
||||
String userAgent;
|
||||
String locale;
|
||||
String timezoneId;
|
||||
public static class Geolocation {
|
||||
// TODO: can we use int somehow?
|
||||
Double longitude;
|
||||
Double latitude;
|
||||
Double accuracy;
|
||||
};
|
||||
Geolocation geolocation;
|
||||
String[] permissions;
|
||||
LinkedHashMap<String, String> extraHTTPHeaders;
|
||||
Boolean offline;
|
||||
public static class HttpCredentials {
|
||||
String username;
|
||||
String password;
|
||||
}
|
||||
HttpCredentials httpCredentials;
|
||||
Integer deviceScaleFactor;
|
||||
Boolean isMobile;
|
||||
Boolean hasTouch;
|
||||
enum ColorScheme {
|
||||
// TODO: noPreference => no-preference
|
||||
dark, light, noPreference
|
||||
}
|
||||
ColorScheme colorScheme;
|
||||
Boolean acceptDownloads;
|
||||
Boolean _recordVideos;
|
||||
public static class _VideoSize {
|
||||
int width;
|
||||
int height;
|
||||
}
|
||||
_VideoSize _videoSize;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class BrowserType extends ChannelOwner {
|
||||
BrowserType(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
public String executablePath() {
|
||||
return initializer.get("executablePath").getAsString();
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return initializer.get("name").getAsString();
|
||||
}
|
||||
|
||||
Browser launch() {
|
||||
return launch(new BrowserTypeLaunchOptions());
|
||||
}
|
||||
Browser launch(BrowserTypeLaunchOptions options) {
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
JsonElement result = sendMessage("launch", params);
|
||||
return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("browser").get("guid").getAsString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.google.gson.JsonObject;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class BrowserTypeLaunchOptions {
|
||||
String executablePath;
|
||||
String[] args;
|
||||
Boolean ignoreAllDefaultArgs;
|
||||
String[] ignoreDefaultArgs;
|
||||
Boolean handleSIGINT;
|
||||
Boolean handleSIGTERM;
|
||||
Boolean handleSIGHUP;
|
||||
Integer timeout;
|
||||
LinkedHashMap<String, String> env;
|
||||
Boolean headless;
|
||||
Boolean devtools;
|
||||
public static class Proxy {
|
||||
String server;
|
||||
String bypass;
|
||||
String username;
|
||||
String password;
|
||||
}
|
||||
Proxy proxy;
|
||||
String downloadsPath;
|
||||
String _videosPath;
|
||||
JsonObject firefoxUserPrefs;
|
||||
Boolean chromiumSandbox;
|
||||
Integer slowMo;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class ChannelOwner {
|
||||
final Connection connection;
|
||||
private final ChannelOwner parent;
|
||||
private final Map<String, ChannelOwner> objects = new HashMap();
|
||||
|
||||
final String type;
|
||||
final String guid;
|
||||
// private T channel;
|
||||
final JsonObject initializer;
|
||||
|
||||
Map<String, ArrayList<CompletableFuture<JsonObject>>> futureEvents = new HashMap<>();
|
||||
|
||||
protected ChannelOwner(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
this(parent.connection, parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
protected ChannelOwner(Connection connection, String type, String guid) {
|
||||
this(connection, null, type, guid, new JsonObject());
|
||||
}
|
||||
|
||||
|
||||
private ChannelOwner(Connection connection, ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
this.connection = connection;
|
||||
this.parent = parent;
|
||||
this.type = type;
|
||||
this.guid = guid;
|
||||
this.initializer = initializer;
|
||||
|
||||
connection.registerObject(guid, this);
|
||||
if (parent != null)
|
||||
parent.objects.put(guid, this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
JsonElement sendMessage(String method, JsonObject params) {
|
||||
return connection.sendMessage(guid, method, params);
|
||||
}
|
||||
|
||||
void sendMessageNoWait(String method, JsonObject params) {
|
||||
connection.sendMessageNoWait(guid, method, params);
|
||||
}
|
||||
|
||||
protected Supplier<JsonObject> waitForEvent(String event) {
|
||||
ArrayList<CompletableFuture<JsonObject>> futures = futureEvents.get(event);
|
||||
if (futures == null) {
|
||||
futures = new ArrayList<>();
|
||||
futureEvents.put(event, futures);
|
||||
}
|
||||
CompletableFuture<JsonObject> result = new CompletableFuture<>();
|
||||
futures.add(result);
|
||||
return () -> {
|
||||
while (!result.isDone()) {
|
||||
connection.processOneMessage();
|
||||
}
|
||||
try {
|
||||
return result.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
final void onEvent(String event, JsonObject parameters) {
|
||||
handleEvent(event, parameters);
|
||||
ArrayList<CompletableFuture<JsonObject>> futures = futureEvents.remove(event);
|
||||
if (futures == null)
|
||||
return;
|
||||
for (CompletableFuture<JsonObject> f : futures) {
|
||||
f.complete(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleEvent(String event, JsonObject params) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
class Message {
|
||||
int id;
|
||||
String guid;
|
||||
String method;
|
||||
JsonObject params;
|
||||
JsonElement result;
|
||||
JsonObject error;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Message{" +
|
||||
"id='" + id + '\'' +
|
||||
", guid='" + guid + '\'' +
|
||||
", method='" + method + '\'' +
|
||||
", params=" + (params == null ? null : "<...>") +
|
||||
", result='" + result + '\'' +
|
||||
", error='" + error + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Connection {
|
||||
private final Transport transport;
|
||||
private final Map<String, ChannelOwner> objects = new HashMap();
|
||||
private final Root root;
|
||||
private int lastId = 0;
|
||||
private final Map<Integer, CompletableFuture<Message>> callbacks = new HashMap();
|
||||
|
||||
class Root extends ChannelOwner {
|
||||
Root(Connection connection) {
|
||||
super(connection, "", "");
|
||||
}
|
||||
}
|
||||
|
||||
public Connection(InputStream in, OutputStream out) {
|
||||
transport = new Transport(in, out);
|
||||
root = new Root(this);
|
||||
}
|
||||
|
||||
public JsonElement sendMessage(String guid, String method, JsonObject params) {
|
||||
CompletableFuture<Message> result = internalSendMessage(guid, method, params);
|
||||
while (!result.isDone()) {
|
||||
processOneMessage();
|
||||
}
|
||||
try {
|
||||
return result.get().result;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessageNoWait(String guid, String method, JsonObject params) {
|
||||
internalSendMessage(guid, method, params);
|
||||
}
|
||||
|
||||
private CompletableFuture<Message> internalSendMessage(String guid, String method, JsonObject params) {
|
||||
int id = ++lastId;
|
||||
CompletableFuture<Message> result = new CompletableFuture();
|
||||
callbacks.put(id, result);
|
||||
JsonObject message = new JsonObject();
|
||||
message.addProperty("id", id);
|
||||
message.addProperty("guid", guid);
|
||||
message.addProperty("method", method);
|
||||
message.add("params", params);
|
||||
transport.send(new Gson().toJson(message));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public ChannelOwner waitForObjectWithKnownName(String guid) {
|
||||
while (!objects.containsKey(guid)) {
|
||||
processOneMessage();
|
||||
}
|
||||
return objects.get(guid);
|
||||
}
|
||||
|
||||
public <T> T getExistingObject(String guid) {
|
||||
T result = (T) objects.get(guid);
|
||||
if (result == null)
|
||||
throw new RuntimeException("Object doesn't exist: " + guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
void registerObject(String guid, ChannelOwner object) {
|
||||
objects.put(guid, object);
|
||||
}
|
||||
|
||||
void unregisterObject(String guid, ChannelOwner object) {
|
||||
objects.remove(guid);
|
||||
}
|
||||
|
||||
void processOneMessage() {
|
||||
String messageString = transport.read();
|
||||
Gson gson = new Gson();
|
||||
Message message = gson.fromJson(messageString, Message.class);
|
||||
dispatch(message);
|
||||
}
|
||||
|
||||
private void dispatch(Message message) {
|
||||
// System.out.println("Message: " + message.method + " " + message.id);
|
||||
if (message.id != 0) {
|
||||
CompletableFuture<Message> callback = callbacks.get(message.id);
|
||||
if (callback == null) {
|
||||
throw new RuntimeException("Cannot find command to respond: " + message.id);
|
||||
}
|
||||
callbacks.remove(message.id);
|
||||
// System.out.println("Message: " + message.id + " " + message);
|
||||
if (message.error == null)
|
||||
callback.complete(message);
|
||||
else
|
||||
callback.completeExceptionally(new RuntimeException(message.error.toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: throw?
|
||||
if (message.method == null)
|
||||
return;
|
||||
if (message.method.equals("__create__")) {
|
||||
createRemoteObject(message.guid, message.params);
|
||||
return;
|
||||
}
|
||||
if (message.method.equals("__dispose__")) {
|
||||
ChannelOwner object = objects.get(message.guid);
|
||||
if (object == null)
|
||||
throw new RuntimeException("Cannot find object to dispose: " + message.guid);
|
||||
object.dispose();
|
||||
return;
|
||||
}
|
||||
ChannelOwner object = objects.get(message.guid);
|
||||
if (object == null)
|
||||
throw new RuntimeException("Cannot find object to call " + message.method + ": " + message.guid);
|
||||
// object._channel.emit(message.method, this._replaceGuidsWithChannels(message.params));
|
||||
object.onEvent(message.method, message.params);
|
||||
}
|
||||
|
||||
private ChannelOwner createRemoteObject(String parentGuid, JsonObject params) {
|
||||
String type = params.get("type").getAsString();
|
||||
String guid = params.get("guid").getAsString();
|
||||
|
||||
ChannelOwner parent = objects.get(parentGuid);
|
||||
if (parent == null)
|
||||
throw new RuntimeException("Cannot find parent object " + parentGuid + " to create " + guid);
|
||||
JsonObject initializer = params.getAsJsonObject("initializer");
|
||||
ChannelOwner result = null;
|
||||
// initializer = this._replaceGuidsWithChannels(initializer);
|
||||
switch (type) {
|
||||
case "BrowserType":
|
||||
result = new BrowserType(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Browser":
|
||||
result = new Browser(parent, type, guid, initializer);
|
||||
break;
|
||||
case "BrowserContext":
|
||||
result = new BrowserContext(parent, type, guid, initializer);
|
||||
break;
|
||||
case "ConsoleMessage":
|
||||
result = new ConsoleMessage(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Dialog":
|
||||
result = new Dialog(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Download":
|
||||
result = new Download(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Electron":
|
||||
// result = new Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Frame":
|
||||
result = new Frame(parent, type, guid, initializer);
|
||||
break;
|
||||
case "JSHandle":
|
||||
// result = new JSHandle(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Page":
|
||||
result = new Page(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Playwright":
|
||||
result = new Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Request":
|
||||
result = new Request(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Response":
|
||||
result = new Response(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Selectors":
|
||||
// result = new Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown type " + type);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class ConsoleMessage extends ChannelOwner {
|
||||
public ConsoleMessage(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return initializer.get("type").getAsString();
|
||||
}
|
||||
|
||||
public String text() {
|
||||
return initializer.get("text").getAsString();
|
||||
}
|
||||
|
||||
// args(): JSHandle[] {
|
||||
// return this._initializer.args.map(JSHandle.from);
|
||||
// }
|
||||
|
||||
public static class Location {
|
||||
String url;
|
||||
int lineNumber;
|
||||
int columnNumber;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return url +
|
||||
":" + lineNumber +
|
||||
":" + columnNumber;
|
||||
}
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return new Gson().fromJson(initializer.get("location"), Location.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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.google.gson.JsonObject;
|
||||
|
||||
public class Dialog extends ChannelOwner {
|
||||
private boolean handled;
|
||||
Dialog(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
public void accept(String promptText) {
|
||||
handled = true;
|
||||
JsonObject params = new JsonObject();
|
||||
if (promptText != null)
|
||||
params.addProperty("promptText", promptText);
|
||||
sendMessageNoWait("accept", params);
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
handled = true;
|
||||
sendMessageNoWait("dismiss", new JsonObject());
|
||||
}
|
||||
|
||||
public String defaultValue() {
|
||||
return initializer.get("defaultValue").getAsString();
|
||||
}
|
||||
|
||||
public String message() {
|
||||
return initializer.get("message").getAsString();
|
||||
}
|
||||
|
||||
// public enum Type { Alert, BeforeUnload, Confirm, Prompt }
|
||||
public String type() {
|
||||
return initializer.get("type").getAsString();
|
||||
}
|
||||
|
||||
boolean isHandled() {
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class Download extends ChannelOwner {
|
||||
public Download(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
public String url() {
|
||||
return initializer.get("url").getAsString();
|
||||
}
|
||||
|
||||
public String suggestedFilename() {
|
||||
return initializer.get("suggestedFilename").getAsString();
|
||||
}
|
||||
|
||||
public String path() {
|
||||
JsonObject params = new JsonObject();
|
||||
JsonElement result = sendMessage("path", params);
|
||||
return result.getAsJsonObject().get("path").getAsString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.microsoft.playwright.impl.Helpers.isFunctionBody;
|
||||
|
||||
public class Frame extends ChannelOwner {
|
||||
Page page;
|
||||
|
||||
Frame(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
public Response navigate(String url) {
|
||||
return navigate(url, new NavigateOptions());
|
||||
}
|
||||
|
||||
public Response navigate(String url, NavigateOptions options) {
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
params.addProperty("url", url);
|
||||
JsonElement result = sendMessage("goto", params);
|
||||
System.out.println("result = " + new Gson().toJson(result));
|
||||
return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("response").get("guid").getAsString());
|
||||
}
|
||||
|
||||
public void click(String selector) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
JsonElement result = sendMessage("click", params);
|
||||
}
|
||||
|
||||
private static SerializedValue serializeValue(Object value) {
|
||||
SerializedValue result = new SerializedValue();
|
||||
if (value == null)
|
||||
result.v = "undefined";
|
||||
else if (value instanceof Double) {
|
||||
double d = ((Double) value).doubleValue();
|
||||
if (d == Double.POSITIVE_INFINITY)
|
||||
result.v = "Infinity";
|
||||
else if (d == Double.NEGATIVE_INFINITY)
|
||||
result.v = "-Infinity";
|
||||
else if (d == -0)
|
||||
result.v = "-0";
|
||||
else if (Double.isNaN(d))
|
||||
result.v="NaN";
|
||||
else
|
||||
result.n = d;
|
||||
}
|
||||
// if (value instanceof Date)
|
||||
else if (value instanceof Boolean)
|
||||
result.b = (Boolean) value;
|
||||
else if (value instanceof Integer)
|
||||
result.n = (Integer) value;
|
||||
else if (value instanceof String)
|
||||
result.s = (String) value;
|
||||
else if (value instanceof List) {
|
||||
List<SerializedValue> list = new ArrayList<>();
|
||||
for (Object o : (List) value)
|
||||
list.add(serializeValue(o));
|
||||
result.a = list.toArray(new SerializedValue[0]);
|
||||
} else if (value instanceof Map) {
|
||||
List<SerializedValue.O> list = new ArrayList<>();
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
for (Map.Entry<String, Object> e : map.entrySet()) {
|
||||
SerializedValue.O o = new SerializedValue.O();
|
||||
o.k = e.getKey();
|
||||
o.v = serializeValue(e.getValue());
|
||||
list.add(o);
|
||||
}
|
||||
result.o = list.toArray(new SerializedValue.O[0]);
|
||||
} else
|
||||
throw new RuntimeException("Unsupported type of argument: " + value);
|
||||
return result;
|
||||
}
|
||||
private static SerializedArgument serializeArgument(Object arg) {
|
||||
SerializedArgument result = new SerializedArgument();
|
||||
result.value = serializeValue(arg);
|
||||
result.handles = new Channel[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static <T> T deserialize(SerializedValue value) {
|
||||
if (value.n != null) {
|
||||
if (value.n.doubleValue() == (double) value.n.intValue())
|
||||
return (T) Integer.valueOf(value.n.intValue());
|
||||
return (T) Double.valueOf(value.n.doubleValue());
|
||||
}
|
||||
if (value.b != null)
|
||||
return (T) value.b;
|
||||
if (value.s != null)
|
||||
return (T) value.s;
|
||||
if (value.v != null) {
|
||||
switch (value.v) {
|
||||
case "undefined":
|
||||
return null;
|
||||
case "Infinity":
|
||||
return (T) Double.valueOf(Double.POSITIVE_INFINITY);
|
||||
case "-Infinity":
|
||||
return (T) Double.valueOf(Double.NEGATIVE_INFINITY);
|
||||
case "-0":
|
||||
return (T) Double.valueOf(-0);
|
||||
case "NaN":
|
||||
return (T) Double.valueOf(Double.NaN);
|
||||
default:
|
||||
throw new RuntimeException("Unexpected value: " + value.v);
|
||||
}
|
||||
}
|
||||
if (value.a != null) {
|
||||
List list = new ArrayList();
|
||||
for (SerializedValue v : value.a)
|
||||
list.add(deserialize(v));
|
||||
return (T) list;
|
||||
}
|
||||
if (value.o != null) {
|
||||
Map map = new LinkedHashMap<>();
|
||||
for (SerializedValue.O o : value.o)
|
||||
map.put(o.k, deserialize(o.v));
|
||||
return (T) map;
|
||||
}
|
||||
throw new RuntimeException("Unexpected result: " + new Gson().toJson(value));
|
||||
}
|
||||
|
||||
public <T> T evalTyped(String expression) {
|
||||
JsonElement json = evaluate(expression, null, false);
|
||||
System.out.println("json = " + new Gson().toJson(json));
|
||||
SerializedValue value = new Gson().fromJson(json.getAsJsonObject().get("value"), SerializedValue.class);
|
||||
return deserialize(value);
|
||||
}
|
||||
|
||||
public JsonElement evaluate(String expression, Object arg, boolean forceExpression) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("expression", expression);
|
||||
params.addProperty("world", "main");
|
||||
if (!isFunctionBody(expression))
|
||||
forceExpression = true;
|
||||
params.addProperty("isFunction", !forceExpression);
|
||||
params.add("arg", new Gson().toJsonTree(serializeArgument(arg)));
|
||||
return sendMessage("evaluateExpression", params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
class Helpers {
|
||||
static boolean isFunctionBody(String expression) {
|
||||
expression = expression.trim();
|
||||
return expression.startsWith("function") ||
|
||||
expression.startsWith("async ") ||
|
||||
expression.contains("=>");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
|
||||
Playwright playwright = Playwright.create();
|
||||
BrowserTypeLaunchOptions options = new BrowserTypeLaunchOptions();
|
||||
options.headless = false;
|
||||
// options.slowMo = 1000;
|
||||
System.out.println("options = " + new Gson().toJson(options));
|
||||
Browser browser = playwright.chromium.launch(options);
|
||||
System.out.println("browser = " + browser);
|
||||
|
||||
BrowserNewContextOptions contextOptions = new BrowserNewContextOptions();
|
||||
contextOptions.viewport = new BrowserNewContextOptions.Viewport();
|
||||
contextOptions.viewport.width = 800;
|
||||
contextOptions.viewport.height = 600;
|
||||
BrowserContext context = browser.newContext(contextOptions);
|
||||
Page page = context.newPage();
|
||||
page.navigate("http://example.com");
|
||||
// page.click("text=web browser engine");
|
||||
|
||||
Supplier<Page> popupSupplier = page.waitForPopup();
|
||||
Supplier<Page> pageSupplier = context.waitForPage();
|
||||
page.evaluate("window.open('http://example.com'); 13");
|
||||
{
|
||||
JsonElement r = page.evaluate("function foo(a) { return a + 1; }", 20);
|
||||
System.out.println("r = " + new Gson().toJson(r));
|
||||
}
|
||||
{
|
||||
List<Integer> r = page.evalTyped("function foo() { return [1,2,3]; }");
|
||||
System.out.println("r = " + new Gson().toJson(r));
|
||||
int p = r.get(0).intValue() + 1;
|
||||
}
|
||||
|
||||
{
|
||||
int r = page.evalTyped("function foo() { return 7; }");
|
||||
System.out.println("int r = " + new Gson().toJson(r));
|
||||
}
|
||||
|
||||
{
|
||||
double r = page.evalTyped("function foo() { return 7.2; }");
|
||||
System.out.println("double r = " + new Gson().toJson(r));
|
||||
}
|
||||
|
||||
Page popup = popupSupplier.get();
|
||||
System.out.println("popup = " + popup);
|
||||
Page page2 = pageSupplier.get();
|
||||
System.out.println(page2 == popup);
|
||||
|
||||
|
||||
|
||||
|
||||
page.addDialogHandler(d -> {
|
||||
System.out.println("Got dialog type: " + d.type());
|
||||
System.out.println(" message = " + d.message());
|
||||
d.accept("abc");
|
||||
});
|
||||
page.evaluate("alert('Hi there!')");
|
||||
System.out.println("After alert");
|
||||
|
||||
|
||||
|
||||
page.addConsoleListener(m -> {
|
||||
System.out.println("Got console message type: " + m.type());
|
||||
System.out.println(" text = " + m.text());
|
||||
System.out.println(" location = " + m.location());
|
||||
});
|
||||
page.evaluate("console.log('A message')");
|
||||
|
||||
browser.close();
|
||||
|
||||
// Disconnect and terminate the threads?
|
||||
// playwright.close();
|
||||
System.out.println("\nDONE.");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public class NavigateOptions {
|
||||
Integer timeout;
|
||||
enum WaitUntil {
|
||||
load,
|
||||
domcontentloaded,
|
||||
networkidle
|
||||
}
|
||||
WaitUntil waitUntil = WaitUntil.load;
|
||||
String referer;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class Page extends ChannelOwner {
|
||||
private final Frame mainFrame;
|
||||
private final List<DialogHandler> dialogHandlers = new ArrayList<>();
|
||||
private final List<ConsoleListener> consoleListeners = new ArrayList<>();
|
||||
|
||||
Page(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
mainFrame = connection.getExistingObject(initializer.getAsJsonObject("mainFrame").get("guid").getAsString());
|
||||
mainFrame.page = this;
|
||||
}
|
||||
|
||||
public Response navigate(String url) {
|
||||
return navigate(url, new NavigateOptions());
|
||||
}
|
||||
public Response navigate(String url, NavigateOptions options) {
|
||||
return mainFrame.navigate(url, options);
|
||||
}
|
||||
|
||||
public void click(String selector) {
|
||||
mainFrame.click(selector);
|
||||
}
|
||||
|
||||
public Supplier<Page> waitForPopup() {
|
||||
Supplier<JsonObject> popupSupplier = waitForEvent("popup");
|
||||
return () -> {
|
||||
JsonObject params = popupSupplier.get();
|
||||
String guid = params.getAsJsonObject("page").get("guid").getAsString();
|
||||
return connection.getExistingObject(guid);
|
||||
};
|
||||
}
|
||||
|
||||
public interface DialogHandler {
|
||||
void handle(Dialog d);
|
||||
}
|
||||
|
||||
public void addDialogHandler(DialogHandler handler) {
|
||||
dialogHandlers.add(handler);
|
||||
}
|
||||
|
||||
public void removeDialogHandler(DialogHandler handler) {
|
||||
dialogHandlers.remove(handler);
|
||||
}
|
||||
|
||||
protected void handleEvent(String event, JsonObject params) {
|
||||
if ("dialog".equals(event)) {
|
||||
String guid = params.getAsJsonObject("dialog").get("guid").getAsString();
|
||||
Dialog dialog = connection.getExistingObject(guid);
|
||||
for (DialogHandler handler: new ArrayList<>(dialogHandlers))
|
||||
handler.handle(dialog);
|
||||
// If no action taken dismiss dialog to not hang.
|
||||
if (!dialog.isHandled())
|
||||
dialog.dismiss();
|
||||
} else if ("console".equals(event)) {
|
||||
String guid = params.getAsJsonObject("message").get("guid").getAsString();
|
||||
ConsoleMessage message = connection.getExistingObject(guid);
|
||||
for (ConsoleListener listener: new ArrayList<>(consoleListeners))
|
||||
listener.handle(message);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ConsoleListener {
|
||||
void handle(ConsoleMessage m);
|
||||
}
|
||||
|
||||
public void addConsoleListener(ConsoleListener listener) {
|
||||
consoleListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeConsoleListener(ConsoleListener listener) {
|
||||
consoleListeners.remove(listener);
|
||||
}
|
||||
|
||||
public <T> T evalTyped(String expression) {
|
||||
return mainFrame.evalTyped(expression);
|
||||
}
|
||||
|
||||
public JsonElement evaluate(String expression) {
|
||||
return evaluate(expression, null);
|
||||
}
|
||||
|
||||
public JsonElement evaluate(String expression, Object arg) {
|
||||
return evaluate(expression, arg, false);
|
||||
}
|
||||
|
||||
public JsonElement evaluate(String expression, Object arg, boolean forceExpression) {
|
||||
return mainFrame.evaluate(expression, arg, forceExpression);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.google.gson.JsonObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
|
||||
public class Playwright extends ChannelOwner {
|
||||
static Playwright create() throws IOException {
|
||||
File cwd = FileSystems.getDefault().getPath(".").toFile();
|
||||
File driver = new File(cwd, "../driver/main.js");
|
||||
System.out.println("driver = " + driver.getCanonicalPath());
|
||||
ProcessBuilder pb = new ProcessBuilder("node", driver.getCanonicalPath());
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
// pb.environment().put("DEBUG", "pw:pro*");
|
||||
Process p = pb.start();
|
||||
Connection connection = new Connection(p.getInputStream(), p.getOutputStream());
|
||||
Playwright playwright = (Playwright)connection.waitForObjectWithKnownName("Playwright");
|
||||
return playwright;
|
||||
}
|
||||
|
||||
public final BrowserType chromium;
|
||||
public final BrowserType firefox;
|
||||
public final BrowserType webkit;
|
||||
|
||||
public Playwright(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
chromium = parent.connection.getExistingObject(initializer.getAsJsonObject("chromium").get("guid").getAsString());
|
||||
firefox = parent.connection.getExistingObject(initializer.getAsJsonObject("firefox").get("guid").getAsString());
|
||||
webkit = parent.connection.getExistingObject(initializer.getAsJsonObject("webkit").get("guid").getAsString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file is generated by generate_java_rpc.js, do not edit manually.
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
class Binary {
|
||||
}
|
||||
|
||||
class Channel {
|
||||
}
|
||||
|
||||
class Metadata{
|
||||
String stack;
|
||||
}
|
||||
|
||||
|
||||
class SerializedValue{
|
||||
Number n;
|
||||
Boolean b;
|
||||
String s;
|
||||
// Possible values: { 'null, 'undefined, 'NaN, 'Infinity, '-Infinity, '-0 }
|
||||
String v;
|
||||
String d;
|
||||
public static class R {
|
||||
String p;
|
||||
String f;
|
||||
}
|
||||
R r;
|
||||
SerializedValue[] a;
|
||||
public static class O {
|
||||
String k;
|
||||
SerializedValue v;
|
||||
}
|
||||
O[] o;
|
||||
Number h;
|
||||
}
|
||||
|
||||
|
||||
class SerializedArgument{
|
||||
SerializedValue value;
|
||||
Channel[] handles;
|
||||
}
|
||||
|
||||
|
||||
class AXNode{
|
||||
String role;
|
||||
String name;
|
||||
String valueString;
|
||||
Number valueNumber;
|
||||
String description;
|
||||
String keyshortcuts;
|
||||
String roledescription;
|
||||
String valuetext;
|
||||
Boolean disabled;
|
||||
Boolean expanded;
|
||||
Boolean focused;
|
||||
Boolean modal;
|
||||
Boolean multiline;
|
||||
Boolean multiselectable;
|
||||
Boolean readonly;
|
||||
Boolean required;
|
||||
Boolean selected;
|
||||
// Possible values: { 'checked, 'unchecked, 'mixed }
|
||||
String checked;
|
||||
// Possible values: { 'pressed, 'released, 'mixed }
|
||||
String pressed;
|
||||
Number level;
|
||||
Number valuemin;
|
||||
Number valuemax;
|
||||
String autocomplete;
|
||||
String haspopup;
|
||||
String invalid;
|
||||
String orientation;
|
||||
AXNode[] children;
|
||||
}
|
||||
|
||||
|
||||
class SerializedError{
|
||||
public static class Error {
|
||||
String message;
|
||||
String name;
|
||||
String stack;
|
||||
}
|
||||
Error error;
|
||||
SerializedValue value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.google.gson.JsonObject;
|
||||
|
||||
public class Request extends ChannelOwner {
|
||||
Request(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.google.gson.JsonObject;
|
||||
|
||||
public class Response extends ChannelOwner {
|
||||
Response(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* 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 java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class Transport {
|
||||
private final BlockingQueue<String> incoming = new ArrayBlockingQueue(1000);
|
||||
private final BlockingQueue<String> outgoing= new ArrayBlockingQueue(1000);
|
||||
|
||||
private final ReaderThread readerThread;
|
||||
private final WriterThread writerThread;
|
||||
|
||||
Transport(InputStream input, OutputStream output) {
|
||||
DataInputStream in = new DataInputStream(new BufferedInputStream(input));
|
||||
readerThread = new ReaderThread(in, incoming);
|
||||
readerThread.start();
|
||||
// TODO: buffer?
|
||||
DataOutputStream out = new DataOutputStream(output);
|
||||
writerThread = new WriterThread(out, outgoing);
|
||||
writerThread.start();
|
||||
}
|
||||
|
||||
public void send(String message) {
|
||||
try {
|
||||
outgoing.put(message);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Failed to send message", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String read() {
|
||||
try {
|
||||
return incoming.take();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Failed to send message", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReaderThread extends Thread {
|
||||
private final DataInputStream in;
|
||||
private final BlockingQueue<String> queue;
|
||||
|
||||
private static int readIntLE(DataInputStream in) throws IOException {
|
||||
int ch1 = in.read();
|
||||
int ch2 = in.read();
|
||||
int ch3 = in.read();
|
||||
int ch4 = in.read();
|
||||
if ((ch1 | ch2 | ch3 | ch4) < 0) {
|
||||
throw new EOFException();
|
||||
} else {
|
||||
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
|
||||
}
|
||||
}
|
||||
|
||||
ReaderThread(DataInputStream in, BlockingQueue<String> queue) {
|
||||
this.in = in;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
try {
|
||||
queue.put(readMessage());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String readMessage() throws IOException {
|
||||
int len = readIntLE(in);
|
||||
byte[] raw = new byte[len];
|
||||
in.readFully(raw, 0, len);
|
||||
return new String(raw, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
class WriterThread extends Thread {
|
||||
private final DataOutputStream out;
|
||||
private final BlockingQueue<String> queue;
|
||||
|
||||
private static void writeIntLE(DataOutputStream out, int v) throws IOException {
|
||||
out.write(v >>> 0 & 255);
|
||||
out.write(v >>> 8 & 255);
|
||||
out.write(v >>> 16 & 255);
|
||||
out.write(v >>> 24 & 255);
|
||||
}
|
||||
|
||||
WriterThread(DataOutputStream out, BlockingQueue<String> queue) {
|
||||
this.out = out;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
try {
|
||||
if (queue.isEmpty())
|
||||
out.flush();
|
||||
sendMessage(queue.take());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(String message) throws IOException {
|
||||
int len = message.length();
|
||||
writeIntLE(out, len);
|
||||
out.writeBytes(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user