通过CLI标记在隐身模式下启用Chrome扩展程序?

Shr*_*ram 6 selenium google-chrome google-chrome-extension selenium-webdriver

我正在使用selenium来测试Chrome扩展程序,部分扩展程序要求用户处于隐身模式.目前,除非添加参数,否则我无法在启动时允许在隐身模式下启用扩展程序user-data-dir=/path/to/directory.

这个问题是它从我的文件系统的深度加载扩展,而不是我可以检查git的方式.

我也尝试将selenium导航到chrome扩展设置页面,但似乎selenium无法驱动chrome://页面.

有关在Chrome驱动程序启动时如何在Chrome扩展程序上启用隐身功能的任何想法?

sup*_*uri 5

这是适用于最新版本的解决方案Chrome 74

  1. 导航chrome://extensions
  2. 单击Details您想要的扩展名的按钮

在此输入图像描述

  1. 复制网址(其中包含您的扩展程序id

现在我们必须导航到上面的网址,然后单击切换按钮 allow in incognito

爪哇:

driver.get("chrome://extensions/?id=bhghoamapcdpbohphigoooaddinpkbai");
JavascriptExecutor js = (JavascriptExecutor) driver; 
js.executeScript("document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input').click()");
Run Code Online (Sandbox Code Playgroud)

Python:

driver.get("chrome://extensions/?id=bhghoamapcdpbohphigoooaddinpkbai")
driver.execute_script("return document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input').click()");
Run Code Online (Sandbox Code Playgroud)

如果您想知道如何以及为什么,请继续阅读

根本原因:

作为 Chrome 浏览器增强功能的一部分,Google 将所有 chrome 选项移至shadow dom. 因此,您无法allow in incognito以 seleniumfind_element方法访问切换元素,该方法将指向页面的原始 dom。所以我们必须切换到shadow dom并访问 中的元素shadow tree

细节:

影子 DOM: 在此输入图像描述

注意:我们将参考图中所示的术语。因此,请仔细阅读图片以便更好地理解。

解决方案:

为了shadow element首先使用,我们必须找到shadow hostShadow dom 所附加的 。下面是根据shadowHost获取shadow root的简单方法。

private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用 ShadowRoot 元素访问影子树元素。

// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));
Run Code Online (Sandbox Code Playgroud)

为了简化上述所有步骤,创建了以下方法。

public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
    WebElement shardowRoot = getShadowRoot(driver, shadowHost);
    return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}
Run Code Online (Sandbox Code Playgroud)

现在您可以通过单个方法调用获取shadowTree元素

WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");
Run Code Online (Sandbox Code Playgroud)

并照常执行操作,如.click(), .getText()

shadowTreeElement.click()
Run Code Online (Sandbox Code Playgroud)

当您只有一层影子 DOM 时,这看起来很简单。但在这里,在这种情况下,我们有多个级别的影子 dom。因此,我们必须通过到达每个影子主机和根来访问该元素。 在此输入图像描述

下面是使用上述方法(getShadowElement 和 getShadowRoot)的代码片段

// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("extensions-manager"));

// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "#viewManager > extensions-detail-view.active");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito");
WebElement allowToggle = shadowElementL2.findElement(By.cssSelector("label#label input"));
allowToggle.click();
Run Code Online (Sandbox Code Playgroud)

您可以在单个 js 调用中实现上述所有步骤,如答案开头提到的(在下面添加只是为了减少混乱)。

WebElement allowToggle = (WebElement) js.executeScript("return document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input')");
Run Code Online (Sandbox Code Playgroud)


小智 -1

如果您尝试在 incodnito 中启用已安装的扩展,请尝试以下代码。它应该与铬一起使用。

 driver.get("chrome://extensions-frame");
  WebElement checkbox = driver.findElement(By.xpath("//label[@class='incognito-control']/input[@type='checkbox']"));
  if (!checkbox.isSelected()) {
    checkbox.click();
  }
Run Code Online (Sandbox Code Playgroud)