Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | <!-- This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | - License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
michael@0 | 4 | |
michael@0 | 5 | |
michael@0 | 6 | <center><b><font size=+2>XPConnect Sample</font></b> |
michael@0 | 7 | |
michael@0 | 8 | <p> |
michael@0 | 9 | <a href="mailto:arielb@rice.edu">Ariel Blackenroth <arielb@rice.edu></a> |
michael@0 | 10 | <br> |
michael@0 | 11 | <a href="mailto:mang@subcarrier.org">Michael Ang <mang@subcarrier.org></a> |
michael@0 | 12 | <br> |
michael@0 | 13 | Last modified |
michael@0 | 14 | <script> |
michael@0 | 15 | document.write(document.lastModified); |
michael@0 | 16 | </script> |
michael@0 | 17 | </center> |
michael@0 | 18 | |
michael@0 | 19 | <p>In the spirit of "worse is better" this somewhat rough guide is being |
michael@0 | 20 | released to the world. It will be expanded upon and improved. |
michael@0 | 21 | |
michael@0 | 22 | <p>XPConnect allows JavaScript |
michael@0 | 23 | to transparantly access and manipulate XPCOM objects; this communication |
michael@0 | 24 | between JavaScript and |
michael@0 | 25 | native code is done by having their interfaces defined in the XPIDL interface |
michael@0 | 26 | definition language. See the <a href="http://www.mozilla.org/scriptable/roadmap.html">Roadmap |
michael@0 | 27 | for documentation on XPCOM, XPConnect, XPTCall and XPIDL</a> for more information. |
michael@0 | 28 | |
michael@0 | 29 | <p><b>Overview</b> |
michael@0 | 30 | |
michael@0 | 31 | <p> |
michael@0 | 32 | This sample demonstrates accessing a XPCOM object through XPConnect. |
michael@0 | 33 | The JavaScript executed when this page loads creates an instance |
michael@0 | 34 | of the object by |
michael@0 | 35 | using the <tt>Components</tt> object, then accesses it through |
michael@0 | 36 | the <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsISample.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>: |
michael@0 | 37 | <br> |
michael@0 | 38 | <pre> |
michael@0 | 39 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 40 | var sample = Components.classes["@mozilla.org/sample;1"].createInstance(); |
michael@0 | 41 | sample = sample.QueryInterface(Components.interfaces.nsISample); |
michael@0 | 42 | </pre> |
michael@0 | 43 | |
michael@0 | 44 | <p> |
michael@0 | 45 | The buttons on the form are connected to JavaScript event handlers which |
michael@0 | 46 | call the methods defined in C++. |
michael@0 | 47 | |
michael@0 | 48 | |
michael@0 | 49 | <p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsISample.idl">nsISample.idl</a></b> |
michael@0 | 50 | <p>This is the interface declaration for the XPCOM object. It defines |
michael@0 | 51 | two functions, their parameters, and one attribute. It also defines |
michael@0 | 52 | the interface's id. The idl file is compiled by the xpidl compiler |
michael@0 | 53 | into a C++ header, nsISample.h and a .xpt file which is a binary representation |
michael@0 | 54 | of the interface used at runtime. |
michael@0 | 55 | <br><tt>attribute string value;</tt> |
michael@0 | 56 | <br><tt>void writeValue(in string aPrefix);</tt> |
michael@0 | 57 | <br><tt>void poke(in string aValue);</tt><b></b> |
michael@0 | 58 | <p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a></b> |
michael@0 | 59 | <p>This contains the implementation of nsISample.idl. SampleImpl |
michael@0 | 60 | inherits from nsISample.h, the header dynamically created by the xpidl |
michael@0 | 61 | compiler. The attribute Value has been expanded into a get and set |
michael@0 | 62 | and the return values have been modified to NS_IMETHOD, a success status |
michael@0 | 63 | for the method. The macro NS_DECL_ISUPPORTS, defined in <a href="http://lxr.mozilla.org/mozilla/source/xpcom/base/nsISupportsUtils.h">mozilla/xpcom/public/nsISupportsUtils.h</a> |
michael@0 | 64 | defines the inherited methods from nsISupports.h. |
michael@0 | 65 | <br><tt>NS_IMPL_ISUPPORTS(SampleImpl, nsISample)</tt> |
michael@0 | 66 | <br>In the constructor, the macro NS_INIT_REFCNT is called which sets the |
michael@0 | 67 | reference count to 0.<p> |
michael@0 | 68 | Note that the methods in the C++ bindings use InterCaps style, while the IDL |
michael@0 | 69 | and JavaScript versions should use interCaps naming. The JavaScript binding |
michael@0 | 70 | matches the case of the IDL, <b>except</b> <a |
michael@0 | 71 | href="http://bugzilla.mozilla.org/show_bug.cgi?id=14460">QueryInterface</a>. |
michael@0 | 72 | <p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSampleFactory.cpp">nsSampleFactory.cpp</a></b> |
michael@0 | 73 | <p>This is the class which builds the instance of the nsSample class. |
michael@0 | 74 | The COM framework uses factories to create instance of implementations |
michael@0 | 75 | rather than having the implementations instantiate themselves in order to |
michael@0 | 76 | increase portability of code. This factory inherits from nsFactory, |
michael@0 | 77 | which is also an XPCOM object. To gain more knowledge of factories |
michael@0 | 78 | see the <a href="http://www.mozilla.org/projects/xpcom/generic-factory.html">generic |
michael@0 | 79 | factory document</a> or the <a href="http://www.mozilla.org/docs/modunote.htm#Basics">Modularization techniques document</a>. |
michael@0 | 80 | <p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.js">nsSample.js</a></b> |
michael@0 | 81 | <p>This file implements the nsISample interface, and associated factory glue, |
michael@0 | 82 | in JavaScript. |
michael@0 | 83 | |
michael@0 | 84 | <p><b>Compiling the idl</b> |
michael@0 | 85 | |
michael@0 | 86 | <p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac) |
michael@0 | 87 | is compiled at build time (except on Mac) thus |
michael@0 | 88 | you will have to build mozilla in order to test this out. If you |
michael@0 | 89 | have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>. |
michael@0 | 90 | |
michael@0 | 91 | <p>Once you have the XPIDL compiler enter the following command at your |
michael@0 | 92 | prompt: |
michael@0 | 93 | <br><tt>D:\mozilla\xpcom\sample>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I |
michael@0 | 94 | d:\mozilla\dist\idl -m header nsISample.idl</tt> |
michael@0 | 95 | |
michael@0 | 96 | <p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder |
michael@0 | 97 | containing the other idl files, needed because nsISample.idl inherits from |
michael@0 | 98 | nsISupports.idl. The <tt>-m header</tt> instruction tells the compiler |
michael@0 | 99 | to build the C++ header. To build the .xpt file substitute <tt>-m |
michael@0 | 100 | typelib</tt>. |
michael@0 | 101 | |
michael@0 | 102 | <p> |
michael@0 | 103 | For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl |
michael@0 | 104 | compiler page</a>. |
michael@0 | 105 | |
michael@0 | 106 | <p><b>Building the Sample</b> |
michael@0 | 107 | |
michael@0 | 108 | <p>To build the Sample just enter |
michael@0 | 109 | <br><tt>d:\mozilla\xpcom\sample>nmake /f makefile.win</tt> |
michael@0 | 110 | |
michael@0 | 111 | <p>In order to do this you need to have your environment variables set |
michael@0 | 112 | correctly. See the <a href="http://www.mozilla.org/build/">Build</a> |
michael@0 | 113 | page for more information. |
michael@0 | 114 | |
michael@0 | 115 | <p><b>Running the sample</b> |
michael@0 | 116 | <p>Using Mozilla, load |
michael@0 | 117 | <a href="resource://res/samples/xpconnect-sample.html">resource://res/samples/xpconnect-sample.html</a> (i.e. what |
michael@0 | 118 | you're reading now). Pay attention |
michael@0 | 119 | to the console when clicking "write". Notice that the value |
michael@0 | 120 | printed is calculated in C++ code defined in <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a>. |
michael@0 | 121 | |
michael@0 | 122 | <!-- XXX keep in sync with stuff in pre tag below --> |
michael@0 | 123 | <script> |
michael@0 | 124 | /* to use nsSample.js version, use "@mozilla.org/jssample;1" */ |
michael@0 | 125 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 126 | var sample = Components.classes["@mozilla.org/sample;1"].createInstance(); |
michael@0 | 127 | sample = sample.QueryInterface(Components.interfaces.nsISample); |
michael@0 | 128 | dump("sample = " + sample + "\n"); |
michael@0 | 129 | |
michael@0 | 130 | function get() |
michael@0 | 131 | { |
michael@0 | 132 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 133 | var field = document.getElementById('Value'); |
michael@0 | 134 | field.value = sample.value; |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | function set() |
michael@0 | 138 | { |
michael@0 | 139 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 140 | var field = document.getElementById('Value'); |
michael@0 | 141 | sample.value = field.value; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | function poke() |
michael@0 | 145 | { |
michael@0 | 146 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 147 | var field = document.getElementById('Value'); |
michael@0 | 148 | sample.poke(field.value); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | function sampleWrite() |
michael@0 | 152 | { |
michael@0 | 153 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 154 | sample.writeValue("here is what I'm writing: "); |
michael@0 | 155 | } |
michael@0 | 156 | </script> |
michael@0 | 157 | |
michael@0 | 158 | <p> |
michael@0 | 159 | <form name="form"> |
michael@0 | 160 | <input type="button" value="Get" onclick="get();"> |
michael@0 | 161 | <input type="button" value="Set" onclick="set();"> |
michael@0 | 162 | <input type="button" value="Poke" onclick="poke();"> |
michael@0 | 163 | <input type="text" id="Value"> |
michael@0 | 164 | <input type="button" value="Write" onclick="sampleWrite();"> |
michael@0 | 165 | <form> |
michael@0 | 166 | |
michael@0 | 167 | <hr> |
michael@0 | 168 | |
michael@0 | 169 | <p> |
michael@0 | 170 | JavaScript and form source: |
michael@0 | 171 | |
michael@0 | 172 | <!-- XXX keep in sync with actual script --> |
michael@0 | 173 | <pre> |
michael@0 | 174 | <script> |
michael@0 | 175 | /* to use nsSample.js version, use "@mozilla.org/jssample;1" */ |
michael@0 | 176 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 177 | var sample = Components.classes["@mozilla.org/sample;1"].createInstance(); |
michael@0 | 178 | sample = sample.QueryInterface(Components.interfaces.nsISample); |
michael@0 | 179 | dump("sample = " + sample + "\n"); |
michael@0 | 180 | |
michael@0 | 181 | function get() |
michael@0 | 182 | { |
michael@0 | 183 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value'); |
michael@0 | 184 | field.value = sample.value; |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | function set() |
michael@0 | 188 | { |
michael@0 | 189 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value'); |
michael@0 | 190 | sample.value = field.value; |
michael@0 | 191 | } |
michael@0 | 192 | |
michael@0 | 193 | function poke() |
michael@0 | 194 | { |
michael@0 | 195 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value'); |
michael@0 | 196 | sample.poke(field.value); |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | function sampleWrite() |
michael@0 | 200 | { |
michael@0 | 201 | netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
michael@0 | 202 | sample.writeValue("here is what I'm writing: "); |
michael@0 | 203 | } |
michael@0 | 204 | </script> |
michael@0 | 205 | |
michael@0 | 206 | <form name="form"> |
michael@0 | 207 | <input type="button" value="Get" onclick="get();"> |
michael@0 | 208 | <input type="button" value="Set" onclick="set();"> |
michael@0 | 209 | <input type="button" value="Poke" onclick="poke();"> |
michael@0 | 210 | <input type="text" id="Value"> |
michael@0 | 211 | <input type="button" value="Write" onclick="sampleWrite();"> |
michael@0 | 212 | <form> |
michael@0 | 213 | |
michael@0 | 214 | </pre> |
michael@0 | 215 | |
michael@0 | 216 | <p> |
michael@0 | 217 | <hr> |
michael@0 | 218 | <b>Resources:</b> |
michael@0 | 219 | <ul> |
michael@0 | 220 | <li><a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/">mozilla/xpcom/sample source directory</a> |
michael@0 | 221 | </ul> |
michael@0 | 222 | <hr> |
michael@0 | 223 | <b>Comments to:</b> |
michael@0 | 224 | <a href="mailto:mang@subcarrier.org?Subject=XPCOM sample documentation">Michael Ang <mang@subcarrier.org></a> |