Back to index

lightning-sunbird  0.9+nobinonly
nsJSInstallTriggerGlobal.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "jsapi.h"
00039 #include "nscore.h"
00040 #include "nsIScriptContext.h"
00041 #include "nsIScriptObjectOwner.h"
00042 #include "nsIScriptGlobalObject.h"
00043 #include "nsCRT.h"
00044 #include "nsString.h"
00045 #include "nsIDOMInstallVersion.h"
00046 #include "nsIDOMInstallTriggerGlobal.h"
00047 #include "nsIDOMWindow.h"
00048 #include "nsIDOMDocument.h"
00049 #include "nsIDocument.h"
00050 #include "nsIDocShell.h"
00051 #include "nsIObserverService.h"
00052 #include "nsInstallTrigger.h"
00053 #include "nsXPITriggerInfo.h"
00054 
00055 #include "nsIComponentManager.h"
00056 #include "nsNetUtil.h"
00057 #include "nsIScriptSecurityManager.h"
00058 
00059 #include "nsSoftwareUpdateIIDs.h"
00060 
00061 extern void ConvertJSValToStr(nsString&  aString,
00062                              JSContext* aContext,
00063                              jsval      aValue);
00064 
00065 extern void ConvertStrToJSVal(const nsString& aProp,
00066                              JSContext* aContext,
00067                              jsval* aReturn);
00068 
00069 extern PRBool ConvertJSValToBool(PRBool* aProp,
00070                                 JSContext* aContext,
00071                                 jsval aValue);
00072 
00073 PR_STATIC_CALLBACK(void)
00074 FinalizeInstallTriggerGlobal(JSContext *cx, JSObject *obj);
00075 
00076 /***********************************************************************/
00077 //
00078 // class for InstallTriggerGlobal
00079 //
00080 JSClass InstallTriggerGlobalClass = {
00081   "InstallTrigger",
00082   JSCLASS_HAS_PRIVATE,
00083   JS_PropertyStub,
00084   JS_PropertyStub,
00085   JS_PropertyStub,
00086   JS_PropertyStub,
00087   JS_EnumerateStub,
00088   JS_ResolveStub,
00089   JS_ConvertStub,
00090   FinalizeInstallTriggerGlobal
00091 };
00092 
00093 
00094 //
00095 // InstallTriggerGlobal finalizer
00096 //
00097 PR_STATIC_CALLBACK(void)
00098 FinalizeInstallTriggerGlobal(JSContext *cx, JSObject *obj)
00099 {
00100   nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(cx, obj);
00101 
00102   if (nsnull != nativeThis) {
00103     // get the js object
00104     nsIScriptObjectOwner *owner = nsnull;
00105     if (NS_OK == nativeThis->QueryInterface(NS_GET_IID(nsIScriptObjectOwner),
00106                                             (void**)&owner)) {
00107       owner->SetScriptObject(nsnull);
00108       NS_RELEASE(owner);
00109     }
00110 
00111     // The addref was part of JSObject construction
00112     NS_RELEASE(nativeThis);
00113   }
00114 }
00115 
00116 static JSBool CreateNativeObject(JSContext *cx, JSObject *obj, nsIDOMInstallTriggerGlobal **aResult)
00117 {
00118     nsresult result;
00119     nsIScriptObjectOwner *owner = nsnull;
00120     nsIDOMInstallTriggerGlobal *nativeThis;
00121 
00122     static NS_DEFINE_CID(kInstallTrigger_CID,
00123                          NS_SoftwareUpdateInstallTrigger_CID);
00124 
00125     result = CallCreateInstance(kInstallTrigger_CID, &nativeThis);
00126     if (NS_FAILED(result)) return JS_FALSE;
00127 
00128     result = nativeThis->QueryInterface(NS_GET_IID(nsIScriptObjectOwner),
00129                                         (void **)&owner);
00130 
00131     if (NS_OK != result)
00132     {
00133         NS_RELEASE(nativeThis);
00134         return JS_FALSE;
00135     }
00136 
00137     owner->SetScriptObject((void *)obj);
00138     JS_SetPrivate(cx, obj, nativeThis);
00139 
00140     *aResult = nativeThis;
00141 
00142     NS_RELEASE(nativeThis);  // we only want one refcnt. JSUtils cleans us up.
00143     return JS_TRUE;
00144 }
00145 
00146 //
00147 // Helper function for URI verification
00148 //
00149 static nsresult
00150 InstallTriggerCheckLoadURIFromScript(JSContext *cx, const nsAString& uriStr)
00151 {
00152     nsresult rv;
00153     nsCOMPtr<nsIScriptSecurityManager> secman(
00154         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID,&rv));
00155     NS_ENSURE_SUCCESS(rv, rv);
00156 
00157     // get the script base URI
00158     nsCOMPtr<nsIURI> scriptURI;
00159     nsCOMPtr<nsIPrincipal> principal;
00160     rv = secman->GetSubjectPrincipal(getter_AddRefs(principal));
00161     NS_ENSURE_SUCCESS(rv, rv);
00162     if (!principal)
00163         return NS_ERROR_FAILURE;
00164 
00165     rv = principal->GetURI(getter_AddRefs(scriptURI));
00166     NS_ENSURE_SUCCESS(rv, rv);
00167 
00168     if (!scriptURI) {
00169       // No URI reachable from the principal, get one from the calling
00170       // window.
00171 
00172       nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
00173       NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
00174 
00175       nsCOMPtr<nsIDOMWindow> window =
00176         do_QueryInterface(scx->GetGlobalObject());
00177       NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
00178 
00179       nsCOMPtr<nsIDOMDocument> domDoc;
00180       window->GetDocument(getter_AddRefs(domDoc));
00181 
00182       nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
00183       NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
00184 
00185       scriptURI = doc->GetDocumentURI();
00186     }
00187 
00188     // convert the requested URL string to a URI
00189     nsCOMPtr<nsIURI> uri;
00190     rv = NS_NewURI(getter_AddRefs(uri), uriStr);
00191     NS_ENSURE_SUCCESS(rv, rv);
00192 
00193     // are we allowed to load this one?
00194     rv = secman->CheckLoadURI(scriptURI, uri,
00195                     nsIScriptSecurityManager::DISALLOW_SCRIPT_OR_DATA);
00196     return rv;
00197 }
00198 
00199 //
00200 // Helper function to get native object
00201 //
00202 // This is our own version of JS_GetInstancePrivate() that in addition
00203 // performs the delayed creation of the native InstallTrigger if necessary
00204 //
00205 static nsIDOMInstallTriggerGlobal* getTriggerNative(JSContext *cx, JSObject *obj)
00206 {
00207   if (!JS_InstanceOf(cx, obj, &InstallTriggerGlobalClass, nsnull))
00208     return nsnull;
00209 
00210   nsIDOMInstallTriggerGlobal *native = (nsIDOMInstallTriggerGlobal*)JS_GetPrivate(cx, obj);
00211   if (!native) {
00212     // xpinstall script contexts delay creation of the native.
00213     CreateNativeObject(cx, obj, &native);
00214   }
00215   return native;
00216 }
00217 
00218 //
00219 // Native method UpdateEnabled
00220 //
00221 PR_STATIC_CALLBACK(JSBool)
00222 InstallTriggerGlobalUpdateEnabled(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00223 {
00224   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00225   if (!nativeThis)
00226     return JS_FALSE;
00227 
00228   *rval = JSVAL_FALSE;
00229 
00230   nsIScriptGlobalObject *globalObject = nsnull;
00231   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00232   if (scriptContext)
00233     globalObject = scriptContext->GetGlobalObject();
00234 
00235   PRBool nativeRet = PR_FALSE;
00236   if (globalObject)
00237     nativeThis->UpdateEnabled(globalObject, XPI_GLOBAL, &nativeRet);
00238 
00239   *rval = BOOLEAN_TO_JSVAL(nativeRet);
00240   return JS_TRUE;
00241 }
00242 
00243 
00244 //
00245 // Native method Install
00246 //
00247 PR_STATIC_CALLBACK(JSBool)
00248 InstallTriggerGlobalInstall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00249 { 
00250   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00251   if (!nativeThis)
00252     return JS_FALSE;
00253 
00254   *rval = JSVAL_FALSE;
00255 
00256   // make sure XPInstall is enabled, return false if not
00257   nsIScriptGlobalObject *globalObject = nsnull;
00258   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00259   if (scriptContext)
00260     globalObject = scriptContext->GetGlobalObject();
00261 
00262   PRBool enabled = PR_FALSE;
00263   nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
00264   if (!enabled || !globalObject)
00265   {
00266     nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
00267     if (os)
00268     {
00269       os->NotifyObservers(globalObject->GetDocShell(),
00270                           "xpinstall-install-blocked", 
00271                           NS_LITERAL_STRING("install").get());
00272     }
00273     return JS_TRUE;
00274   }
00275 
00276 
00277   nsCOMPtr<nsIScriptSecurityManager> secman(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
00278   if (!secman)
00279   {
00280     JS_ReportError(cx, "Could not the script security manager service.");
00281     return JS_FALSE;
00282   }
00283   // get the principal.  if it doesn't exist, die.
00284   nsCOMPtr<nsIPrincipal> principal;
00285   secman->GetSubjectPrincipal(getter_AddRefs(principal));
00286   if (!principal)
00287   {
00288     JS_ReportError(cx, "Could not get the Subject Principal during InstallTrigger.Install()");
00289     return JS_FALSE;
00290   }
00291 
00292   // get window.location to construct relative URLs
00293   nsCOMPtr<nsIURI> baseURL;
00294   JSObject* global = JS_GetGlobalObject(cx);
00295   if (global)
00296   {
00297     jsval v;
00298     if (JS_GetProperty(cx,global,"location",&v))
00299     {
00300       nsAutoString location;
00301       ConvertJSValToStr( location, cx, v );
00302       NS_NewURI(getter_AddRefs(baseURL), location);
00303     }
00304   }
00305 
00306   PRBool abortLoad = PR_FALSE;
00307 
00308   // parse associative array of installs
00309   if ( argc >= 1 && JSVAL_IS_OBJECT(argv[0]) && JSVAL_TO_OBJECT(argv[0]) )
00310   {
00311     nsXPITriggerInfo *trigger = new nsXPITriggerInfo();
00312     if (!trigger)
00313       return JS_FALSE;
00314 
00315     trigger->SetPrincipal(principal);
00316 
00317     JSIdArray *ida = JS_Enumerate( cx, JSVAL_TO_OBJECT(argv[0]) );
00318     if ( ida )
00319     {
00320       jsval v;
00321       const PRUnichar *name, *URL;
00322       const PRUnichar *iconURL = nsnull;
00323       const char *hash;
00324 
00325       for (int i = 0; i < ida->length && !abortLoad; i++ )
00326       {
00327         JS_IdToValue( cx, ida->vector[i], &v );
00328         name = NS_REINTERPRET_CAST(const PRUnichar*, JS_GetStringChars( JS_ValueToString( cx, v ) ));
00329 
00330         URL = iconURL = nsnull;
00331         hash = nsnull;
00332         JS_GetUCProperty( cx, JSVAL_TO_OBJECT(argv[0]), NS_REINTERPRET_CAST(const jschar*, name), nsCRT::strlen(name), &v );
00333         if ( JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) ) 
00334         {
00335           jsval v2;
00336           if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "URL", &v2 ) && !JSVAL_IS_VOID(v2))
00337             URL = NS_REINTERPRET_CAST(const PRUnichar*, JS_GetStringChars( JS_ValueToString( cx, v2 ) ));
00338 
00339           if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "IconURL", &v2 ) && !JSVAL_IS_VOID(v2))
00340             iconURL = NS_REINTERPRET_CAST(const PRUnichar*, JS_GetStringChars( JS_ValueToString( cx, v2 ) ));
00341 
00342           if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "Hash", &v2) && !JSVAL_IS_VOID(v2))
00343             hash = NS_REINTERPRET_CAST(const char*, JS_GetStringBytes( JS_ValueToString( cx, v2 ) ));
00344         }
00345         else
00346         {
00347           URL = NS_REINTERPRET_CAST(const PRUnichar*, JS_GetStringChars( JS_ValueToString( cx, v ) ));
00348         }
00349 
00350         if ( name && URL )
00351         {
00352             // Get relative URL to load
00353             nsAutoString xpiURL(URL);
00354             if (baseURL)
00355             {
00356                 nsCAutoString resolvedURL;
00357                 baseURL->Resolve(NS_ConvertUTF16toUTF8(xpiURL), resolvedURL);
00358                 xpiURL = NS_ConvertUTF8toUTF16(resolvedURL);
00359             }
00360 
00361             nsAutoString icon(iconURL);
00362             if (iconURL && baseURL)
00363             {
00364                 nsCAutoString resolvedIcon;
00365                 baseURL->Resolve(NS_ConvertUTF16toUTF8(icon), resolvedIcon);
00366                 icon = NS_ConvertUTF8toUTF16(resolvedIcon);
00367             }
00368 
00369             // Make sure we're allowed to load this URL and the icon URL
00370             nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, xpiURL);
00371             if (NS_FAILED(rv))
00372                 abortLoad = PR_TRUE;
00373 
00374             if (!abortLoad && iconURL)
00375             {
00376                 rv = InstallTriggerCheckLoadURIFromScript(cx, icon);
00377                 if (NS_FAILED(rv))
00378                     abortLoad = PR_TRUE;
00379             }
00380 
00381             if (!abortLoad)
00382             {
00383                 // Add the install item to the trigger collection
00384                 nsXPITriggerItem *item =
00385                     new nsXPITriggerItem( name, xpiURL.get(), icon.get(), hash );
00386                 if ( item )
00387                 {
00388                     trigger->Add( item );
00389                 }
00390                 else
00391                     abortLoad = PR_TRUE;
00392             }
00393         }
00394         else
00395             abortLoad = PR_TRUE;
00396       }
00397       JS_DestroyIdArray( cx, ida );
00398     }
00399 
00400 
00401     // save callback function if any (ignore bad args for now)
00402     if ( argc >= 2 && JS_TypeOfValue(cx,argv[1]) == JSTYPE_FUNCTION )
00403     {
00404         trigger->SaveCallback( cx, argv[1] );
00405     }
00406 
00407 
00408     // pass on only if good stuff found
00409     if (!abortLoad && trigger->Size() > 0)
00410     {
00411         PRBool result;
00412         nativeThis->Install(globalObject, trigger, &result);
00413         *rval = BOOLEAN_TO_JSVAL(result);
00414         return JS_TRUE;
00415     }
00416     // didn't pass it on so we must delete trigger
00417     delete trigger;
00418   }
00419 
00420   JS_ReportError(cx, "Incorrect arguments to InstallTrigger.Install()");
00421   return JS_FALSE;
00422 }
00423 
00424 
00425 //
00426 // Native method InstallChrome
00427 //
00428 PR_STATIC_CALLBACK(JSBool)
00429 InstallTriggerGlobalInstallChrome(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00430 {
00431   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00432   if (!nativeThis)
00433     return JS_FALSE;
00434 
00435   uint32       chromeType = NOT_CHROME;
00436   nsAutoString sourceURL;
00437   nsAutoString name;
00438 
00439   *rval = JSVAL_FALSE;
00440 
00441   // get chromeType first, the update enabled check for skins skips whitelisting
00442   if (argc >=1)
00443       JS_ValueToECMAUint32(cx, argv[0], &chromeType);
00444 
00445   // make sure XPInstall is enabled, return if not
00446   nsIScriptGlobalObject *globalObject = nsnull;
00447   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00448   if (scriptContext)
00449       globalObject = scriptContext->GetGlobalObject();
00450 
00451   PRBool enabled = PR_FALSE;
00452   nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
00453   if (!enabled || !globalObject)
00454   {
00455     nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
00456     if (os)
00457     {
00458       os->NotifyObservers(globalObject->GetDocShell(),
00459                           "xpinstall-install-blocked", 
00460                           NS_LITERAL_STRING("install").get());
00461     }
00462     return JS_TRUE;
00463   }
00464 
00465 
00466   // get window.location to construct relative URLs
00467   nsCOMPtr<nsIURI> baseURL;
00468   JSObject* global = JS_GetGlobalObject(cx);
00469   if (global)
00470   {
00471     jsval v;
00472     if (JS_GetProperty(cx,global,"location",&v))
00473     {
00474       nsAutoString location;
00475       ConvertJSValToStr( location, cx, v );
00476       NS_NewURI(getter_AddRefs(baseURL), location);
00477     }
00478   }
00479 
00480 
00481   if ( argc >= 3 )
00482   {
00483     ConvertJSValToStr(sourceURL, cx, argv[1]);
00484     ConvertJSValToStr(name, cx, argv[2]);
00485 
00486     if (baseURL)
00487     {
00488         nsCAutoString resolvedURL;
00489         baseURL->Resolve(NS_ConvertUTF16toUTF8(sourceURL), resolvedURL);
00490         sourceURL = NS_ConvertUTF8toUTF16(resolvedURL);
00491     }
00492 
00493     // Make sure caller is allowed to load this url.
00494     nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, sourceURL);
00495     if (NS_FAILED(rv))
00496         return JS_FALSE;
00497 
00498     if ( chromeType & CHROME_ALL )
00499     {
00500         // there's at least one known chrome type
00501         nsXPITriggerItem* item = new nsXPITriggerItem(name.get(),
00502                                                       sourceURL.get(), 
00503                                                       nsnull);
00504 
00505         PRBool nativeRet = PR_FALSE;
00506         nativeThis->InstallChrome(globalObject, chromeType, item, &nativeRet);
00507         *rval = BOOLEAN_TO_JSVAL(nativeRet);
00508     }
00509   }
00510   return JS_TRUE;
00511 }
00512 
00513 
00514 //
00515 // Native method StartSoftwareUpdate
00516 //
00517 PR_STATIC_CALLBACK(JSBool)
00518 InstallTriggerGlobalStartSoftwareUpdate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00519 {
00520   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00521   if (!nativeThis)
00522     return JS_FALSE;
00523 
00524   PRBool       nativeRet;
00525   PRInt32      flags = 0;
00526 
00527   *rval = JSVAL_FALSE;
00528 
00529   // make sure XPInstall is enabled, return if not
00530   nsIScriptGlobalObject *globalObject = nsnull;
00531   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00532   if (scriptContext)
00533       globalObject = scriptContext->GetGlobalObject();
00534 
00535   PRBool enabled = PR_FALSE;
00536   nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
00537   if (!enabled || !globalObject)
00538   {
00539     nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
00540     if (os)
00541     {
00542       os->NotifyObservers(globalObject->GetDocShell(),
00543                           "xpinstall-install-blocked", 
00544                           NS_LITERAL_STRING("install").get());
00545     }
00546     return JS_TRUE;
00547   }
00548 
00549   // get window.location to construct relative URLs
00550   nsCOMPtr<nsIURI> baseURL;
00551   JSObject* global = JS_GetGlobalObject(cx);
00552   if (global)
00553   {
00554     jsval v;
00555     if (JS_GetProperty(cx,global,"location",&v))
00556     {
00557       nsAutoString location;
00558       ConvertJSValToStr( location, cx, v );
00559       NS_NewURI(getter_AddRefs(baseURL), location);
00560     }
00561   }
00562 
00563   
00564   if ( argc >= 1 )
00565   {
00566     nsAutoString xpiURL;
00567     ConvertJSValToStr(xpiURL, cx, argv[0]);
00568     if (baseURL)
00569     {
00570         nsCAutoString resolvedURL;
00571         baseURL->Resolve(NS_ConvertUTF16toUTF8(xpiURL), resolvedURL);
00572         xpiURL = NS_ConvertUTF8toUTF16(resolvedURL);
00573     }
00574 
00575     // Make sure caller is allowed to load this url.
00576     nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, xpiURL);
00577     if (NS_FAILED(rv))
00578         return JS_FALSE;
00579 
00580     if (argc >= 2 && !JS_ValueToInt32(cx, argv[1], (int32 *)&flags))
00581     {
00582         JS_ReportError(cx, "StartSoftwareUpdate() 2nd parameter must be a number");
00583         return JS_FALSE;
00584     }
00585 
00586     if(NS_OK == nativeThis->StartSoftwareUpdate(globalObject, xpiURL, flags, &nativeRet))
00587     {
00588         *rval = BOOLEAN_TO_JSVAL(nativeRet);
00589     }
00590   }
00591   else
00592   {
00593     JS_ReportError(cx, "Function StartSoftwareUpdate requires 2 parameters");
00594     return JS_FALSE;
00595   }
00596 
00597   return JS_TRUE;
00598 }
00599 
00600 
00601 //
00602 // Native method CompareVersion
00603 //
00604 PR_STATIC_CALLBACK(JSBool)
00605 InstallTriggerGlobalCompareVersion(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00606 {
00607   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00608   if (!nativeThis)
00609     return JS_FALSE;
00610 
00611   nsAutoString regname;
00612   nsAutoString version;
00613   int32        major,minor,release,build;
00614 
00615   // In case of error or disabled return NOT_FOUND
00616   PRInt32 nativeRet = nsIDOMInstallTriggerGlobal::NOT_FOUND;
00617   *rval = INT_TO_JSVAL(nativeRet);
00618 
00619   // make sure XPInstall is enabled, return if not
00620   nsIScriptGlobalObject *globalObject = nsnull;
00621   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00622   if (scriptContext)
00623       globalObject = scriptContext->GetGlobalObject();
00624 
00625   PRBool enabled = PR_FALSE;
00626   nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
00627   if (!enabled)
00628       return JS_TRUE;
00629 
00630 
00631   if (argc < 2 )
00632   {
00633     JS_ReportError(cx, "CompareVersion requires at least 2 parameters");
00634     return JS_FALSE;
00635   }
00636   else if ( !JSVAL_IS_STRING(argv[0]) )
00637   {
00638     JS_ReportError(cx, "Invalid parameter passed to CompareVersion");
00639     return JS_FALSE;
00640   }
00641 
00642   // get the registry name argument
00643   ConvertJSValToStr(regname, cx, argv[0]);
00644 
00645   if (argc == 2 )
00646   {
00647     //  public int CompareVersion(String registryName, String version)
00648     //  --OR-- CompareVersion(String registryNamve, InstallVersion version)
00649 
00650     ConvertJSValToStr(version, cx, argv[1]);
00651     if(NS_OK != nativeThis->CompareVersion(regname, version, &nativeRet))
00652     {
00653           return JS_FALSE;
00654     }
00655   }
00656   else
00657   {
00658     //  public int CompareVersion(String registryName,
00659     //                            int    major,
00660     //                            int    minor,
00661     //                            int    release,
00662     //                            int    build);
00663     //
00664     //  minor, release, and build values are optional
00665 
00666     major = minor = release = build = 0;
00667 
00668     if(!JS_ValueToInt32(cx, argv[1], &major))
00669     {
00670       JS_ReportError(cx, "2th parameter must be a number");
00671       return JS_FALSE;
00672     }
00673     if( argc > 2 && !JS_ValueToInt32(cx, argv[2], &minor) )
00674     {
00675       JS_ReportError(cx, "3th parameter must be a number");
00676       return JS_FALSE;
00677     }
00678     if( argc > 3 && !JS_ValueToInt32(cx, argv[3], &release) )
00679     {
00680       JS_ReportError(cx, "4th parameter must be a number");
00681       return JS_FALSE;
00682     }
00683     if( argc > 4 && !JS_ValueToInt32(cx, argv[4], &build) )
00684     {
00685       JS_ReportError(cx, "5th parameter must be a number");
00686       return JS_FALSE;
00687     }
00688 
00689     if(NS_OK != nativeThis->CompareVersion(regname, major, minor, release, build, &nativeRet))
00690     {
00691       return JS_FALSE;
00692     }
00693   }
00694 
00695   *rval = INT_TO_JSVAL(nativeRet);
00696   return JS_TRUE;
00697 }
00698 
00699 //
00700 // Native method GetVersion
00701 //
00702 PR_STATIC_CALLBACK(JSBool)
00703 InstallTriggerGlobalGetVersion(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00704 {
00705   nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
00706   if (!nativeThis)
00707     return JS_FALSE;
00708 
00709   nsAutoString regname;
00710   nsAutoString version;
00711 
00712   // In case of error return a null value
00713   *rval = JSVAL_NULL;
00714 
00715   // make sure XPInstall is enabled, return if not
00716   nsIScriptGlobalObject *globalObject = nsnull;
00717   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
00718   if (scriptContext)
00719       globalObject = scriptContext->GetGlobalObject();
00720 
00721   PRBool enabled = PR_FALSE;
00722   nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
00723   if (!enabled)
00724       return JS_TRUE;
00725 
00726 
00727   // get the registry name argument
00728   ConvertJSValToStr(regname, cx, argv[0]);
00729 
00730   if(nativeThis->GetVersion(regname, version) == NS_OK && !version.IsEmpty() )
00731   {
00732       ConvertStrToJSVal(version, cx, rval);
00733   }
00734 
00735   return JS_TRUE;
00736 }
00737 
00738 //
00739 // InstallTriggerGlobal class methods
00740 //
00741 static JSFunctionSpec InstallTriggerGlobalMethods[] =
00742 {
00743   // -- obsolete forms, do not document. Kept for 4.x compatibility
00744   {"UpdateEnabled",             InstallTriggerGlobalUpdateEnabled,             0},
00745   {"StartSoftwareUpdate",       InstallTriggerGlobalStartSoftwareUpdate,       2},
00746   {"CompareVersion",            InstallTriggerGlobalCompareVersion,            5},
00747   {"GetVersion",                InstallTriggerGlobalGetVersion,                2},
00748   {"updateEnabled",             InstallTriggerGlobalUpdateEnabled,             0},
00749   // -- new forms to match JS style --
00750   {"enabled",                   InstallTriggerGlobalUpdateEnabled,             0},
00751   {"install",                   InstallTriggerGlobalInstall,                   2},
00752   {"installChrome",             InstallTriggerGlobalInstallChrome,             2},
00753   {"startSoftwareUpdate",       InstallTriggerGlobalStartSoftwareUpdate,       2},
00754   {"compareVersion",            InstallTriggerGlobalCompareVersion,            5},
00755   {"getVersion",                InstallTriggerGlobalGetVersion,                2},
00756   {0}
00757 };
00758 
00759 
00760 static JSConstDoubleSpec diff_constants[] =
00761 {
00762     { nsIDOMInstallTriggerGlobal::MAJOR_DIFF,    "MAJOR_DIFF" },
00763     { nsIDOMInstallTriggerGlobal::MINOR_DIFF,    "MINOR_DIFF" },
00764     { nsIDOMInstallTriggerGlobal::REL_DIFF,      "REL_DIFF"   },
00765     { nsIDOMInstallTriggerGlobal::BLD_DIFF,      "BLD_DIFF"   },
00766     { nsIDOMInstallTriggerGlobal::EQUAL,         "EQUAL"      },
00767     { nsIDOMInstallTriggerGlobal::NOT_FOUND,     "NOT_FOUND"  },
00768     { CHROME_SKIN,                               "SKIN"       },
00769     { CHROME_LOCALE,                             "LOCALE"     },
00770     { CHROME_CONTENT,                            "CONTENT"    },
00771     { CHROME_ALL,                                "PACKAGE"    },
00772     {0}
00773 };
00774 
00775 
00776 
00777 nsresult InitInstallTriggerGlobalClass(JSContext *jscontext, JSObject *global, void** prototype)
00778 {
00779   JSObject *proto = nsnull;
00780 
00781   if (prototype != nsnull)
00782     *prototype = nsnull;
00783 
00784     proto = JS_InitClass(jscontext,                       // context
00785                          global,                          // global object
00786                          nsnull,                          // parent proto
00787                          &InstallTriggerGlobalClass,      // JSClass
00788                          nsnull,                          // JSNative ctor
00789                          nsnull,                          // ctor args
00790                          nsnull,                          // proto props
00791                          nsnull,                          // proto funcs
00792                          nsnull,                          // ctor props (static)
00793                          InstallTriggerGlobalMethods);    // ctor funcs (static)
00794 
00795 
00796     if (nsnull == proto) return NS_ERROR_FAILURE;
00797 
00798     if ( PR_FALSE == JS_DefineConstDoubles(jscontext, proto, diff_constants) )
00799             return NS_ERROR_FAILURE;
00800 
00801     if (prototype != nsnull)
00802       *prototype = proto;
00803 
00804   return NS_OK;
00805 }
00806 
00807 
00808 
00809 //
00810 // InstallTriggerGlobal class initialization
00811 //
00812 nsresult NS_InitInstallTriggerGlobalClass(nsIScriptContext *aContext, void **aPrototype)
00813 {
00814   JSContext *jscontext = (JSContext *)aContext->GetNativeContext();
00815   JSObject *proto = nsnull;
00816   JSObject *constructor = nsnull;
00817   JSObject *global = JS_GetGlobalObject(jscontext);
00818   jsval vp;
00819 
00820   if ((PR_TRUE != JS_LookupProperty(jscontext, global, "InstallTriggerGlobal", &vp)) ||
00821       !JSVAL_IS_OBJECT(vp) ||
00822       ((constructor = JSVAL_TO_OBJECT(vp)) == nsnull) ||
00823       (PR_TRUE != JS_LookupProperty(jscontext, JSVAL_TO_OBJECT(vp), "prototype", &vp)) ||
00824       !JSVAL_IS_OBJECT(vp))
00825   {
00826     nsresult rv = InitInstallTriggerGlobalClass(jscontext, global, (void**)&proto);
00827     if (NS_FAILED(rv)) return rv;
00828   }
00829   else if ((nsnull != constructor) && JSVAL_IS_OBJECT(vp))
00830   {
00831     proto = JSVAL_TO_OBJECT(vp);
00832   }
00833   else
00834   {
00835     return NS_ERROR_FAILURE;
00836   }
00837 
00838   if (aPrototype)
00839     *aPrototype = proto;
00840 
00841   return NS_OK;
00842 }
00843 
00844 
00845 //
00846 // Method for creating a new InstallTriggerGlobal JavaScript object
00847 //
00848 nsresult
00849 NS_NewScriptInstallTriggerGlobal(nsIScriptContext *aContext,
00850                                  nsISupports *aSupports, nsISupports *aParent,
00851                                  void **aReturn)
00852 {
00853   NS_PRECONDITION(nsnull != aContext && nsnull != aSupports &&
00854                   nsnull != aReturn,
00855                   "null argument to NS_NewScriptInstallTriggerGlobal");
00856 
00857   JSObject *proto;
00858   JSObject *parent = nsnull;
00859   JSContext *jscontext = (JSContext *)aContext->GetNativeContext();
00860   nsresult result = NS_OK;
00861   nsIDOMInstallTriggerGlobal *installTriggerGlobal;
00862 
00863   nsCOMPtr<nsIScriptObjectOwner> owner(do_QueryInterface(aParent));
00864 
00865   if (owner) {
00866     if (NS_OK != owner->GetScriptObject(aContext, (void **)&parent)) {
00867       return NS_ERROR_FAILURE;
00868     }
00869   } else {
00870     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aParent));
00871 
00872     if (sgo) {
00873       parent = sgo->GetGlobalJSObject();
00874     } else {
00875       return NS_ERROR_FAILURE;
00876     }
00877   }
00878 
00879   if (NS_OK != NS_InitInstallTriggerGlobalClass(aContext, (void **)&proto)) {
00880     return NS_ERROR_FAILURE;
00881   }
00882 
00883   result = CallQueryInterface(aSupports, &installTriggerGlobal);
00884   if (NS_OK != result) {
00885     return result;
00886   }
00887 
00888   // create a js object for this class
00889   *aReturn = JS_NewObject(jscontext, &InstallTriggerGlobalClass, proto, parent);
00890   if (nsnull != *aReturn) {
00891     // connect the native object to the js object
00892     JS_SetPrivate(jscontext, (JSObject *)*aReturn, installTriggerGlobal);
00893   }
00894   else {
00895     NS_RELEASE(installTriggerGlobal);
00896     return NS_ERROR_FAILURE;
00897   }
00898 
00899   return NS_OK;
00900 }
00901