Selenium: FirefoxProfile passed to FirefoxDriver ctor not considered when using Marionette

Created on 4 Aug 2016  Â·  15Comments  Â·  Source: SeleniumHQ/selenium

Meta -

OS: Ubuntu 14.04 LTS, 64bit
Selenium Version: 3.0.0-beta1
Browser: Firefox
Browser Version: 47.0.1

Expected Behavior -

Firefox starts with the passed profile.

Actual Behavior -

Firefox starts with an empty profile.

Steps to reproduce -

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.

C-java D-marionette E-less easy G-w3c I-defect

All 15 comments

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:

  1. Change _GeckoDriverService.Builder_ to accept the passed profile and binary arguments.
  2. Create a method in _GeckoDriverService_ that accepts the capabilities and feeds in the 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.
  3. Update _FirefoxDriver#createCommandExecutor_ to pass binary and profile to the _GeckoDriverService.Builder_.
  4. Make this ctor modify the capabilities so that it takes the updated capabilities.

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:

  • Selenium version that you are using.
  • Sample code
  • Firefox version
  • Geckodriver version
  • Complete stacktrace

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.

Was this page helpful?
0 / 5 - 0 ratings