Add custom parameter to FirefoxProfile?
Closed this issue · 10 comments
Hello @stevepryde I was trying to set a custom User-Agent for geckodriver as I understand to set it we should do the following in python
profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "whatever you want")
But as I see there's no such option currently
thirtyfour/src/common/capabilities/firefox.rs
Lines 126 to 139 in dd8830d
I could imagine that there's a bigger list of such settings so might a custom parameter not a bad idea?
PS: I didn't test setting of preference
Yeah I think that is a good idea. As for how to adapt what is there, I'm not sure. Feel free to submit a PR if you have an idea of how you'd like to solve it.
@stevepryde
Does FirefoxProfile even work?
Error: An argument passed to the WebDriver server was invalid:
Status: 400
Additional info:
profile is not a string
Error: invalid argument
Stacktrace:
Because this says it only accepts a Base64 encoded string
Fix: #60
Simple test
use anyhow::Result;
use thirtyfour::{FirefoxCapabilities, WebDriver, WebDriverCommands};
#[tokio::main]
pub async fn main() -> Result<()> {
// User agent string
let user_agent = "Custom";
// Set user agent in capabilities
let mut caps = FirefoxCapabilities::new();
caps.add_firefox_option(
"prefs",
serde_json::json!({ "general.useragent.override": user_agent }),
)?;
// Start webdriver and get user agent string
let c = WebDriver::new("http://localhost:4445", caps).await?;
c.get("https://www.google.si").await?;
let js_user_agent: serde_json::Value = c
.execute_script(r#"return navigator.userAgent;"#)
.await?
.convert()?;
// Test
assert_eq!(user_agent, &js_user_agent);
// Exit
c.close().await?;
Ok(())
}
Maye an impl like this:
This code goes in Capabilities
(This is for adding keys and supporting mutiple nestings)
fn add_key(
&mut self,
key: &[&str],
subkey: &str,
value: impl Serialize,
) -> WebDriverResult<()> {
let mut v = self.get_mut();
let part = &[subkey];
let mut keys = key.into_iter().chain(part.iter()).peekable();
// Move to last avaliable key
while let Some(key) = keys.peek() {
if v[key].is_null() {
break;
}
v = &mut v[key];
keys.next();
}
// Create missing nested objects
for key in keys {
v[key] = json!({});
v = &mut v[key];
}
// Set value
*v = to_value(value)?;
Ok(())
}
This code goes in FirefoxCapabilities
fn set_preference(
&mut self,
key: &str,
value: impl Serialize,
) -> WebDriverResult<()> {
self.add_key(&["moz:firefoxOptions", "prefs"], key, value)
}
Or renaming FirefoxProfile
into FirefoxPreferences
and having it work the same as Capabilities
AKA having helper methods like set_user_agent(agent: &str)
, ... and a genric methods like set(key: &str, value impl Serialize)
, unset(key: &str)
, ...
Or renaming
FirefoxProfile
intoFirefoxPreferences
and having it work the same asCapabilities
AKA having helper methods likeset_user_agent(agent: &str)
, ... and a genric methods likeset(key: &str, value impl Serialize)
,unset(key: &str)
, ...
I like this option. However I don't have bandwidth for this currently. Would you be interested in making this change?
@stevepryde did it. #61
Thanks so much for this. I've also added your above "test" as examples/firefox_preferences.rs (modified a little to align with other examples).