diff --git a/playwright/src/main/java/com/microsoft/playwright/Browser.java b/playwright/src/main/java/com/microsoft/playwright/Browser.java index 031d01d5..faa4ecad 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Browser.java +++ b/playwright/src/main/java/com/microsoft/playwright/Browser.java @@ -218,11 +218,14 @@ public interface Browser extends AutoCloseable { */ public RecordVideo recordVideo; /** - * Populates context with given storage state. This method can be used to initialize context with logged-in information - * obtained via [{@code method: BrowserContext.storageState}]. Either a path to the file with saved storage, or an object with - * the following fields: + * Populates context with given storage state. This option can be used to initialize context with logged-in information + * obtained via [{@code method: BrowserContext.storageState}]. + */ + public String storageState; + /** + * Populates context with given storage state. This option can be used to initialize context with logged-in information + * obtained via [{@code method: BrowserContext.storageState}]. Path to the file with saved storage state. */ - public BrowserContext.StorageState storageState; public Path storageStatePath; /** * Changes the timezone of the context. See @@ -307,13 +310,11 @@ public interface Browser extends AutoCloseable { this.recordVideo = new RecordVideo(); return this.recordVideo; } - public NewContextOptions withStorageState(BrowserContext.StorageState storageState) { + public NewContextOptions withStorageState(String storageState) { this.storageState = storageState; - this.storageStatePath = null; return this; } - public NewContextOptions withStorageState(Path storageStatePath) { - this.storageState = null; + public NewContextOptions withStorageStatePath(Path storageStatePath) { this.storageStatePath = storageStatePath; return this; } @@ -507,11 +508,14 @@ public interface Browser extends AutoCloseable { */ public RecordVideo recordVideo; /** - * Populates context with given storage state. This method can be used to initialize context with logged-in information - * obtained via [{@code method: BrowserContext.storageState}]. Either a path to the file with saved storage, or an object with - * the following fields: + * Populates context with given storage state. This option can be used to initialize context with logged-in information + * obtained via [{@code method: BrowserContext.storageState}]. + */ + public String storageState; + /** + * Populates context with given storage state. This option can be used to initialize context with logged-in information + * obtained via [{@code method: BrowserContext.storageState}]. Path to the file with saved storage state. */ - public BrowserContext.StorageState storageState; public Path storageStatePath; /** * Changes the timezone of the context. See @@ -596,13 +600,11 @@ public interface Browser extends AutoCloseable { this.recordVideo = new RecordVideo(); return this.recordVideo; } - public NewPageOptions withStorageState(BrowserContext.StorageState storageState) { + public NewPageOptions withStorageState(String storageState) { this.storageState = storageState; - this.storageStatePath = null; return this; } - public NewPageOptions withStorageState(Path storageStatePath) { - this.storageState = null; + public NewPageOptions withStorageStatePath(Path storageStatePath) { this.storageStatePath = storageStatePath; return this; } diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index 5c3866a4..f9a5591c 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -54,46 +54,6 @@ public interface BrowserContext extends AutoCloseable { } } - class StorageState { - public List cookies; - public List origins; - - public static class OriginState { - public final String origin; - public List localStorage; - - public static class LocalStorageItem { - public String name; - public String value; - public LocalStorageItem(String name, String value) { - this.name = name; - this.value = value; - } - } - - public OriginState(String origin) { - this.origin = origin; - } - - public OriginState withLocalStorage(List localStorage) { - this.localStorage = localStorage; - return this; - } - } - - public StorageState() { - cookies = new ArrayList<>(); - origins = new ArrayList<>(); - } - - public List cookies() { - return this.cookies; - } - public List origins() { - return this.origins; - } - } - void onClose(Consumer handler); void offClose(Consumer handler); @@ -431,13 +391,13 @@ public interface BrowserContext extends AutoCloseable { * @param offline Whether to emulate network being offline for the browser context. */ void setOffline(boolean offline); - default StorageState storageState() { + default String storageState() { return storageState(null); } /** * Returns storage state for this browser context, contains current cookies and local storage snapshot. */ - StorageState storageState(StorageStateOptions options); + String storageState(StorageStateOptions options); default void unroute(String url) { unroute(url, null); } default void unroute(Pattern url) { unroute(url, null); } default void unroute(Predicate url) { unroute(url, null); } diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserType.java b/playwright/src/main/java/com/microsoft/playwright/BrowserType.java index 13c66dc3..96fb6f51 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserType.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserType.java @@ -658,8 +658,9 @@ public interface BrowserType { * context will automatically close the browser. * * @param userDataDir Path to a User Data Directory, which stores browser session data like cookies and local storage. More details for - * [Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md) and - * [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile). + * [Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction) and + * [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options#User_Profile). Note that Chromium's user + * data directory is the **parent** directory of the "Profile Path" seen at {@code chrome://version}. */ BrowserContext launchPersistentContext(Path userDataDir, LaunchPersistentContextOptions options); /** diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java index 6e73baf5..35caa42f 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java @@ -313,12 +313,12 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext { } @Override - public StorageState storageState(StorageStateOptions options) { + public String storageState(StorageStateOptions options) { return withLogging("BrowserContext.storageState", () -> { JsonElement json = sendMessage("storageState"); - StorageState storageState = gson().fromJson(json, StorageState.class); + String storageState = json.toString(); if (options != null && options.path != null) { - Utils.writeToFile(json.toString().getBytes(StandardCharsets.UTF_8), options.path); + Utils.writeToFile(storageState.getBytes(StandardCharsets.UTF_8), options.path); } return storageState; }); diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java index 0869968b..33f1779b 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java @@ -16,6 +16,7 @@ package com.microsoft.playwright.impl; +import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.microsoft.playwright.*; @@ -23,6 +24,8 @@ import com.microsoft.playwright.*; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -90,14 +93,23 @@ class BrowserImpl extends ChannelOwner implements Browser { options = new NewContextOptions(); } if (options.storageStatePath != null) { - try (FileReader reader = new FileReader(options.storageStatePath.toFile())) { - options.storageState = gson().fromJson(reader, BrowserContext.StorageState.class); + try { + byte[] bytes = Files.readAllBytes(options.storageStatePath); + options.storageState = new String(bytes, StandardCharsets.UTF_8); options.storageStatePath = null; } catch (IOException e) { throw new PlaywrightException("Failed to read storage state from file", e); } } + JsonObject storageState = null; + if (options.storageState != null) { + storageState = new Gson().fromJson(options.storageState, JsonObject.class); + options.storageState = null; + } JsonObject params = gson().toJsonTree(options).getAsJsonObject(); + if (storageState != null) { + params.add("storageState", storageState); + } JsonElement result = sendMessage("newContext", params); BrowserContextImpl context = connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("context").get("guid").getAsString()); if (options.recordVideo != null) { diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java index 0b527337..571cb7ce 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStorageState.java @@ -43,9 +43,10 @@ public class TestBrowserContextStorageState extends TestBase { page.evaluate("localStorage['name1'] = 'value1';"); page.navigate("https://www.domain.com"); page.evaluate("localStorage['name2'] = 'value2';"); - BrowserContext.StorageState storageState = context.storageState(); - - assertJsonEquals("[{\n" + + String storageState = context.storageState(); + assertJsonEquals("{" + + "cookies:[]," + + "origins:[{\n" + " origin: 'https://www.example.com',\n" + " localStorage: [{\n" + " name: 'name1',\n" + @@ -57,15 +58,22 @@ public class TestBrowserContextStorageState extends TestBase { " name: 'name2',\n" + " value: 'value2'\n" + " }]\n" + - "}]", storageState.origins()); + "}]}", new Gson().fromJson(storageState, JsonObject.class)); } @Test void shouldSetLocalStorage() { - BrowserContext.StorageState storageState = new BrowserContext.StorageState(); - storageState.origins.add(new BrowserContext.StorageState.OriginState("https://www.example.com") - .withLocalStorage(Arrays.asList( - new BrowserContext.StorageState.OriginState.LocalStorageItem("name1", "value1")))); + String storageState = "{\n" + + " origins: [\n" + + " {\n" + + " origin: 'https://www.example.com',\n" + + " localStorage: [{\n" + + " name: 'name1',\n" + + " value: 'value1'\n" + + " }]\n" + + " }\n" + + " ]\n" + + "}"; BrowserContext context = browser.newContext(new Browser.NewContextOptions().withStorageState(storageState)); Page page = context.newPage(); page.route("**/*", route -> { @@ -90,7 +98,7 @@ public class TestBrowserContextStorageState extends TestBase { " return document.cookie;\n" + "}"); Path path = tempDir.resolve("storage-state.json"); - BrowserContext.StorageState state = context.storageState(new BrowserContext.StorageStateOptions().withPath(path)); + context.storageState(new BrowserContext.StorageStateOptions().withPath(path)); JsonObject expected = new Gson().fromJson( "{\n" + " \"cookies\":[\n" + @@ -117,7 +125,7 @@ public class TestBrowserContextStorageState extends TestBase { try (InputStreamReader reader = new InputStreamReader(new FileInputStream(path.toFile()), StandardCharsets.UTF_8)) { assertEquals(expected, new Gson().fromJson(reader, JsonObject.class)); } - BrowserContext context2 = browser.newContext(new Browser.NewContextOptions().withStorageState(path)); + BrowserContext context2 = browser.newContext(new Browser.NewContextOptions().withStorageStatePath(path)); Page page2 = context2.newPage(); page2.route("**/*", route -> { route.fulfill(new Route.FulfillOptions().withBody("")); diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION index 25637939..e9735ae2 100644 --- a/scripts/CLI_VERSION +++ b/scripts/CLI_VERSION @@ -1 +1 @@ -1.9.0-next-1612297085000 +1.9.0-next-1612316912000 diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index 1d1bb873..9b51c059 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -21,11 +21,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import javax.crypto.spec.PSource; import java.io.*; import java.nio.file.FileSystems; import java.util.*; -import java.util.stream.Collectors; import static java.util.Arrays.asList; import static java.util.Collections.reverse; @@ -826,12 +824,6 @@ class Field extends Element { output.add(offset + access + "Optional<" + type.toJava() + "> " + name + ";"); return; } - if (asList("Browser.newContext.options.storageState", - "Browser.newPage.options.storageState").contains(jsonPath)) { - output.add(offset + access + type.toJava() + " " + name + ";"); - output.add(offset + access + "Path " + name + "Path;"); - return; - } output.add(offset + access + type.toJava() + " " + name + ";"); } @@ -896,20 +888,6 @@ class Field extends Element { output.add(offset + "}"); return; } - if (asList("Browser.newContext.options.storageState", - "Browser.newPage.options.storageState").contains(jsonPath)) { - output.add(offset + "public " + parentClass + " withStorageState(BrowserContext.StorageState storageState) {"); - output.add(offset + " this.storageState = storageState;"); - output.add(offset + " this.storageStatePath = null;"); - output.add(offset + " return this;"); - output.add(offset + "}"); - output.add(offset + "public " + parentClass + " withStorageState(Path storageStatePath) {"); - output.add(offset + " this.storageState = null;"); - output.add(offset + " this.storageStatePath = storageStatePath;"); - output.add(offset + " return this;"); - output.add(offset + "}"); - return; - } if ("Route.continue_.options.postData".equals(jsonPath)) { output.add(offset + "public " + parentClass + " withPostData(String postData) {"); output.add(offset + " this.postData = postData.getBytes(StandardCharsets.UTF_8);"); @@ -1153,46 +1131,6 @@ class Interface extends TypeDefinition { output.add(offset + " }"); output.add(offset + "}"); output.add(""); - output.add(offset + "class StorageState {"); - output.add(offset + " public List cookies;"); - output.add(offset + " public List origins;"); - output.add(""); - output.add(offset + " public static class OriginState {"); - output.add(offset + " public final String origin;"); - output.add(offset + " public List localStorage;"); - output.add(""); - output.add(offset + " public static class LocalStorageItem {"); - output.add(offset + " public String name;"); - output.add(offset + " public String value;"); - output.add(offset + " public LocalStorageItem(String name, String value) {"); - output.add(offset + " this.name = name;"); - output.add(offset + " this.value = value;"); - output.add(offset + " }"); - output.add(offset + " }"); - output.add(""); - output.add(offset + " public OriginState(String origin) {"); - output.add(offset + " this.origin = origin;"); - output.add(offset + " }"); - output.add(""); - output.add(offset + " public OriginState withLocalStorage(List localStorage) {"); - output.add(offset + " this.localStorage = localStorage;"); - output.add(offset + " return this;"); - output.add(offset + " }"); - output.add(offset + " }"); - output.add(""); - output.add(offset + " public StorageState() {"); - output.add(offset + " cookies = new ArrayList<>();"); - output.add(offset + " origins = new ArrayList<>();"); - output.add(offset + " }"); - output.add(""); - output.add(offset + " public List cookies() {"); - output.add(offset + " return this.cookies;"); - output.add(offset + " }"); - output.add(offset + " public List origins() {"); - output.add(offset + " return this.origins;"); - output.add(offset + " }"); - output.add(offset + "}"); - output.add(""); break; } case "Browser": { @@ -1440,6 +1378,7 @@ public class ApiGenerator { // Rename in place. object.addProperty("name", alias); } + overrideType(object); for (Map.Entry entry : object.entrySet()) { if (isSupported(entry.getValue())) { filterOtherLangs(entry.getValue()); @@ -1453,6 +1392,21 @@ public class ApiGenerator { } } + private static void overrideType(JsonObject jsonObject) { + if (!jsonObject.has("langs")) { + return; + } + JsonObject langs = jsonObject.getAsJsonObject("langs"); + if (!langs.has("types")) { + return; + } + JsonElement type = langs.getAsJsonObject("types").get("java"); + if (type == null) { + return; + } + jsonObject.add("type", type); + } + private static String alias(JsonObject jsonObject) { if (!jsonObject.has("langs")) { return null; diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java index 1c1b4ae1..7e13369d 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/Types.java @@ -173,7 +173,6 @@ class Types { add("BrowserContext.addCookies.cookies.sameSite", "\"Lax\"|\"None\"|\"Strict\"", "SameSite", new Empty()); add("BrowserContext.route.url", "RegExp|function(URL):boolean|string", "String"); add("BrowserContext.unroute.url", "RegExp|function(URL):boolean|string", "String"); - add("BrowserContext.storageState", "Object", "StorageState", new Empty()); add("Page.waitForNavigation.options.url", "RegExp|function(URL):boolean|string", "Custom"); add("Page.waitForNavigation.options", "Object", "WaitForNavigationOptions"); add("Page.waitForRequest.options", "Object", "WaitForRequestOptions"); @@ -198,8 +197,6 @@ class Types { add("BrowserContext.setGeolocation.geolocation", "Object|null", "Geolocation", new Empty()); add("Browser.newContext.options.geolocation", "Object", "Geolocation", new Empty()); - add("Browser.newContext.options.storageState", "Object|path", "BrowserContext.StorageState", new Empty()); - add("Browser.newPage.options.storageState", "Object|path", "BrowserContext.StorageState", new Empty()); add("Browser.newPage.options.geolocation", "Object", "Geolocation", new Empty()); add("BrowserType.launchPersistentContext.options.geolocation", "Object", "Geolocation", new Empty());