/caps/src/nsJSPrincipals.cpp

http://github.com/zpao/v8monkey · C++ · 224 lines · 144 code · 27 blank · 53 comment · 21 complexity · c5a20dfbd0dad332d545aec0ba0b4940 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is mozilla.org code.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications Corporation.
  19. * Portions created by the Initial Developer are Copyright (C) 1999
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either of the GNU General Public License Version 2 or later (the "GPL"),
  26. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. #include "xpcprivate.h"
  38. #include "nsString.h"
  39. #include "nsIObjectOutputStream.h"
  40. #include "nsIObjectInputStream.h"
  41. #include "nsJSPrincipals.h"
  42. #include "plstr.h"
  43. #include "nsXPIDLString.h"
  44. #include "nsCOMPtr.h"
  45. #include "jsapi.h"
  46. #include "jsxdrapi.h"
  47. #include "nsIJSRuntimeService.h"
  48. #include "nsIServiceManager.h"
  49. #include "nsMemory.h"
  50. #include "nsStringBuffer.h"
  51. static JSBool
  52. nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other)
  53. {
  54. nsJSPrincipals *nsjsprin = static_cast<nsJSPrincipals *>(jsprin);
  55. nsJSPrincipals *nsother = static_cast<nsJSPrincipals *>(other);
  56. bool result;
  57. nsresult rv = nsjsprin->nsIPrincipalPtr->Subsumes(nsother->nsIPrincipalPtr,
  58. &result);
  59. return NS_SUCCEEDED(rv) && result;
  60. }
  61. static void
  62. nsDestroyJSPrincipals(JSContext *cx, struct JSPrincipals *jsprin)
  63. {
  64. nsJSPrincipals *nsjsprin = static_cast<nsJSPrincipals *>(jsprin);
  65. // We need to destroy the nsIPrincipal. We'll do this by adding
  66. // to the refcount and calling release
  67. // Note that we don't want to use NS_IF_RELEASE because it will try
  68. // to set nsjsprin->nsIPrincipalPtr to nsnull *after* nsjsprin has
  69. // already been destroyed.
  70. #ifdef NS_BUILD_REFCNT_LOGGING
  71. // The refcount logging considers AddRef-to-1 to indicate creation,
  72. // so trick it into thinking it's otherwise, but balance the
  73. // Release() we do below.
  74. nsjsprin->refcount++;
  75. nsjsprin->nsIPrincipalPtr->AddRef();
  76. nsjsprin->refcount--;
  77. #else
  78. nsjsprin->refcount++;
  79. #endif
  80. nsjsprin->nsIPrincipalPtr->Release();
  81. // The nsIPrincipal that we release owns the JSPrincipal struct,
  82. // so we don't need to worry about "codebase"
  83. }
  84. static JSBool
  85. nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp)
  86. {
  87. nsresult rv;
  88. if (xdr->mode == JSXDR_ENCODE) {
  89. nsIObjectOutputStream *stream =
  90. reinterpret_cast<nsIObjectOutputStream*>(xdr->userdata);
  91. // Flush xdr'ed data to the underlying object output stream.
  92. uint32_t size;
  93. char *data = (char*) ::JS_XDRMemGetData(xdr, &size);
  94. rv = stream->Write32(size);
  95. if (NS_SUCCEEDED(rv)) {
  96. rv = stream->WriteBytes(data, size);
  97. if (NS_SUCCEEDED(rv)) {
  98. ::JS_XDRMemResetData(xdr);
  99. // Require that GetJSPrincipals has been called already by the
  100. // code that compiled the script that owns the principals.
  101. nsJSPrincipals *nsjsprin =
  102. static_cast<nsJSPrincipals*>(*jsprinp);
  103. rv = stream->WriteObject(nsjsprin->nsIPrincipalPtr, true);
  104. }
  105. }
  106. } else {
  107. NS_ASSERTION(JS_XDRMemDataLeft(xdr) == 0, "XDR out of sync?!");
  108. nsIObjectInputStream *stream =
  109. reinterpret_cast<nsIObjectInputStream*>(xdr->userdata);
  110. nsCOMPtr<nsIPrincipal> prin;
  111. rv = stream->ReadObject(true, getter_AddRefs(prin));
  112. if (NS_SUCCEEDED(rv)) {
  113. PRUint32 size;
  114. rv = stream->Read32(&size);
  115. if (NS_SUCCEEDED(rv)) {
  116. char *data = nsnull;
  117. if (size != 0)
  118. rv = stream->ReadBytes(size, &data);
  119. if (NS_SUCCEEDED(rv)) {
  120. char *olddata;
  121. uint32_t oldsize;
  122. // Any decode-mode JSXDRState whose userdata points to an
  123. // nsIObjectInputStream instance must use nsMemory to Alloc
  124. // and Free its data buffer. Swap the new buffer we just
  125. // read for the old, exhausted data.
  126. olddata = (char*) ::JS_XDRMemGetData(xdr, &oldsize);
  127. nsMemory::Free(olddata);
  128. ::JS_XDRMemSetData(xdr, data, size);
  129. prin->GetJSPrincipals(xdr->cx, jsprinp);
  130. }
  131. }
  132. }
  133. }
  134. if (NS_FAILED(rv)) {
  135. ::JS_ReportError(xdr->cx, "can't %scode principals (failure code %x)",
  136. (xdr->mode == JSXDR_ENCODE) ? "en" : "de",
  137. (unsigned int) rv);
  138. return JS_FALSE;
  139. }
  140. return JS_TRUE;
  141. }
  142. nsresult
  143. nsJSPrincipals::Startup()
  144. {
  145. nsCOMPtr<nsIJSRuntimeService> rtsvc = nsXPConnect::GetXPConnect();
  146. if (!rtsvc)
  147. return NS_ERROR_FAILURE;
  148. JSRuntime *rt;
  149. rtsvc->GetRuntime(&rt);
  150. NS_ASSERTION(rt != nsnull, "no JSRuntime?!");
  151. JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(rt);
  152. NS_ASSERTION(callbacks, "Need a callbacks struct by now!");
  153. NS_ASSERTION(!callbacks->principalsTranscoder,
  154. "oops, JS_SetPrincipalsTranscoder wars!");
  155. callbacks->principalsTranscoder = nsTranscodeJSPrincipals;
  156. return NS_OK;
  157. }
  158. nsJSPrincipals::nsJSPrincipals()
  159. {
  160. codebase = nsnull;
  161. refcount = 0;
  162. destroy = nsDestroyJSPrincipals;
  163. subsume = nsJSPrincipalsSubsume;
  164. nsIPrincipalPtr = nsnull;
  165. }
  166. nsresult
  167. nsJSPrincipals::Init(nsIPrincipal *aPrincipal, const nsCString& aCodebase)
  168. {
  169. if (nsIPrincipalPtr) {
  170. NS_ERROR("Init called twice!");
  171. return NS_ERROR_UNEXPECTED;
  172. }
  173. nsIPrincipalPtr = aPrincipal;
  174. nsStringBuffer* buf = nsStringBuffer::FromString(aCodebase);
  175. char* data;
  176. if (buf) {
  177. buf->AddRef();
  178. data = static_cast<char*>(buf->Data());
  179. } else {
  180. PRUint32 len = aCodebase.Length();
  181. buf = nsStringBuffer::Alloc(len + 1); // addrefs
  182. if (!buf) {
  183. return NS_ERROR_OUT_OF_MEMORY;
  184. }
  185. data = static_cast<char*>(buf->Data());
  186. memcpy(data, aCodebase.get(), len);
  187. data[len] = '\0';
  188. }
  189. codebase = data;
  190. return NS_OK;
  191. }
  192. nsJSPrincipals::~nsJSPrincipals()
  193. {
  194. if (codebase) {
  195. nsStringBuffer::FromData(codebase)->Release();
  196. }
  197. }