Bug 713550 - Move Base64 code on nsXPConnect to XPCOM / xpcpublic.h; r=bholley+khuey
authorMs2ger <ms2ger@gmail.com>
Wed, 28 Dec 2011 09:13:38 +0100
changeset 83407 d144d8a5af9e89faa160725f063cd10f531bc3b2
parent 83406 62021daf7d1dca66423d0ec961510e3c67a185c9
child 83443 010fe7e7df1a9797a4b6b43c17462943db5d9a84
push idunknown
push userunknown
push dateunknown
reviewersbholley
bugs713550
milestone12.0a1
Bug 713550 - Move Base64 code on nsXPConnect to XPCOM / xpcpublic.h; r=bholley+khuey
content/base/src/nsContentUtils.cpp
dom/base/nsStructuredCloneContainer.cpp
dom/workers/FileReaderSync.cpp
dom/workers/Makefile.in
dom/workers/WorkerScope.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
xpcom/io/Base64.cpp
xpcom/io/Base64.h
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -188,30 +188,31 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 
 #include "mozAutoDocUpdate.h"
 #include "imgICache.h"
-#include "xpcprivate.h"
+#include "xpcprivate.h" // nsXPConnect
 #include "nsScriptSecurityManager.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentDLF.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif
 #include "nsDOMTouchEvent.h"
 #include "nsIScriptElement.h"
 #include "nsIContentViewer.h"
 #include "nsIObjectLoadingContent.h"
 
+#include "mozilla/Base64.h"
 #include "mozilla/Preferences.h"
 
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla;
@@ -628,29 +629,29 @@ nsresult
 nsContentUtils::Btoa(const nsAString& aBinaryData,
                      nsAString& aAsciiBase64String)
 {
   if (!Is8bit(aBinaryData)) {
     aAsciiBase64String.Truncate();
     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
   }
 
-  return nsXPConnect::Base64Encode(aBinaryData, aAsciiBase64String);
+  return Base64Encode(aBinaryData, aAsciiBase64String);
 }
 
 nsresult
 nsContentUtils::Atob(const nsAString& aAsciiBase64String,
                      nsAString& aBinaryData)
 {
   if (!Is8bit(aAsciiBase64String)) {
     aBinaryData.Truncate();
     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
   }
 
-  nsresult rv = nsXPConnect::Base64Decode(aAsciiBase64String, aBinaryData);
+  nsresult rv = Base64Decode(aAsciiBase64String, aBinaryData);
   if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
   }
   return rv;
 }
 
 bool
 nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -40,17 +40,20 @@
 
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 #include "nsIJSContextStack.h"
 #include "nsIScriptContext.h"
 #include "nsIVariant.h"
 #include "nsServiceManagerUtils.h"
 #include "nsContentUtils.h"
-#include "xpcprivate.h"
+
+#include "mozilla/Base64.h"
+
+using namespace mozilla;
 
 NS_IMPL_ADDREF(nsStructuredCloneContainer)
 NS_IMPL_RELEASE(nsStructuredCloneContainer)
 
 NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
   NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
@@ -119,17 +122,17 @@ nsStructuredCloneContainer::InitFromBase
                                            PRUint32 aFormatVersion,
                                            JSContext *aCx)
 {
   NS_ENSURE_STATE(!mData);
 
   NS_ConvertUTF16toUTF8 data(aData);
 
   nsCAutoString binaryData;
-  nsresult rv = nsXPConnect::Base64Decode(data, binaryData);
+  nsresult rv = Base64Decode(data, binaryData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Copy the string's data into our own buffer.
   mData = (PRUint64*) malloc(binaryData.Length());
   NS_ENSURE_STATE(mData);
   memcpy(mData, binaryData.get(), binaryData.Length());
 
   mSize = binaryData.Length();
@@ -166,17 +169,17 @@ nsStructuredCloneContainer::DeserializeT
 nsresult
 nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
 {
   NS_ENSURE_STATE(mData);
   aOut.Truncate();
 
   nsCAutoString binaryData(reinterpret_cast<char*>(mData), mSize);
   nsCAutoString base64Data;
-  nsresult rv = nsXPConnect::Base64Encode(binaryData, base64Data);
+  nsresult rv = Base64Encode(binaryData, base64Data);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aOut.Assign(NS_ConvertASCIItoUTF16(base64Data));
   return NS_OK;
 }
 
 nsresult
 nsStructuredCloneContainer::GetSerializedNBytes(PRUint64 *aSize)
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -41,17 +41,16 @@
 
 #include "nsIDOMFile.h"
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jstypedarray.h"
 #include "nsJSUtils.h"
-#include "xpcprivate.h"
 
 #include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSyncPrivate.h"
 #include "WorkerInlines.h"
 
 #define FUNCTION_FLAGS \
   JSPROP_ENUMERATE
--- a/dom/workers/Makefile.in
+++ b/dom/workers/Makefile.in
@@ -72,17 +72,16 @@ CPPSRCS = \
   XMLHttpRequest.cpp \
   XMLHttpRequestPrivate.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
   -I$(topsrcdir)/content/base/src \
   -I$(topsrcdir)/content/events/src \
   -I$(topsrcdir)/dom/base \
-  -I$(topsrcdir)/js/xpconnect/src \
   -I$(topsrcdir)/xpcom/build \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += test
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -37,20 +37,21 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "WorkerScope.h"
 
 #include "jsapi.h"
+#include "jsdbgapi.h"
 #include "jscntxt.h"
 
 #include "nsTraceRefcnt.h"
-#include "xpcprivate.h"
+#include "xpcpublic.h"
 
 #include "ChromeWorkerScope.h"
 #include "Events.h"
 #include "EventTarget.h"
 #include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSync.h"
 #include "ListenerManager.h"
@@ -543,17 +544,17 @@ private:
     }
 
     jsval string;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &string)) {
       return false;
     }
 
     jsval result;
-    if (!nsXPConnect::Base64Decode(aCx, string, &result)) {
+    if (!xpc::Base64Decode(aCx, string, &result)) {
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, result);
     return true;
   }
 
   static JSBool
@@ -569,17 +570,17 @@ private:
     }
 
     jsval binary;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &binary)) {
       return false;
     }
 
     jsval result;
-    if (!nsXPConnect::Base64Encode(aCx, binary, &result)) {
+    if (!xpc::Base64Encode(aCx, binary, &result)) {
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, result);
     return true;
   }
 };
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -85,16 +85,17 @@
 #include "nsIConsoleService.h"
 #include "nsIStorageStream.h"
 #include "nsIStringStream.h"
 #include "prmem.h"
 #if defined(XP_WIN)
 #include "nsILocalFileWin.h"
 #endif
 #include "xpcprivate.h"
+#include "xpcpublic.h"
 #include "nsIResProtocolHandler.h"
 
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/Omnijar.h"
 
 #include "jsdbgapi.h"
 
@@ -230,26 +231,26 @@ Debug(JSContext *cx, uintN argc, jsval *
 }
 
 static JSBool
 Atob(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!argc)
         return true;
 
-    return nsXPConnect::Base64Decode(cx, JS_ARGV(cx, vp)[0], &JS_RVAL(cx, vp));
+    return xpc::Base64Decode(cx, JS_ARGV(cx, vp)[0], &JS_RVAL(cx, vp));
 }
 
 static JSBool
 Btoa(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!argc)
         return true;
 
-    return nsXPConnect::Base64Encode(cx, JS_ARGV(cx, vp)[0], &JS_RVAL(cx, vp));
+    return xpc::Base64Encode(cx, JS_ARGV(cx, vp)[0], &JS_RVAL(cx, vp));
 }
 
 static JSBool
 File(JSContext *cx, uintN argc, jsval *vp)
 {
     nsresult rv;
 
     if (!argc) {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -49,26 +49,29 @@
 #include "jsatom.h"
 #include "jsfriendapi.h"
 #include "jsgc.h"
 #include "nsThreadUtilsInternal.h"
 #include "dom_quickstubs.h"
 #include "nsNullPrincipal.h"
 #include "nsIURI.h"
 #include "nsJSEnvironment.h"
-#include "plbase64.h"
 
 #include "XrayWrapper.h"
 #include "WrapperFactory.h"
 #include "AccessCheck.h"
 
 #include "jsdIDebuggerService.h"
 
 #include "XPCQuickStubs.h"
 #include "dombindings.h"
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Base64.h"
+
 #include "nsWrapperCacheInlines.h"
 
 NS_IMPL_THREADSAFE_ISUPPORTS7(nsXPConnect,
                               nsIXPConnect,
                               nsISupportsWeakReference,
                               nsIThreadObserver,
                               nsIJSRuntimeService,
                               nsIJSContextStack,
@@ -2792,165 +2795,72 @@ nsXPConnect::GetCaller(JSContext **aJSCo
 {
     XPCCallContext *ccx = XPCPerThreadData::GetData(nsnull)->GetCallContext();
     *aJSContext = ccx->GetJSContext();
 
     // Set to the caller in XPC_WN_Helper_{Call,Construct}
     *aObj = ccx->GetFlattenedJSObject();
 }
 
-// static
-nsresult
-nsXPConnect::Base64Encode(const nsACString &aBinaryData, nsACString &aString)
+namespace xpc {
+
+bool
+Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
 {
-  // Check for overflow.
-  if (aBinaryData.Length() > (PR_UINT32_MAX / 4) * 3)
-      return NS_ERROR_FAILURE;
-
-  PRUint32 stringLen = ((aBinaryData.Length() + 2) / 3) * 4;
-
-  char *buffer;
-
-  // Add one byte for null termination.
-  if (aString.SetCapacity(stringLen + 1) &&
-      (buffer = aString.BeginWriting()) &&
-      PL_Base64Encode(aBinaryData.BeginReading(), aBinaryData.Length(), buffer)) {
-      // PL_Base64Encode doesn't null terminate the buffer for us when we pass
-      // the buffer in. Do that manually.
-      buffer[stringLen] = '\0';
-
-      aString.SetLength(stringLen);
-      return NS_OK;
-  }
-
-  aString.Truncate();
-  return NS_ERROR_INVALID_ARG;
-}
-
-// static
-nsresult
-nsXPConnect::Base64Encode(const nsAString &aString, nsAString &aBinaryData)
-{
-    NS_LossyConvertUTF16toASCII string(aString);
-    nsCAutoString binaryData;
-
-    nsresult rv = Base64Encode(string, binaryData);
-    if (NS_SUCCEEDED(rv))
-        CopyASCIItoUTF16(binaryData, aBinaryData);
-    else
-        aBinaryData.Truncate();
-
-    return rv;
-}
-
-// static
-JSBool
-nsXPConnect::Base64Encode(JSContext *cx, jsval val, jsval *out)
-{
-    NS_ASSERTION(cx, "Null context!");
-    NS_ASSERTION(out, "Null jsval pointer!");
-
-    jsval root = val;
+    MOZ_ASSERT(cx);
+    MOZ_ASSERT(out);
+
+    JS::Value root = val;
     xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
                                  xpc_qsACString::eStringify);
     if (!encodedString.IsValid())
         return false;
 
     nsCAutoString result;
-    if (NS_FAILED(nsXPConnect::Base64Encode(encodedString, result))) {
+    if (NS_FAILED(mozilla::Base64Encode(encodedString, result))) {
         JS_ReportError(cx, "Failed to encode base64 data!");
         return false;
     }
 
     JSString *str = JS_NewStringCopyN(cx, result.get(), result.Length());
     if (!str)
         return false;
 
     *out = STRING_TO_JSVAL(str);
     return true;
 }
 
-// static
-nsresult
-nsXPConnect::Base64Decode(const nsACString &aString, nsACString &aBinaryData)
+bool
+Base64Decode(JSContext *cx, JS::Value val, JS::Value *out)
 {
-  // Check for overflow.
-  if (aString.Length() > PR_UINT32_MAX / 3)
-      return NS_ERROR_FAILURE;
-
-  PRUint32 binaryDataLen = ((aString.Length() * 3) / 4);
-
-  char *buffer;
-
-  // Add one byte for null termination.
-  if (aBinaryData.SetCapacity(binaryDataLen + 1) &&
-      (buffer = aBinaryData.BeginWriting()) &&
-      PL_Base64Decode(aString.BeginReading(), aString.Length(), buffer)) {
-      // PL_Base64Decode doesn't null terminate the buffer for us when we pass
-      // the buffer in. Do that manually, taking into account the number of '='
-      // characters we were passed.
-      if (!aString.IsEmpty() && aString[aString.Length() - 1] == '=') {
-          if (aString.Length() > 1 && aString[aString.Length() - 2] == '=')
-              binaryDataLen -= 2;
-          else
-              binaryDataLen -= 1;
-      }
-      buffer[binaryDataLen] = '\0';
-
-      aBinaryData.SetLength(binaryDataLen);
-      return NS_OK;
-  }
-
-  aBinaryData.Truncate();
-  return NS_ERROR_INVALID_ARG;
-}
-
-// static
-nsresult
-nsXPConnect::Base64Decode(const nsAString &aBinaryData, nsAString &aString)
-{
-    NS_LossyConvertUTF16toASCII binaryData(aBinaryData);
-    nsCAutoString string;
-
-    nsresult rv = Base64Decode(binaryData, string);
-    if (NS_SUCCEEDED(rv))
-        CopyASCIItoUTF16(string, aString);
-    else
-        aString.Truncate();
-
-    return rv;
-}
-
-// static
-JSBool
-nsXPConnect::Base64Decode(JSContext *cx, jsval val, jsval *out)
-{
-    NS_ASSERTION(cx, "Null context!");
-    NS_ASSERTION(out, "Null jsval pointer!");
-
-    jsval root = val;
+    MOZ_ASSERT(cx);
+    MOZ_ASSERT(out);
+
+    JS::Value root = val;
     xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
                                  xpc_qsACString::eNull);
     if (!encodedString.IsValid())
         return false;
 
     nsCAutoString result;
-    if (NS_FAILED(nsXPConnect::Base64Decode(encodedString, result))) {
+    if (NS_FAILED(mozilla::Base64Decode(encodedString, result))) {
         JS_ReportError(cx, "Failed to decode base64 string!");
         return false;
     }
 
     JSString *str = JS_NewStringCopyN(cx, result.get(), result.Length());
     if (!str)
         return false;
 
     *out = STRING_TO_JSVAL(str);
     return true;
 }
 
+} // namespace xpc
+
 NS_IMETHODIMP
 nsXPConnect::SetDebugModeWhenPossible(bool mode, bool allowSyncDisable)
 {
     gDesiredDebugMode = mode;
     if (!mode && allowSyncDisable)
         CheckForDebugMode(mRuntime->GetJSRuntime());
     return NS_OK;
 }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -527,34 +527,16 @@ public:
 
     JSBool IsShuttingDown() const {return mShuttingDown;}
 
     void EnsureGCBeforeCC() { mNeedGCBeforeCC = true; }
 
     nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
     nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
 
-    static nsresult Base64Encode(const nsACString &aString,
-                                 nsACString &aBinary);
-
-    static nsresult Base64Encode(const nsAString &aString,
-                                 nsAString &aBinaryData);
-
-    // If this returns false then an exception will be set on cx.
-    static JSBool Base64Encode(JSContext *cx, jsval val, jsval *out);
-
-    static nsresult Base64Decode(const nsACString &aBinaryData,
-                                 nsACString &aString);
-
-    static nsresult Base64Decode(const nsAString &aBinaryData,
-                                 nsAString &aString);
-
-    // If this returns false then an exception will be set on cx.
-    static JSBool Base64Decode(JSContext *cx, jsval val, jsval *out);
-
     // nsCycleCollectionParticipant
     NS_IMETHOD Root(void *p);
     NS_IMETHOD Unlink(void *p);
     NS_IMETHOD Unroot(void *p);
     NS_IMETHOD Traverse(void *p,
                         nsCycleCollectionTraversalCallback &cb);
 
     // nsCycleCollectionLanguageRuntime
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -191,16 +191,20 @@ xpc_UnmarkGrayObject(JSObject *obj)
 
 // No JS can be on the stack when this is called. Probably only useful from
 // xpcshell.
 NS_EXPORT_(void)
 xpc_ActivateDebugMode();
 
 namespace xpc {
 
+// If these functions return false, then an exception will be set on cx.
+bool Base64Encode(JSContext *cx, JS::Value val, JS::Value *out);
+bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out);
+
 /**
  * Convert an nsString to jsval, returning true on success.
  * Note, the ownership of the string buffer may be moved from str to rval.
  * If that happens, str will point to an empty string after this call.
  */
 bool StringToJsval(JSContext *cx, nsString &str, JS::Value *rval);
 
 } // namespace xpc
--- a/xpcom/io/Base64.cpp
+++ b/xpcom/io/Base64.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -34,16 +34,19 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "Base64.h"
 
 #include "nsIInputStream.h"
+#include "nsStringGlue.h"
+
+#include "plbase64.h"
 
 namespace {
 
 // BEGIN base64 encode code copied and modified from NSPR
 const unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 template <typename T>
 static void
@@ -250,9 +253,105 @@ nsresult
 Base64EncodeInputStream(nsIInputStream *aInputStream, 
                         nsAString &aDest,
                         PRUint32 aCount,
                         PRUint32 aOffset)
 {
   return EncodeInputStream<nsAString>(aInputStream, aDest, aCount, aOffset);
 }
 
+nsresult
+Base64Encode(const nsACString &aBinaryData, nsACString &aString)
+{
+  // Check for overflow.
+  if (aBinaryData.Length() > (PR_UINT32_MAX / 4) * 3) {
+    return NS_ERROR_FAILURE;
+  }
+
+  PRUint32 stringLen = ((aBinaryData.Length() + 2) / 3) * 4;
+
+  char *buffer;
+
+  // Add one byte for null termination.
+  if (aString.SetCapacity(stringLen + 1) &&
+    (buffer = aString.BeginWriting()) &&
+    PL_Base64Encode(aBinaryData.BeginReading(), aBinaryData.Length(), buffer)) {
+    // PL_Base64Encode doesn't null terminate the buffer for us when we pass
+    // the buffer in. Do that manually.
+    buffer[stringLen] = '\0';
+
+    aString.SetLength(stringLen);
+    return NS_OK;
+  }
+
+  aString.Truncate();
+  return NS_ERROR_INVALID_ARG;
+}
+
+nsresult
+Base64Encode(const nsAString &aString, nsAString &aBinaryData)
+{
+  NS_LossyConvertUTF16toASCII string(aString);
+  nsCAutoString binaryData;
+
+  nsresult rv = Base64Encode(string, binaryData);
+  if (NS_SUCCEEDED(rv)) {
+    CopyASCIItoUTF16(binaryData, aBinaryData);
+  } else {
+    aBinaryData.Truncate();
+  }
+
+  return rv;
+}
+
+nsresult
+Base64Decode(const nsACString &aString, nsACString &aBinaryData)
+{
+  // Check for overflow.
+  if (aString.Length() > PR_UINT32_MAX / 3) {
+    return NS_ERROR_FAILURE;
+  }
+
+  PRUint32 binaryDataLen = ((aString.Length() * 3) / 4);
+
+  char *buffer;
+
+  // Add one byte for null termination.
+  if (aBinaryData.SetCapacity(binaryDataLen + 1) &&
+    (buffer = aBinaryData.BeginWriting()) &&
+    PL_Base64Decode(aString.BeginReading(), aString.Length(), buffer)) {
+    // PL_Base64Decode doesn't null terminate the buffer for us when we pass
+    // the buffer in. Do that manually, taking into account the number of '='
+    // characters we were passed.
+    if (!aString.IsEmpty() && aString[aString.Length() - 1] == '=') {
+      if (aString.Length() > 1 && aString[aString.Length() - 2] == '=') {
+        binaryDataLen -= 2;
+      } else {
+        binaryDataLen -= 1;
+      }
+    }
+    buffer[binaryDataLen] = '\0';
+
+    aBinaryData.SetLength(binaryDataLen);
+    return NS_OK;
+  }
+
+  aBinaryData.Truncate();
+  return NS_ERROR_INVALID_ARG;
+}
+
+nsresult
+Base64Decode(const nsAString &aBinaryData, nsAString &aString)
+{
+  NS_LossyConvertUTF16toASCII binaryData(aBinaryData);
+  nsCAutoString string;
+
+  nsresult rv = Base64Decode(binaryData, string);
+  if (NS_SUCCEEDED(rv)) {
+    CopyASCIItoUTF16(string, aString);
+  } else {
+    aString.Truncate();
+  }
+
+  return rv;
+}
+
 } // namespace mozilla
--- a/xpcom/io/Base64.h
+++ b/xpcom/io/Base64.h
@@ -50,11 +50,21 @@ Base64EncodeInputStream(nsIInputStream *
                         PRUint32 aCount,
                         PRUint32 aOffset = 0);
 nsresult
 Base64EncodeInputStream(nsIInputStream *aInputStream, 
                         nsAString &aDest,
                         PRUint32 aCount,
                         PRUint32 aOffset = 0);
 
+nsresult
+Base64Encode(const nsACString &aString, nsACString &aBinary);
+nsresult
+Base64Encode(const nsAString &aString, nsAString &aBinaryData);
+
+nsresult
+Base64Decode(const nsACString &aBinaryData, nsACString &aString);
+nsresult
+Base64Decode(const nsAString &aBinaryData, nsAString &aString);
+
 } // namespace mozilla
 
 #endif