Selenium Webdriver: Firefox Headless Inject Javascript To Modify Browser Property
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
Solution 1:
I found the solution to the problem by following this post. In few words, by using an extensions it is possible to inject javascript code into the Web page also with firefox. In order to avoid a waste of time for the other users, the main files are:
Python file: selenium+firefox
import json
import os
import sys
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.firefox.firefox_profile import AddonFormatError
# Patch in support for WebExtensions in Firefox.# See: https://intoli.com/blog/firefox-extensions-with-selenium/classFirefoxProfileWithWebExtensionSupport(webdriver.FirefoxProfile):
def_addon_details(self, addon_path):
try:
returnsuper()._addon_details(addon_path)
except AddonFormatError:
try:
withopen(os.path.join(addon_path, "manifest.json"), "r") as f:
manifest = json.load(f)
return {
"id": manifest["applications"]["gecko"]["id"],
"version": manifest["version"],
"name": manifest["name"],
"unpack": False,
}
except (IOError, KeyError) as e:
raise AddonFormatError(str(e), sys.exc_info()[2])
profile_folder="profile_path"
profile=FirefoxProfileWithWebExtensionSupport(profile_folder)
extension_directory="extension"
profile.add_extension(extension_directory)
# firefox dev it is necessary for custom profile, not for standard one
firefox_binary="/usr/bin/firefox-dev"
options=webdriver.FirefoxOptions()
# firefox 56+ headless mode https://developer.mozilla.org/en-US/Firefox/Headless_mode
options.set_headless(True)
driver=webdriver.Firefox(options=options, firefox_profile=profile, firefox_binary=firefox_binary)
test_url="https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html";
driver.get(test_url)
file="selenium-firefox-extension-profile-script-second-test.png"
driver.save_screenshot(file)
test_url="https://intoli.com/blog/making-chrome-headless-undetectable/chrome-headless-test.html";
driver.get(test_url)
file="selenium-firefox-extension-profile-script-first-test.png"
driver.save_screenshot(file)
driver.quit()
Extensions files: manifest.js and content.js
{
"manifest_version": 2,
"name": "Smart Extension",
"version": "1.0.0",
"applications": {
"gecko": {
"id": "user@protonmail.com"
}
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_start"
}
]
}
var script=document.createElement("script");
script.src=browser.extension.getURL("myscript.js");
script.async=false;
document.documentElement.appendChild(script);
Javascript file: myscript.js
// overwrite the `languages` property to use a custom getterObject.defineProperty(navigator, "languages", {
get: function() {
return ["en", "es"];
}
});
// Overwrite the `plugins` property to use a custom getter.Object.defineProperty(navigator, "plugins", {
get: () =>newArray(Math.floor(Math.random() * 6) + 1),
});
// Pass the Webdriver testObject.defineProperty(navigator, "webdriver", {
get: () =>false,
});
// hairline: store the existing descriptorconst elementDescriptor=Object.getOwnPropertyDescriptor(HTMLElement.prototype, "offsetHeight");
// redefine the property with a patched descriptorObject.defineProperty(HTMLDivElement.prototype, "offsetHeight", {
...elementDescriptor,
get: function() {
if (this.id === "modernizr") {
return1;
}
return elementDescriptor.get.apply(this);
},
});
["height", "width"].forEach(property => {
// store the existing descriptorconst imageDescriptor=Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, property);
// redefine the property with a patched descriptorObject.defineProperty(HTMLImageElement.prototype, property, {
...imageDescriptor,
get: function() {
// return an arbitrary non-zero dimension if the image failed to loadif (this.complete && this.naturalHeight == 0) {
return24;
}
// otherwise, return the actual dimensionreturn imageDescriptor.get.apply(this);
},
});
});
const getParameter=WebGLRenderingContext.getParameter;
WebGLRenderingContext.prototype.getParameter=function(parameter) {
// UNMASKED_VENDOR_WEBGL WebGLRenderingContext.prototype.VENDORif (parameter === 37445) {
return"Intel Open Source Technology Center";
}
// UNMASKED_RENDERER_WEBGL WebGLRenderingContext.prototype.RENDERERif (parameter === 37446) {
return"Mesa DRI Intel(R) Ivybridge Mobile";
}
returngetParameter(parameter);
};
This works well for all tests in graphical mode while in headless mode all tests except WebGL test which seems affect to a bug.
Post a Comment for "Selenium Webdriver: Firefox Headless Inject Javascript To Modify Browser Property"