Skip to content

Commit

Permalink
增强 Browser 关闭逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
fanyong920 committed Nov 22, 2024
1 parent ca19d06 commit d13eb41
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 39 deletions.
6 changes: 4 additions & 2 deletions example/src/main/java/com/ruiyun/example/J_RequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ public void test2() throws Exception {
System.out.println("url: " + request.url() + ", id: " + request.id());
try {
Response response1 = request.response();
System.out.println("response: " + new String(response1.content()));
System.out.println("response1: " + new String(response1.content()));
} catch (Exception e) {
System.out.println("request(id:" + request.id() + ")重定向,不能获取response.content()");
}
}
}else {
System.out.println("response2: " + new String(response.content()));
}
});
//这个页面有重定向请求,你可以按F12打开devtool开发者工具,自己刷新页面看网络请求
Expand Down Expand Up @@ -94,7 +96,7 @@ public void test4() throws Exception {
//如果不设置 domcontentloaded 算页面导航完成的话,那么goTo方法会超时,因为图片请求被拦截了,页面不会达到loaded阶段
options.setWaitUntil(Collections.singletonList(PuppeteerLifeCycle.DOMCONTENT_LOADED));
page.goTo("https://www.baidu.com/", options);
Thread.sleep(115000);
Thread.sleep(2000);
}
}

Expand Down
5 changes: 5 additions & 0 deletions example/src/main/java/com/ruiyun/example/S_PageApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
import com.ruiyun.jvppeteer.entities.Viewport;
import com.ruiyun.jvppeteer.entities.VisionDeficiency;
import com.ruiyun.jvppeteer.entities.WaitForSelectorOptions;
import com.ruiyun.jvppeteer.exception.JvppeteerException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import org.junit.Test;

