Friday, May 7, 2010

Lesson #1: Improper XPCOM definitions can lead to silent failure

I've been tasked with implementing electrolysis (e10s) support for FTP. That means letting child processes (content) send requests to the parent process (chrome), which actually does the networking - while from the perspective of the child process, the interface to an FTP channel is the same.

As this is just my second week at Mozilla, I am still learning the build process, fundamental technologies like XPCOM, and other stuff about the codebase. So I ran into some problems, which I'll mention here on the blog in hopes that they help other people that search for the same keywords.

So, lesson #1 is: Improper XPCOM definitions can lead to silent failure.

Specifically, the issue was that this:

  NS_IMPL_ADDREF_INHERITED(FTPChannelChild, FTPBaseChannel)
  NS_IMPL_RELEASE_INHERITED(FTPChannelChild, FTPBaseChannel)

  NS_INTERFACE_MAP_BEGIN(FTPChannelChild)
    NS_INTERFACE_MAP_ENTRY(nsIRequest)
    NS_INTERFACE_MAP_ENTRY(nsIChannel) 
    NS_INTERFACE_MAP_ENTRY(nsIFTPChannel)
  NS_INTERFACE_MAP_END_INHERITING(FTPBaseChannel)

was needed, and I was missing the nsIRequest line. I missed it because nsIRequest is a parent interface, and I didn't realize it was also necessary. And, indeed, when sent through JavaScript to a function that expects to receive an object with that interface, it fails. What was tricky was it silently failed - I called a JavaScript function, which was known to work, and it simply returned a failure code, without even starting the function. Only by stepping through all the JS embedding code did it eventually become clear to me that a call to QueryInterface was failing, so the JS embedding code was failing to set up the parameters for the JS function, and not even calling it.

No comments:

Post a Comment