I'm trying to figure out how is possible to use selenium webdriver with python or java to inject javascript in order to modify browser property/attribute. My final object is to get something similar to this with selenium and firefox since it is a more open and flexible choice.
Puppeter and chromium file test.js
:
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({
args: ["--no-sandbox"],
headless: true,
});
const page = await browser.newPage();
const fs = require("fs");
// In your puppeteer script, assuming the javascriptChromium.js file is in same folder of our script
const preloadFile = fs.readFileSync("./javascriptChromium.js", "utf8");
await page.evaluateOnNewDocument(preloadFile);
const testUrl="https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html";
await page.goto(testUrl);
// save screenshot
await page.screenshot({path: "puppeteer-chromium-async-script-test.png"});
await browser.close()
})();
Javascript file javascriptChromium.js
// overwrite the `languages` property to use a custom getter
Object.defineProperty(navigator, "languages", {
get: function() {
return ["en-US", "en", "es"];
}
});
// Overwrite the `plugins` property to use a custom getter.
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5],
});
// Pass the Webdriver test
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
This code works well and I checked that the property are changed via this test Web site.
Now, selenium and firefox:
import os
from selenium import webdriver
def readJSFile(scriptFile):
with open(scriptFile, 'r') as fileHandle:
script=fileHandle.read()
return script
injectedJavascript=readJSFile("./javascriptFirefox.js")
options=webdriver.FirefoxOptions()
options.set_headless(True)
driver=webdriver.Firefox(options=options)
driver.set_script_timeout(3)
# inject JavaScript
try:
driver.execute_async_script(injectedJavascript)
except:
print("Timeout")
# solution found here https://stackoverflow.com/questions/17385779/how-do-i-load-a-javascript-file-into-the-dom-using-selenium
driver.execute_script("var s=window.document.createElement('script'); s.src='javascriptFirefox.js';window.document.head.appendChild(s);")
testUrl="https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html";
driver.get(testUrl)
# example sync script
time=driver.execute_script("return performance.timing.loadEventEnd - performance.timing.navigationStart;")
print(time)
# example async script
time=driver.execute_async_script("var callback = arguments[arguments.length-1]; const time = () => { total=performance.timing.loadEventEnd - performance.timing.navigationStart; callback(total); }; time();")
print(time)
file="selenium-firefox-async-script-test.png"
driver.save_screenshot(file)
driver.quit()
Javascript file javascriptFirefox.js
// overwrite the `languages` property to use a custom getter
const setProperty = () => {
Object.defineProperty(navigator, "languages", {
get: function() {
return ["en-US", "en", "es"];
}
});
// Overwrite the `plugins` property to use a custom getter.
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5],
});
// Pass the Webdriver test
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
callback();
};
setProperty();
I'm new of javascript, but what seems different between the two approaches (puppeteer and selenium) is about how they manage the current tab/page. The former via page class and method page.evaluateOnNewDocument while for the latter I did not find and equivalent way. I tried also the use greasemonkey or violentlmonkey to inject javascript without success.
Do you have any suggestions?
Thank you