Wednesday, April 7, 2010

Watir 102: Javascripting XPCOM to remove session cookies in a FireWatir script

Yesterday (see previous entry) I was playing with FireWatir and found that I needed to remove session cookies to ensure a clean starting point for my script. XPCOM allowed me to read back cookies and it seemed very likely that it would also facilitate deletion.

The Mozilla Developer Center cookies examples were very close to what I needed. nsICookieManager.remove seemed perfect. In a FireWatir script it looked like what I needed to read/write cookies was something like this:

def removeCookie(brwsr, host, name, path)
   cmd = "Components.classes['@mozilla.org/cookiemanager;1']"
   cmd += ".getService(Components.interfaces.nsICookieManager)"
   cmd += ".remove(\"" + host + "\", \"" + name + "\", \"" + path + "\", false)";
   puts "Removing cookie " + name + " from " + host + " for path " + path
   result = brwsr.execute_script "#{cmd}\n"   
end

def readCookies(brwsr, site)
   cmd = "var uri = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService)"
   cmd += ".newURI(\"" + site + "\", null, null);"
   cmd += "Components.classes['@mozilla.org/cookieService;1']"
   cmd += ".getService(Components.interfaces.nsICookieService)"
   cmd += ".getCookieString(uri, null);"
   result = brwsr.execute_script "#{cmd}\n"   
end

In my initial attempts to use this I passed in "http://myhost" and although the method succeeded subsequent logging of the updated cookie string showed no change at all. After some fumbling around I discovered a detailed example of manipulating cookies through javascript in an extension. The main difference in their example was no protocol:// in front of the host/domain name. After that it worked perfectly. A simple example follows:

require "watir"

protocol = "http";
host = "mytesthost";
initial_path = "/somethingfuntotest"

site = protocol + "://" + host

def url(brwsr)
   return brwsr.js_eval("document.location.toString();")
end

def readCookies(brwsr, site)
   cmd = "var uri = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService)"
   cmd += ".newURI(\"" + site + "\", null, null);"
   cmd += "Components.classes['@mozilla.org/cookieService;1']"
   cmd += ".getService(Components.interfaces.nsICookieService)"
   cmd += ".getCookieString(uri, null);"
   result = brwsr.execute_script "#{cmd}\n"   
end

#Ref https://developer.mozilla.org/en/nsICookieManager
#Ref http://www.springenwerk.com/2007/07/using-cookies-with-firefox-extensions.html
#Usage removeCookie(brwsr, "myhostname", "SessionIdCookieName", "/")
#Note that passing http://myhostname for host does not appear to work
def removeCookie(brwsr, host, name, path)
   cmd = "Components.classes['@mozilla.org/cookiemanager;1']"
   cmd += ".getService(Components.interfaces.nsICookieManager)"
   cmd += ".remove(\"" + host + "\", \"" + name + "\", \"" + path + "\", false)";
   puts "Removing cookie " + name + " from " + host + " for path " + path
   result = brwsr.execute_script "#{cmd}\n"   
end

Watir::Browser.default = "firefox"
brwsr = Watir::Browser.new

#May have a session id
puts "Cookies for " + site + ": " + readCookies(brwsr, site)
removeCookie(brwsr, host, "JSESSIONID", "/")
#Session id is now gone ... yay!
puts "Cookies for " + site + ": " + readCookies(brwsr, site)

2 comments:

Jacinthe said...

Nice code! Thanks for sharing.
Rumah Dijual

Jacinthe said...

Nice post. I learn something more difficult on completely different blogs everyday. It is going to always be stimulating to learn content from different writers and follow a bit of something from their store. I'd desire to use some with the content on my weblog whether you don't mind. Natually I'll give you a hyperlink on your web blog. Thanks for sharing.
Outsourcing Service Indonesia

Post a Comment