dom/base/nsStructuredCloneContainer.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: set ts=8 sw=2 et tw=80:
     3  *
     4  * This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #include "nsStructuredCloneContainer.h"
    10 #include "nsCOMPtr.h"
    11 #include "nsIScriptContext.h"
    12 #include "nsIVariant.h"
    13 #include "nsIXPConnect.h"
    14 #include "nsServiceManagerUtils.h"
    15 #include "nsContentUtils.h"
    16 #include "jsapi.h"
    17 #include "js/StructuredClone.h"
    19 #include "mozilla/Base64.h"
    21 using namespace mozilla;
    23 NS_IMPL_ADDREF(nsStructuredCloneContainer)
    24 NS_IMPL_RELEASE(nsStructuredCloneContainer)
    26 NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
    27   NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
    28   NS_INTERFACE_MAP_ENTRY(nsISupports)
    29 NS_INTERFACE_MAP_END
    31 nsStructuredCloneContainer::nsStructuredCloneContainer()
    32   : mData(nullptr), mSize(0), mVersion(0)
    33 {
    34 }
    36 nsStructuredCloneContainer::~nsStructuredCloneContainer()
    37 {
    38   free(mData);
    39 }
    41 nsresult
    42 nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
    43                                           JSContext* aCx)
    44 {
    45   NS_ENSURE_STATE(!mData);
    46   NS_ENSURE_ARG_POINTER(aCx);
    48   // Make sure that we serialize in the right context.
    49   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
    50   JS::Rooted<JS::Value> jsData(aCx, aData);
    51   bool success = JS_WrapValue(aCx, &jsData);
    52   NS_ENSURE_STATE(success);
    54   uint64_t* jsBytes = nullptr;
    55   success = JS_WriteStructuredClone(aCx, jsData, &jsBytes, &mSize,
    56                                     nullptr, nullptr,
    57                                     JS::UndefinedHandleValue);
    58   NS_ENSURE_STATE(success);
    59   NS_ENSURE_STATE(jsBytes);
    61   // Copy jsBytes into our own buffer.
    62   mData = (uint64_t*) malloc(mSize);
    63   if (!mData) {
    64     mSize = 0;
    65     mVersion = 0;
    67     JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
    68     return NS_ERROR_FAILURE;
    69   }
    70   else {
    71     mVersion = JS_STRUCTURED_CLONE_VERSION;
    72   }
    74   memcpy(mData, jsBytes, mSize);
    76   JS_ClearStructuredClone(jsBytes, mSize, nullptr, nullptr);
    77   return NS_OK;
    78 }
    80 nsresult
    81 nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
    82                                            uint32_t aFormatVersion,
    83                                            JSContext *aCx)
    84 {
    85   NS_ENSURE_STATE(!mData);
    87   NS_ConvertUTF16toUTF8 data(aData);
    89   nsAutoCString binaryData;
    90   nsresult rv = Base64Decode(data, binaryData);
    91   NS_ENSURE_SUCCESS(rv, rv);
    93   // Copy the string's data into our own buffer.
    94   mData = (uint64_t*) malloc(binaryData.Length());
    95   NS_ENSURE_STATE(mData);
    96   memcpy(mData, binaryData.get(), binaryData.Length());
    98   mSize = binaryData.Length();
    99   mVersion = aFormatVersion;
   100   return NS_OK;
   101 }
   104 nsresult
   105 nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
   106                                                  nsIVariant **aData)
   107 {
   108   NS_ENSURE_STATE(mData);
   109   NS_ENSURE_ARG_POINTER(aData);
   110   *aData = nullptr;
   112   // Deserialize to a JS::Value.
   113   JS::Rooted<JS::Value> jsStateObj(aCx);
   114   bool hasTransferable = false;
   115   bool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
   116                                         &jsStateObj, nullptr, nullptr) &&
   117                  JS_StructuredCloneHasTransferables(mData, mSize,
   118                                                     &hasTransferable);
   119   // We want to be sure that mData doesn't contain transferable objects
   120   MOZ_ASSERT(!hasTransferable);
   121   NS_ENSURE_STATE(success && !hasTransferable);
   123   // Now wrap the JS::Value as an nsIVariant.
   124   nsCOMPtr<nsIVariant> varStateObj;
   125   nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
   126   NS_ENSURE_STATE(xpconnect);
   127   xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
   128   NS_ENSURE_STATE(varStateObj);
   130   NS_ADDREF(*aData = varStateObj);
   131   return NS_OK;
   132 }
   134 nsresult
   135 nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
   136 {
   137   NS_ENSURE_STATE(mData);
   138   aOut.Truncate();
   140   nsAutoCString binaryData(reinterpret_cast<char*>(mData), mSize);
   141   nsAutoCString base64Data;
   142   nsresult rv = Base64Encode(binaryData, base64Data);
   143   NS_ENSURE_SUCCESS(rv, rv);
   145   aOut.Assign(NS_ConvertASCIItoUTF16(base64Data));
   146   return NS_OK;
   147 }
   149 nsresult
   150 nsStructuredCloneContainer::GetSerializedNBytes(uint64_t *aSize)
   151 {
   152   NS_ENSURE_STATE(mData);
   153   NS_ENSURE_ARG_POINTER(aSize);
   155   // mSize is a size_t, while aSize is a uint64_t.  We rely on an implicit cast
   156   // here so that we'll get a compile error if a size_t-to-uint64_t cast is
   157   // narrowing.
   158   *aSize = mSize;
   160   return NS_OK;
   161 }
   163 nsresult
   164 nsStructuredCloneContainer::GetFormatVersion(uint32_t *aFormatVersion)
   165 {
   166   NS_ENSURE_STATE(mData);
   167   NS_ENSURE_ARG_POINTER(aFormatVersion);
   168   *aFormatVersion = mVersion;
   169   return NS_OK;
   170 }

mercurial