Advanced FireWatir – cheat sheet

by Matt 20. October 2009 18:18

OK, so the last post was a bit heavy. Er, detailed. The upshot is that FireWatir, a Ruby library for automating Firefox via the JSSh (JavaScript Shell) extension can get access to the same APIs used by JavaScript Firefox extensions, allowing for some very low level automation of Firefox. The example in that post showed how to send arbitrary extra headers when navigating to a page:

# Essentially a copy of goto(uri) but can pass headers through the request
# Pass a list of headers, e.g. [ "X-Forwarded-For: 10.15.142.22", "cheese: toast" ]
# (Note that we should also be able to post data through this mozilla method)
def goto_with_headers(url, headers)
  #set_defaults()
  get_window_number()
  set_browser_document()
  h = ""
  headers.each {|value| h += "#{value}\\r\\n" }
  # Load the given url.
  jssh_command = "var headers ="
jssh_command += "Components.classes['@mozilla.org/io/string-input-stream;1']"
jssh_command += ".createInstance(Components.interfaces.nsIStringInputStream);
" jssh_command += " headers.setData(\"#{h}\", #{h.length});" # first null is referrer, second is postData jssh_command += " #{BROWSER_VAR}.webNavigation.loadURI(\"#{url}\", 0, null,”
jssh_command += "null, headers);
" $jssh_socket.send("#{jssh_command}\n", 0) read_socket() wait() end

I thought it might be useful to show another example, without having to explain the background. If you’re interested in details, read the last post.

Right. Let’s automate Firefox’s preferences. Again, searching for what extensions do, they use the nsIPrefBranch interface to get and set preferences. We’ll do the same.

Instead of using the createInstance method to get the interface, we’re going to use getService (presumably because the preferences service object is already in memory, and we want to get a handle on that, rather than a new instance). In Javascript:

var prefs = Components.classes[\"@mozilla.org/preferences-service;1\"]
    .getService(Components.interfaces.nsIPrefBranch);"
prefs.setBoolPref("app.update.enabled", true);

And the Ruby helper method from my version of FireWatir::Firefox (note the escaped quotes):

def set_bool_preference(key, value)
  jssh_command = "var prefs = Components"
jssh_command += ".classes[\"@mozilla.org/preferences-service;1\"]
" jssh_command += ".getService(Components.interfaces.nsIPrefBranch);" jssh_command += " prefs.setBoolPref(\"#{key}\", #{value});" $jssh_socket.send("#{jssh_command}\n", 0) read_socket() end

Other preferences are stored as strings and as comma separated string values:

def set_string_preference(key, value)
  jssh_command = "var prefs = Components"
jssh_command += ".classes[\"@mozilla.org/preferences-service;1\"]
" jssh_command += ".getService(Components.interfaces.nsIPrefBranch);" jssh_command += " prefs.setCharPref(\"#{key}\", \"#{value}\");" $jssh_socket.send("#{jssh_command}\n", 0) read_socket() end def add_string_preference(key, value) jssh_command = "var prefs = Components"
jssh_command += ".classes[\"@mozilla.org/preferences-service;1\"]
" jssh_command += ".getService(Components.interfaces.nsIPrefBranch);" jssh_command += " var value = prefs.getCharPref(\"#{key}\");" jssh_command += " if (value === '') { value = \"#{value}\"; } else {" jssh_command += " var values = value.split(\",\");" jssh_command += " if (values.indexOf(\"#{value}\") === -1) {"
jssh_command += " values.push(\"#{value}\");"
jssh_command += " }
" jssh_command += " value = values.join(\",\");" jssh_command += " }" jssh_command += " prefs.setCharPref(\"#{key}\", value);" $jssh_socket.send("#{jssh_command}\n", 0) read_socket() end

These can be used to make sure that your test environment’s version of Firefox is correctly setup before using. And if you’re wondering what to use for “key”, then take a browse through Firefox’s about:config (then Google it to see what it does). Here’s what I’m using at work:

browser.set_bool_preference("browser.download.manager.showWhenStarting", false)
# Convert "/" to "\". Double escaped because we're putting it into a JS string
browser.set_string_preference("browser.download.dir",
default_download_dir.gsub(/\//, '\\\\\\')) browser.add_string_preference("browser.helperApps.neverAsk.saveToDisk",
"application/zip") browser.add_string_preference("browser.helperApps.neverAsk.saveToDisk",
"application/postscript") browser.set_bool_preference("app.update.enabled", false) browser.set_bool_preference("browser.search.update", false) browser.set_bool_preference("extensions.update.enabled", false) browser.set_bool_preference("browser.sessionstore.resume_from_crash", false) browser.add_string_preference("network.automatic-ntlm-auth.trusted-uris",
"http://xxx.example.com") browser.add_string_preference("network.automatic-ntlm-auth.trusted-uris",
"http://yyy.examplecom") browser.add_string_preference("network.automatic-ntlm-auth.trusted-uris",
"http://zzz.example.com")

Most useful keys?

  • network.automatic-ntlm-auth.trusted-uris. With this, I can add a domain to automatically get NTLM authentication, so I know my tests won’t get stuck at an authentication prompt.
  • browser.helperApps.neverAsk.saveToDisk. I didn’t even know this one existed, but it’s great. This is a comma separated list of mime types that will always get saved to disk, so again, I know that I won’t get stuck at the confirm download prompt. (This is my favourite – previously, we’ve had to set these up by hand by actually downloading an instance of the file. I’m very happy to be automating this.)

Handy, eh?

One more post to go – let’s dive a bit deeper.

Tags: , , ,

Comments (11) -

Ethan
Ethan
10/22/2009 3:02:01 PM #

You may be interested in work that I have done with JsshSocket, relating to other work I have done with FireWatir. You can see JsshSocket, and related JsshObject, at:

github.com/.../jssh_socket.rb

I have change a lot of FireWatir code (well, most of the firewatir code in fact) to rely on JsshObjects.

Basically, this exposes properties and methods of javascript objects into ruby in a similar manner to how WIN32OLE does. For example, I've rewritten the preference functions you have to use JsshObjects, much more simply, and much more ruby-like:

def set_bool_preference(key, value)
  prefs=jssh_socket.Components.classes['@mozilla.org/preferences-service;1'].getService(jssh_socket.Components.interfaces.nsIPrefBranch)
  prefs.setBoolPref(key, value)
end

def set_string_preference(key, value)
  prefs=jssh_socket.Components.classes['@mozilla.org/preferences-service;1'].getService(jssh_socket.Components.interfaces.nsIPrefBranch)
  prefs.setCharPref(key, value)
end

def add_string_preference(key, new_value)
  prefs=jssh_socket.Components.classes['@mozilla.org/preferences-service;1'].getService(jssh_socket.Components.interfaces.nsIPrefBranch)
  curr_value = prefs.getCharPref(key)
  if curr_value != ''
    values = curr_value.split(',')
    unless values.include?(new_value)
      values << new_value
    end
    new_value=values.join(',')
  end
  prefs.setCharPref(key, new_value)
end

Reply

matt
matt
11/15/2009 5:34:47 PM #

I love this! It's a much nicer way of defining the methods than I had. I hope this makes it into the main FireWatir code... Thanks for the heads up!

Reply

Bus Hire Adelaide
Bus Hire Adelaide
3/6/2011 6:03:10 AM #

Great  blog you've written. I found your information really great  and I really love the look of the blog. I've been trying to find a blog with a good appearance like yours. Thanks for the fantastic blog, I'm going to make my blog similar to yours it's really good.

Reply

nitric pure
nitric pure
4/6/2011 8:04:11 AM #

Am I the only one who thinks your blog theme is pretty cool? I'm thinking maybe its a custom design that you made? Regards, Ian

Reply

Modesta Solverud
Modesta Solverud
5/4/2011 1:32:29 AM #

you are my  inhalation , I own   few blogs   and  occasionally  run out from to post   : (.  -Penelope

Reply

suv review
suv review
7/20/2011 10:25:21 PM #

Una pagina sarà dedicata agli accessori, una alle giacche e ai giubbotti. Troverai le indicazioni per lo spaccio o negozio Moncler più vicino a casa tua e tutte le offerte più vantaggiose di questo prestigioso marchio.

Reply

best hybrid cars 2011
best hybrid cars 2011
7/22/2011 4:49:52 AM #

Una pagina sarà dedicata agli accessori, una alle giacche e ai giubbotti. Troverai le indicazioni per lo spaccio o negozio Moncler più vicino a casa tua e tutte le offerte più vantaggiose di questo prestigioso marchio.

Reply

anm123
anm123
8/3/2011 6:16:58 PM #

As she approached he spoke in <a href="www.ubagsmall.com/.../...vas-Totally-BHQ.html"; >louis vuitton damier azur totally pm</a>  a low,In the women,Carefully picked up the white bottle real estate broker,Her gold hair was all piled up in waves and crinkles <a href="www.ubagsmall.com/.../...as-Berkeley-AQW.html"; >louis vuitton damier azur berkeley handbag</a>  and things,but we,as if they already beheld the New World,Fei Chen louis vuitton damier azur totally pm is a mobilization of the atmosphere of <a href="www.ubagsmall.com/.../...s-Key-Pouch-CGP.html"; >louis vuitton damier azur key pouch</a>  the players,He had settled <a href="www.ubagsmall.com/.../...re-Backpack-AAF.html"; >louis vuitton damier azur pochette bosphore</a>  in the rough country across the county line,spit louis vuitton damier azur berkeley handbag out the crisp tired sweetly,even blackmail to his father,Besides,t get anything out of him,and having louis vuitton damier azur <a href="www.ubagsmall.com/.../...arah-Wallet-CBI.html"; >louis vuitton damier azur sarah wallet</a>  key pouch had to <a href="www.ubagsmall.com/.../...ippy-Wallet-CBL.html"; >louis vuitton damier azur zippy wallet</a>  do <a href="www.ubagsmall.com/.../...as-Berkeley-BND.html"; >louis vuitton damier ebene canvas berkeley</a>  everything off her own bat for years,A narrow passage led directly through the house into the garden behind,and what she discovered she used to her own advantage with Lou.

Reply

Brandon Nickles
Brandon Nickles
8/6/2011 2:40:39 AM #

Great blog I will defenitly be back to visit more. Keep it up!

Reply

Michael Cole
Michael Cole United States
10/15/2011 5:21:38 PM #

Surprisingly insightful many thanks, I think your current followers may well want way more posts of this nature maintain the good work.

Reply

Nicholas
Nicholas
11/10/2011 6:06:28 PM #

Solid thinking. Great article

Reply

Add comment

biuquote
  • Comment
  • Preview
Loading

Rel=Me

Month List

RecentComments

Comment RSS