Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unable to access chrome message passing API from selenium execute_script

I need to send a value to the chrome extension from the browser automation script. the way I'm currently attempting to do it is by trying to invoke the chrome.runtime.sendMessage API from selenium to communicate some value to a chrome extension. The python code is:

import os
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options



chrome_options = Options()
chrome_options.add_extension('/home/lurscher/plugin.crx')
browser = webdriver.Chrome(chrome_options=chrome_options)
browser.get(url)
browser.execute_script("chrome.runtime.sendMessage({someValue: "+str(args.value)+"}, function(response) { console.log('value sent. '+response)})")

I get this error:

Traceback (most recent call last):
  File "tools/selenium/open_page.py", line 17, in <module>
    browser.execute_script("chrome.runtime.sendMessage({someValue: "+str(args.value)+"}, function(response) { console.log('value sent. '+response)})")
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 397, in execute_script
    {'script': script, 'args':converted_args})['value']
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 165, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 164, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: u"unknown error: Cannot call method 'sendMessage' of undefined\n  (Session info: chrome=28.0.1500.71)\n  (Driver info: chromedriver=2.1,platform=Linux 3.5.0-17-generic x86_64)" 

Question: Any idea what I'm doing wrong?

I need to send a value to the chrome extension from the browser automation script. How Do I Do It?

like image 805
lurscher Avatar asked Oct 16 '13 02:10

lurscher


People also ask

Is Selenium compatible with Chrome?

Through WebDriver, Selenium supports all major browsers on the market such as Chrome/Chromium, Firefox, Internet Explorer, Edge, and Safari.


1 Answers

Got a similar error when running this: (JavaScript)

this.driver.executeScript(function () {
    chrome.runtime.sendMessage('start');
});
WebDriverError: unknown error: Cannot read property 'sendMessage' of undefined

It seems to me that chrome.runtime is always available regardless of whether you’re developing extensions or just browsing the web. (Open an Incognito window and evaluate it in the console; it’s there.) So it has to be something to do with WebDriver.

From what I could gather on the interwebs, you must extra configure your driver: https://groups.google.com/forum/#!topic/chromedriver-users/7wF9EHF2jxQ

options.excludeSwitches('test-type'); // this makes chrome.runtime available
builder.setChromeOptions(options);

However this makes the above error evolves into:

WebDriverError: unknown error: Invalid arguments to connect.

That’s because your test page is trying to communicate with your extension which isn’t allowed as per the Chrome specs unless you declare that page in your manifest. e.g.:

"externally_connectable": {
    "matches": [
    "http://localhost:8000/mytest.html”
    ]
}

However you must now include the extension id in your sendMessage call:

this.driver.executeScript(function () {
    chrome.runtime.sendMessage('kjnfjpehjfekjjhcgkodhnpfkoalhehl', 'start');
});

Which I think is a bit awkward.

I would recommend something along the lines of what MGR has suggested that is using a content script to proxy your sendMessage call as content scripts don’t have the restriction imposed on external pages.

What I did was to trigger an event from my tests that would be picked up by a content script which is the one making the sendMessage function call:

In your tests:

this.driver.executeScript(function () {
    var event = document.createEvent('HTMLEvents');
    event.initEvent('extension-button-click', true, true);
    document.dispatchEvent(event);
});

Declare a content script in your manifest:

"content_scripts": [
    { "matches": ["<all_urls>"], "js": ["content_script.js"] }
]

And in content_script.js:

document.addEventListener('extension-button-click', function () {
    chrome.runtime.sendMessage('start');
});

Hope it helps

like image 115
customcommander Avatar answered Oct 14 '22 12:10

customcommander