Back to index

lightning-sunbird  0.9+nobinonly
nsJSPrincipals.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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) 1999
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 "nsString.h"
00039 #include "nsIObjectOutputStream.h"
00040 #include "nsIObjectInputStream.h"
00041 #include "nsJSPrincipals.h"
00042 #include "plstr.h"
00043 #include "nsXPIDLString.h"
00044 #include "nsCOMPtr.h"
00045 #include "jsapi.h"
00046 #include "jsxdrapi.h"
00047 #include "nsIJSRuntimeService.h"
00048 #include "nsIServiceManager.h"
00049 #include "nsMemory.h"
00050 
00051 JS_STATIC_DLL_CALLBACK(void *)
00052 nsGetPrincipalArray(JSContext *cx, JSPrincipals *prin)
00053 {
00054     return nsnull;
00055 }
00056 
00057 JS_STATIC_DLL_CALLBACK(JSBool)
00058 nsGlobalPrivilegesEnabled(JSContext *cx, JSPrincipals *jsprin)
00059 {
00060     return JS_TRUE;
00061 }
00062 
00063 JS_STATIC_DLL_CALLBACK(JSBool)
00064 nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other)
00065 {
00066     nsJSPrincipals *nsjsprin = NS_STATIC_CAST(nsJSPrincipals *, jsprin);
00067     nsJSPrincipals *nsother  = NS_STATIC_CAST(nsJSPrincipals *, other);
00068 
00069     JSBool result;
00070     nsresult rv = nsjsprin->nsIPrincipalPtr->Subsumes(nsother->nsIPrincipalPtr,
00071                                                       &result);
00072     return NS_SUCCEEDED(rv) && result;
00073 }
00074 
00075 JS_STATIC_DLL_CALLBACK(void)
00076 nsDestroyJSPrincipals(JSContext *cx, struct JSPrincipals *jsprin)
00077 {
00078     nsJSPrincipals *nsjsprin = NS_STATIC_CAST(nsJSPrincipals *, jsprin);
00079 
00080     // We need to destroy the nsIPrincipal. We'll do this by adding
00081     // to the refcount and calling release
00082 
00083     // Note that we don't want to use NS_IF_RELEASE because it will try
00084     // to set nsjsprin->nsIPrincipalPtr to nsnull *after* nsjsprin has
00085     // already been destroyed.
00086 #ifdef NS_BUILD_REFCNT_LOGGING
00087     // The refcount logging considers AddRef-to-1 to indicate creation,
00088     // so trick it into thinking it's otherwise, but balance the
00089     // Release() we do below.
00090     nsjsprin->refcount++;
00091     nsjsprin->nsIPrincipalPtr->AddRef();
00092     nsjsprin->refcount--;
00093 #else
00094     nsjsprin->refcount++;
00095 #endif
00096     if (nsjsprin->nsIPrincipalPtr)
00097         nsjsprin->nsIPrincipalPtr->Release();
00098     // The nsIPrincipal that we release owns the JSPrincipal struct,
00099     // so we don't need to worry about "codebase"
00100 }
00101 
00102 JS_STATIC_DLL_CALLBACK(JSBool)
00103 nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
00104 {
00105     nsresult rv;
00106 
00107     if (xdr->mode == JSXDR_ENCODE) {
00108         nsIObjectOutputStream *stream =
00109             NS_REINTERPRET_CAST(nsIObjectOutputStream*, xdr->userdata);
00110 
00111         // Flush xdr'ed data to the underlying object output stream.
00112         uint32 size;
00113         char *data = (char*) ::JS_XDRMemGetData(xdr, &size);
00114 
00115         rv = stream->Write32(size);
00116         if (NS_SUCCEEDED(rv)) {
00117             rv = stream->WriteBytes(data, size);
00118             if (NS_SUCCEEDED(rv)) {
00119                 ::JS_XDRMemResetData(xdr);
00120 
00121                 // Require that GetJSPrincipals has been called already by the
00122                 // code that compiled the script that owns the principals.
00123                 nsJSPrincipals *nsjsprin =
00124                     NS_STATIC_CAST(nsJSPrincipals*, *jsprinp);
00125 
00126                 rv = stream->WriteObject(nsjsprin->nsIPrincipalPtr, PR_TRUE);
00127             }
00128         }
00129     } else {
00130         NS_ASSERTION(JS_XDRMemDataLeft(xdr) == 0, "XDR out of sync?!");
00131         nsIObjectInputStream *stream =
00132             NS_REINTERPRET_CAST(nsIObjectInputStream*, xdr->userdata);
00133 
00134         nsCOMPtr<nsIPrincipal> prin;
00135         rv = stream->ReadObject(PR_TRUE, getter_AddRefs(prin));
00136         if (NS_SUCCEEDED(rv)) {
00137             PRUint32 size;
00138             rv = stream->Read32(&size);
00139             if (NS_SUCCEEDED(rv)) {
00140                 char *data = nsnull;
00141                 if (size != 0)
00142                     rv = stream->ReadBytes(size, &data);
00143                 if (NS_SUCCEEDED(rv)) {
00144                     char *olddata;
00145                     uint32 oldsize;
00146 
00147                     // Any decode-mode JSXDRState whose userdata points to an
00148                     // nsIObjectInputStream instance must use nsMemory to Alloc
00149                     // and Free its data buffer.  Swap the new buffer we just
00150                     // read for the old, exhausted data.
00151                     olddata = (char*) ::JS_XDRMemGetData(xdr, &oldsize);
00152                     nsMemory::Free(olddata);
00153                     ::JS_XDRMemSetData(xdr, data, size);
00154 
00155                     prin->GetJSPrincipals(xdr->cx, jsprinp);
00156                 }
00157             }
00158         }
00159     }
00160 
00161     if (NS_FAILED(rv)) {
00162         ::JS_ReportError(xdr->cx, "can't %scode principals (failure code %x)",
00163                          (xdr->mode == JSXDR_ENCODE) ? "en" : "de",
00164                          (unsigned int) rv);
00165         return JS_FALSE;
00166     }
00167     return JS_TRUE;
00168 }
00169 
00170 nsresult
00171 nsJSPrincipals::Startup()
00172 {
00173     static const char rtsvc_id[] = "@mozilla.org/js/xpc/RuntimeService;1";
00174     nsCOMPtr<nsIJSRuntimeService> rtsvc(do_GetService(rtsvc_id));
00175     if (!rtsvc)
00176         return NS_ERROR_FAILURE;
00177 
00178     JSRuntime *rt;
00179     rtsvc->GetRuntime(&rt);
00180     NS_ASSERTION(rt != nsnull, "no JSRuntime?!");
00181 
00182     JSPrincipalsTranscoder oldpx;
00183     oldpx = ::JS_SetPrincipalsTranscoder(rt, nsTranscodeJSPrincipals);
00184     NS_ASSERTION(oldpx == nsnull, "oops, JS_SetPrincipalsTranscoder wars!");
00185 
00186     return NS_OK;
00187 }
00188 
00189 nsJSPrincipals::nsJSPrincipals()
00190 {
00191     codebase = nsnull;
00192     getPrincipalArray = nsGetPrincipalArray;
00193     globalPrivilegesEnabled = nsGlobalPrivilegesEnabled;
00194     refcount = 0;
00195     destroy = nsDestroyJSPrincipals;
00196     subsume = nsJSPrincipalsSubsume;
00197     nsIPrincipalPtr = nsnull;
00198 }
00199 
00200 nsresult
00201 nsJSPrincipals::Init(nsIPrincipal *aPrincipal, const char *aCodebase)
00202 {
00203     if (nsIPrincipalPtr) {
00204         NS_ERROR("Init called twice!");
00205         return NS_ERROR_UNEXPECTED;
00206     }
00207 
00208     nsIPrincipalPtr = aPrincipal;
00209     codebase = PL_strdup(aCodebase);
00210     if (!codebase)
00211         return NS_ERROR_OUT_OF_MEMORY;
00212 
00213     return NS_OK;
00214 }
00215 
00216 nsJSPrincipals::~nsJSPrincipals()
00217 {
00218     if (codebase)
00219         PL_strfree(codebase);
00220 }