Working on code generator | Anny G's blog

Working on code generator

Written on Jul 28, 2018

Addressing differences in how components are defined

Services.jsm exposes a bunch of components and not all of them are treated equally. Some of them are exposed only if another class has been registered, or if the current platform is android. Sometimes we want to expose additional interfaces that we know the component implements for sure and sometimes the component might not be implementing those interfaces. Trying to take care of all of those differences and passing extra parameters to the Service object (in python) will be a nightmare and not very elegant.

For example,

So, at least

So here is my plan

I was also thinking about how I will eliminate all calls to Services.jsm or at least make it so they are forwarded to Components.Services. For testing, I could make it so that I comment out all of Services.jsm and instead define a global like so const Services = Components.Services. This will allow me to quickly test if all of the Services are working as expected instead of replacing all of them at once and discovering some of them are not working.

Another thing I could do is to create a mochitest of some sort and get each service manually and ensure that I get no errors while retrieving them. This can be an additional level of testing, in case not all of the exposed services are used by JavaScript consumers.

Components.classes

I need to figure out what exactly the following code bit means

if ("@mozilla.org/browser/enterprisepolicies;1" in Cc) {
  initTable.policies = ["@mozilla.org/browser/enterprisepolicies;1", "nsIEnterprisePolicies"];
}

From this mdn article

Note that Components.classes reflects only those component classes that have been previously installed and registered with the component manager using ContractIDs. If you want to use a class which was only registered with their CID, use Components.classesByID instead of Components.classes to retrieve it.

How do we check if a certain component has registered with their contract id in C++?

Fast forward to 3 minutes later, somehow, I stumbled upon XPCOM Reference, and from there I found Core XPCOM functions and there I saw this:

The NS_GetComponentRegistrar function returns a reference to the XPCOM Component Registrar.

Registrar sounds like something that could be useful to me! Looking at the method overview of nsIComponentRegistrar we can see that one of the functions is boolean isContractIDRegistered(in string aContractID);. From the documentation,

This method is used to test for the existence of a class implementing a specific ContractID.

I think this is what I was looking for! To double check, I will do a code search for the use of this function to see if it’s ever used in C++ code.

Indeed, it is used in several places including here:

nsCOMPtr<nsIComponentRegistrar> registrar;
nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv) && registrar) {
   bool result;
   rv = registrar->IsContractIDRegistered(contractID.get(), &result);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   ...
}