Changes between Version 22 and Version 23 of I2P_Browser_develop_n_hacks

Jun 16, 2019 10:03:11 PM (9 months ago)


  • I2P_Browser_develop_n_hacks

    v22 v23  
    2424Whenever JS is mentioned in this document, it is meant as a technology to contribute to internal Mozilla functionality in most cases unless otherwise spesified. JavaScript is mostly used in those areas of the source code that care for user interface events. Most of the following document will explain the C++ aspect of the application.
     26=== The firefox interfaces concept ===
     28The concept of interfaces is something that is used in the CORBA technology, for example. Both CORBA and Mozilla use a similar language to describe interfaces, which is XPIDL (IDL means Interface Definition Language).
     30In a CORBA environment, life is more restrictive and difficult, because you have inter-process and inter-network communication – something which Mozilla is not actively using. In a distributed CORBA environment, it is difficult to change the components of an interface, because you are usually unable to replace all running systems at the same time. If you want to change something, you have to define a new version of an interface, but you might still be required to support the old one.
     32As Mozilla is not a distributed application as of writing, it is currently possible to change most interfaces as the development process requires it. But because the Mozilla browser runs embedded in some environments, those environments must be able to rely on a fixed interface; therefore, interfaces can be frozen. This state is usually indicated in the interface definition. As Mozilla stabilizes over time, the ratio of frozen to not frozen interfaces is likely to increase.
     34One step of building Mozilla is automatically translating the interface definition files into C/C++ header files. That’s the job of Mozilla’s own IDL compiler, xpidl.
     36Besides of the methods and data members, interfaces have additional attributes. They have a UUID, a number to uniquely identify an interface. Interfaces can have the scriptable attribute, which means they will be accessible from the JavaScript code. A scriptable interface is restricted to only use data types for parameters that are valid within the JavaScript runtime.
     38=== XPCOM / nsISupports / nsCOMPtr ===
     40XPCOM is Mozilla’s own implementation of COM – the component object model. The XP in front means it is cross-platform (do not confuse this with XP as it appears in product names for a certain operating system manufacturer). The fact that it is cross-platform makes XPCOM more versatile than any other form of COM.
     42You should definitely read the introductory documents on XPCOM on To get you started, one could say that [ XPCOM] is the engine that makes the COM concept work. This includes playing the role of an object broker.
     44Typically, an interface describes an object that can be used to get a job done. If you have a job to do, you need to request an implementation that provides the interface. That implementation can reside within another component. To decide which particular implementation you want, you are using a contract ID, which is a text based identifier. The contract ID is a contract on the behaviour of the implementation, accessible using the well defined interface. The XPCOM runtime system knows which class implements which contract ID, and which component provides it.
     46Even if your code stays completely within one component, and therefore using COM is not a strict requirement, it is very often used anyway. One reason is flexibility. Another is to allow sharing functionality with those portions of the Mozilla logic that are implemented using JavaScript. Mozilla provides a technology called XPConnect that enables communication between interpreted JavaScript and compiled C++ at runtime.
     48Whenever you request an instance of a COM object at runtime, a class object will be created and you will be given an interface pointer. For several reasons it was decided that these instances are reference counted. One reason is efficiency, since making unnecessary copies of objects should be avoided. Another requirement is that when data objects must be passed between threads, each thread needs to keep a pointer to the same data object in memory. Finally, the same data object might be referenced by multiple components, or stored in multiple lists.
     50As the lifetime of each reference is different, it is easiest to have each object maintain a reference count, to remember how often it is currently referenced by something else. When you are given a reference to an object (be it from the XPCOM engine directly or from a function call), you have to make sure that you care for reference counting. You must tell the object whether you want to keep a reference to it, or whether you are finished with it, and remove the reference. That way, the object can decide on its own whether it is still needed. When its not needed anymore, it deletes itself from memory.
     52In order to implement this generic functionality, all classes in Mozilla that implement any interface share the common base class nsISupports, which implements the reference counter and automatic destruction functionality. A similar base class exists in every implementation of COM.
     54There is a general rule that you must clean up what you allocate. For instance, if you add a reference, you are strongly encouraged to release the reference as soon as it is no longer needed. If you don’t, you might cause problems such as memory leaks.
     56In C++, this can be done by explicit method calls to methods of the nsISupports base class. But calling these methods is not only easy to forget, but it also makes your code less readable – especially since many functions/methods have multiple exit points (i.e. return statements).
     58You have to make sure that you release all your referenced objects in each of your exit points. To make this easier, and to not have to repeat many release calls, a general helper class has been provided for dealing with pointers to COM objects, whose name is nsCOMPtr. This is something special to XPCOM and makes coding COM much easier. It simulates a pointer by overriding certain operators. Although there might be some edge cases, the following general rule should be followed for nearly all code: Whenever you’d expect to use a pointer variable “interface*” to an object that implements an interface, use a local “nsCOMPtr<interface>” variable instead. As soon as this pointer goes “out of scope”, its destructor will automatically decrease the reference count, triggering destruction if possible.
     60In interpreted JavaScript this is easier to code, because of garbage collection. There is some magic that automatically releases the references when possible. However, this magic requires that you don’t introduce cycles. For example, if you have two objects, and each contain a reference to the other, but nobody else keeps a reference to them, this can not be detected. Those objects will live in memory for the rest of program execution.
     62=== Exceptions / nsresult ===
     64Code execution can fail at runtime. One programming mechanism to deal with failure is to use exceptions. While Mozilla uses Exceptions in its JavaScript code portions, it does not in C++. One of several reasons for this is exceptions haven’t always been portable, so what was done in the past has stuck. Mozilla C++ code uses return codes to simulate exceptions. That means that while you can use try-catch blocks in JavaScript, in C++ you should check the return code whenever you call an interface method. That return code is of type nsresult. For this reason, the logical return type, as defined in the IDL file, is mapped to an additional method parameter in the C++ code.
     66The nsresult type is intended to transport additional failure reasons. Instead of simply reporting failure or success, an integer type is used instead, to allow for the definition of a lot of different error codes.
     68There are some general result codes, like NS_OK, which is used to indicate that everything went well and program flow can continue, or NS_ERROR_FAILURE, which is used if something went wrong, but no more details need to be provided as of yet.
     70In addition to that, each component can request its own range of integers to define error codes that will not overlap with those failure codes used in other areas of an application. Look at mozilla/xpcom/base/nsError.h for more information.