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

8
我正在使用selenium测试chrome扩展程序,而扩展程序的一部分需要用户处于隐身模式。目前,我还没有找到一种方法可以在启动时允许扩展程序在隐身模式下运行,除非添加参数user-data-dir=/path/to/directory。但是,这样做会从我的文件系统深处加载扩展程序,而无法将其纳入git中进行检查。
我还尝试过将selenium导航到chrome扩展程序设置页面,但似乎selenium无法驱动chrome://页面。
有什么想法可以在chrome driver启动时启用chrome扩展程序的隐身模式吗?

这可能与此链接重复:https://dev59.com/52Qm5IYBdhLWcg3wqwbn?rq=1 - Dayton Wang
@gui47 不完全是重复的问题:那个问题询问如何从扩展内启用,而这个问题则询问如何通过命令行启用。 - Xan
1
我明白了。我认为可以通过创建快捷方式并添加两个开关来运行和启用扩展。"C:\Users%user%\AppData\Local\Google\Chrome\Application\chrome.exe" --incognito --enable-extensions - Dayton Wang
4个回答

5

以下是针对最新版本的Chrome 74的解决方案。

  1. 导航至 chrome://extensions
  2. 点击所需扩展的 详情 按钮

enter image description here

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

现在我们必须导航到上述URL,然后单击始终允许进入无痕浏览按钮。

Java:

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()");

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()");

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

根本原因:

作为Chrome浏览器的增强功能的一部分,谷歌将所有Chrome选项移动到了影子DOM中。因此,您无法像使用selenium的 find_element 方法那样访问允许在隐身模式下切换元素,该方法将指向页面的原始DOM。因此,我们必须切换到影子DOM并访问影子树中的元素。

详情:

影子 DOM: enter image description here

注意:我们将引用图片中显示的术语。因此,请参考图片以获得更好的理解。

解决方案:

为了使用影子元素,首先我们必须找到附加了影子DOM影子主机。以下是一个简单的基于shadowHost获取影子根的方法。

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

然后,您可以使用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"));

为了简化以上所有步骤,创建了以下方法。
public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
    WebElement shardowRoot = getShadowRoot(driver, shadowHost);
    return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}

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

WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");

然后像平常一样执行操作,比如 .click(), .getText()

shadowTreeElement.click()

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

enter image description here

以下是使用上述方法(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();

您可以通过在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')");

1
在 Chrome 版本 69 中,这段代码可以正常工作(Python 版本):
driver.get('chrome://extensions')
go_to_extension_js_code = '''
var extensionName = 'TestRevolution';
var extensionsManager = document.querySelector('extensions-manager');
var extensionsItemList = extensionsManager.shadowRoot.querySelector(
'extensions-item-list');
var extensions = extensionsItemList.shadowRoot.querySelectorAll(
'extensions-item');
for (var i = 0; i < extensions.length; i += 1) {
    var extensionItem = extensions[i].shadowRoot;
    if (extensionItem.textContent.indexOf(extensionName) > -1) {
        extensionItem.querySelector('#detailsButton').click();
    }
}
'''
enable_incognito_mode_js_code = '''
var extensionsManager = document.querySelector('extensions-manager');
var extensionsDetailView = extensionsManager.shadowRoot.querySelector(
'extensions-detail-view');
var allowIncognitoRow = extensionsDetailView.shadowRoot.querySelector(
'#allow-incognito');
allowIncognitoRow.shadowRoot.querySelector('#crToggle').click();
'''
driver.execute_script(go_to_extension_js_code)
driver.execute_script(enable_incognito_mode_js_code)

只需记得将 var extensionName = 'TestRevolution'; 这一行更改为你的扩展名即可。


0

我在编程方面还是新手,但是在查看Chrome的crisper.js位于chrome://extensions/后,我找到了另一种方法。

首先,您需要知道扩展程序的ID。您可以通过将id常量here或使用pako的方法获取id来完成。对于我的扩展程序,它是"lmpekldgmhemmmbllpdmafmlofflampm"

然后使用--incognito和addExtension启动Chrome,然后执行JavaScript以在隐身模式下启用。

例如:

    public class test2 {

    static String dir = System.getProperty("user.dir");
    static WebDriver driver;
    static JavascriptExecutor js;

    public static void main(String[] args) throws InterruptedException, IOException{

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--incognito");
        options.addExtensions(new File(dir + "\\randua.crx"));

        System.setProperty("webdriver.chrome.driver",dir + "\\chromedriver73.exe");
        driver = new ChromeDriver(options);
        js = (JavascriptExecutor) driver;

        String extID = "lmpekldgmhemmmbllpdmafmlofflampm";

        driver.get("chrome://extensions-frame/");
        new WebDriverWait(driver, 60).until(webDriver -> js.executeScript("return document.readyState").equals("complete"));

        js.executeScript("chrome.developerPrivate.updateExtensionConfiguration({extensionId: \"" + extID + "\",incognitoAccess: true})");

        Thread.sleep(1000);

    } 
}

希望能有所帮助 :)

-1

如果您正在尝试在隐身模式下启用已安装的扩展程序,则尝试以下代码。它应该适用于Chrome浏览器。

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

他们在新扩展中改变了一切,现在您的解决方案不再起作用。它变得越来越复杂和丑陋。 - Olivier Pons

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接