Bug 1264642 - Part 5. Make SerializedStructuredClone{Read,Write}Info use SerializedStructuredCloneBuffer. r=baku draft
authorKan-Ru Chen <kanru@kanru.info>
Tue, 07 Jun 2016 16:49:43 +0800
changeset 404023 32661b703932c5f0f35aacfe6ec1f9d9abf0e311
parent 404022 bac19b6e82e95f9e7b12017356a8cc8460f7a998
child 404024 967e23e167d467b739819cdfdd6530719339d906
push id27077
push userbmo:kchen@mozilla.com
push dateMon, 22 Aug 2016 16:38:55 +0000
reviewersbaku
bugs1264642
milestone51.0a1
Bug 1264642 - Part 5. Make SerializedStructuredClone{Read,Write}Info use SerializedStructuredCloneBuffer. r=baku MozReview-Commit-ID: KUz3E5Sw5W3
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IndexedDatabase.h
dom/indexedDB/IndexedDatabaseInlines.h
dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -425,18 +425,16 @@ private:
 
   nsresult
   GetResult(JSContext* aCx,
             StructuredCloneReadInfo* aCloneInfo,
             JS::MutableHandle<JS::Value> aResult)
   {
     bool ok = IDBObjectStore::DeserializeValue(aCx, *aCloneInfo, aResult);
 
-    aCloneInfo->mCloneBuffer.clear();
-
     if (NS_WARN_IF(!ok)) {
       return NS_ERROR_DOM_DATA_CLONE_ERR;
     }
 
     return NS_OK;
   }
 
   nsresult
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -14835,38 +14835,38 @@ TransactionBase::VerifyRequestParams(con
 
   RefPtr<FullObjectStoreMetadata> objMetadata =
     GetMetadataForObjectStoreId(aParams.objectStoreId());
   if (NS_WARN_IF(!objMetadata)) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
-  if (NS_WARN_IF(aParams.cloneInfo().data().IsEmpty())) {
+  if (NS_WARN_IF(!aParams.cloneInfo().data().data.Size())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
   if (objMetadata->mCommonMetadata.autoIncrement() &&
       objMetadata->mCommonMetadata.keyPath().IsValid() &&
       aParams.key().IsUnset()) {
     const SerializedStructuredCloneWriteInfo cloneInfo = aParams.cloneInfo();
 
     if (NS_WARN_IF(!cloneInfo.offsetToKeyProp())) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
 
-    if (NS_WARN_IF(cloneInfo.data().Length() < sizeof(uint64_t))) {
+    if (NS_WARN_IF(cloneInfo.data().data.Size() < sizeof(uint64_t))) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
 
     if (NS_WARN_IF(cloneInfo.offsetToKeyProp() >
-                   (cloneInfo.data().Length() - sizeof(uint64_t)))) {
+                   (cloneInfo.data().data.Size() - sizeof(uint64_t)))) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
   } else if (NS_WARN_IF(aParams.cloneInfo().offsetToKeyProp())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
@@ -19060,17 +19060,19 @@ DatabaseOperationBase::GetStructuredClon
 
   char* uncompressedBuffer = reinterpret_cast<char*>(uncompressed.Elements());
 
   if (NS_WARN_IF(!snappy::RawUncompress(compressed, compressedLength,
                                         uncompressedBuffer))) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
-  aInfo->mData.SwapElements(uncompressed);
+  if (!aInfo->mData.WriteBytes(uncompressedBuffer, uncompressed.Length())) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   if (!aFileIds.IsVoid()) {
     AutoTArray<int64_t, 10> array;
     nsresult rv = ConvertFileIdsToArray(aFileIds, array);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
@@ -25422,16 +25424,23 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
   rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   MOZ_ASSERT(!keyUnset || mMetadata->mCommonMetadata.autoIncrement(),
              "Should have key unless autoIncrement");
 
+  const JSStructuredCloneData& data = mParams.cloneInfo().data().data;
+  size_t cloneDataSize = data.Size();
+  nsCString cloneData;
+  cloneData.SetLength(cloneDataSize);
+  auto iter = data.Iter();
+  data.ReadBytes(iter, cloneData.BeginWriting(), cloneDataSize);
+
   int64_t autoIncrementNum = 0;
 
   if (mMetadata->mCommonMetadata.autoIncrement()) {
     if (keyUnset) {
       autoIncrementNum = mMetadata->mNextAutoIncrementId;
 
       MOZ_ASSERT(autoIncrementNum > 0);
 
@@ -25443,39 +25452,36 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
     } else if (key.IsFloat() &&
                key.ToFloat() >= mMetadata->mNextAutoIncrementId) {
       autoIncrementNum = floor(key.ToFloat());
     }
 
     if (keyUnset && keyPath.IsValid()) {
       const SerializedStructuredCloneWriteInfo& cloneInfo = mParams.cloneInfo();
       MOZ_ASSERT(cloneInfo.offsetToKeyProp());
-      MOZ_ASSERT(cloneInfo.data().Length() > sizeof(uint64_t));
+      MOZ_ASSERT(cloneDataSize > sizeof(uint64_t));
       MOZ_ASSERT(cloneInfo.offsetToKeyProp() <=
-                 (cloneInfo.data().Length() - sizeof(uint64_t)));
+                 (cloneDataSize - sizeof(uint64_t)));
 
       // Special case where someone put an object into an autoIncrement'ing
       // objectStore with no key in its keyPath set. We needed to figure out
       // which row id we would get above before we could set that properly.
-      uint8_t* keyPropPointer =
-        const_cast<uint8_t*>(cloneInfo.data().Elements() +
-                             cloneInfo.offsetToKeyProp());
+      char* keyPropPointer = cloneData.BeginWriting() + cloneInfo.offsetToKeyProp();
       uint64_t keyPropValue =
         ReinterpretDoubleAsUInt64(static_cast<double>(autoIncrementNum));
 
       LittleEndian::writeUint64(keyPropPointer, keyPropValue);
     }
   }
 
   key.BindToStatement(stmt, NS_LITERAL_CSTRING("key"));
 
   // Compress the bytes before adding into the database.
-  const char* uncompressed =
-    reinterpret_cast<const char*>(mParams.cloneInfo().data().Elements());
-  size_t uncompressedLength = mParams.cloneInfo().data().Length();
+  const char* uncompressed = cloneData.BeginReading();
+  size_t uncompressedLength = cloneDataSize;
 
   // We don't have a smart pointer class that calls free, so we need to
   // manage | compressed | manually.
   {
     size_t compressedLength = snappy::MaxCompressedLength(uncompressedLength);
 
     char* compressed = static_cast<char*>(malloc(compressedLength));
     if (NS_WARN_IF(!compressed)) {
@@ -25797,17 +25803,17 @@ nsresult
 ObjectStoreGetRequestOp::ConvertResponse(
                              uint32_t aIndex,
                              SerializedStructuredCloneReadInfo& aSerializedInfo)
 {
   MOZ_ASSERT(aIndex < mResponse.Length());
 
   StructuredCloneReadInfo& info = mResponse[aIndex];
 
-  info.mData.SwapElements(aSerializedInfo.data());
+  aSerializedInfo.data().data = Move(info.mData);
 
   FallibleTArray<BlobOrMutableFile> blobs;
   nsresult rv = ConvertBlobsToActors(mBackgroundParent,
                                      mDatabase,
                                      info.mFiles,
                                      blobs);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -26520,17 +26526,17 @@ IndexGetRequestOp::GetResponse(RequestRe
       for (uint32_t count = mResponse.Length(), index = 0;
            index < count;
            index++) {
         StructuredCloneReadInfo& info = mResponse[index];
 
         SerializedStructuredCloneReadInfo& serializedInfo =
           fallibleCloneInfos[index];
 
-        info.mData.SwapElements(serializedInfo.data());
+        serializedInfo.data().data = Move(info.mData);
 
         FallibleTArray<BlobOrMutableFile> blobs;
         nsresult rv = ConvertBlobsToActors(mBackgroundParent,
                                            mDatabase,
                                            info.mFiles,
                                            blobs);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           aResponse = rv;
@@ -26554,17 +26560,17 @@ IndexGetRequestOp::GetResponse(RequestRe
   aResponse = IndexGetResponse();
 
   if (!mResponse.IsEmpty()) {
     StructuredCloneReadInfo& info = mResponse[0];
 
     SerializedStructuredCloneReadInfo& serializedInfo =
       aResponse.get_IndexGetResponse().cloneInfo();
 
-    info.mData.SwapElements(serializedInfo.data());
+    serializedInfo.data().data = Move(info.mData);
 
     FallibleTArray<BlobOrMutableFile> blobs;
     nsresult rv =
       ConvertBlobsToActors(mBackgroundParent,
                            mDatabase,
                            info.mFiles,
                            blobs);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -26868,17 +26874,17 @@ CursorOpBase::PopulateResponseFromStatem
         mResponse = nsTArray<ObjectStoreCursorResponse>();
       } else {
         MOZ_ASSERT(mResponse.type() ==
                      CursorResponse::TArrayOfObjectStoreCursorResponse);
       }
 
       auto& responses = mResponse.get_ArrayOfObjectStoreCursorResponse();
       auto& response = *responses.AppendElement();
-      response.cloneInfo().data().SwapElements(cloneInfo.mData);
+      response.cloneInfo().data().data = Move(cloneInfo.mData);
       response.key() = mCursor->mKey;
 
       mFiles.AppendElement(Move(cloneInfo.mFiles));
       break;
     }
 
     case OpenCursorParams::TObjectStoreOpenKeyCursorParams: {
       MOZ_ASSERT(aInitializeResponse);
@@ -26906,17 +26912,17 @@ CursorOpBase::PopulateResponseFromStatem
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       MOZ_ASSERT(aInitializeResponse);
       mResponse = IndexCursorResponse();
 
       auto& response = mResponse.get_IndexCursorResponse();
-      response.cloneInfo().data().SwapElements(cloneInfo.mData);
+      response.cloneInfo().data().data = Move(cloneInfo.mData);
       response.key() = mCursor->mKey;
       response.sortKey() = mCursor->mSortKey;
       response.objectKey() = mCursor->mObjectKey;
 
       mFiles.AppendElement(Move(cloneInfo.mFiles));
       break;
     }
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -862,25 +862,16 @@ CommonStructuredCloneReadCallback(JSCont
 
     return result;
   }
 
   return StructuredCloneHolder::ReadFullySerializableObjects(aCx, aReader,
                                                              aTag);
 }
 
-// static
-void
-ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer)
-{
-  if (!aBuffer.empty()) {
-    aBuffer.clear();
-  }
-}
-
 } // namespace
 
 const JSClass IDBObjectStore::sDummyPropJSClass = {
   "IDBObjectStore Dummy",
   0 /* flags */
 };
 
 IDBObjectStore::IDBObjectStore(IDBTransaction* aTransaction,
@@ -1037,61 +1028,52 @@ IDBObjectStore::AppendIndexUpdateInfo(
 
 // static
 void
 IDBObjectStore::ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo)
 {
   // This is kind of tricky, we only want to release stuff on the main thread,
   // but we can end up being called on other threads if we have already been
   // cleared on the main thread.
-  if (aReadInfo.mCloneBuffer.empty() && !aReadInfo.mFiles.Length()) {
+  if (!aReadInfo.mFiles.Length()) {
     return;
   }
 
-  ClearStructuredCloneBuffer(aReadInfo.mCloneBuffer);
   aReadInfo.mFiles.Clear();
 }
 
 // static
 bool
 IDBObjectStore::DeserializeValue(JSContext* aCx,
                                  StructuredCloneReadInfo& aCloneReadInfo,
                                  JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-  size_t dataLen = aCloneReadInfo.mData.Length();
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static const JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<ValueDeserializationHelper>,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr
   };
 
   // FIXME: Consider to use StructuredCloneHolder here and in other
   //        deserializing methods.
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               JS::StructuredCloneScope::SameProcessSameThread,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
@@ -1099,40 +1081,32 @@ IDBObjectStore::DeserializeValue(JSConte
 bool
 IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
                                       StructuredCloneReadInfo& aCloneReadInfo,
                                       JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-  size_t dataLen = aCloneReadInfo.mData.Length();
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static const JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<IndexDeserializationHelper>,
     nullptr,
     nullptr
   };
 
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               JS::StructuredCloneScope::SameProcessSameThread,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
@@ -1142,44 +1116,35 @@ IDBObjectStore::DeserializeIndexValue(JS
 bool
 IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
                                         StructuredCloneReadInfo& aCloneReadInfo,
                                         JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-
-  size_t dataLen = aCloneReadInfo.mData.Length();
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<UpgradeDeserializationHelper>,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr
   };
 
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               JS::StructuredCloneScope::SameProcessSameThread,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
@@ -1301,38 +1266,19 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
   StructuredCloneWriteInfo cloneWriteInfo(mTransaction->Database());
   nsTArray<IndexUpdateInfo> updateInfo;
 
   aRv = GetAddInfo(aCx, value, aKey, cloneWriteInfo, key, updateInfo);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  FallibleTArray<uint8_t> cloneData;
-  size_t size = cloneWriteInfo.mCloneBuffer.data().Size();
-
-  if (NS_WARN_IF(!cloneData.SetLength(size, fallible))) {
-    aRv = NS_ERROR_OUT_OF_MEMORY;
-    return nullptr;
-  }
-
-  const char* buf;
-  auto iter = cloneWriteInfo.mCloneBuffer.data().Iter();
-  cloneWriteInfo.mCloneBuffer.data().FlattenBytes(iter, &buf, size);
-
-  // FIXME Bug XXXXXX Change SerializedStructuredCloneReadInfo and
-  // SerializedStructuredCloneWriteInfo to use JSStructuredCloneData
-  // instead of raw buffer.
-  memcpy(cloneData.Elements(), buf, size);
-
-  cloneWriteInfo.mCloneBuffer.clear();
-
   ObjectStoreAddPutParams commonParams;
   commonParams.objectStoreId() = Id();
-  commonParams.cloneInfo().data().SwapElements(cloneData);
+  commonParams.cloneInfo().data().data = Move(cloneWriteInfo.mCloneBuffer.data());
   commonParams.cloneInfo().offsetToKeyProp() = cloneWriteInfo.mOffsetToKeyProp;
   commonParams.key() = key;
   commonParams.indexUpdateInfos().SwapElements(updateInfo);
 
   // Convert any blobs or mutable files into DatabaseOrMutableFile.
   nsTArray<StructuredCloneWriteInfo::BlobOrMutableFile>& blobOrMutableFiles =
     cloneWriteInfo.mBlobOrMutableFiles;
 
--- a/dom/indexedDB/IndexedDatabase.h
+++ b/dom/indexedDB/IndexedDatabase.h
@@ -40,23 +40,20 @@ struct StructuredCloneFile
 
   // In IndexedDatabaseInlines.h
   inline bool
   operator==(const StructuredCloneFile& aOther) const;
 };
 
 struct StructuredCloneReadInfo
 {
-  nsTArray<uint8_t> mData;
+  JSStructuredCloneData mData;
   nsTArray<StructuredCloneFile> mFiles;
   IDBDatabase* mDatabase;
 
-  // XXX Remove!
-  JSAutoStructuredCloneBuffer mCloneBuffer;
-
   // In IndexedDatabaseInlines.h
   inline
   StructuredCloneReadInfo();
 
   // In IndexedDatabaseInlines.h
   inline
   ~StructuredCloneReadInfo();
 
--- a/dom/indexedDB/IndexedDatabaseInlines.h
+++ b/dom/indexedDB/IndexedDatabaseInlines.h
@@ -49,17 +49,17 @@ StructuredCloneReadInfo::StructuredClone
   : mDatabase(nullptr)
 {
   MOZ_COUNT_CTOR(StructuredCloneReadInfo);
 }
 
 inline
 StructuredCloneReadInfo::StructuredCloneReadInfo(
                              SerializedStructuredCloneReadInfo&& aCloneReadInfo)
-  : mData(Move(aCloneReadInfo.data()))
+  : mData(Move(aCloneReadInfo.data().data))
   , mDatabase(nullptr)
 {
   MOZ_COUNT_CTOR(StructuredCloneReadInfo);
 }
 
 inline
 StructuredCloneReadInfo::~StructuredCloneReadInfo()
 {
@@ -67,17 +67,16 @@ StructuredCloneReadInfo::~StructuredClon
 }
 
 inline StructuredCloneReadInfo&
 StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
 {
   MOZ_ASSERT(&aCloneReadInfo != this);
 
   mData = Move(aCloneReadInfo.mData);
-  mCloneBuffer = Move(aCloneReadInfo.mCloneBuffer);
   mFiles.Clear();
   mFiles.SwapElements(aCloneReadInfo.mFiles);
   mDatabase = aCloneReadInfo.mDatabase;
   aCloneReadInfo.mDatabase = nullptr;
   return *this;
 }
 
 } // namespace indexedDB
--- a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
+++ b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
@@ -25,16 +25,19 @@ using class mozilla::dom::indexedDB::Key
   from "mozilla/dom/indexedDB/Key.h";
 
 using class mozilla::dom::indexedDB::KeyPath
   from "mozilla/dom/indexedDB/KeyPath.h";
 
 using mozilla::dom::quota::PersistenceType
   from "mozilla/dom/quota/PersistenceType.h";
 
+using mozilla::SerializedStructuredCloneBuffer
+  from "ipc/IPCMessageUtils.h";
+
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 struct SerializedKeyRange
 {
   Key lower;
   Key upper;
@@ -52,23 +55,23 @@ union NullableMutableFile
 union BlobOrMutableFile
 {
   PBlob;
   NullableMutableFile;
 };
 
 struct SerializedStructuredCloneReadInfo
 {
-  uint8_t[] data;
+  SerializedStructuredCloneBuffer data;
   BlobOrMutableFile[] blobs;
 };
 
 struct SerializedStructuredCloneWriteInfo
 {
-  uint8_t[] data;
+  SerializedStructuredCloneBuffer data;
   uint64_t offsetToKeyProp;
 };
 
 struct IndexUpdateInfo
 {
   int64_t indexId;
   Key value;
   Key localizedValue;