XPCOM, Components, Services, QueryInterface, Jul, 25, 2018 | Anny G's blog

XPCOM, Components, Services, QueryInterface, Jul, 25, 2018

Written on Jul 24, 2018

Some of the things Mozilla Foundation is involved with

WIP

I have managed to get the pipeline for the code generator to work for one simple service scriptloader. I now need to look into more services, and see how I can implement the complicated ones. The one I am currently looking at is io. In services.jsm there is a following code

XPCOMUtils.defineLazyGetter(Services, "io", () => {
  return Cc["@mozilla.org/network/io-service;1"]
           .getService(Ci.nsIIOService)
           .QueryInterface(Ci.nsISpeculativeConnect);
});

So when we call Services.io we will get the object that is returned by the above lambda function.

Components.classes

According to this MDN article,

Components.classes is a read-only object whose properties implement the nsIJSCID interface. Each object represents one of the classes of XPCOM components that can be constructed or accessed as an XPCOM service.

Query Interface

Let’s recall QueryInterface function. From reading this MDN article

The function QueryInterface(...) is a function provided by all components which can be used to get a specific interface of that component. This function takes one parameter, the interface that you want to get.

and from reading Creating Applications with Mozilla book,

QueryInterface

A method used to match an interface with a desired implementation. The implementation can be in C, C++, JavaScript, Python, and other languages for which appropriate bindings are created. You can have multiple implementations for an interface. Through QueryInterface, you can ask for and assign the desired interface to its implementation. Each XPCOM object needs to implement QueryInterface in order to return an instance of that object’s class.

And also, tangentially related, I learned more about Components object. According to the above book,

In XPConnect, XPCOM interfaces, classIDs, and progIDs are stored as global JavaScript objects and properties that can be manipulated directly through a top-level object called Components. This object accesses any component that is declared “scriptable” in an XPCOM IDL interface. Through the Components object, you can access and use the services that these interfaces provide. The Component object’s top-level properties and methods include: QueryInterface, interfaces

and more! You might have guessed it but here is what exactly interfaces are:

interfaces

A read-only object array containing all the interfaces declared scriptable in the IDL file. The object name has the same name as the interface it represents.

Confusion

I have been reading a lot about XPCOM and I am forgetting the difference between components, classes, services.

Some of the functionality that the browser provides needs to be used by both consumers in core browser written in C++ and by the front-end of the browser which is written in JavaScript. XPCOM provides us with a way to implement such functionality in one language and expose it to a different language. There are clearly defined interfaces, which are language agnostic and they are specified using IDL, and they attempt to outline different functionality that a browser can provide. A component is a reusable piece of code that implements such an interface (one or more of such interfaces). Some of the components need to be instantiated every time they are used and they are called classes, and others exist as singleton instances and don’t need to be invoked every time they are used and they are called services.

Thoughts In Progress

So now we see that in the above code example, Services.io needs to return a nsIIOService service that also has an interface nsISpeculativeConnect. Let’s check if we can find a class that implements both such things, to see if I understood correctly everything I just read.

Indeed, nsIOService implements both. Now, I need to think about how I will make sure that the correct class will be returned when the getter is called. I’m going to look at the implementation of QueryInterface.

Update

My mentor pointed me towards this code so I will be doing something like this

if (IS_WN_REFLECTOR(obj))
      auto tearOff = XPCWrappedNative::Get(obj)->FindTearOff(*iid);

to get a tear off object which will allow us to access both interfaces.

More updates

I kept trying to include xpcprivate.h but the compiler kept giving me an error

... Services.cpp:31:10: fatal error: 'XPCWrappedNative.cpp' file not found

Then I realized I need to modify xpcom/build/moz.build so that it will include the appropriate files in the build.