10

Selenium2, by default, starts firefox with a fresh profile. I like that for a default, but for some good reasons (access to my bookmarks, saved passwords, use my add-ons, etc.) I want to start with my default profile.

There is supposed to be a property controlling this but I think the docs are out of sync with the source, because as far as I can tell webdriver.firefox.bin is the only one that works. E.g. starting selenium with:

java -jar selenium-server-standalone-2.5.0.jar -Dwebdriver.firefox.bin=not-there

works (i.e. it complains). But this has no effect:

java -jar selenium-server-standalone-2.5.0.jar -Dwebdriver.firefox.profile=default

("default" is the name in profiles.ini, but I've also tried with "Profile0" which is the name of the section in profiles.ini).

I'm using PHPWebdriver (which uses JsonWireProtocol) to access:

$webdriver = new WebDriver("localhost", "4444");

$webdriver->connect("firefox");

I tried doing it from the PHP side:

$webdriver->connect("firefox","",array('profile'=>'default') );

or:

$webdriver->connect("firefox","",array('profile'=>'Profile0') );

with no success (firefox starts, but not using my profile).

I also tried the hacker's approach of creating a batch file:

#!/bin/bash
/usr/bin/firefox -P default

And then starting Selenium with: java -jar selenium-server-standalone-2.5.0.jar -Dwebdriver.firefox.bin="/usr/local/src/selenium/myfirefox"

Firefox starts, but not using by default profile and, worse, everything hangs: selenium does not seem able to communicate with firefox when started this way.

P.S. I saw Selenium - Custom Firefox profile I tried this:

java -jar selenium-server-standalone-2.5.0.jar -firefoxProfileTemplate "not-there"

And it refuses to run! Excited, thinking I might be on to something, I tried:

java -jar selenium-server-standalone-2.5.0.jar -firefoxProfileTemplate /path/to/0abczyxw.default/

This does nothing. I.e. it still starts with a new profile :-(

Community
  • 1
  • 1
Darren Cook
  • 27,837
  • 13
  • 117
  • 217

6 Answers6

10

Simon Stewart answered this on the mailing list for me.

To summarize his reply: you take your firefox profile, zip it up (zip, not tgz), base64-encode it, then send the whole thing as a /session json request (put the base64 string in the firefox_profile key of the Capabilities object).

An example way to do this on Linux:

cd /your/profile
zip -r profile *
base64 profile.zip > profile.zip.b64

And then if you're using PHPWebDriver when connecting do:

$webdriver->connect("firefox", "", array("firefox_profile" => file_get_contents("/your/profile/profile.zip.b64")))

NOTE: It still won't be my real profile, rather a copy of it. So bookmarks won't be remembered, the cache won't be filled, etc.

David Sickmiller
  • 1,145
  • 8
  • 8
Darren Cook
  • 27,837
  • 13
  • 117
  • 217
  • Thanks, that was really helpful. Would be nice if the PHP code to zip the profile and then encode to base64 was provided so one could do everything in PHP. – David Dec 29 '11 at 00:24
  • Reconfirming what has already been stated... This is the way to go. Worked flawless for us when we wanted to pipe all selenium requests thru a proxy. – anonymous-one May 12 '12 at 20:24
5
java -jar selenium-server-standalone-2.21.0.jar -Dwebdriver.firefox.profile=default

should work. the bug is fixed.

Just update your selenium-server.

j0k
  • 22,600
  • 28
  • 79
  • 90
5

Here is the Java equivalent. I am sure there is something similar available in php.

ProfilesIni profile = new ProfilesIni();
FirefoxProfile ffprofile = profile.getProfile("default");
WebDriver driver = new FirefoxDriver(ffprofile);

If you want to additonal extensions you can do something like this as well.

ProfilesIni profile = new ProfilesIni();
FirefoxProfile ffprofile = profile.getProfile("default");
ffprofile.addExtension(new File("path/to/my/firebug.xpi"));
WebDriver driver = new FirefoxDriver(ffprofile);
nilesh
  • 14,131
  • 7
  • 65
  • 79
  • Thanks @nilesh. Am I correct in thinking this is using WebDriver directly; you are not starting `selenium-server-standalone.jar` and therefore not using JsonWireProtocol? – Darren Cook Sep 08 '11 at 01:26
  • This is using webdriver directly. I am not sure what you mean by starting with stand alone jar. WebDriver itself uses JsonWireProtocol to communicate http://code.google.com/p/selenium/wiki/JsonWireProtocol – nilesh Sep 08 '11 at 01:47
  • Ah, interesting. So your above java snippet somehow gets turned into JSON and web service calls? If I could just track down what those calls are then I could implement it in the PHP library. But whatever it is doing is not documented at the URL you gave, and I've not see any other docs for the JsonWireProtocol. I think I'll contact the Selenium developers. – Darren Cook Sep 08 '11 at 12:53
1

I did It in Zend like this:

    public function indexAction(){
    $appdata = 'C:\Users\randomname\AppData\Roaming\Mozilla\Firefox' . "\\";
    $temp = 'C:\Temp\\';
    $hash = md5(rand(0, 999999999999999999));
    if(!isset($this->params['p'])){
        shell_exec("\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\" -CreateProfile " . $hash);
    }else{
        $hash = $this->params['p'];
    }
    $ini = new Zend_Config_Ini('C:\Users\randomname\AppData\Roaming\Mozilla\Firefox\profiles.ini');
    $path = false;
    foreach ($ini as $key => $value){
        if(isset($value->Name) && $value->Name == $hash){
            $path = $value->Path;
            break;
        }
    }
    if($path === false){
        die('<pre>No profile found with name: ' . $hash);
    }
    echo "<pre>Profile : $hash \nProfile Path : " . $appdata . "$path \n";
    echo "Files: \n";
    $filesAndDirs = $this->getAllFiles($appdata . $path);
    $files = $filesAndDirs[0];
    foreach ($files as $file){
        echo "  $file\n";
    }
    echo "Dirs : \n";
    $dirs = array_reverse($filesAndDirs[1]);
    foreach ($dirs as $dir){
        echo "  $dir\n";
    }
    echo 'Zipping : ';
    $zip = new ZipArchive();
    $zipPath = md5($path) . ".temp.zip";
    $zipRet = $zip->open($temp .$zipPath, ZipArchive::CREATE);
    echo ($zipRet === true)?"Succes\n":"Error $zipRet\n";
    echo "Zip name : $zipPath\n";
    foreach ($dirs as $dir){
        $zipRet = $zip->addEmptyDir($dir);
        if(!($zipRet === true) ){
            echo "Error creating folder: $dir\n";
        }
    }
    foreach ($files as $file){
        $zipRet = $zip->addFile($appdata . $path ."\\". $file,$file);
        if(!($zipRet === true && file_exists($appdata . $path . "\\".  $file) && is_readable($appdata . $path . "\\". $file))){
            echo "Error zipping file: $appdata$path/$file\n";
        }
    }
    $zipRet = $zip->addFile($appdata . $path ."\\prefs.js",'user.js');
    if(!($zipRet === true && file_exists($appdata . $path . "\\".  $file) && is_readable($appdata . $path . "\\". $file))){
        echo "Error zipping file: $appdata$path/$file\n";
    }
    $zipRet = $zip->close();
    echo "Closing zip : " . (($zipRet === true)?("Succes\n"):("Error:\n"));
    if($zipRet !== true){
        var_dump($zipRet);
    }
    echo "Reading zip in string\n";
    $zipString = file_get_contents($temp .$zipPath);
    echo "Encoding zip\n";
    $zipString = base64_encode($zipString);
    echo $zipString . "\n";
    require 'webdriver.php';
    echo "Connecting Selenium\n";
    $webDriver = new WebDriver("localhost",'4444');
    if(!$webDriver->connect("firefox","",array('firefox_profile'=>$zipString))
{
        die('Selenium is not running');
    }
}
    private function getAllFiles($path,$WithPath = false){
    $return = array();
    $dirs = array();
    if (is_dir($path)) {
        if ($dh = opendir($path)) {
            while (($file = readdir($dh)) !== false) {
                if(!in_array($file, array('.','..'))){
                    if(is_dir($path . "\\" . $file)){
                        $returned = $this->getAllFiles($path . "\\" . $file,(($WithPath==false)?'':$WithPath) . $file . "\\");
                        $return = array_merge($return,$returned[0]);
                        $dirs = array_merge($dirs,$returned[1]);
                        $dirs[] = (($WithPath==false)?'':$WithPath) . $file;
                    }else{
                        $return[] = (($WithPath==false)?'':$WithPath) . $file;
                    }
                }
            }
            closedir($dh);
        }
    }
    return array($return,$dirs);
}

The Idea is that you give in the get/post/zend parameters P with the name of the profile if not a random wil be created, and he will zip all the files put it in the temp folder and put it in.

EaterOfCode
  • 2,202
  • 3
  • 20
  • 33
1

I was curious about this as well and what I got to work was very simple. I use the command /Applications/Firefox.app/Contents/MacOS/firefox-bin -P to bring up Profile Manager. After I found which profile I needed to use I used the following code to activate the profile browser = Selenium::WebDriver.for :firefox, :profile => "batman".

This pulled all of my bookmarks and plug-ins that were associated with that profile.

Hope this helps.

Curtis Miller
  • 580
  • 1
  • 9
  • 31
1

From my understanding, it is not possible to use the -Dwebdriver.firefox.profile=<name> command line parameter since it will not be taken into account in your use case because of the current code design. Since I faced the same issue and did not want to upload a profile directory every time a new session is created, I've implemented this patch that introduces a new firefox_profile_name parameter that can be used in the JSON capabilities to target a specific Firefox profile on the remote server. Hope this helps.

Stéphane
  • 3,884
  • 1
  • 30
  • 27
  • Great @Stéphane - if I've understood your patch, that is exactly what I was after. I've not tested it yet, but is it safe? (i.e. in its tidyup stage selenium deletes the temporary profile directory it creates; don't you need explicit code to stop that happening?) – Darren Cook Oct 02 '11 at 07:23
  • Yes, it is safe. Selenium will in fact make a temporary copy of this profile and use it (like a template). – Stéphane Dec 28 '12 at 15:16