Compare Revisions

Introduction to XPCOM for the DOM

Revision 113688:

Revision 113688 by Bamanzi on

Revision 113689:

Revision 113689 by Bamanzi on

Title:
Introduction to XPCOM for the DOM
Introduction to XPCOM for the DOM
Slug:
Introduction_to_XPCOM_for_the_DOM
Introduction_to_XPCOM_for_the_DOM
Tags:
"Developing Mozilla"
"Developing Mozilla"
Content:

Revision 113688
Revision 113689
nn26      <div style="background:#FFFF9C">
26      <p>27        <p>
27        Important note: This document assumes some knowledge of C28          Important note: This document assumes some knowledge of
> , specially the object-oriented part of it. I learned C by readi> C , specially the object-oriented part of it. I learned C by rea
>ng "C Primer" from Stanley Lippman and Josee Lajoie, then experim>ding "C Primer" from Stanley Lippman and Josee Lajoie, then exper
>enting on the DOM code. I recommend that book to all the beginner>imenting on the DOM code. I recommend that book to all the beginn
>s out there.>ers out there.
28      </p>29        </p>
29    </div>30      </div>
30    <div id="chapteronea">31      <div id="chapteronea">
31      <h3 name="A._Introduction_to_the_introduction">32        <h3 name="A._Introduction_to_the_introduction">
32        A. Introduction to the introduction33          A. Introduction to the introduction
33      </h3>34        </h3>
34      <p>35        <p>
35        The DOM makes extensive use of XPCOM. In fact, to do anyt36          The DOM makes extensive use of XPCOM. In fact, to do an
>hing with the DOM implementation you need XPCOM. You do not, howe>ything with the DOM implementation you need XPCOM. You do not, ho
>ver, need to know all the hairy details, if you just intend to re>wever, need to know all the hairy details, if you just intend to 
>ad the code or to work with the existing framework. The numerous >read the code or to work with the existing framework. The numerou
>macros and facilities brought by the DOM, as well as nsCOMPtr's, >s macros and facilities brought by the DOM, as well as nsCOMPtr's
>make our life much easier. In this chapter I will attempt to cove>, make our life much easier. In this chapter I will attempt to co
>r the most widespread use of XPCOM in the DOM, avoiding the detai>ver the most widespread use of XPCOM in the DOM, avoiding the det
>ls as much as possible. I will introduce nsCOMPtr's, interfaces, >ails as much as possible. I will introduce nsCOMPtr's, interfaces
>reference counting, and the nsISupports interface. A tutorial abo>, reference counting, and the nsISupports interface. A tutorial a
>ut how to add a new interface is also provided, and eventually, a>bout how to add a new interface is also provided, and eventually,
> more detailed discussion of class inheritance in C .> a more detailed discussion of class inheritance in C .
36      </p>37        </p>
37    </div>38      </div>
38    <div id="chapteroneb">39      <div id="chapteroneb">
39      <h3 name="B_Interfaces">40        <h3 name="B_Interfaces">
40        B Interfaces41          B Interfaces
41      </h3>42        </h3>
42      <p>43        <p>
43        Object-oriented programming is based on the used of <b>in44          Object-oriented programming is based on the used of <b>
>heritance</b> between <b>classes</b>. Furthermore, a class can be>inheritance</b> between <b>classes</b>. Furthermore, a class can 
> de declared to be "abstract" if it declares some methods but doe>be de declared to be "abstract" if it declares some methods but d
>s not implement them entirely. Pushing this concept to its maximu>oes not implement them entirely. Pushing this concept to its maxi
>m, a class can be "purely virtual" if it declares methods without>mum, a class can be "purely virtual" if it declares methods witho
> implementing any of them. Such a class is called an interface. T>ut implementing any of them. Such a class is called an interface.
>he goal of interfaces is to have a single ... interface to a set > The goal of interfaces is to have a single ... interface to a se
>of methods that manipulate an object (often represented by a clas>t of methods that manipulate an object (often represented by a cl
>s), without worrying about the details of the implementation. If >ass), without worrying about the details of the implementation. I
>you know a class implements an interface, just use the methods in>f you know a class implements an interface, just use the methods 
> the interface, and you don't have to care if the implementation >in the interface, and you don't have to care if the implementatio
>of the interface (the concrete class) changes. XPCOM pushes this >n of the interface (the concrete class) changes. XPCOM pushes thi
>concept to the extreme. Pure virtual methods are declared with th>s concept to the extreme. Pure virtual methods are declared with 
>e following syntax:>the following syntax:
44      </p>45        </p>
45      <p>46        <p>
46        <code>virtual nsresult FunctionFoo() = 0;</code>47          <code>virtual nsresult FunctionFoo() = 0;</code>
47      </p>48        </p>
48      <p>49        <p>
49        An interface is thus simply a C class where all the membe50          An interface is thus simply a C class where all the mem
>r functions are declared as pure virtual functions. An interface >ber functions are declared as pure virtual functions. An interfac
>can also be defined using <a class="external" href="http://www.mo>e can also be defined using <a class="external" href="http://www.
>zilla.org/scriptable/xpidl/">XPIDL</a>. This is described in Sect>mozilla.org/scriptable/xpidl/">XPIDL</a>. This is described in Se
>ion 1.E, "How to add an interface".>ction 1.E, "How to add an interface".
50      </p>51        </p>
51      <p>52        <p>
52        Since an interface doesn't have any implementation, it ha53          Since an interface doesn't have any implementation, it 
>s to be implemented by a non-abstract class -- a concrete class. >has to be implemented by a non-abstract class -- a concrete class
>If the interface is called nsIFoo and the class is called nsFoo, >. If the interface is called nsIFoo and the class is called nsFoo
>we say that "nsFoo implements nsIFoo", or that "nsFoo inherits fr>, we say that "nsFoo implements nsIFoo", or that "nsFoo inherits 
>om nsIFoo". The C code is the following:>from nsIFoo". The C code is the following:
53      </p>54        </p>
54      <p>55        <p>
55        <code>class nsFoo&nbsp;: public nsIFoo</code>56          <code>class nsFoo&nbsp;: public nsIFoo</code>
56      </p>57        </p>
57      <p>58        <p>
58        For those unfamiliar with object-oriented C , this means 59          For those unfamiliar with object-oriented C , this mean
>that nsFoo is declared as "derived from" nsIFoo, and that nsIFoo >s that nsFoo is declared as "derived from" nsIFoo, and that nsIFo
>is a "base class" of nsFoo. For this introduction you don't need >o is a "base class" of nsFoo. For this introduction you don't nee
>to know more about object-oriented C . However the Section 1.F pr>d to know more about object-oriented C . However the Section 1.F 
>ovides a more detailed discussion about it, and is necessary to u>provides a more detailed discussion about it, and is necessary to
>nderstand most of the DOM code.> understand most of the DOM code.
59      </p>60        </p>
60      <p>61        <p>
61        An instance of a class (called an object) can be allocate62          An instance of a class (called an object) can be alloca
>d dynamically (on the heap, or free store), using the syntax>ted dynamically (on the heap, or free store), using the syntax
62      </p>63        </p>
63      <p>64        <p>
64        <code>nsFoo *fooptr = new nsFoo;</code>65          <code>nsFoo *fooptr = new nsFoo;</code>
65      </p>66        </p>
66      <p>67        <p>
67        That object can then be manipulated only through fooptr. 68          That object can then be manipulated only through fooptr
>Let's consider what happens when the class nsFoo implements an in>. Let's consider what happens when the class nsFoo implements an 
>terface nsIFoo. You can manipulate the nsFoo object directly thro>interface nsIFoo. You can manipulate the nsFoo object directly th
>ugh fooptr, however your code will not be very robust. Indeed, if>rough fooptr, however your code will not be very robust. Indeed, 
> someone decides to change the name or the signature of the metho>if someone decides to change the name or the signature of the met
>ds you use, you will have to change all the calls to those method>hods you use, you will have to change all the calls to those meth
>s throughout your code. As opposed to a concreate class, an inter>ods throughout your code. As opposed to a concreate class, an int
>face is supposed to be more stable through time. Indeed, many int>erface is supposed to be more stable through time. Indeed, many i
>erfaces in the Mozilla code are frozen (this is indicated by the >nterfaces in the Mozilla code are frozen (this is indicated by th
>comment @Frozen ï¿½ the begining of the interface definition). Th>e comment @Frozen ï¿½ the begining of the interface definition). 
>at means that the interface will never change anymore. The good t>That means that the interface will never change anymore. The good
>hing is that your code will (in the best condition) last forever.> thing is that your code will (in the best condition) last foreve
> The bad thing is that we have to find a way to improve those int>r. The bad thing is that we have to find a way to improve those i
>erfaces, and freezing them obliges implementers to create new int>nterfaces, and freezing them obliges implementers to create new i
>erfaces. In summary, manipulate an interface rather than its impl>nterfaces. In summary, manipulate an interface rather than its im
>ementation whenever possible! A pointer to an interface nsIFoo im>plementation whenever possible! A pointer to an interface nsIFoo 
>plemented by nsFoo can be declared as follows>implemented by nsFoo can be declared as follows
68      </p>69        </p>
69      <p>70        <p>
70        <code>nsIFoo *fooptr = new nsFoo;</code>71          <code>nsIFoo *fooptr = new nsFoo;</code>
71      </p>72        </p>
72      <p>73        <p>
73        A pointer such as fooptr is then called a "pointer to an 74          A pointer such as fooptr is then called a "pointer to a
>interface nsIFoo implemented by an instance of the nsFoo class", >n interface nsIFoo implemented by an instance of the nsFoo class"
>or "pointer to nsIFoo" in short. From now on, when I speak of a ">, or "pointer to nsIFoo" in short. From now on, when I speak of a
>pointer to an interface", I really mean a "pointer to an interfac> "pointer to an interface", I really mean a "pointer to an interf
>e implemented by an instance of a concrete C class". The importan>ace implemented by an instance of a concrete C class". The import
>t thing to note is that a pointer to nsIFoo can <i>only</i> call >ant thing to note is that a pointer to nsIFoo can <i>only</i> cal
>the methods defined on the nsIFoo interface, and on its parents. >l the methods defined on the nsIFoo interface, and on its parents
>For instance, if nsFoo implements two different interfaces, nsIFo>. For instance, if nsFoo implements two different interfaces, nsI
>o and nsIBar, a pointer to nsIFoo cannot call the methods defined>Foo and nsIBar, a pointer to nsIFoo cannot call the methods defin
> on nsIBar and vice-versa.>ed on nsIBar and vice-versa.
74      </p>75        </p>
75      <p>76        <p>
76        Note: the previous paragraph is extremely important. If y77          Note: the previous paragraph is extremely important. If
>ou haven't grasped it completely, there is no need to read furthe> you haven't grasped it completely, there is no need to read furt
>r.>her.
77      </p>78        </p>
78      <p>79        <p>
79        Reference counting basics80          Reference counting basics
80      </p>81        </p>
81      <p>82        <p>
82        XPCOM uses a reference counting mechanism (refcount in sh83          XPCOM uses a reference counting mechanism (refcount in 
>ort) to make sure that no object is deleted while interface point>short) to make sure that no object is deleted while interface poi
>ers still point at that object. Indeed, dereferencing a pointer t>nters still point at that object. Indeed, dereferencing a pointer
>hat points to a deleted object can have bad consequences. That is> that points to a deleted object can have bad consequences. That 
> why each time a pointer to an interface is assigned the address >is why each time a pointer to an interface is assigned the addres
>of an object, we have to increase the reference count of that obj>s of an object, we have to increase the reference count of that o
>ect by one. The function that does this is called "AddRef" and is>bject by one. The function that does this is called "AddRef" and 
> defined in the nsISupports interface. When the pointer no longer>is defined in the nsISupports interface. When the pointer no long
>s holds the address of that object, it has to decrease the refere>ers holds the address of that object, it has to decrease the refe
>nce count of that object by one. This is done using the "Release">rence count of that object by one. This is done using the "Releas
> function, also defined in the nsISupports interface. When the re>e" function, also defined in the nsISupports interface. When the 
>ference count of an object hits 0 (zero), the object deletes itse>reference count of an object hits 0 (zero), the object deletes it
>lf. This is why it is very important to keep track of the referen>self. This is why it is very important to keep track of the refer
>ce count of each object. In the first case, if we forget to AddRe>ence count of each object. In the first case, if we forget to Add
>f the object, the object may delete itself before we are done usi>Ref the object, the object may delete itself before we are done u
>ng the pointer, which would cause a crash when dereferencing it. >sing the pointer, which would cause a crash when dereferencing it
>In the second case, if we forget to Release the object, it will n>. In the second case, if we forget to Release the object, it will
>ever delete itself, which will cause "memory leaks", i.e. the mem> never delete itself, which will cause "memory leaks", i.e. the m
>ory is never returned because we keep the object around even if w>emory is never returned because we keep the object around even if
>e don't need it. In both cases it's very bad, and we have to be e> we don't need it. In both cases it's very bad, and we have to be
>xtremely careful with the refcounting.> extremely careful with the refcounting.
83      </p>84        </p>
84      <p>85        <p>
85        Fortunately, there are nsCOMPtr's to make our life easier86          Fortunately, there are nsCOMPtr's to make our life easi
>.>er.
86      </p>87        </p>
87    </div>88      </div>
88    <div id="chapteronec">89      <div id="chapteronec">
89      <h3 name="C._nsCOMPtr">90        <h3 name="C._nsCOMPtr">
90        C. nsCOMPtr91          C. nsCOMPtr
91      </h3>92        </h3>
92      <p>93        <p>
93        Scott Collins blessed us with the <a class="external" hre94          Scott Collins blessed us with the <a class="external" h
>f="http://www.mozilla.org/projects/xpcom/nsCOMPtr.html">nsCOMPtr<>ref="http://www.mozilla.org/projects/xpcom/nsCOMPtr.html">nsCOMPt
>/a>, now let's use them. nsCOMPtr's are an extension of the C aut>r</a>, now let's use them. nsCOMPtr's are an extension of the C a
>o_ptr, managing the reference counting operations for you, and pr>uto_ptr, managing the reference counting operations for you, and 
>oviding several facilities for comparison, initialization, etc...>providing several facilities for comparison, initialization, etc.
> An nsCOMPtr is used like an usual pointer to an interface in mos>.. An nsCOMPtr is used like an usual pointer to an interface in m
>t cases. An usual pointer to an interface nsIFoo is declared as f>ost cases. An usual pointer to an interface nsIFoo is declared as
>ollows:> follows:
94      </p>95        </p>
95      <p>96        <p>
96        <code>nsIFoo *fooptr;</code>97          <code>nsIFoo *fooptr;</code>
97      </p>98        </p>
98      <p>99        <p>
99        An nsCOMPtr to the same nsIFoo interface is declared as f100          An nsCOMPtr to the same nsIFoo interface is declared as
>ollows:> follows:
100      </p>101        </p>
101      <p>102        <p>
102        <code>nsCOMPtr&lt;nsIFoo&gt; fooptr;</code>103          <code>nsCOMPtr&lt;nsIFoo&gt; fooptr;</code>
103      </p>104        </p>
104      <p>105        <p>
105        The rest of the use of nsCOMPtr's is described in the nex106          The rest of the use of nsCOMPtr's is described in the n
>t Section. For more information about nsCOMPtr's, please read the>ext Section. For more information about nsCOMPtr's, please read t
> <a class="external" href="http://www.mozilla.org/projects/xpcom/>he <a class="external" href="http://www.mozilla.org/projects/xpco
>nsCOMPtr.html#users_guide">User's Guide</a>.>m/nsCOMPtr.html#users_guide">User's Guide</a>.
106      </p>107        </p>
107    </div>108      </div>
108    <div id="chapteroned">109      <div id="chapteroned">
109      <h3 name="D._QueryInterface.28.29">110        <h3 name="D._QueryInterface.28.29">
110        D. QueryInterface()111          D. QueryInterface()
111      </h3>112        </h3>
112      <p>113        <p>
113        Consider again the class nsFoo that implements two interf114          Consider again the class nsFoo that implements two inte
>aces, nsIFoo and nsIFoo2:>rfaces, nsIFoo and nsIFoo2:
114      </p>115        </p>
115      <p>116        <p>
116        <code>class nsFoo&nbsp;: public nsIFoo, public nsIFoo2</c117          <code>class nsFoo&nbsp;: public nsIFoo, public nsIFoo2<
>ode>>/code>
117      </p>118        </p>
118      <p>119        <p>
119        Let's assume an instance of nsFoo was somehow created (th120          Let's assume an instance of nsFoo was somehow created (
>is assertion is true most of the time). You would like to manipul>this assertion is true most of the time). You would like to manip
>ate that object with a method defined on the nsIFoo interface. Th>ulate that object with a method defined on the nsIFoo interface. 
>e goal is to retrieve a pointer to the nsIFoo interface. To do so>The goal is to retrieve a pointer to the nsIFoo interface. To do 
>, there are too main techniques, and the context should tell you >so, there are too main techniques, and the context should tell yo
>what to use. The first technique is to use a "Getter", the second>u what to use. The first technique is to use a "Getter", the seco
> is to use a static cast on the "this" pointer.>nd is to use a static cast on the "this" pointer.
120      </p>121        </p>
121      <p>122        <p>
122        A getter is a function defined in global scope or in clas123          A getter is a function defined in global scope or in cl
>s scope that will "return" a pointer to the required interface. G>ass scope that will "return" a pointer to the required interface.
>enerally getters work like this: First, declare a pointer to an i> Generally getters work like this: First, declare a pointer to an
>nterface, ifooptr without assigning it. Pass the address of the p> interface, ifooptr without assigning it. Pass the address of the
>ointer to the getter function. The getter function will then assi> pointer to the getter function. The getter function will then as
>gn to the pointer the correct address and will QueryInterface the>sign to the pointer the correct address and will QueryInterface t
> pointer to that interface. ifooptr is now a pointer to an interf>he pointer to that interface. ifooptr is now a pointer to an inte
>ace assigned to the address of a real object, and you can thus no>rface assigned to the address of a real object, and you can thus 
>w call methods defined on nsIFoo through ifooptr. Here is some ex>now call methods defined on nsIFoo through ifooptr. Here is some 
>ample code.>example code.
123      </p>124        </p>
124      <p>125        <p>
125        <br>126          <br>
126      </p>127        </p>
127      <pre class="eval">128        <pre class="eval">
n132      <p>n133        <p>
133        The peculiar syntax, getter_AddRefs(pointer), is the nsCO134          The peculiar syntax, getter_AddRefs(pointer), is the ns
>MPtr counterpart to the usual "&amp;" (address-of) C operator. It>COMPtr counterpart to the usual "&amp;" (address-of) C operator. 
> means that the Getter method will call the AddRef method for you>It means that the Getter method will call the AddRef method for y
>. This is a contract between the caller, who says "I don't add a >ou. This is a contract between the caller, who says "I don't add 
>reference to this object because you have already done it", and t>a reference to this object because you have already done it", and
>he callee who says "I add a reference to this object, so don't do> the callee who says "I add a reference to this object, so don't 
> it!". If both the caller and the callee perform the AddRef, the >do it!". If both the caller and the callee perform the AddRef, th
>object will be leaked, because one of the two references will nev>e object will be leaked, because one of the two references will n
>er be released!>ever be released!
134      </p>135        </p>
135      <p>136        <p>
136        Please note that all Getter functions <b>have to AddRef</137          Please note that all Getter functions <b>have to AddRef
>b> the returned pointer. If you're just using the Getter function></b> the returned pointer. If you're just using the Getter functi
> though, you don't need to worry about it. More about this in the>on though, you don't need to worry about it. More about this in t
> <a class="external" href="http://www.mozilla.org/projects/xpcom/>he <a class="external" href="http://www.mozilla.org/projects/xpco
>Ownership.html">XPCOM Ownership Guide</a>.>m/Ownership.html">XPCOM Ownership Guide</a>.
137      </p>138        </p>
138      <p>139        <p>
139        Please also note that some interfaces are not refcounted,140          Please also note that some interfaces are not refcounte
> like the frames and views. For those you have to use raw interfa>d, like the frames and views. For those you have to use raw inter
>ce pointers, and you don't have to perform any manual refcounting>face pointers, and you don't have to perform any manual refcounti
>.>ng.
140      </p>141        </p>
141      <p>142        <p>
142        Let's say that you now want to execute a function declare143          Let's say that you now want to execute a function decla
>d on the nsIFoo2 interface, also implemented by nsFoo. However, i>red on the nsIFoo2 interface, also implemented by nsFoo. However,
>fooptr does not give you access to that function, since it is a p> ifooptr does not give you access to that function, since it is a
>ointer to nsIFoo, for the reasons mentioned in Section 1.B. XPCOM> pointer to nsIFoo, for the reasons mentioned in Section 1.B. XPC
> provides a handy method to get a pointer to an interface when yo>OM provides a handy method to get a pointer to an interface when 
>u have a pointer to another interface, and both interfaces are im>you have a pointer to another interface, and both interfaces are 
>plemented by the same object. This method is QueryInterface(). It>implemented by the same object. This method is QueryInterface(). 
> is defined on the nsISupports interface. <b>Every single interfa>It is defined on the nsISupports interface. <b>Every single inter
>ce in Mozilla inherits from nsISupports</b>. This is one of the m>face in Mozilla inherits from nsISupports</b>. This is one of the
>ain rules of XPCOM. The goal is the following: find out whether a> main rules of XPCOM. The goal is the following: find out whether
>n object (an instance of a class) implements a given interface. T> an object (an instance of a class) implements a given interface.
>his is what QueryInterface() does. You pass an interface and the > This is what QueryInterface() does. You pass an interface and th
>address of a pointer to store the interface to QueryInterface(). >e address of a pointer to store the interface to QueryInterface()
>If the interface is implemented by the object, the pointer passed>. If the interface is implemented by the object, the pointer pass
> in will be assigned to the address of the object. If the interfa>ed in will be assigned to the address of the object. If the inter
>ce is not implemented by the object, QueryInterface() will return>face is not implemented by the object, QueryInterface() will retu
> NS_NOINTERFACE, and the pointer passed in will be null.>rn NS_NOINTERFACE, and the pointer passed in will be null.
143      </p>144        </p>
144      <p>145        <p>
145        QueryInterface() is handy to hide the implementation of a146          QueryInterface() is handy to hide the implementation of
>n object from the user. Just call QueryInterface() then call the > an object from the user. Just call QueryInterface() then call th
>method on the interface. You don't need to know anything else. So>e method on the interface. You don't need to know anything else. 
> how do we use QueryInterface() to get a pointer to nsIFoo2 if we>So how do we use QueryInterface() to get a pointer to nsIFoo2 if 
> have a pointer to nsIFoo? Since we cannot re-use ifooptr, we cre>we have a pointer to nsIFoo? Since we cannot re-use ifooptr, we c
>ate a new pointer to nsIFoo2, ifooptr2. The following syntax is t>reate a new pointer to nsIFoo2, ifooptr2. The following syntax is
>he preferred one (to use only with nsCOMPtr's):> the preferred one (to use only with nsCOMPtr's):
146      </p>147        </p>
147      <p>148        <p>
148        <br>149          <br>
149      </p>150        </p>
150      <pre class="eval">151        <pre class="eval">
n153      <p>n154        <p>
154        That syntax is the preferred one to declare and initializ155          That syntax is the preferred one to declare and initial
>e an nsCOMPtr at the same time. If you have to assign it another >ize an nsCOMPtr at the same time. If you have to assign it anothe
>address later, you can easily do>r address later, you can easily do
155      </p>156        </p>
156      <p>157        <p>
157        <br>158          <br>
158      </p>159        </p>
159      <pre class="eval">160        <pre class="eval">
n163      <p>n164        <p>
164        This syntax however is just a convenient shortcut to the 165          This syntax however is just a convenient shortcut to th
>real function. Below is how one would use the QueryInterface() fu>e real function. Below is how one would use the QueryInterface() 
>nction with raw pointers.>function with raw pointers.
165      </p>166        </p>
166      <p>167        <p>
167        <br>168          <br>
168      </p>169        </p>
169      <pre class="eval">170        <pre class="eval">
n173      <p>n174        <p>
174        NS_GET_IID is a macro that evaluates to the IID of the ar175          NS_GET_IID is a macro that evaluates to the IID of the 
>gument. It is a convenient way of comparing two interfaces for eq>argument. It is a convenient way of comparing two interfaces for 
>uality. We have already seen what getter_AddRefs() does to nsCOMP>equality. We have already seen what getter_AddRefs() does to nsCO
>tr's. In this case we pass the address of the ifooptr2 pointer. S>MPtr's. In this case we pass the address of the ifooptr2 pointer.
>ince nsFoo implements nsIFoo2, ifooptr2 will be assigned the addr> Since nsFoo implements nsIFoo2, ifooptr2 will be assigned the ad
>ess of the current instance of nsFoo. We can now call the methods>dress of the current instance of nsFoo. We can now call the metho
> defined on nsIFoo2 through ifooptr2:>ds defined on nsIFoo2 through ifooptr2:
175      </p>176        </p>
176      <p>177        <p>
177        <code>ifooptr2-&gt;FunctionOfnsIFoo2();</code>178          <code>ifooptr2-&gt;FunctionOfnsIFoo2();</code>
178      </p>179        </p>
179      <p>180        <p>
180        If we now try to QueryInterface to an interface that is <181          If we now try to QueryInterface to an interface that is
>i>not</i> implemented by nsFoo, the pointer passed in will be nul> <i>not</i> implemented by nsFoo, the pointer passed in will be n
>l. This is why, unless you are really really really sure of what >ull. This is why, unless you are really really really sure of wha
>you are doing, you should always check for the null-ness of the n>t you are doing, you should always check for the null-ness of the
>sCOMPtr. The following example demonstrates this.> nsCOMPtr. The following example demonstrates this.
181      </p>182        </p>
182      <p>183        <p>
183        <br>184          <br>
184      </p>185        </p>
185      <pre class="eval">186        <pre class="eval">
n192      <p>n193        <p>
193        It is also worth noting that QueryInterface is null-safe.194          It is also worth noting that QueryInterface is null-saf
> For example, in the previous example, nothing bad will happen if>e. For example, in the previous example, nothing bad will happen 
> ifooptr is null. Additionally, the return value of a call to Que>if ifooptr is null. Additionally, the return value of a call to Q
>ryInterface should not be returned unless there is a good reason >ueryInterface should not be returned unless there is a good reaso
>for that. If you are concerned that it could return NS_NOINTERFAC>n for that. If you are concerned that it could return NS_NOINTERF
>E, return NS_OK, as the previous example shows.>ACE, return NS_OK, as the previous example shows.
194      </p>195        </p>
195      <p>196        <p>
196        At the beginning of this section, I talked about a second197          At the beginning of this section, I talked about a seco
> solution to get a pointer to an interface. This should be used i>nd solution to get a pointer to an interface. This should be used
>n the case a getter function is not available. As you probably kn> in the case a getter function is not available. As you probably 
>ow, the "this" member of an object is a pointer to that object. Y>know, the "this" member of an object is a pointer to that object.
>ou can thus simply cast "this" statically to the desired interfac> You can thus simply cast "this" statically to the desired interf
>e. You should however be absolutely sure of what you are doing be>ace. You should however be absolutely sure of what you are doing 
>fore coding such a cast. It can lead to troubles with refcounting>before coding such a cast. It can lead to troubles with refcounti
>.>ng.
197      </p>198        </p>
198      <p>199        <p>
199        Here is a simple problem I encountered recently: In a mem200          Here is a simple problem I encountered recently: In a m
>ber function of the nsHTMLAnchorElement class, I had to get a poi>ember function of the nsHTMLAnchorElement class, I had to get a p
>nter to the nsIContent interface implemented by the nsHTMLAnchorE>ointer to the nsIContent interface implemented by the nsHTMLAncho
>lement object. However there is no such getter. I had to use the >rElement object. However there is no such getter. I had to use th
>second solution:>e second solution:
200      </p>201        </p>
201      <p>202        <p>
202        <br>203          <br>
203      </p>204        </p>
204      <pre class="eval">205        <pre class="eval">
n209      <p>n210        <p>
210        The second form should be used with care, and is recommen211          The second form should be used with care, and is recomm
>ded only for advanced XPCOM'ers.>ended only for advanced XPCOM'ers.
211      </p>212        </p>
212      <p>213        <p>
213        The use of XPCOM and nsCOMPtr's described until now cover214          The use of XPCOM and nsCOMPtr's described until now cov
>s about 80% of what you need to know to read the code, and even w>ers about 80% of what you need to know to read the code, and even
>rite some. I could go on about do_GetService, explain the impleme> write some. I could go on about do_GetService, explain the imple
>ntation of QueryInterface, etc, but I feel this is not worth the >mentation of QueryInterface, etc, but I feel this is not worth th
>trouble. For the more advanced topics of XPCOM, please see <a cla>e trouble. For the more advanced topics of XPCOM, please see <a c
>ss="external" href="http://mozilla.org/projects/xpcom/">the XPCOM>lass="external" href="http://mozilla.org/projects/xpcom/">the XPC
> project page</a>.>OM project page</a>.
214      </p>215        </p>
215      <p>216        <p>
216        The next section is a tutorial on how to add a new interf217          The next section is a tutorial on how to add a new inte
>ace to the Mozilla DOM, with build instructions et al, and the la>rface to the Mozilla DOM, with build instructions et al, and the 
>st section is a discussion of the more advanced topics of object->last section is a discussion of the more advanced topics of objec
>oriented C , interface inheritance, and other fun stuff.>t-oriented C , interface inheritance, and other fun stuff.
217      </p>218        </p>
218    </div>219      </div>
219    <div id="chapteronee">220      <div id="chapteronee">
220      <h3 name="E._Tutorial_:_How_to_add_a_new_interface">221        <h3 name="E._Tutorial_:_How_to_add_a_new_interface">
221        E. Tutorial&nbsp;: How to add a new interface222          E. Tutorial&nbsp;: How to add a new interface
222      </h3>223        </h3>
223      <h4 name="E.a._Introduction">224        <h4 name="E.a._Introduction">
224        E.a. Introduction225          E.a. Introduction
225      </h4>226        </h4>
226      <p>227        <p>
227        The purpose of this tutorial is to describe the process o228          The purpose of this tutorial is to describe the process
>f adding a new interface to the DOM and then implementing it. A g> of adding a new interface to the DOM and then implementing it. A
>ood understanding of the previous sections is preferred to unders> good understanding of the previous sections is preferred to unde
>tand this tutorial. You could want to add a new interface for sev>rstand this tutorial. You could want to add a new interface for s
>eral reasons, like the addition of a new DOM object, or to respec>everal reasons, like the addition of a new DOM object, or to resp
>t an eventual "Interface freeze". First we will take a look at XP>ect an eventual "Interface freeze". First we will take a look at 
>IDL and how it can help you define interfaces. Next we will descr>XPIDL and how it can help you define interfaces. Next we will des
>ibe the build system, makefiles, etc... And finally, we will look>cribe the build system, makefiles, etc... And finally, we will lo
> at the implementation of our new interface through the creation >ok at the implementation of our new interface through the creatio
>of an nsIDOMFabian interface (Fabian is my first name&nbsp;;-).>n of an nsIDOMFabian interface (Fabian is my first name&nbsp;;-).
228      </p>229        </p>
229      <h4 name="E.b._XPIDL">230        <h4 name="E.b._XPIDL">
230        E.b. XPIDL231          E.b. XPIDL
231      </h4>232        </h4>
232      <p>233        <p>
233        XPIDL stands for Cross-Platform Interface Definition Lang234          XPIDL stands for Cross-Platform Interface Definition La
>uage. Instead of coding interfaces directly in C , one can use XP>nguage. Instead of coding interfaces directly in C , one can use 
>IDL. It simplifies greatly the task of defining interfaces, and o>XPIDL. It simplifies greatly the task of defining interfaces, and
>ffers some interesting features, like automatic generation of doc> offers some interesting features, like automatic generation of d
>umentation, and XPT generation. The first thing to do is to decid>ocumentation, and XPT generation. The first thing to do is to dec
>e what our interface, nsIDOMFabian, will do. For the purpose of t>ide what our interface, nsIDOMFabian, will do. For the purpose of
>his document, I have chosen to implement a new HTML interface cal> this document, I have chosen to implement a new HTML interface c
>led nsIDOMFabian. It will be implemented by the class nsHTMLDocum>alled nsIDOMFabian. It will be implemented by the class nsHTMLDoc
>ent.>ument.
234      </p>235        </p>
235      <p>236        <p>
236        The syntax of XPIDL is straightforward:237          The syntax of XPIDL is straightforward:
237      </p>238        </p>
238      <pre class="eval">239        <pre class="eval">
n250      <p>n251        <p>
251        This is the definition of the nsIDOMFabian interface. The252          This is the definition of the nsIDOMFabian interface. T
> <i>uuid</i> of the interface is a unique identifier. Every inter>he <i>uuid</i> of the interface is a unique identifier. Every int
>face needs one. You can generate them using guidgen on windows, o>erface needs one. You can generate them using guidgen on windows,
>r by issuing the command "mozbot uuid" in #mozilla on irc.mozilla> or by issuing the command "mozbot uuid" in #mozilla on irc.mozil
>.org.>la.org.
252      </p>253        </p>
253      <p>254        <p>
254        At compile-time, the XPIDL compiler will turn this interf255          At compile-time, the XPIDL compiler will turn this inte
>ace definition into real C code, a header file that will contain >rface definition into real C code, a header file that will contai
>the pure abstract class. This class will look like this:>n the pure abstract class. This class will look like this:
255      </p>256        </p>
256      <pre class="eval">257        <pre class="eval">
n275      <p>n276        <p>
276        As we can see, the auto-generated header file contains th277          As we can see, the auto-generated header file contains 
>e IID of our interface, and a "pure abstract class" is correctly >the IID of our interface, and a "pure abstract class" is correctl
>defined. The XPIDL compiler turns the IDL methods and attributes >y defined. The XPIDL compiler turns the IDL methods and attribute
>into C functions according to the following rules:>s into C functions according to the following rules:
277      </p>278        </p>
278      <p>279        <p>
279        The methods of the interface keep the same name in C . Ho280          The methods of the interface keep the same name in C . 
>wever in IDL we have to use the so-called "interCaps" model. That>However in IDL we have to use the so-called "interCaps" model. Th
> means that the first letter is lower-cased, and the other letter>at means that the first letter is lower-cased, and the other lett
>s that begin a new word are upper-cased. For example, in IDL we'd>ers that begin a new word are upper-cased. For example, in IDL we
> write getElementById, which in C would be translated to GetEleme>'d write getElementById, which in C would be translated to GetEle
>ntById.>mentById.
280      </p>281        </p>
281      <p>282        <p>
282        NS_IMETHOD is a macro that basically means "virtual nsres283          NS_IMETHOD is a macro that basically means "virtual nsr
>ult". The argument list and return type are turned into correct C>esult". The argument list and return type are turned into correct
> types according to rules not described here.> C types according to rules not described here.
283      </p>284        </p>
284      <p>285        <p>
285        The attributes of the interface become two functions: a g286          The attributes of the interface become two functions: a
>etter, and a setter. In our example, since the attribute is decla> getter, and a setter. In our example, since the attribute is dec
>red as read-only, only a getter is defined: GetNeat. The argument>lared as read-only, only a getter is defined: GetNeat. The argume
> is a pointer to an object of type PRBool, automatically generate>nt is a pointer to an object of type PRBool, automatically genera
>d by XPIDL. Clever uh. Note that the same interCaps model applies>ted by XPIDL. Clever uh. Note that the same interCaps model appli
> to IDL attributes as well.>es to IDL attributes as well.
286      </p>287        </p>
287      <p>288        <p>
288        The three macros are explained in detail in Section 1.E.d289          The three macros are explained in detail in Section 1.E
>. The next step is to build our new interface.>.d. The next step is to build our new interface.
289      </p>290        </p>
290      <h4 name="E.c_Build_System">291        <h4 name="E.c_Build_System">
291        E.c Build System292          E.c Build System
292      </h4>293        </h4>
293      <p>294        <p>
294        This is the really easy part: it's just copying what's al295          This is the really easy part: it's just copying what's 
>ready there. First, we have to decide in which directory we will >already there. First, we have to decide in which directory we wil
>place our interface. The most logical choice for us is in dom/pub>l place our interface. The most logical choice for us is in dom/p
>lic/idl/html, where all the HTML interfaces live. Next, we have t>ublic/idl/html, where all the HTML interfaces live. Next, we have
>o add nsIDOMFabian.idl to all the makefiles of this directory. Th> to add nsIDOMFabian.idl to all the makefiles of this directory. 
>is includes, if needed, "MANIFEST", "makefile.win", "Makefile.in">This includes, if needed, "MANIFEST", "makefile.win", "Makefile.i
>, etc... Simply copy the existing entries for nsIDOMFabian. <b>Wa>n", etc... Simply copy the existing entries for nsIDOMFabian. <b>
>rning: In Makefiles, there is a mix of TABS and whitespaces. Make>Warning: In Makefiles, there is a mix of TABS and whitespaces. Ma
> sure you copy exactly the other entries</b>.>ke sure you copy exactly the other entries</b>.
295      </p>296        </p>
296      <p>297        <p>
297        Then type "make" in dom/ to build the interface. If all g298          Then type "make" in dom/ to build the interface. If all
>oes well, a file nsIDOMFabian.h should be in dom/public/idl/html/> goes well, a file nsIDOMFabian.h should be in dom/public/idl/htm
>_xpidlgen/, and it should contain the C code for our interface. F>l/_xpidlgen/, and it should contain the C code for our interface.
>rom my own experience unfortunately it sometimes necessary to bui> From my own experience unfortunately it sometimes necessary to b
>ld "distclean" before it works.>uild "distclean" before it works.
298      </p>299        </p>
299      <h4 name="E.d_Interface_implementation">300        <h4 name="E.d_Interface_implementation">
300        E.d Interface implementation301          E.d Interface implementation
301      </h4>302        </h4>
302      <p>303        <p>
303        Let's take a closer look at how interfaces are implemente304          Let's take a closer look at how interfaces are implemen
>d. We already know that an interface has to be implemented by a c>ted. We already know that an interface has to be implemented by a
>oncrete C class. This class can implement multiple interfaces, di> concrete C class. This class can implement multiple interfaces, 
>rectly or through inheritance (see the next section for a discuss>directly or through inheritance (see the next section for a discu
>ion of inheritance). We also saw that an interface defined in XPI>ssion of inheritance). We also saw that an interface defined in X
>DL contains methods and attributes, which are transformed into C >PIDL contains methods and attributes, which are transformed into 
>functions by the XPIDL compiler. The class that implements the in>C functions by the XPIDL compiler. The class that implements the 
>terface has to explicitly implement each method and implement the>interface has to explicitly implement each method and implement t
> setter and the getter of each attribute defined on the interface>he setter and the getter of each attribute defined on the interfa
>. If the attribute is read-only, only a getter is necessary, of c>ce. If the attribute is read-only, only a getter is necessary, of
>ourse.> course.
304      </p>305        </p>
305      <p>306        <p>
306        I have chosen to implement nsIDOMFabian in the nsHTMLDocu307          I have chosen to implement nsIDOMFabian in the nsHTMLDo
>ment class, which is defined in <a class="external" href="http://>cument class, which is defined in <a class="external" href="http:
>lxr.mozilla.org/seamonkey/source/content/html/document/src/nsHTML>//lxr.mozilla.org/seamonkey/source/content/html/document/src/nsHT
>Document.h">nsHTMLDocument.h</a>. There are three things to do: m>MLDocument.h">nsHTMLDocument.h</a>. There are three things to do:
>odify the class declaration, the class body, then code the functi> modify the class declaration, the class body, then code the func
>ons declared on the interface.>tions declared on the interface.
307      </p>308        </p>
308      <p>309        <p>
309        Modification of the class declaration and class body:310          Modification of the class declaration and class body:
310      </p>311        </p>
311      <pre class="eval">312        <pre class="eval">
n323      <p>n324        <p>
324        First we have to declare nsHTMLDocument as inheriting fro325          First we have to declare nsHTMLDocument as inheriting f
>m nsIDOMFabian. Then, in the class public interface, we use the m>rom nsIDOMFabian. Then, in the class public interface, we use the
>acro NS_DECL_NSIDOMFABIAN to declare the methods necessary to the> macro NS_DECL_NSIDOMFABIAN to declare the methods necessary to t
> implementation of our interface. Remember, this macro is auto-ge>he implementation of our interface. Remember, this macro is auto-
>nerated by the XPIDL compiler. It declares all the methods that w>generated by the XPIDL compiler. It declares all the methods that
>ill be implemented on the class for the nsIDOMFabian interface. A> will be implemented on the class for the nsIDOMFabian interface.
> typical NS_DECL_NSIFOO macro looks like this:> A typical NS_DECL_NSIFOO macro looks like this:
325      </p>326        </p>
326      <pre class="eval">327        <pre class="eval">
n332      <p>n333        <p>
333        This macro has to be used in the class definition, and me334          This macro has to be used in the class definition, and 
>ans that the class nsFoo will have a method nsFoo::GetBar(). Now >means that the class nsFoo will have a method nsFoo::GetBar(). No
>that the functions are declared, we can finally code them.>w that the functions are declared, we can finally code them.
334      </p>335        </p>
335      <p>336        <p>
336        There are various possibilities to implement the function337          There are various possibilities to implement the functi
>s. The first one is the most straightforward. The functions we ha>ons. The first one is the most straightforward. The functions we 
>ve to implement are nsHTMLDocument::Fabian() and nsHTMLDocument::>have to implement are nsHTMLDocument::Fabian() and nsHTMLDocument
>GetNeat(). So let's just code them.>::GetNeat(). So let's just code them.
337      </p>338        </p>
338      <p>339        <p>
339        <br>340          <br>
340      </p>341        </p>
341      <pre class="eval">342        <pre class="eval">
n364      <p>n365        <p>
365        This code is of course written in nsHTMLDocument.cpp. The366          This code is of course written in nsHTMLDocument.cpp. T
> functions are very simple, but it is only a proof-of-concept. A >he functions are very simple, but it is only a proof-of-concept. 
>second possibility is to use the "Interface forwarding macro". Th>A second possibility is to use the "Interface forwarding macro". 
>is macro is also auto-generated by the XPIDL compiler. Below is t>This macro is also auto-generated by the XPIDL compiler. Below is
>he theory behind interface forwarding, followed by an example of > the theory behind interface forwarding, followed by an example o
>nsIDOMFabian.>f nsIDOMFabian.
366      </p>367        </p>
367      <h5 name="Theory">368        <h5 name="Theory">
368        Theory369          Theory
369      </h5>370        </h5>
370      <p>371        <p>
371        Let's assume we have the real class nsFoo which inherits 372          Let's assume we have the real class nsFoo which inherit
>from the real class nsBar. Let's also assume that nsFoo implement>s from the real class nsBar. Let's also assume that nsFoo impleme
>s the interface nsIFoo. One possible way for nsFoo to implement n>nts the interface nsIFoo. One possible way for nsFoo to implement
>sIFoo is to forward the methods on the interface to the implement> nsIFoo is to forward the methods on the interface to the impleme
>ation of those methods on the class nsBar.>ntation of those methods on the class nsBar.
372      </p>373        </p>
373      <p>374        <p>
374        <br>375          <br>
375      </p>376        </p>
376      <pre class="eval">377        <pre class="eval">
n398      <p>n399        <p>
399        For such code to work, nsBar of course has to implement G400          For such code to work, nsBar of course has to implement
>etProp, SetProp, and Meth. Note that nsBar implements the methods> GetProp, SetProp, and Meth. Note that nsBar implements the metho
> of the interface nsIFoo, but <b>does not</b> inherit from that i>ds of the interface nsIFoo, but <b>does not</b> inherit from that
>nterface. This is the <b>only</b> case where you would use interf> interface. This is the <b>only</b> case where you would use inte
>ace forwarding.>rface forwarding.
400      </p>401        </p>
401      <p>402        <p>
402        Instead of having to type the three methods and forward t403          Instead of having to type the three methods and forward
>hem to nsBar, we can use the "Interface forwarding macro", NS_FOR> them to nsBar, we can use the "Interface forwarding macro", NS_F
>WARD_NSIFOO.>ORWARD_NSIFOO.
403      </p>404        </p>
404      <pre class="eval">405        <pre class="eval">
n413      <p>n414        <p>
414        The meaning of this macro is easy to grasp. It will forwa415          The meaning of this macro is easy to grasp. It will for
>rd all the methods on the nsIFoo interface to the implementation >ward all the methods on the nsIFoo interface to the implementatio
>on the _to class.>n on the _to class.
415      </p>416        </p>
416      <p>417        <p>
417        Application to nsIDOMFabian: we could code our two functi418          Application to nsIDOMFabian: we could code our two func
>ons in nsDocument, then forward nsIDOMFabian to nsDocument from n>tions in nsDocument, then forward nsIDOMFabian to nsDocument from
>sHTMLDocument. This would allow us to be able to re-use the nsDoc> nsHTMLDocument. This would allow us to be able to re-use the nsD
>ument code in nsXMLDocument, for example. This technique is alrea>ocument code in nsXMLDocument, for example. This technique is alr
>dy used for most of the document methods.>eady used for most of the document methods.
418      </p>419        </p>
419      <p>420        <p>
420        <br>421          <br>
421      </p>422        </p>
422      <pre class="eval">423        <pre class="eval">
n453      <p>n454        <p>
454        This was an easy example of "Interface forwarding". These455          This was an easy example of "Interface forwarding". The
> two ways are the most common to implement an interface in the DO>se two ways are the most common to implement an interface in the 
>M. There are other ways that are a little more complicated, not w>DOM. There are other ways that are a little more complicated, not
>orth detailing here.> worth detailing here.
455      </p>456        </p>
456      <p>457        <p>
457        <b>Important note: the nsISupports interface, implemented458          <b>Important note: the nsISupports interface, implement
> by all the DOM classes, CANNOT be implemented with forwarding or>ed by all the DOM classes, CANNOT be implemented with forwarding 
> declaration macros. Special macros are provided to implement nsI>or declaration macros. Special macros are provided to implement n
>Supports</b>>sISupports</b>
458      </p>459        </p>
459      <p>460        <p>
460        This closes this tutorial about how to add a new interfac461          This closes this tutorial about how to add a new interf
>e. Simply make a full rebuild. I recommend building distclean. <b>ace. Simply make a full rebuild. I recommend building distclean. 
>>Your methods will not be available from JavaScript</b>, however,><b>Your methods will not be available from JavaScript</b>, howeve
> because nsIDOMFabian is not in the Class Info. Please see the {{>r, because nsIDOMFabian is not in the Class Info. Please see the 
>mediawiki.external('hacking.html#oneh User\'s guide of Class Info>{{mediawiki.external('hacking.html#oneh User\'s guide of Class In
>')}} to learn how to add it.>fo')}} to learn how to add it.
461      </p>462        </p>
462    </div>463      </div>
463    <div id="chapteronef">464      <div id="chapteronef">
464      <h3 name="F._Interface_inheritance_.28Advanced_topic.29">465        <h3 name="F._Interface_inheritance_.28Advanced_topic.29">
465        F. Interface inheritance (Advanced topic)466          F. Interface inheritance (Advanced topic)
466      </h3>467        </h3>
467      <p>468        <p>
468        The inheritance model in Mozilla is of course the same as469          The inheritance model in Mozilla is of course the same 
> the class inheritance model of C . If you are familiar with obje>as the class inheritance model of C . If you are familiar with ob
>ct-oriented programming you will have no problem understanding th>ject-oriented programming you will have no problem understanding 
>is discussion.>this discussion.
469      </p>470        </p>
470      <h5 name="Raw_interface_inheritance">471        <h5 name="Raw_interface_inheritance">
471        Raw interface inheritance472          Raw interface inheritance
472      </h5>473        </h5>
473      <p>474        <p>
474        The first concept is easy to grasp, it's the "interface i475          The first concept is easy to grasp, it's the "interface
>nheritance". If we look at any interface definition, in XPIDL or > inheritance". If we look at any interface definition, in XPIDL o
>as a header, we can see that it always inherits from another inte>r as a header, we can see that it always inherits from another in
>rface. For instance, we have the following "chain" for the nsIDOM>terface. For instance, we have the following "chain" for the nsID
>HTMLAnchorElement interface:<br>>OMHTMLAnchorElement interface:<br>
475        nsISupports -&gt; nsIDOMNode -&gt; nsIDOMElement -&gt; ns476          nsISupports -&gt; nsIDOMNode -&gt; nsIDOMElement -&gt; 
>IDOMHTMLElement -&gt; nsIDOMHTMLAnchorElement.>nsIDOMHTMLElement -&gt; nsIDOMHTMLAnchorElement.
476      </p>477        </p>
477      <p>478        <p>
478        This means that, if a class implements one of the interfa479          This means that, if a class implements one of the inter
>ces in the chain, it has to also implement <i>all the ancestors o>faces in the chain, it has to also implement <i>all the ancestors
>f that interface</i>. For example if a real class implements nsID> of that interface</i>. For example if a real class implements ns
>OMElement, it also has to implement nsIDOMNode and nsISupports.>IDOMElement, it also has to implement nsIDOMNode and nsISupports.
479      </p>480        </p>
480      <h5 name="Theory_2">481        <h5 name="Theory_2">
481        Theory482          Theory
482      </h5>483        </h5>
483      <p>484        <p>
484        Now that we know what interface inheritance means, we can485          Now that we know what interface inheritance means, we c
> look at more generic cases. We will first see this in a very the>an look at more generic cases. We will first see this in a very t
>oretical way, and then we will use the nsHTMLAnchorElement exampl>heoretical way, and then we will use the nsHTMLAnchorElement exam
>e to illustrate the discussion.>ple to illustrate the discussion.
485      </p>486        </p>
486      <p>487        <p>
487        Let's assume we have a DOM object Foo, implemented by the488          Let's assume we have a DOM object Foo, implemented by t
> real class nsFoo. We also have another real class, nsBar, as wel>he real class nsFoo. We also have another real class, nsBar, as w
>l as three interfaces, nsIFoo1, nsIFoo2, and nsIFoo3. The situati>ell as three interfaces, nsIFoo1, nsIFoo2, and nsIFoo3. The situa
>on is the following:>tion is the following:
488      </p>489        </p>
489      <p>490        <p>
490        <br>491          <br>
491      </p>492        </p>
492      <pre class="eval">493        <pre class="eval">
n498      <p>n499        <p>
499        In this situation, the nsIFoo2 interface inherits from th500          In this situation, the nsIFoo2 interface inherits from 
>e nsIFoo3 interface, as described above. nsFoo implements nsIFoo2>the nsIFoo3 interface, as described above. nsFoo implements nsIFo
>, and thus also nsIFoo3, and nsBar implements nsIFoo1. The real c>o2, and thus also nsIFoo3, and nsBar implements nsIFoo1. The real
>lass nsFoo inherits from the other real class nsBar. The rules de> class nsFoo inherits from the other real class nsBar. The rules 
>scribing inheritance are the following:>describing inheritance are the following:
500      </p>501        </p>
501      <ul>502        <ul>
502        <li>nsFoo implements nsIFoo1 automatically, because it in503          <li>nsFoo implements nsIFoo1 automatically, because it 
>herits from a class that already implements nsIFoo1.>inherits from a class that already implements nsIFoo1.
503        </li>504          </li>
504        <li>nsBar <i>has</i> to implement nsIFoo1.505          <li>nsBar <i>has</i> to implement nsIFoo1.
505        </li>506          </li>
506        <li>nsFoo <i>has</i> to implement nsIFoo2 and nsIFoo3, un507          <li>nsFoo <i>has</i> to implement nsIFoo2 and nsIFoo3, 
>less they are <i>forwarded</i> to nsBar. Interface forwarding is >unless they are <i>forwarded</i> to nsBar. Interface forwarding i
>described in Section 1.E.d.>s described in Section 1.E.d.
507        </li>508          </li>
508      </ul>509        </ul>
509      <p>510        <p>
510        These rules are pretty simple, and are widely used in the511          These rules are pretty simple, and are widely used in t
> DOM code. It gets trickier with a lot of classes and interfaces,>he DOM code. It gets trickier with a lot of classes and interface
> but you can always reduce the problem to the above situation.>s, but you can always reduce the problem to the above situation.
511      </p>512        </p>
512      <h5 name="Example">513        <h5 name="Example">
513        Example514          Example
514      </h5>515        </h5>
515      <p>516        <p>
516        Let's take a look at a simple example, the HTML Anchor El517          Let's take a look at a simple example, the HTML Anchor 
>ement. First, let's illustrate the interface inheritance rules. I>Element. First, let's illustrate the interface inheritance rules.
>f we look at nsIDOMHTMLAnchorElement (which contains the methods > If we look at nsIDOMHTMLAnchorElement (which contains the method
>and properties defined by the W3C for this element), we can see t>s and properties defined by the W3C for this element), we can see
>hat it inherits from another interface, nsIDOMHTMLElement:> that it inherits from another interface, nsIDOMHTMLElement:
517      </p>518        </p>
518      <p>519        <p>
519        <br>520          <br>
520      </p>521        </p>
521      <pre class="eval">522        <pre class="eval">
n524      <p>n525        <p>
525        This means that whatever class implements the nsIDOMHTMLA526          This means that whatever class implements the nsIDOMHTM
>nchorElement interface will also have to implement the nsIDOMHTML>LAnchorElement interface will also have to implement the nsIDOMHT
>Element interface. If we look at nsIDOMHTMLElement, we can see th>MLElement interface. If we look at nsIDOMHTMLElement, we can see 
>at it inherits from nsIDOMElement, which inherits from nsIDOMNode>that it inherits from nsIDOMElement, which inherits from nsIDOMNo
>, which inherits from nsISupports. Any class implementing nsIDOMH>de, which inherits from nsISupports. Any class implementing nsIDO
>TMLAnchorElement will have to implement all the mentioned interfa>MHTMLAnchorElement will have to implement all the mentioned inter
>ces, because of inheritance. How the interfaces are implemented i>faces, because of inheritance. How the interfaces are implemented
>s described in paragraph 1.E.d.> is described in paragraph 1.E.d.
526      </p>527        </p>
527      <p>528        <p>
528        The interface inheritance shows that the top-level interf529          The interface inheritance shows that the top-level inte
>ace is nsISupports. All interfaces have to inherit from nsISuppor>rface is nsISupports. All interfaces have to inherit from nsISupp
>ts, directly or indirectly. It defines three methods, AddRef(), R>orts, directly or indirectly. It defines three methods, AddRef(),
>elease(), and QueryInterface(), which is explained in Section 1.B> Release(), and QueryInterface(), which is explained in Section 1
>. nsISupports rests peacefully in <a class="external" href="http:>.B. nsISupports rests peacefully in <a class="external" href="htt
>//lxr.mozilla.org/seamonkey/source/xpcom/base/nsISupports.idl">xp>p://lxr.mozilla.org/seamonkey/source/xpcom/base/nsISupports.idl">
>com/base/</a>, unmodified since 1999. For more information about >xpcom/base/</a>, unmodified since 1999. For more information abou
>XPCOM interfaces and nsISupports, please read the <a class="exter>t XPCOM interfaces and nsISupports, please read the <a class="ext
>nal" href="http://www.mozilla.org/docs/modunote.htm">Modularizati>ernal" href="http://www.mozilla.org/docs/modunote.htm">Modulariza
>on techniques</a> guide.>tion techniques</a> guide.
529      </p>530        </p>
530      <p>531        <p>
531        To illustrate the inherited implementation of an interfac532          To illustrate the inherited implementation of an interf
>e, let's take a look at the real class that implements the HTML A>ace, let's take a look at the real class that implements the HTML
>nchor Element. It is nsHTMLAnchorElement. We can see that the inh> Anchor Element. It is nsHTMLAnchorElement. We can see that the i
>eritance chain for the real classes looks like this:>nheritance chain for the real classes looks like this:
532      </p>533        </p>
533      <p>534        <p>
534        <br>535          <br>
535      </p>536        </p>
536      <pre class="eval">537        <pre class="eval">
n539      <p>n540        <p>
540        We can see this in the class definitions:541          We can see this in the class definitions:
541      </p>542        </p>
542      <p>543        <p>
543        <br>544          <br>
544      </p>545        </p>
545      <pre class="eval">546        <pre class="eval">
n550      <p>n551        <p>
551        Looking at the class definitions, we can see that nsGener552          Looking at the class definitions, we can see that nsGen
>icHTMLElement and nsGenericHTMLContainerElement don't implement a>ericHTMLElement and nsGenericHTMLContainerElement don't implement
>ny interface directly. However nsGenericElement does:> any interface directly. However nsGenericElement does:
552      </p>553        </p>
553      <p>554        <p>
554        <br>555          <br>
555      </p>556        </p>
556      <pre class="eval">557        <pre class="eval">
n559      <p>n560        <p>
560        This of course means that nsGenericElement implements the561          This of course means that nsGenericElement implements t
> nsIHTMLContent interface. The interface inheritance chain for ns>he nsIHTMLContent interface. The interface inheritance chain for 
>IHTMLContent looks like this:>nsIHTMLContent looks like this:
561      </p>562        </p>
562      <p>563        <p>
563        <br>564          <br>
564      </p>565        </p>
565      <pre class="eval">566        <pre class="eval">
t569      <p>t570        <p>
570        nsGenericElement has to implement all of the above interf571          nsGenericElement has to implement all of the above inte
>aces, and <i>all the real classes inheriting from nsGenericElemen>rfaces, and <i>all the real classes inheriting from nsGenericElem
>t will automatically implement all those interfaces</i>. This is >ent will automatically implement all those interfaces</i>. This i
>consistent with the rules we have defined earlier in this paragra>s consistent with the rules we have defined earlier in this parag
>ph.>raph.
571      </p>572        </p>
572    </div>573      </div>
573    <div id="resources">574      <div id="resources">
574      Resources of interest:<br>575        Resources of interest:<br>
575      {{mediawiki.external('../../../scriptable/xpidl/ The XPIDL 576        {{mediawiki.external('../../../scriptable/xpidl/ The XPID
>reference')}}<br>>L reference')}}<br>
576      {{mediawiki.external('classes/ Mapping DOM Objects to their577        {{mediawiki.external('classes/ Mapping DOM Objects to the
> C class')}}<br>>ir C class')}}<br>
577      {{mediawiki.external('../../modunote.htm Modularization tec578        {{mediawiki.external('../../modunote.htm Modularization t
>hniques')}}>echniques')}}
578    </div>579      </div>
579    <hr>580      <hr>
580    <div id="footer">581      <div id="footer">
581      <ul>582        <ul>
582        <li>{{mediawiki.external('../../../sitemap.html Site Map'583          <li>{{mediawiki.external('../../../sitemap.html Site Ma
>)}}>p')}}
583        </li>584          </li>
584        <li>{{mediawiki.external('../../../security/ Security Upd585          <li>{{mediawiki.external('../../../security/ Security U
>ates')}}>pdates')}}
585        </li>586          </li>
586        <li>{{mediawiki.external('../../../contact/ Contact Us')}587          <li>{{mediawiki.external('../../../contact/ Contact Us'
>}>)}}
587        </li>588          </li>
588        <li>{{mediawiki.external('../../../foundation/donate.html589          <li>{{mediawiki.external('../../../foundation/donate.ht
> Donate')}}>ml Donate')}}
589        </li>590          </li>
590      </ul>591        </ul>
591      <p>592        <p>
592        Portions of this content are Â© 1998–2007 by individual593          Portions of this content are Â© 1998–2007 by individu
> mozilla.org contributors; content available under a Creative Com>al mozilla.org contributors; content available under a Creative C
>mons license | <a class="external" href="http://www.mozilla.org/f>ommons license | <a class="external" href="http://www.mozilla.org
>oundation/licensing/website-content.html">Details</a>.>/foundation/licensing/website-content.html">Details</a>.
593      </p>594        </p>
595      </div>

Back to History