-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[🚀 Feature]: Language bindings for Firefox Prefs JS API #14266
Comments
@MatzFan, thank you for creating this issue. We will troubleshoot it as soon as we can. Info for maintainersTriage this issue by using labels.
If information is missing, add a helpful comment and then
If the issue is a question, add the
If the issue is valid but there is no time to troubleshoot it, consider adding the
If the issue requires changes or fixes from an external project (e.g., ChromeDriver, GeckoDriver, MSEdgeDriver, W3C),
add the applicable
After troubleshooting the issue, please add the Thank you! |
So as a proof of concept I've created a Ruby module to do this. It can get and set prefs exactly as set out above. I've omitted the tests here for brevity, please let me know if you are interested in supporting this - or if I am reinventing a wheel! module Selenium
module WebDriver
module Firefox
# representation of a Firefox pref API: https://firefox-source-docs.mozilla.org/devtools/preferences.html
class Preference
PREF_TYPES = { 'PREF_BOOL' => 128, 'PREF_INT' => 64, 'PREF_INVALID' => 0, 'PREF_STRING' => 32 }.freeze
GET_METHODS = { 0 => 'getStringPref', 32 => 'getStringPref', 64 => 'getIntPref', 128 => 'getBoolPref' }.freeze
SET_METHODS = { 32 => 'setStringPref', 64 => 'setIntPref', 128 => 'setBoolPref' }.freeze
def initialize(driver)
@driver = driver
end
def [](str)
execute_script_and_preserve_context str
end
def []=(str, val)
execute_script_and_preserve_context str, val
end
private
def execute_script_and_preserve_context(str, val = nil)
@driver.in_chrome_context { @driver.execute_script(script_string(str, val)) }
end
def script_string(str, val)
val ? setter_script(str, val) : getter_script(str)
end
def getter_script(str)
type = pref_type(str)
"return Services.prefs.#{GET_METHODS[type]}('#{str}'#{default(type)})"
end
def default(type)
type.zero? ? ", ''" : '' # empty string default arg if pref not found, otherwise no default arg
end
def setter_script(str, val)
"Services.prefs.#{set_method(str, val)}('#{str}', #{quote_str(val)})"
end
def set_method(str, val)
type = pref_type(str)
return SET_METHODS[type] unless type.zero?
return 'setBoolPref' if val.instance_of?(TrueClass) || val.instance_of?(FalseClass)
return 'setIntPref' if val.is_a? Integer
'setStringPref' # everthing else gets set as a string
end
def pref_type(string)
@driver.execute_script("return Services.prefs.getPrefType('#{string}')")
end
def quote_str(value)
value.is_a?(String) ? "'#{value}'" : value
end
end
# adds Driver#pref method and [] and []= methods on that object
module FirefoxPrefs
def pref
in_chrome_context { Preference.new(self) }
end
def in_chrome_context
old_context = context
self.context = 'chrome'
yield
ensure
self.context = old_context
end
end
class Driver
prepend FirefoxPrefs
end
end
end
end |
FWIW here is an example of a Python project using Selenium which uses the Firefox Prefs JS API to set driver prefs. |
We are looking for projects to host on https://github.com/seleniumhq-community/, if you wish to work on this, it would be a great plugin that can be added as a dependency by any user. Would you be interested in doing that? |
@diemol if you are not interested in incorporating such functionality directly into Selenium (it adds a dependency on the Firefox Prefs JS API) I was planning to simply release my code as a Ruby gem. Are Selenium Community repos simply mirrors of contributors' projects? If so I see no reason why I wouldn't set up a mirror there - and also for my Selenium Tor Browser project too. Can you point me to the docs on Selenium Community? |
Selenium is meant to be a base library where users can build things on top. This use case is the perfect example of that. The community org is meant to host projects driven and owned by the community, with the advantage of using the Selenium name to promote them. We don't have any formal docs because we are getting started. If you are interested, please join our Slack workspace, and we can chat about this. |
I will close this as the issue has not had any more activity. |
Feature and motivation
I would like to be able to get the value of a preference set in
about:config
dynamically. These are set when instantiating a driver viaOptions[:prefs]
values). I'd also like to be able to dynamically set a preference.The JS API for Firefox prefs seems straightforward. I do note that Firefox CDP is being deprecated IFO BiDi, could someone confirm whether this JS API is part of that scope or not?
Usage example
From your own Ruby tests I see here that you get a preference value like so, by passing a JS string to the
Driver#execute_script
method.Something like this would be much better:
And the equivalent to set a pref value:
The text was updated successfully, but these errors were encountered: