Enabling Chrome Extension in Incognito Mode via CLI flags?
Asked Answered
H

4

8

I'm using selenium to test a chrome extension and part of the extension requires the user to be in incognito mode. Currently, I've not been able to enable the extension to be allowed in incognito mode upon startup except by adding the argument user-data-dir=/path/to/directory.

The problem with this is that it loads the extension from the depths of my file system, rather than in a way I can check into git.

I've also tried navigating selenium to the chrome extensions settings page but it seems that selenium can't drive chrome:// pages.

Any ideas on to how to enable incognito on the chrome extension on boot of the chrome driver?

Hispania answered 17/12, 2014 at 20:53 Comment(3)
It's Probably duplicated with this one: #17438854Shortlived
@gui47 Not exactly a duplicate: that question asks about enabling from within the extension, here it asks for enabling from the command line.Nigrescent
Well I see. I argue there is a way to run and turn on the extension by creating a shortcut and add the two switches. "C:\Users\%user%\AppData\Local\Google\Chrome\Application\chrome.exe" --incognito --enable-extensionsShortlived
L
6

Here is the solution that will work with the latest version of Chrome 74.

  1. Navigate to chrome://extensions
  2. Click on Details button for your desired extension

enter image description here

  1. Copy the url (This contains your extension id)

Now we have to navigate to the above url and then click on the allow in incognito toggle.

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

Continue Reading, if you want to know how and why

Root Cause:

As part of enhancements to the chrome browser, google moved all the chrome option in to shadow dom. So you can not access allow in incognito toggle element as selenium find_element method which will point to the original dom of the page. So we have to switch to the shadow dom and access the elements in the shadow tree.

Details:

Shadow DOM: enter image description here

Note: We will be referring to the terms shown in the picture. So please go through the picture for better understanding.

Solution:

In order to work with shadow element first we have to find the shadow host to which the shadow dom is attached. Here is the simple method to get the shadow root based on the shadowHost.

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

And then you can access the shadow tree element using the shadowRoot Element.

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

In order to simplify all the above steps created the below method.

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

Now you can get the shadowTree Element with single method call

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

And perform the operations as usual like .click(), .getText().

shadowTreeElement.click()

This Looks simple when you have only one level of shadow DOM. But here, in this case we have multiple levels of shadow doms. So we have to access the element by reaching each shadow host and root. enter image description here

Below is the snippet using the methods that mentioned above (getShadowElement and 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();

You can achieve all the above steps in single js call as at mentioned at the beginning of the answer (added below just to reduce the confusion).

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')");
Langford answered 1/6, 2019 at 22:33 Comment(0)
L
1

In chrome version 69 this code works (Python version):

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)

Just remember to change var extensionName = 'TestRevolution'; line to your extension name.

Lundgren answered 21/3, 2019 at 19:36 Comment(0)
E
0

I'm still newbie in coding, but I figured another method after looking in chrome's crisper.js at chrome://extensions/ .

First you need to know the extension ID. You can do it by making the id constant here, or using pako's method on obtaining the id's. For mine it's "lmpekldgmhemmmbllpdmafmlofflampm"

Then launch chrome with --incognito and addExtension, then execute the javascript to enable in incognito.

Example:

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

    } 
}

Hope it helps :)

Exorbitant answered 16/4, 2019 at 11:23 Comment(0)
Q
-1

If you are trying to enable the already installed extension in incodnito, then try the below code . It should work with chrome.

 driver.get("chrome://extensions-frame");
  WebElement checkbox = driver.findElement(By.xpath("//label[@class='incognito-control']/input[@type='checkbox']"));
  if (!checkbox.isSelected()) {
    checkbox.click();
  }
Quinque answered 14/11, 2017 at 19:49 Comment(1)
They've changed everything in the new extensions and now your solution doesn't work anymore. It's getting much more complicated and ugly.Porterfield

© 2022 - 2024 — McMap. All rights reserved.