Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enabling Chrome Extension in Incognito Mode via CLI flags?

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?

like image 549
Shri Ganeshram Avatar asked Dec 17 '14 20:12

Shri Ganeshram


People also ask

How do I enable extensions in incognito edge?

Enable Extension in the Edge browser in Incognito mode. Open your Edge browser and type edge://extensions in the search bar and press Enter. Select the Extension you want to enable for Incognito mode and click on Details. Scroll down to 'Allow in Inprivate' and enable this option.


2 Answers

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')");
like image 101
supputuri Avatar answered Sep 23 '22 00:09

supputuri


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.

like image 38
pawelbylina Avatar answered Sep 24 '22 00:09

pawelbylina