Accessing priviledged Javascript APIs from your web page in Firefox with Selenium

Firefox is internally built on Javascript components using native C++ bindings. These components are normally exposed only for add-ons. The functionality includes high level stuff like bookmark management and low level functionality like direct disk access.

You might have special situations when you want to directly access these APIs from a  web page you control. One such situation is automated testing where your Javascript test framework might, for the performance reasons, write some test data directly to disk or socket for efficient communication with your host testing process. Another use case is when you are building a Very Special Web Applications and you need to give the admin users some extra special functionality which would be cumbersome to develop using traditional HTML / HTTP platforms.

Note: Enabling XPCOM access globally in your everyday browser is not something you should do due to security implications.

Here is a quick example how you can enable privileged APIs in Selenium Test Driver in Python:

source_uri = "ADDRESS_TO_YOUR_WEB_PAGE_ON_TEST_SERVER"

profile = webdriver.firefox.firefox_profile.FirefoxProfile()

parsed = urlparse.urlparse(source_uri)
host_base = "%s://%s" % (parsed.scheme, parsed.netloc)

print "Enabling XPCOM for codebase", host_base

set_pref = profile.set_preference
set_pref("signed.applets.codebase_principal_support", True)
set_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect");
set_pref("capability.principal.codebase.p0.id", host_base);
set_pref("capability.principal.codebase.p0.subjectName", "");

# This opens a new Firefox browser where the settings
# have been modified to allow XPCom access from URL
# you specified above
self.browser = webdriver.Firefox(firefox_profile=profile)
self.browser.get(source_uri) # Load page

Then you can whitelist Javascript functions for XPCOM access:

/** Decorate the target function to have special XP priviledges.
 * You need to do this for each individual Javascript function
 */
function UseXPCOM(f) {
    return function() {
        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
        return f.apply(this, arguments);
    };
};

And here is an example how you now can have raw disk access for writing files directly from Javascript:

       /** Open file for binary writing access */
       openFileForBinaryWrite : UseXPCOM(function(filename) {
            this.outputFilename = filename;
            this.outputFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
            this.outputFile.initWithPath(filename);
            var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);

            // PR_WRONLY + PR_CREATE_FILE + PR_APPEND, default mode, no behaviour flags
            stream.init(this.outputFile, 0x02 | 0x10, 00600, false);
            this.stream = Components.classes["@mozilla.org/binaryoutputstream;1"].createInstance(Components.interfaces.nsIBinaryOutputStream);

            this.stream.setOutputStream(stream);
        }),

And now you can write there:

this.stream.writeBytes("my bytes");

More about XPCOM APIs.

See the orignal post for syntax highlighted examples.

 

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

Leave a Reply

Your email address will not be published. Required fields are marked *