OS: Ubuntu 14.04 LTS, 64bit
Selenium Version: 3.0.0-beta1
Browser: Firefox
Browser Version: 47.0.1
Firefox starts with the passed profile.
Firefox starts with an empty profile.
Invoke the FirefoxDriver constructor with a reference to a FirefoxProfile object as argument, e.g.:
WebDriver driver = new FirefoxDriver(new FirefoxBinary(), profile);
driver.get("http://seleniumhq.org");
The only workaround I've seen is to use capabilities that have the profile set. But since the profile is extracted from the caps anyway and FirefoxDriver provides a proper constructor to pass the profile directly, I'm wondering why you pointlessly force the user to use caps.
As the legacy driver works fine with this way, Marionette should do so too.
Please log GeckoDriver issues with Mozilla.
https://github.com/mozilla/geckodriver/issues
Please be sure to include a completely reproducible test script for them, without a way to reproduce the issue you are seeing there is no good way for them to fix the problem. A reproducible test script includes a WebDriver script and a link to the page in question. If you can not provide a link, create one using jsfiddle.net
This is NOT a geckodriver issue (as they correctly evaluate the passed capabilities) but a FirefoxDriver issue since the passed FirefoxProfile is completely ignored. If you don't want to support this way of FirefoxDriver construction any longer, please mark them as deprecated. Otherwise, handle the passed parameters appropriately since users don't pass them just for fun.
To be more precise. The Java code of FirefoxDriver reads:
private static final CommandExecutor createCommandExecutor(Capabilities desiredCapabilities,
FirefoxBinary binary,
FirefoxProfile profile) {
if (isLegacy(desiredCapabilities)) {
return new LazyCommandExecutor(binary, profile);
}
GeckoDriverService.Builder builder = new GeckoDriverService.Builder();
builder.usingPort(0);
return new DriverCommandExecutor(builder.build());
}
The legacy mode is handled correctly but in case Marionette should be used, the passed profile is just ignored instead of adding it to the passed caps.
The GeckoDriver does not need to be started with a profile, doesn't support it. The DesiredCapabilities need to have "firefox_profile" added to them, so you should be using the FirefoxDriver(Capabilities) constructor instead, which will be compatible with the old way and the new... although the constructors could use some cleanup / deprecation.
@krmahadevan pointed out in https://github.com/mozilla/geckodriver/issues/236 that the reason why people are having problems using Firefox profiles with geckodriver is that the profile passed to the Java bindings’ ctor is not being used when creating a _DriverCommandExecutor_ in https://github.com/SeleniumHQ/selenium/blob/master/java/client/src/org/openqa/selenium/firefox/FirefoxDriver.java#L236-L245:
private static final CommandExecutor createCommandExecutor(Capabilities desiredCapabilities,
FirefoxBinary binary,
FirefoxProfile profile) {
if (isLegacy(desiredCapabilities)) {
return new LazyCommandExecutor(binary, profile);
}
GeckoDriverService.Builder builder = new GeckoDriverService.Builder();
builder.usingPort(0);
return new DriverCommandExecutor(builder.build());
}
As far as I can tell, we need to:
profile and binary arguments.firefox_profile and firefox_binary with a Base64-encoded version of _FirefoxProfile_ and a the full path to the browser binary, and which returns the modified set of capabilities.binary and profile to the _GeckoDriverService.Builder_.I suspect the _ChromeDriver_ class uses a similar approach, and it can be used for inspiration.
Fixed in 8bfa175bd62c0eb078ea1505e872788f7ed48446
The passed profile is still ignored as described in this defect's "Steps To Reproduce".
It works, if you replace (or complement) desiredCapabilities.setCapability(FirefoxDriver.PROFILE, profile); by new FirefoxOptions().setProfile(profile).addTo(desiredCapabilities);, since the code of 8bfa175 does only have an influence if a FirefoxOption object is added to the desiredCapabilities.
It finally works now, thanks to https://github.com/SeleniumHQ/selenium/commit/2a746cc50f1dcac25457bbd5647527ed883c89ab.
But the question remains why there is still an 'official' way to instantiate FirefoxDrivers this way instead of deprecating these constructors and advise users to use Capabilities.
BTW what's the intention of passing two types of capabilities? ChromeDriver, for example, just needs one. I know that it's off-topic but other users may struggle with it too.
But you still need the workaround above to use the constructor public FirefoxDriver(GeckoDriverService driverService, Capabilities desiredCapabilities,
Capabilities requiredCapabilities) with an self-defined _driverService_, since populateProfileis not public, and without populateProfile (and no options set in _desiredCapabilities_), the profile in the _desiredCapabilities_ is still ignored.
That's correct. Thanks for pointing it out.
I tried to use FirefoxOptions and I got this:
org.openqa.selenium.SessionNotCreatedException: Unable to create new remote session. desired capabilities = Capabilities [{marionette=true, firefoxOptions=org.openqa.selenium.firefox.FirefoxOptions@385e9564, moz:firefoxOptions=org.openqa.selenium.firefox.FirefoxOptions@385e9564...}], required capabilities = Capabilities [{}]
What can I do?
@Moustakas42 Since this issue is already closed, I would suggest that you please open up a new issue (you can refer to this issue in that new issue) adding details about the following in your issue:
Hi all, this thread seems to be the end-all be-all regarding the Firefox Profile issues so I have a question on how to implement this update into my Python code--apologies if this is not the place for this question. My code currently reads as:
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList", 1)
fp.set_preference("browser.helperApps.alwaysAsk.force", False)
fp.set_preference("browser.download.manager.showWhenStarting",False)
fp.set_preference("browser.download.dir", "H:\Downloads")
fp.set_preference("browser.download.downloadDir","H:\Downloads")
fp.set_preference("browser.download.defaultFolder","H:\Downloads")
binary = FirefoxBinary(r'C:\Program Files (x86)\Mozilla Firefox\Firefox.exe')
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
driver = webdriver.Firefox(capabilities=firefox_capabilities,firefox_binary=binary, firefox_profile = fp)
As earlier threads, such as https://github.com/mozilla/geckodriver/issues/236, explain the issue I was having, I understand that much. I'm confused as to how to update my code now. I'm assuming I need to remove my firefox_profile and update my capabilities, but not exactly sure how to do that. Thanks for any input.
Can someone help me with this piece of code
//Extension path
String extFilePath = "C:\Program Files\vinIIext.xpi";
//*****FIREFOX**********
//Set the desired capabilities to the browser we wish to use:
DesiredCapabilities dc = DesiredCapabilities.firefox();
//Instantiate Firefox
FirefoxProfile profile = new FirefoxProfile();
profile.addExtension(new File(extFilePath));
WebDriver webDriver = new FirefoxDriver(profile);
The last line will say "Cannot resolve constructor"
@nabeelrahman Please don’t hijack old, closed issues. Your question is client specific, so you should consult with your client’s documentation or raise an issue there.