Back to index

lightning-sunbird  0.9+nobinonly
xpcsample1.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1999
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /* xpconnect api sample */
00041 
00042 #include "xpcsample1.h"
00043 #include "nsIXPConnect.h"
00044 #include "jsapi.h"
00045 #include "nsIGenericFactory.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsCOMPtr.h"
00048 
00049 /***************************************************************************/
00050 // forward declare the below classes for clarity
00051 class nsXPCSample_ClassA;
00052 class nsXPCSample_ClassB;
00053 class nsXPCSample_ClassC;
00054 
00055 /***************************************************************************/
00056 // declare the classes
00057 
00058 class nsXPCSample_ClassA : public nsIXPCSample_ClassA
00059 {
00060 public:
00061     NS_DECL_ISUPPORTS
00062     NS_DECL_NSIXPCSAMPLE_CLASSA
00063 
00064     nsXPCSample_ClassA(PRInt32 aValue);
00065     virtual ~nsXPCSample_ClassA();
00066 
00067 private:
00068     PRInt32 mValue;
00069     nsCOMPtr<nsIXPCSample_ClassB> mClassB;
00070 };
00071 
00072 /********************************/
00073 
00074 class nsXPCSample_ClassB : public nsIXPCSample_ClassB
00075 {
00076 public:
00077     NS_DECL_ISUPPORTS
00078     NS_DECL_NSIXPCSAMPLE_CLASSB
00079 
00080     nsXPCSample_ClassB(PRInt32 aValue);
00081     virtual ~nsXPCSample_ClassB();
00082 
00083 private:
00084     PRInt32 mValue;
00085     nsCOMPtr<nsIXPCSample_ClassC> mClassC;
00086 };
00087 
00088 /********************************/
00089 
00090 class nsXPCSample_ClassC : public nsIXPCSample_ClassC
00091 {
00092 public:
00093     NS_DECL_ISUPPORTS
00094     NS_DECL_NSIXPCSAMPLE_CLASSC
00095 
00096     nsXPCSample_ClassC(PRInt32 aValue);
00097     virtual ~nsXPCSample_ClassC();
00098 
00099 private:
00100     PRInt32 mValue;
00101 };
00102 
00103 /***************************************************************************/
00104 // implement the 'root' ClassA for this odd sample
00105 
00106 NS_IMPL_ISUPPORTS1(nsXPCSample_ClassA, nsIXPCSample_ClassA)
00107 
00108 nsXPCSample_ClassA::nsXPCSample_ClassA(PRInt32 aValue)
00109     :   mValue(aValue)
00110 {
00111 }
00112 
00113 nsXPCSample_ClassA::~nsXPCSample_ClassA()
00114 {
00115     // empty
00116 }
00117 
00118 /* attribute PRInt32 someValue; */
00119 NS_IMETHODIMP nsXPCSample_ClassA::GetSomeValue(PRInt32 *aSomeValue)
00120 {
00121     *aSomeValue = mValue;
00122     return NS_OK;
00123 }
00124 
00125 NS_IMETHODIMP nsXPCSample_ClassA::SetSomeValue(PRInt32 aSomeValue)
00126 {
00127     mValue = aSomeValue;
00128     return NS_OK;
00129 }
00130 
00131 /* readonly attribute nsIXPCSample_ClassB B; */
00132 NS_IMETHODIMP nsXPCSample_ClassA::GetB(nsIXPCSample_ClassB * *aB)
00133 {
00134     if(!mClassB && !(mClassB = new nsXPCSample_ClassB(mValue)))
00135         return NS_ERROR_FAILURE;
00136     *aB = mClassB;
00137     NS_ADDREF(*aB);
00138     return NS_OK;
00139 }
00140 
00141 /***************************************************************************/
00142 // implement ClassB for this odd sample
00143 
00144 NS_IMPL_ISUPPORTS1(nsXPCSample_ClassB, nsIXPCSample_ClassB)
00145 
00146 nsXPCSample_ClassB::nsXPCSample_ClassB(PRInt32 aValue)
00147     :   mValue(aValue)
00148 {
00149 }
00150 
00151 nsXPCSample_ClassB::~nsXPCSample_ClassB()
00152 {
00153     // empty
00154 }
00155 
00156 /* attribute PRInt32 someValue; */
00157 NS_IMETHODIMP nsXPCSample_ClassB::GetSomeValue(PRInt32 *aSomeValue)
00158 {
00159     *aSomeValue = mValue;
00160     return NS_OK;
00161 }
00162 
00163 NS_IMETHODIMP nsXPCSample_ClassB::SetSomeValue(PRInt32 aSomeValue)
00164 {
00165     mValue = aSomeValue;
00166     return NS_OK;
00167 }
00168 
00169 /* readonly attribute nsIXPCSample_ClassC C; */
00170 NS_IMETHODIMP nsXPCSample_ClassB::GetC(nsIXPCSample_ClassC * *aC)
00171 {
00172     if(!mClassC && !(mClassC = new nsXPCSample_ClassC(mValue)))
00173         return NS_ERROR_FAILURE;
00174     *aC = mClassC;
00175     NS_ADDREF(*aC);
00176     return NS_OK;
00177 }
00178 
00179 /***************************************************************************/
00180 // implement ClassC for this odd sample
00181 
00182 NS_IMPL_ISUPPORTS1(nsXPCSample_ClassC, nsIXPCSample_ClassC)
00183 
00184 nsXPCSample_ClassC::nsXPCSample_ClassC(PRInt32 aValue)
00185     :   mValue(aValue)
00186 {
00187 }
00188 
00189 nsXPCSample_ClassC::~nsXPCSample_ClassC()
00190 {
00191     // empty
00192 }
00193 
00194 /* attribute PRInt32 someValue; */
00195 NS_IMETHODIMP nsXPCSample_ClassC::GetSomeValue(PRInt32 *aSomeValue)
00196 {
00197     *aSomeValue = mValue;
00198     return NS_OK;
00199 }
00200 
00201 NS_IMETHODIMP nsXPCSample_ClassC::SetSomeValue(PRInt32 aSomeValue)
00202 {
00203     mValue = aSomeValue;
00204     return NS_OK;
00205 }
00206 
00207 /***************************************************************************/
00208 // implement the hooker-upper (see the comment in the xpcsample1.idl)
00209 
00210 class nsXPCSample_HookerUpper : public nsIXPCSample_HookerUpper
00211 {
00212 public:
00213     NS_DECL_ISUPPORTS
00214     NS_DECL_NSIXPCSAMPLE_HOOKERUPPER
00215 
00216     nsXPCSample_HookerUpper();
00217     virtual ~nsXPCSample_HookerUpper();
00218 };
00219 
00220 NS_IMPL_ISUPPORTS1(nsXPCSample_HookerUpper, nsIXPCSample_HookerUpper)
00221 
00222 nsXPCSample_HookerUpper::nsXPCSample_HookerUpper()
00223 {
00224 }
00225 
00226 nsXPCSample_HookerUpper::~nsXPCSample_HookerUpper()
00227 {
00228     // empty
00229 }
00230 
00231 /* void createSampleObjectAtGlobalScope (in string name, in PRInt32 value); */
00232 NS_IMETHODIMP
00233 nsXPCSample_HookerUpper::CreateSampleObjectAtGlobalScope(const char *name, PRInt32 value)
00234 {
00235     // we use the xpconnect native call context stuff to get the current
00236     // JSContext. Again, this would not be necessary if we were setting up
00237     // our own JSContext instead of resonding to a call inside a running
00238     // context.
00239 
00240     // get the xpconnect service
00241     nsresult rv;
00242     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
00243     if(NS_FAILED(rv))
00244         return NS_ERROR_FAILURE;
00245 
00246     // get the xpconnect native call context
00247     nsCOMPtr<nsIXPCNativeCallContext> callContext;
00248     xpc->GetCurrentNativeCallContext(getter_AddRefs(callContext));
00249     if(!callContext)
00250         return NS_ERROR_FAILURE;
00251 
00252     // verify that we are being called from JS (i.e. the current call is
00253     // to this object - though we don't verify that it is to this exact method)
00254     nsCOMPtr<nsISupports> callee;
00255     callContext->GetCallee(getter_AddRefs(callee));
00256     if(!callee || callee.get() != (nsISupports*)this)
00257         return NS_ERROR_FAILURE;
00258 
00259     // Get JSContext of current call
00260     JSContext* cx;
00261     rv = callContext->GetJSContext(&cx);
00262     if(NS_FAILED(rv) || !cx)
00263         return NS_ERROR_FAILURE;
00264 
00265     // Get the xpc wrapper (for 'this') so that we can get its JSObject
00266     nsCOMPtr<nsIXPConnectWrappedNative> calleeWrapper;
00267     callContext->GetCalleeWrapper(getter_AddRefs(calleeWrapper));
00268     if(!calleeWrapper)
00269         return NS_ERROR_FAILURE;
00270 
00271     // Get the JSObject of the wrapper
00272     JSObject* calleeJSObject;
00273     rv = calleeWrapper->GetJSObject(&calleeJSObject);
00274     if(NS_FAILED(rv) || !calleeJSObject)
00275         return NS_ERROR_FAILURE;
00276 
00277     // Now we walk the parent chain of the wrapper's JSObject to get at the
00278     // global object to which we'd like to attack the new property (which is
00279     // the point of this whole exercise!)
00280     JSObject* tempJSObject;
00281     JSObject* globalJSObject = calleeJSObject;
00282     while(tempJSObject = JS_GetParent(cx, globalJSObject))
00283         globalJSObject = tempJSObject;
00284 
00285     // --- if we did this all at JSContext setup time then only the following
00286     // is necessary...
00287 
00288     // Create the new native object
00289     nsXPCSample_ClassA* classA = new nsXPCSample_ClassA(value);
00290     if(!classA)
00291         return NS_ERROR_FAILURE;
00292 
00293     // Build an xpconnect wrapper around the object
00294     nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
00295     rv = xpc->WrapNative(cx, globalJSObject, classA,
00296                          NS_GET_IID(nsXPCSample_ClassA),
00297                          getter_AddRefs(wrapper));
00298     if(NS_FAILED(rv) || !wrapper)
00299         return NS_ERROR_FAILURE;
00300 
00301     // Get the JSObject of the new wrapper we just built around our ClassA obj
00302     JSObject* ourJSObject;
00303     rv = wrapper->GetJSObject(&ourJSObject);
00304     if(NS_FAILED(rv) || !ourJSObject)
00305         return NS_ERROR_FAILURE;
00306 
00307     // Now we can use the JSAPI to add this JSObject as a property of the
00308     // global object.
00309 
00310     if(!JS_DefineProperty(cx,
00311                           globalJSObject,       // add property to this object
00312                           "A",                  // give property this name
00313                           OBJECT_TO_JSVAL(ourJSObject),
00314                           nsnull, nsnull,
00315                           JSPROP_PERMANENT |    // these flags are optional
00316                           JSPROP_READONLY |
00317                           JSPROP_ENUMERATE))
00318         return NS_ERROR_FAILURE;
00319 
00320     // all is well - new object was added!
00321     return NS_OK;
00322 }
00323 
00324 /***************************************************************************/
00325 // generic factory and component registration stuff...
00326 
00327 NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCSample_HookerUpper)
00328 
00329 static const nsModuleComponentInfo components[] = {
00330 { "sample xpc component",
00331   { 0x97380cf0, 0xc21b, 0x11d3, { 0x98, 0xc9, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } },
00332   NS_NSXPCSAMPLE_HOOKERUPPER_CONTRACTID,
00333   nsXPCSample_HookerUpperConstructor }
00334 };
00335 
00336 NS_IMPL_NSGETMODULE(xpconnect_samples, components)
00337