import java.io.IOException;
Expand Down Expand Up @@ -484,6 +486,9 @@ public void test11() throws IOException {
page.goTo("https://pptr.nodejs.cn/api/puppeteer.waitforselectoroptions/", false);
WaitForSelectorOptions options = new WaitForSelectorOptions(true, false);
ElementHandle elementHandle = page.waitForSelector("#__docusaurus_skipToContent_fallback > div > div > main > div > div > div.col.docItemCol_VOVn > div > article > div.theme-doc-markdown.markdown > header > h1", options);
if(Objects.isNull(elementHandle)) {
throw new JvppeteerException("No such element");
}
elementHandle.dispose();
System.out.println(elementHandle.id());
browser.close();
Expand Down
55 changes: 48 additions & 7 deletions example/src/main/java/com/ruiyun/example/U_BroswerApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import com.ruiyun.jvppeteer.entities.*;
import com.ruiyun.jvppeteer.events.DownloadProgressEvent;
import com.ruiyun.jvppeteer.events.DownloadWillBeginEvent;
import java.util.ArrayList;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -91,13 +91,13 @@ public void test5() throws Exception {
try (Browser browser = Puppeteer.launch(launchOptions)) {
BrowserContext browserContext = browser.createBrowserContext();
AtomicBoolean complete = new AtomicBoolean(false);
browser.on(Browser.BrowserEvent.Browser_downloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
browser.on(Browser.BrowserEvent.DownloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
System.out.println("downloadProgressEvent: " + downloadProgressEvent);
if (downloadProgressEvent.getState().equals(DownloadState.Completed)) {
complete.set(true);
}
});
browser.on(Browser.BrowserEvent.Browser_downloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
browser.on(Browser.BrowserEvent.DownloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
System.out.println("downloadWillBeginEvent: " + downloadWillBeginEvent);
});
Page page = browserContext.newPage();
Expand Down Expand Up @@ -138,13 +138,13 @@ public void test6() throws Exception {
try (Browser browser = Puppeteer.launch(launchOptions)) {
BrowserContext browserContext = browser.createBrowserContext();
Map<String, AtomicBoolean> atomicBooleanMap = new ConcurrentHashMap<>();
browser.on(Browser.BrowserEvent.Browser_downloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
browser.on(Browser.BrowserEvent.DownloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
System.out.println("downloadProgressEvent: " + downloadProgressEvent);
if (downloadProgressEvent.getState().equals(DownloadState.Completed)) {
atomicBooleanMap.get(downloadProgressEvent.getGuid()).set(true);
}
});
browser.on(Browser.BrowserEvent.Browser_downloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
browser.on(Browser.BrowserEvent.DownloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
System.out.println("downloadWillBeginEvent: " + downloadWillBeginEvent);
atomicBooleanMap.put(downloadWillBeginEvent.getGuid(), new AtomicBoolean(false));
});
Expand Down Expand Up @@ -183,13 +183,54 @@ public void test7() throws Exception {
try (Browser browser = Puppeteer.launch(launchOptions)) {
BrowserContext browserContext = browser.createBrowserContext();
Map<String, AtomicBoolean> atomicBooleanMap = new ConcurrentHashMap<>();
browser.on(Browser.BrowserEvent.Browser_downloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
browser.on(Browser.BrowserEvent.DownloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
System.out.println("downloadProgressEvent: " + downloadProgressEvent);
if (downloadProgressEvent.getState().equals(DownloadState.Completed)) {
atomicBooleanMap.get(downloadProgressEvent.getGuid()).set(true);
}
});
browser.on(Browser.BrowserEvent.Browser_downloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
browser.on(Browser.BrowserEvent.DownloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
System.out.println("downloadWillBeginEvent: " + downloadWillBeginEvent);
atomicBooleanMap.put(downloadWillBeginEvent.getGuid(), new AtomicBoolean(false));
});
Page page = browserContext.newPage();
//配置下载行为,下载的BrowserContextId(不配置就是使用默认的浏览器上下文),下载路径,下载事件是否接受
browser.setDownloadBehavior(new DownloadOptions(DownloadBehavior.Allow, browserContext.getId(), "C:\\Users\\fanyong\\Desktop\\typescriptPri\\127.0.6533.99", true));
page.goTo("https://mirrors.huaweicloud.com/openjdk/22.0.2/");
//点击,进行下载
page.click("body > pre:nth-child(4) > a:nth-child(6)");
Thread.sleep(1000);
//点击,进行下载
page.click("body > pre:nth-child(4) > a:nth-child(5)");
Thread.sleep(3000);
//取消下载
for (Map.Entry<String, AtomicBoolean> entry : atomicBooleanMap.entrySet()) {
browser.cancelDownload(entry.getKey(), browserContext.getId());
}
}
}

/**
* 开启chrome log
*
* @throws Exception 异常
*/
@Test
public void test() throws Exception {
List<String> args = new ArrayList<>();
args.add("--enable-logging=stderr --v=2");
args.add("-log-file=D:\\chrome_debug.log");
launchOptions.setArgs(args);
try (Browser browser = Puppeteer.launch(launchOptions)) {
BrowserContext browserContext = browser.createBrowserContext();
Map<String, AtomicBoolean> atomicBooleanMap = new ConcurrentHashMap<>();
browser.on(Browser.BrowserEvent.DownloadProgress, (Consumer<DownloadProgressEvent>) downloadProgressEvent -> {
System.out.println("downloadProgressEvent: " + downloadProgressEvent);
if (downloadProgressEvent.getState().equals(DownloadState.Completed)) {
atomicBooleanMap.get(downloadProgressEvent.getGuid()).set(true);
}
});
browser.on(Browser.BrowserEvent.DownloadWillBegin, (Consumer<DownloadWillBeginEvent>) downloadWillBeginEvent -> {
System.out.println("downloadWillBeginEvent: " + downloadWillBeginEvent);
atomicBooleanMap.put(downloadWillBeginEvent.getGuid(), new AtomicBoolean(false));
});
Expand Down
35 changes: 19 additions & 16 deletions src/main/java/com/ruiyun/jvppeteer/core/Browser.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class Browser extends EventEmitter<Browser.BrowserEvent> implements AutoC
private final TargetManager targetManager;
private String executablePath;
private List<String> defaultArgs;
volatile boolean isClosing;


Browser(Product product, Connection connection, List<String> contextIds, Viewport viewport, Process process, Runnable closeCallback, Function<Target, Boolean> targetFilterCallback, Function<Target, Boolean> isPageTargetCallback, boolean waitForInitiallyDiscoveredTargets) {
Expand Down Expand Up @@ -88,8 +89,8 @@ public class Browser extends EventEmitter<Browser.BrowserEvent> implements AutoC
}

private final Consumer<Object> emitDisconnected = (ignore) -> this.emit(BrowserEvent.Disconnected, true);
private final Consumer<Object> emitDownloadProgress = (event) -> this.emit(BrowserEvent.Browser_downloadProgress, event);
private final Consumer<Object> emitDownloadWillBegin = (event) -> this.emit(BrowserEvent.Browser_downloadWillBegin, event);
private final Consumer<Object> emitDownloadProgress = (event) -> this.emit(BrowserEvent.DownloadProgress, event);
private final Consumer<Object> emitDownloadWillBegin = (event) -> this.emit(BrowserEvent.DownloadWillBegin, event);

private void attach() {
this.connection.on(CDPSession.CDPSessionEvent.CDPSession_Disconnected, this.emitDisconnected);
Expand Down Expand Up @@ -371,6 +372,7 @@ public String userAgent() throws JsonProcessingException {

@Override
public void close() {
this.isClosing = true;
this.closeCallback.run();
this.disconnect();
}
Expand Down Expand Up @@ -492,51 +494,52 @@ public void cancelDownload(String guid, String browserContextId) {
this.connection.send("Browser.cancelDownload", params);
}

/**
* 是否正在关闭浏览器,用于判断是浏览器自己关闭还是程序手动关闭
*
* @return 是否
*/
public boolean isClosing() {
return this.isClosing;
}

public enum BrowserEvent {
/**
* 创建target
* {@link Target}
*/
TargetCreated("targetcreated"),
TargetCreated,
/**
* 销毁target
* {@link Target}
*/
TargetDestroyed("targetdestroyed"),
TargetDestroyed,
/**
* target变化
* {@link Target}
*/
TargetChanged("targetchanged"),
TargetChanged,
/**
* 发现target
* {@link TargetInfo}
*/
TargetDiscovered("targetdiscovered"),
TargetDiscovered,
/**
* 断开连接
* Object
*/
Disconnected("disconnected"),
Disconnected,
/**
* 下载进度时触发
*/
Browser_downloadProgress("Browser.downloadProgress"),
DownloadProgress,

/**
* 当页面准备开始下载时促发
*/
Browser_downloadWillBegin("Browser.downloadWillBegin");
private final String eventName;
DownloadWillBegin

BrowserEvent(String eventName) {
this.eventName = eventName;
}

public String getEventName() {
return eventName;
}
}

}
15 changes: 9 additions & 6 deletions src/main/java/com/ruiyun/jvppeteer/core/BrowserRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand All @@ -24,6 +24,7 @@
import org.slf4j.LoggerFactory;


import static com.ruiyun.jvppeteer.util.FileUtil.removeFolder;
import static com.ruiyun.jvppeteer.util.FileUtil.removeFolderOnExit;

public class BrowserRunner {
Expand Down Expand Up @@ -114,7 +115,7 @@ public void destroy() {
}
try {
if (exec != null) {
LOGGER.info("kill chrome process by pid,command: {}", command);
LOGGER.trace("kill chrome process by pid,command: {}", command);
exec.waitFor(Constant.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
}
} finally {
Expand Down Expand Up @@ -245,18 +246,20 @@ public void closeBrowser() {
return;
}
//发送关闭指令
if (this.connection != null && !this.connection.closed()) {
this.connection.send("Browser.close");
if (Objects.nonNull(this.connection) && !this.connection.closed()) {
this.connection.send("Browser.close", null, null, false);
}
this.destroy();
this.closed = true;

}

private void deleteTempUserDir() {
if (StringUtil.isNotEmpty(this.tempDirectory)) {
try {
removeFolderOnExit(this.tempDirectory);
removeFolder(this.tempDirectory);
if (Paths.get(this.tempDirectory).toFile().exists()) {
removeFolderOnExit(this.tempDirectory);
}
} catch (Exception ignored) {
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public abstract class BrowserLauncher {
protected Product product;
protected String cacheDir;
protected String executablePath;

public BrowserLauncher(String cacheDir, Product product) {
super();
this.cacheDir = cacheDir;
Expand Down Expand Up @@ -140,6 +141,7 @@ protected Browser run(LaunchOptions options, List<String> chromeArguments, Strin
if (options.getWaitForInitialPage()) {
browser.waitForTarget(t -> TargetType.PAGE.equals(t.type()), options.getTimeout());
}
connection.setBrowser(browser);
runner.setPid(getBrowserPid(runner.getProcess()));
return browser;
} catch (IOException | InterruptedException e) {
Expand Down Expand Up @@ -187,7 +189,9 @@ public Browser connect(ConnectOptions options) throws IOException, InterruptedEx
browserContextIds = Constant.OBJECTMAPPER.readerFor(javaType).readValue(result.get("browserContextIds"));
GetVersionResponse version = getVersion(connection);
Product product = version.getProduct().toLowerCase().contains("firefox") ? Product.FIREFOX : Product.CHROME;
return Browser.create(product, connection, browserContextIds, options.getAcceptInsecureCerts(), options.getDefaultViewport(), null, closeFunction, options.getTargetFilter(), options.getIsPageTarget(), true);
Browser browser = Browser.create(product, connection, browserContextIds, options.getAcceptInsecureCerts(), options.getDefaultViewport(), null, closeFunction, options.getTargetFilter(), options.getIsPageTarget(), true);
connection.setBrowser(browser);
return browser;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public JsonNode send(String method, Map<String, Object> params, Integer timeout,
*/
public void detach() {
if (this.connection == null) {
throw new JvppeteerException("Session already detached. Most likely the" + this.targetType + "has been closed.");
throw new JvppeteerException("Session already detached. Most likely the " + this.targetType + "has been closed.");
}
Map<String, Object> params = ParamsFactory.create();
params.put(SESSION_ID, this.sessionId);
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/com/ruiyun/jvppeteer/transport/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruiyun.jvppeteer.common.Constant;
import com.ruiyun.jvppeteer.common.ParamsFactory;
import com.ruiyun.jvppeteer.core.Browser;
import com.ruiyun.jvppeteer.entities.TargetInfo;
import com.ruiyun.jvppeteer.events.EventEmitter;
import com.ruiyun.jvppeteer.exception.JvppeteerException;
Expand Down Expand Up @@ -55,7 +56,9 @@ public class Connection extends EventEmitter<CDPSession.CDPSessionEvent> impleme
final Set<String> manuallyAttached = new HashSet<>();
private final CallbackRegistry callbacks = new CallbackRegistry();//并发
final AtomicLong id = new AtomicLong(1);
ExecutorService handleMessageExecutorService = Executors.newSingleThreadExecutor(r -> new Thread(r, JV_HANDLE_MESSAGE_THREAD + eventThreadId.getAndIncrement()));
private Browser browser;

ExecutorService handleMessageExecutorService = Executors.newSingleThreadExecutor(r -> new Thread(r, JV_HANDLE_MESSAGE_THREAD + messageThreadId.getAndIncrement()));

public Connection(String url, ConnectionTransport transport, int delay, int timeout) {
super();
Expand Down Expand Up @@ -155,7 +158,6 @@ protected static void resolveCallback(CallbackRegistry callbacks, JsonNode respo
}

private static final AtomicLong messageThreadId = new AtomicLong(1);
private static final AtomicLong eventThreadId = new AtomicLong(1);

public boolean isAutoAttached(String targetId) {
return !this.manuallyAttached.remove(targetId);
Expand Down Expand Up @@ -290,7 +292,8 @@ private void onClose() {
return;
this.closed = true;
this.transport.setConnection(null);
waitForHandleMessageThreadFinish();
this.handleMessageExecutorService.shutdown();
// waitForHandleMessageThreadFinish();
this.callbacks.clear();
for (CDPSession session : this.sessions.values())
session.onClosed();
Expand All @@ -317,5 +320,13 @@ public List<ProtocolException> getPendingProtocolErrors() {
public boolean closed() {
return this.closed;
}

public Browser browser() {
return browser;
}

public void setBrowser(Browser browser) {
this.browser = browser;
}
}

Loading

0 comments on commit d13eb41

Please sign in to comment.