in spring-ai-alibaba-jmanus/src/main/java/com/alibaba/cloud/ai/example/manus/tool/browser/InteractiveTextProcessor.java [97:183]
private void processIframes(WebDriver driver, String parentPath, WebElement parentIframe) {
// 查找当前上下文中的所有iframe
List<WebElement> iframes = driver.findElements(By.tagName("iframe"));
log.info("找到 {} 个iframe", iframes.size());
for (int i = 0; i < iframes.size(); i++) {
WebElement iframe = iframes.get(i);
// 确保iframe已加载完成
boolean isIframeLoaded = false;
int maxAttempts = 20; // 最大尝试次数
int attempts = 0;
while (!isIframeLoaded && attempts < maxAttempts) {
try {
// 尝试获取iframe的document.readyState
JavascriptExecutor js = (JavascriptExecutor) driver;
driver.switchTo().frame(iframe);
String readyState = (String) js.executeScript("return document.readyState");
log.info("iframe readyState: {}, attempts: {}", readyState, attempts);
if ("complete".equals(readyState)) {
isIframeLoaded = true;
driver.switchTo().parentFrame(); // 切回父frame
log.info("iframe loaded successfully");
break;
}
driver.switchTo().parentFrame(); // 切回父frame
attempts++;
Thread.sleep(500); // 等待500毫秒
}
catch (Exception e) {
log.info("等待iframe加载第{}次失败: {}", attempts, e.getMessage());
attempts++;
try {
Thread.sleep(500);
}
catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
if (!isIframeLoaded) {
log.warn("iframe加载超时,跳过处理此iframe");
return;
}
// 构建iframe路径
String currentPath = parentPath.isEmpty() ? String.valueOf(i) : parentPath + "/" + i;
try {
// 切换到iframe
driver.switchTo().frame(iframe);
// 获取iframe中的交互元素并添加到缓存
List<WebElementWrapper> iframeElements = getInteractiveElementsInner(driver);
for (WebElementWrapper wrapper : iframeElements) {
// 设置iframe信息
wrapper.setIframeElement(iframe);
wrapper.setIframePath(currentPath);
this.interactiveElementsCache.add(wrapper);
}
// 递归处理嵌套iframe
processIframes(driver, currentPath, iframe);
// 切回父级上下文
if (parentIframe == null) {
driver.switchTo().defaultContent();
}
else {
driver.switchTo().parentFrame();
}
}
catch (Exception e) {
log.warn("处理iframe失败,路径: {}, 错误: {}", currentPath, e.getMessage());
// 确保即使处理某个iframe失败,也回到正确的上下文
if (parentIframe == null) {
driver.switchTo().defaultContent();
}
else {
driver.switchTo().parentFrame();
}
}
}
}