Reference Counting Helpers ========================== RefPtr versus nsCOMPtr ---------------------- The general rule of thumb is to use ``nsCOMPtr`` when ``T`` is an interface type which inherits from ``nsISupports``, and ``RefPtr`` when ``T`` is a concrete type. This basic rule derives from some ``nsCOMPtr`` code being factored into the ``nsCOMPtr_base`` base class, which stores the pointer as a ``nsISupports*``. This design was intended to save some space in the binary (though it is unclear if it still does). Since ``nsCOMPtr`` stores the pointer as ``nsISupports*``, it must be possible to unambiguously cast from ``T*`` to ``nsISupports**``. Many concrete classes inherit from more than one XPCOM interface, meaning that they cannot be used with ``nsCOMPtr``, which leads to the suggestion to use ``RefPtr`` for these classes. ``nsCOMPtr`` also requires that the target type ``T`` be a valid target for ``QueryInterface`` so that it can assert that the stored pointer is a canonical ``T`` pointer (i.e. that ``mRawPtr->QueryInterface(T_IID) == mRawPtr``). do_XXX() nsCOMPtr helpers ------------------------- There are a number of ``do_XXX`` helper methods across the codebase which can be assigned into ``nsCOMPtr`` (and sometimes ``RefPtr``) to perform explicit operations based on the target pointer type. In general, when these operations succeed, they will initialize the smart pointer with a valid value, and otherwise they will silently initialize the smart pointer to ``nullptr``. ``do_QueryInterface`` and ``do_QueryObject`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Attempts to cast the provided object to the target class using the XPCOM ``QueryInterface`` mechanism. In general, use ``do_QueryInterface`` may only be used to cast between interface types in a ``nsCOMPtr``, and ``do_QueryObject`` in situations when downcasting to concrete types. ``do_GetInterface`` ~~~~~~~~~~~~~~~~~~~ Looks up an object implementing the requested interface using the ``nsIInterfaceRequestor`` interface. If the target object doesn't implement ``nsIInterfaceRequestor`` or doesn't provide the given interface, initializes the smart pointer with ``nullptr``. ``do_GetService`` ~~~~~~~~~~~~~~~~~ Looks up the component defined by the passed-in CID or ContractID string in the component manager, and returns a pointer to the service instance. This may start the service if it hasn't been started already. The resulting service will be cast to the target interface type using ``QueryInterface``. ``do_CreateInstance`` ~~~~~~~~~~~~~~~~~~~~~ Looks up the component defined by the passed-in CID or ContractID string in the component manager, creates and returns a new instance. The resulting object will be cast to the target interface type using ``QueryInterface``. ``do_QueryReferent`` and ``do_GetWeakReference`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When passed a ``nsIWeakReference*`` (e.g. from a ``nsWeakPtr``), ``do_QueryReferent`` attempts to re-acquire a strong reference to the held type, and cast it to the target type with ``QueryInterface``. Initializes the smart pointer with ``nullptr`` if either of these steps fail. In contrast ``do_GetWeakReference`` does the opposite, using ``QueryInterface`` to cast the type to ``nsISupportsWeakReference*``, and acquire a ``nsIWeakReference*`` to the passed-in object.