Skip to content

Commit 0608243

Browse files
authored
cherry-pick(#982): feat: roll driver to 1.23.1-beta, implement routeFromHar.update (#983)
1 parent b8bd59a commit 0608243

File tree

13 files changed

+237
-58
lines changed

13 files changed

+237
-58
lines changed

playwright/src/main/java/com/microsoft/playwright/BrowserContext.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ class RouteFromHAROptions {
184184
* <p> Defaults to abort.
185185
*/
186186
public HarNotFound notFound;
187+
/**
188+
* If specified, updates the given HAR with the actual network information instead of serving from file.
189+
*/
190+
public Boolean update;
187191
/**
188192
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
189193
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
@@ -203,26 +207,25 @@ public RouteFromHAROptions setNotFound(HarNotFound notFound) {
203207
return this;
204208
}
205209
/**
206-
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
207-
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
210+
* If specified, updates the given HAR with the actual network information instead of serving from file.
208211
*/
209-
public RouteFromHAROptions setUrl(String url) {
210-
this.url = url;
212+
public RouteFromHAROptions setUpdate(boolean update) {
213+
this.update = update;
211214
return this;
212215
}
213216
/**
214217
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
215218
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
216219
*/
217-
public RouteFromHAROptions setUrl(Pattern url) {
220+
public RouteFromHAROptions setUrl(String url) {
218221
this.url = url;
219222
return this;
220223
}
221224
/**
222225
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
223226
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
224227
*/
225-
public RouteFromHAROptions setUrl(Predicate<String> url) {
228+
public RouteFromHAROptions setUrl(Pattern url) {
226229
this.url = url;
227230
return this;
228231
}

playwright/src/main/java/com/microsoft/playwright/Page.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,10 @@ class RouteFromHAROptions {
20072007
* <p> Defaults to abort.
20082008
*/
20092009
public HarNotFound notFound;
2010+
/**
2011+
* If specified, updates the given HAR with the actual network information instead of serving from file.
2012+
*/
2013+
public Boolean update;
20102014
/**
20112015
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
20122016
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
@@ -2026,26 +2030,25 @@ public RouteFromHAROptions setNotFound(HarNotFound notFound) {
20262030
return this;
20272031
}
20282032
/**
2029-
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
2030-
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
2033+
* If specified, updates the given HAR with the actual network information instead of serving from file.
20312034
*/
2032-
public RouteFromHAROptions setUrl(String url) {
2033-
this.url = url;
2035+
public RouteFromHAROptions setUpdate(boolean update) {
2036+
this.update = update;
20342037
return this;
20352038
}
20362039
/**
20372040
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
20382041
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
20392042
*/
2040-
public RouteFromHAROptions setUrl(Pattern url) {
2043+
public RouteFromHAROptions setUrl(String url) {
20412044
this.url = url;
20422045
return this;
20432046
}
20442047
/**
20452048
* A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern
20462049
* will be surved from the HAR file. If not specified, all requests are served from the HAR file.
20472050
*/
2048-
public RouteFromHAROptions setUrl(Predicate<String> url) {
2051+
public RouteFromHAROptions setUrl(Pattern url) {
20492052
this.url = url;
20502053
return this;
20512054
}

playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@
2727
import java.net.URL;
2828
import java.nio.charset.StandardCharsets;
2929
import java.nio.file.Path;
30+
import java.nio.file.Paths;
3031
import java.util.*;
3132
import java.util.function.Consumer;
3233
import java.util.function.Predicate;
3334
import java.util.regex.Pattern;
3435

36+
import static com.microsoft.playwright.impl.Serialization.addHarUrlFilter;
3537
import static com.microsoft.playwright.impl.Serialization.gson;
3638
import static com.microsoft.playwright.impl.Utils.isSafeCloseError;
39+
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
3740
import static java.nio.charset.StandardCharsets.UTF_8;
3841
import static java.nio.file.Files.readAllBytes;
3942
import static java.util.Arrays.asList;
@@ -51,7 +54,17 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
5154
final TimeoutSettings timeoutSettings = new TimeoutSettings();
5255
Path videosDir;
5356
URL baseUrl;
54-
Path recordHarPath;
57+
final Map<String, HarRecorder> harRecorders = new HashMap<>();
58+
59+
static class HarRecorder {
60+
final Path path;
61+
final HarContentPolicy contentPolicy;
62+
63+
HarRecorder(Path har, HarContentPolicy policy) {
64+
path = har;
65+
contentPolicy = policy;
66+
}
67+
}
5568

5669
enum EventType {
5770
CLOSE,
@@ -74,6 +87,12 @@ enum EventType {
7487
this.request = connection.getExistingObject(initializer.getAsJsonObject("APIRequestContext").get("guid").getAsString());
7588
}
7689

90+
void setRecordHar(Path path, HarContentPolicy policy) {
91+
if (path != null) {
92+
harRecorders.put("", new HarRecorder(path, policy));
93+
}
94+
}
95+
7796
void setBaseUrl(String spec) {
7897
try {
7998
this.baseUrl = new URL(spec);
@@ -178,15 +197,31 @@ private void closeImpl() {
178197
}
179198
isClosedOrClosing = true;
180199
try {
181-
if (recordHarPath != null) {
182-
JsonObject json = sendMessage("harExport").getAsJsonObject();
200+
for (Map.Entry<String, HarRecorder> entry : harRecorders.entrySet()) {
201+
JsonObject params = new JsonObject();
202+
params.addProperty("harId", entry.getKey());
203+
JsonObject json = sendMessage("harExport", params).getAsJsonObject();
183204
ArtifactImpl artifact = connection.getExistingObject(json.getAsJsonObject("artifact").get("guid").getAsString());
184205
// In case of CDP connection browser is null but since the connection is established by
185206
// the driver it is safe to consider the artifact local.
186207
if (browser() != null && browser().isRemote) {
187208
artifact.isRemote = true;
188209
}
189-
artifact.saveAs(recordHarPath);
210+
211+
// Server side will compress artifact if content is attach or if file is .zip.
212+
HarRecorder harParams = entry.getValue();
213+
boolean isCompressed = harParams.contentPolicy == HarContentPolicy.ATTACH || harParams.path.toString().endsWith(".zip");
214+
boolean needCompressed = harParams.path.toString().endsWith(".zip");
215+
if (isCompressed && !needCompressed) {
216+
String tmpPath = harParams.path + ".tmp";
217+
artifact.saveAs(Paths.get(tmpPath));
218+
JsonObject unzipParams = new JsonObject();
219+
unzipParams.addProperty("zipFile", tmpPath);
220+
unzipParams.addProperty("harFile", harParams.path.toString());
221+
connection.localUtils.sendMessage("harUnzip", unzipParams);
222+
} else {
223+
artifact.saveAs(harParams.path);
224+
}
190225
artifact.delete();
191226
}
192227

@@ -351,6 +386,10 @@ public void routeFromHAR(Path har, RouteFromHAROptions options) {
351386
if (options == null) {
352387
options = new RouteFromHAROptions();
353388
}
389+
if (options.update != null && options.update) {
390+
recordIntoHar(null, har, options);
391+
return;
392+
}
354393
UrlMatcher matcher = UrlMatcher.forOneOf(baseUrl, options.url);
355394
HARRouter harRouter = new HARRouter(connection.localUtils, har, options.notFound);
356395
onClose(context -> harRouter.dispose());
@@ -368,6 +407,22 @@ private void route(UrlMatcher matcher, Consumer<Route> handler, RouteOptions opt
368407
});
369408
}
370409

410+
void recordIntoHar(PageImpl page, Path har, RouteFromHAROptions options) {
411+
JsonObject params = new JsonObject();
412+
if (page != null) {
413+
params.add("page", page.toProtocolRef());
414+
}
415+
JsonObject jsonOptions = new JsonObject();
416+
jsonOptions.addProperty("path", har.toAbsolutePath().toString());
417+
jsonOptions.addProperty("content", HarContentPolicy.ATTACH.name().toLowerCase());
418+
jsonOptions.addProperty("mode", HarMode.MINIMAL.name().toLowerCase());
419+
addHarUrlFilter(jsonOptions, options.url);
420+
params.add("options", jsonOptions);
421+
JsonObject json = sendMessage("harStart", params).getAsJsonObject();
422+
String harId = json.get("harId").getAsString();
423+
harRecorders.put(harId, new HarRecorder(har, HarContentPolicy.ATTACH));
424+
}
425+
371426
@Override
372427
public void setDefaultNavigationTimeout(double timeout) {
373428
withLogging("BrowserContext.setDefaultNavigationTimeout", () -> {

playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.function.Consumer;
3131
import java.util.regex.Pattern;
3232

33+
import static com.microsoft.playwright.impl.Serialization.addHarUrlFilter;
3334
import static com.microsoft.playwright.impl.Serialization.gson;
3435
import static com.microsoft.playwright.impl.Utils.*;
3536
import static com.microsoft.playwright.impl.Utils.convertType;
@@ -137,24 +138,22 @@ private BrowserContextImpl newContextImpl(NewContextOptions options) {
137138
}
138139
JsonObject recordHar = null;
139140
Path recordHarPath = options.recordHarPath;
141+
HarContentPolicy harContentPolicy = null;
140142
if (options.recordHarPath != null) {
141143
recordHar = new JsonObject();
142144
recordHar.addProperty("path", options.recordHarPath.toString());
143145
if (options.recordHarContent != null) {
144-
recordHar.addProperty("content", options.recordHarContent.toString().toLowerCase());
146+
harContentPolicy = options.recordHarContent;
145147
} else if (options.recordHarOmitContent != null && options.recordHarOmitContent) {
146-
recordHar.addProperty("content", HarContentPolicy.OMIT.toString().toLowerCase());
148+
harContentPolicy = HarContentPolicy.OMIT;
147149
}
148-
if (options.recordHarMode != null) {
149-
recordHar.addProperty("mode", options.recordHarMode.toString().toLowerCase());
150+
if (harContentPolicy != null) {
151+
recordHar.addProperty("content", harContentPolicy.name().toLowerCase());
150152
}
151-
if (options.recordHarUrlFilter instanceof String) {
152-
recordHar.addProperty("urlGlob", (String) options.recordHarUrlFilter);
153-
} else if (options.recordHarUrlFilter instanceof Pattern) {
154-
Pattern pattern = (Pattern) options.recordHarUrlFilter;
155-
recordHar.addProperty("urlRegexSource", pattern.pattern());
156-
recordHar.addProperty("urlRegexFlags", toJsRegexFlags(pattern));
153+
if (options.recordHarMode != null) {
154+
recordHar.addProperty("mode", options.recordHarMode.name().toLowerCase());
157155
}
156+
addHarUrlFilter(recordHar, options.recordHarUrlFilter);
158157
options.recordHarPath = null;
159158
options.recordHarMode = null;
160159
options.recordHarOmitContent = null;
@@ -210,7 +209,7 @@ private BrowserContextImpl newContextImpl(NewContextOptions options) {
210209
if (options.baseURL != null) {
211210
context.setBaseUrl(options.baseURL);
212211
}
213-
context.recordHarPath = recordHarPath;
212+
context.setRecordHar(recordHarPath, harContentPolicy);
214213
contexts.add(context);
215214
return context;
216215
}
@@ -231,9 +230,7 @@ private void startTracingImpl(Page page, StartTracingOptions options) {
231230
}
232231
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
233232
if (page != null) {
234-
JsonObject jsonPage = new JsonObject();
235-
jsonPage.addProperty("guid", ((PageImpl) page).guid);
236-
params.add("page", jsonPage);
233+
params.add("page", ((PageImpl) page).toProtocolRef());
237234
}
238235
sendMessage("startTracing", params);
239236
}

playwright/src/main/java/com/microsoft/playwright/impl/BrowserTypeImpl.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@
2222
import com.microsoft.playwright.Browser;
2323
import com.microsoft.playwright.BrowserType;
2424
import com.microsoft.playwright.PlaywrightException;
25+
import com.microsoft.playwright.options.HarContentPolicy;
2526

2627
import java.io.IOException;
2728
import java.nio.file.Path;
2829
import java.util.function.Consumer;
2930

31+
import static com.microsoft.playwright.impl.Serialization.addHarUrlFilter;
3032
import static com.microsoft.playwright.impl.Serialization.gson;
33+
import static com.microsoft.playwright.impl.Utils.convertType;
3134

3235
class BrowserTypeImpl extends ChannelOwner implements BrowserType {
3336
LocalUtils localUtils;
@@ -152,20 +155,52 @@ public BrowserContextImpl launchPersistentContext(Path userDataDir, LaunchPersis
152155
private BrowserContextImpl launchPersistentContextImpl(Path userDataDir, LaunchPersistentContextOptions options) {
153156
if (options == null) {
154157
options = new LaunchPersistentContextOptions();
158+
} else {
159+
// Make a copy so that we can nullify some fields below.
160+
options = convertType(options, LaunchPersistentContextOptions.class);
155161
}
156-
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
157-
params.addProperty("userDataDir", userDataDir.toString());
162+
JsonObject recordHar = null;
163+
Path recordHarPath = options.recordHarPath;
164+
HarContentPolicy harContentPolicy = null;
158165
if (options.recordHarPath != null) {
159-
JsonObject recordHar = new JsonObject();
166+
recordHar = new JsonObject();
160167
recordHar.addProperty("path", options.recordHarPath.toString());
168+
if (options.recordHarContent != null) {
169+
harContentPolicy = options.recordHarContent;
170+
} else if (options.recordHarOmitContent != null && options.recordHarOmitContent) {
171+
harContentPolicy = HarContentPolicy.OMIT;
172+
}
173+
if (harContentPolicy != null) {
174+
recordHar.addProperty("content", harContentPolicy.name().toLowerCase());
175+
}
176+
if (options.recordHarMode != null) {
177+
recordHar.addProperty("mode", options.recordHarMode.toString().toLowerCase());
178+
}
179+
addHarUrlFilter(recordHar, options.recordHarUrlFilter);
180+
options.recordHarPath = null;
181+
options.recordHarMode = null;
182+
options.recordHarOmitContent = null;
183+
options.recordHarContent = null;
184+
options.recordHarUrlFilter = null;
185+
} else {
161186
if (options.recordHarOmitContent != null) {
162-
recordHar.addProperty("omitContent", true);
187+
throw new PlaywrightException("recordHarOmitContent is set but recordHarPath is null");
188+
}
189+
if (options.recordHarUrlFilter != null) {
190+
throw new PlaywrightException("recordHarUrlFilter is set but recordHarPath is null");
163191
}
164-
params.remove("recordHarPath");
165-
params.remove("recordHarOmitContent");
192+
if (options.recordHarMode != null) {
193+
throw new PlaywrightException("recordHarMode is set but recordHarPath is null");
194+
}
195+
if (options.recordHarContent != null) {
196+
throw new PlaywrightException("recordHarContent is set but recordHarPath is null");
197+
}
198+
}
199+
200+
JsonObject params = gson().toJsonTree(options).getAsJsonObject();
201+
params.addProperty("userDataDir", userDataDir.toString());
202+
if (recordHar != null) {
166203
params.add("recordHar", recordHar);
167-
} else if (options.recordHarOmitContent != null) {
168-
throw new PlaywrightException("recordHarOmitContent is set but recordHarPath is null");
169204
}
170205
if (options.recordVideoDir != null) {
171206
JsonObject recordVideo = new JsonObject();
@@ -195,7 +230,7 @@ private BrowserContextImpl launchPersistentContextImpl(Path userDataDir, LaunchP
195230
if (options.baseURL != null) {
196231
context.setBaseUrl(options.baseURL);
197232
}
198-
context.recordHarPath = options.recordHarPath;
233+
context.setRecordHar(recordHarPath, harContentPolicy);
199234
return context;
200235
}
201236

playwright/src/main/java/com/microsoft/playwright/impl/ChannelOwner.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,10 @@ <T> T runUntil(Runnable code, Waitable<T> waitable) {
108108

109109
void handleEvent(String event, JsonObject parameters) {
110110
}
111+
112+
JsonObject toProtocolRef() {
113+
JsonObject json = new JsonObject();
114+
json.addProperty("guid", guid);
115+
return json;
116+
}
111117
}

playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,9 +510,7 @@ FrameExpectResult expect(String expression, FrameExpectOptions options) {
510510

511511
JsonObject toProtocol() {
512512
JsonObject result = new JsonObject();
513-
JsonObject frameJson = new JsonObject();
514-
frameJson.addProperty("guid", frame.guid);
515-
result.add("frame", frameJson);
513+
result.add("frame", frame.toProtocolRef());
516514
result.addProperty("selector", selector);
517515
return result;
518516
}

playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,10 @@ public void routeFromHAR(Path har, RouteFromHAROptions options) {
974974
if (options == null) {
975975
options = new RouteFromHAROptions();
976976
}
977+
if (options.update != null && options.update) {
978+
browserContext.recordIntoHar(this, har, convertType(options, BrowserContext.RouteFromHAROptions.class));
979+
return;
980+
}
977981
UrlMatcher matcher = UrlMatcher.forOneOf(browserContext.baseUrl, options.url);
978982
HARRouter harRouter = new HARRouter(connection.localUtils, har, options.notFound);
979983
onClose(context -> harRouter.dispose());

0 commit comments

Comments
 (0)