2020-03-17 14:47:22 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2020-11-23 19:06:52 +03:00
|
|
|
#include "mozilla/dom/IndexedDatabase.h"
|
2020-03-17 14:47:22 +03:00
|
|
|
#include "IndexedDatabaseInlines.h"
|
|
|
|
|
|
|
|
#include "IDBDatabase.h"
|
|
|
|
#include "IDBMutableFile.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/FileBlobImpl.h"
|
|
|
|
#include "mozilla/dom/StructuredCloneTags.h"
|
|
|
|
#include "mozilla/dom/WorkerPrivate.h"
|
|
|
|
#include "mozilla/dom/WorkerScope.h"
|
|
|
|
#include "MainThreadUtils.h"
|
|
|
|
#include "jsapi.h"
|
2020-11-23 19:21:38 +03:00
|
|
|
#include "nsIFile.h"
|
2020-03-17 14:47:22 +03:00
|
|
|
#include "nsIGlobalObject.h"
|
|
|
|
#include "nsQueryObject.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
|
|
|
|
namespace mozilla::dom::indexedDB {
|
|
|
|
namespace {
|
|
|
|
struct MOZ_STACK_CLASS MutableFileData final {
|
|
|
|
nsString type;
|
|
|
|
nsString name;
|
|
|
|
|
|
|
|
MOZ_COUNTED_DEFAULT_CTOR(MutableFileData)
|
|
|
|
|
|
|
|
MOZ_COUNTED_DTOR(MutableFileData)
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MOZ_STACK_CLASS BlobOrFileData final {
|
|
|
|
uint32_t tag = 0;
|
|
|
|
uint64_t size = 0;
|
|
|
|
nsString type;
|
|
|
|
nsString name;
|
|
|
|
int64_t lastModifiedDate = INT64_MAX;
|
|
|
|
|
|
|
|
MOZ_COUNTED_DEFAULT_CTOR(BlobOrFileData)
|
|
|
|
|
|
|
|
MOZ_COUNTED_DTOR(BlobOrFileData)
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MOZ_STACK_CLASS WasmModuleData final {
|
|
|
|
uint32_t bytecodeIndex;
|
|
|
|
uint32_t compiledIndex;
|
|
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
explicit WasmModuleData(uint32_t aFlags)
|
|
|
|
: bytecodeIndex(0), compiledIndex(0), flags(aFlags) {
|
|
|
|
MOZ_COUNT_CTOR(WasmModuleData);
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_COUNTED_DTOR(WasmModuleData)
|
|
|
|
};
|
|
|
|
|
|
|
|
bool StructuredCloneReadString(JSStructuredCloneReader* aReader,
|
|
|
|
nsCString& aString) {
|
|
|
|
uint32_t length;
|
|
|
|
if (!JS_ReadBytes(aReader, &length, sizeof(uint32_t))) {
|
|
|
|
NS_WARNING("Failed to read length!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
length = NativeEndian::swapFromLittleEndian(length);
|
|
|
|
|
|
|
|
if (!aString.SetLength(length, fallible)) {
|
|
|
|
NS_WARNING("Out of memory?");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
char* const buffer = aString.BeginWriting();
|
|
|
|
|
|
|
|
if (!JS_ReadBytes(aReader, buffer, length)) {
|
|
|
|
NS_WARNING("Failed to read type!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReadFileHandle(JSStructuredCloneReader* aReader,
|
|
|
|
MutableFileData* aRetval) {
|
|
|
|
static_assert(SCTAG_DOM_MUTABLEFILE == 0xFFFF8004, "Update me!");
|
|
|
|
MOZ_ASSERT(aReader && aRetval);
|
|
|
|
|
|
|
|
nsCString type;
|
|
|
|
if (!StructuredCloneReadString(aReader, type)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CopyUTF8toUTF16(type, aRetval->type);
|
|
|
|
|
|
|
|
nsCString name;
|
|
|
|
if (!StructuredCloneReadString(aReader, name)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CopyUTF8toUTF16(name, aRetval->name);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReadBlobOrFile(JSStructuredCloneReader* aReader, uint32_t aTag,
|
|
|
|
BlobOrFileData* aRetval) {
|
|
|
|
static_assert(SCTAG_DOM_BLOB == 0xffff8001 &&
|
|
|
|
SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 &&
|
|
|
|
SCTAG_DOM_FILE == 0xffff8005,
|
|
|
|
"Update me!");
|
|
|
|
|
|
|
|
MOZ_ASSERT(aReader);
|
|
|
|
MOZ_ASSERT(aTag == SCTAG_DOM_FILE ||
|
|
|
|
aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE ||
|
|
|
|
aTag == SCTAG_DOM_BLOB);
|
|
|
|
MOZ_ASSERT(aRetval);
|
|
|
|
|
|
|
|
aRetval->tag = aTag;
|
|
|
|
|
|
|
|
uint64_t size;
|
|
|
|
if (NS_WARN_IF(!JS_ReadBytes(aReader, &size, sizeof(uint64_t)))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aRetval->size = NativeEndian::swapFromLittleEndian(size);
|
|
|
|
|
|
|
|
nsCString type;
|
|
|
|
if (NS_WARN_IF(!StructuredCloneReadString(aReader, type))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyUTF8toUTF16(type, aRetval->type);
|
|
|
|
|
|
|
|
// Blobs are done.
|
|
|
|
if (aTag == SCTAG_DOM_BLOB) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aTag == SCTAG_DOM_FILE ||
|
|
|
|
aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE);
|
|
|
|
|
|
|
|
int64_t lastModifiedDate;
|
|
|
|
if (aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE) {
|
|
|
|
lastModifiedDate = INT64_MAX;
|
|
|
|
} else {
|
|
|
|
if (NS_WARN_IF(!JS_ReadBytes(aReader, &lastModifiedDate,
|
|
|
|
sizeof(lastModifiedDate)))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
lastModifiedDate = NativeEndian::swapFromLittleEndian(lastModifiedDate);
|
|
|
|
}
|
|
|
|
|
|
|
|
aRetval->lastModifiedDate = lastModifiedDate;
|
|
|
|
|
|
|
|
nsCString name;
|
|
|
|
if (NS_WARN_IF(!StructuredCloneReadString(aReader, name))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyUTF8toUTF16(name, aRetval->name);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReadWasmModule(JSStructuredCloneReader* aReader, WasmModuleData* aRetval) {
|
|
|
|
static_assert(SCTAG_DOM_WASM_MODULE == 0xFFFF8006, "Update me!");
|
|
|
|
MOZ_ASSERT(aReader && aRetval);
|
|
|
|
|
|
|
|
uint32_t bytecodeIndex;
|
|
|
|
uint32_t compiledIndex;
|
|
|
|
if (NS_WARN_IF(!JS_ReadUint32Pair(aReader, &bytecodeIndex, &compiledIndex))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aRetval->bytecodeIndex = bytecodeIndex;
|
|
|
|
aRetval->compiledIndex = compiledIndex;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
template <typename StructuredCloneFile>
|
|
|
|
class ValueDeserializationHelper;
|
|
|
|
|
|
|
|
class ValueDeserializationHelperBase {
|
2020-03-17 14:47:22 +03:00
|
|
|
public:
|
2020-03-19 14:35:03 +03:00
|
|
|
static bool CreateAndWrapWasmModule(JSContext* aCx,
|
|
|
|
const StructuredCloneFileBase& aFile,
|
|
|
|
const WasmModuleData& aData,
|
|
|
|
JS::MutableHandle<JSObject*> aResult) {
|
2020-03-17 14:47:22 +03:00
|
|
|
MOZ_ASSERT(aCx);
|
2020-03-19 14:35:03 +03:00
|
|
|
MOZ_ASSERT(aFile.Type() == StructuredCloneFileBase::eWasmBytecode);
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
// Both on the parent and child side, just create a plain object here,
|
|
|
|
// support for de-serialization of WebAssembly.Modules has been removed in
|
|
|
|
// bug 1561876. Full removal is tracked in bug 1487479.
|
2020-03-19 14:30:26 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
|
|
|
if (NS_WARN_IF(!obj)) {
|
2020-03-17 14:47:22 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
aResult.set(obj);
|
|
|
|
return true;
|
2020-03-17 14:47:22 +03:00
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
template <typename StructuredCloneFile>
|
2020-03-17 14:47:22 +03:00
|
|
|
static bool CreateAndWrapBlobOrFile(JSContext* aCx, IDBDatabase* aDatabase,
|
|
|
|
const StructuredCloneFile& aFile,
|
|
|
|
const BlobOrFileData& aData,
|
|
|
|
JS::MutableHandle<JSObject*> aResult) {
|
|
|
|
MOZ_ASSERT(aCx);
|
|
|
|
MOZ_ASSERT(aData.tag == SCTAG_DOM_FILE ||
|
|
|
|
aData.tag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE ||
|
|
|
|
aData.tag == SCTAG_DOM_BLOB);
|
2020-03-19 14:35:03 +03:00
|
|
|
MOZ_ASSERT(aFile.Type() == StructuredCloneFileBase::eBlob);
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
const auto blob = ValueDeserializationHelper<StructuredCloneFile>::GetBlob(
|
|
|
|
aCx, aDatabase, aFile);
|
2020-03-17 14:47:22 +03:00
|
|
|
if (NS_WARN_IF(!blob)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aData.tag == SCTAG_DOM_BLOB) {
|
|
|
|
blob->Impl()->SetLazyData(VoidString(), aData.type, aData.size,
|
|
|
|
INT64_MAX);
|
|
|
|
MOZ_ASSERT(!blob->IsFile());
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
// XXX The comment below is somewhat confusing, since it seems to imply
|
|
|
|
// that this branch is only executed when called from ActorsParent, but
|
|
|
|
// it's executed from both the parent and the child side code.
|
|
|
|
|
2020-03-17 14:47:22 +03:00
|
|
|
// ActorsParent sends here a kind of half blob and half file wrapped into
|
|
|
|
// a DOM File object. DOM File and DOM Blob are a WebIDL wrapper around a
|
|
|
|
// BlobImpl object. SetLazyData() has just changed the BlobImpl to be a
|
|
|
|
// Blob (see the previous assert), but 'blob' still has the WebIDL DOM
|
|
|
|
// File wrapping.
|
|
|
|
// Before exposing it to content, we must recreate a DOM Blob object.
|
|
|
|
|
|
|
|
const RefPtr<Blob> exposedBlob =
|
|
|
|
Blob::Create(blob->GetParentObject(), blob->Impl());
|
|
|
|
if (NS_WARN_IF(!exposedBlob)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return WrapAsJSObject(aCx, exposedBlob, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
blob->Impl()->SetLazyData(aData.name, aData.type, aData.size,
|
|
|
|
aData.lastModifiedDate * PR_USEC_PER_MSEC);
|
|
|
|
|
|
|
|
MOZ_ASSERT(blob->IsFile());
|
|
|
|
const RefPtr<File> file = blob->ToFile();
|
|
|
|
MOZ_ASSERT(file);
|
|
|
|
|
|
|
|
return WrapAsJSObject(aCx, file, aResult);
|
|
|
|
}
|
2020-03-19 14:35:03 +03:00
|
|
|
};
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
template <>
|
|
|
|
class ValueDeserializationHelper<StructuredCloneFileParent>
|
|
|
|
: public ValueDeserializationHelperBase {
|
|
|
|
public:
|
|
|
|
static bool CreateAndWrapMutableFile(JSContext* aCx,
|
|
|
|
StructuredCloneFileParent& aFile,
|
|
|
|
const MutableFileData& aData,
|
|
|
|
JS::MutableHandle<JSObject*> aResult) {
|
2020-03-17 14:47:22 +03:00
|
|
|
MOZ_ASSERT(aCx);
|
2020-03-19 14:35:03 +03:00
|
|
|
MOZ_ASSERT(aFile.Type() == StructuredCloneFileBase::eBlob);
|
|
|
|
|
|
|
|
// We are in an IDB SQLite schema upgrade where we don't care about a real
|
|
|
|
// 'MutableFile', but we just care of having a proper |mType| flag.
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
aFile.MutateType(StructuredCloneFileBase::eMutableFile);
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
// Just make a dummy object.
|
2020-03-17 14:47:22 +03:00
|
|
|
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
2020-03-19 14:35:03 +03:00
|
|
|
|
2020-03-17 14:47:22 +03:00
|
|
|
if (NS_WARN_IF(!obj)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aResult.set(obj);
|
|
|
|
return true;
|
|
|
|
}
|
2020-03-19 14:35:03 +03:00
|
|
|
|
|
|
|
static RefPtr<Blob> GetBlob(JSContext* aCx, IDBDatabase* aDatabase,
|
|
|
|
const StructuredCloneFileParent& aFile) {
|
|
|
|
// This is chrome code, so there is no parent, but still we want to set a
|
|
|
|
// correct parent for the new File object.
|
|
|
|
const auto global = [aDatabase, aCx]() -> nsCOMPtr<nsIGlobalObject> {
|
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
if (aDatabase && aDatabase->GetParentObject()) {
|
|
|
|
return aDatabase->GetParentObject();
|
|
|
|
}
|
|
|
|
return xpc::CurrentNativeGlobal(aCx);
|
|
|
|
}
|
|
|
|
const WorkerPrivate* const workerPrivate =
|
|
|
|
GetCurrentThreadWorkerPrivate();
|
|
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
|
|
|
|
WorkerGlobalScope* const globalScope = workerPrivate->GlobalScope();
|
|
|
|
MOZ_ASSERT(globalScope);
|
|
|
|
|
|
|
|
return do_QueryObject(globalScope);
|
|
|
|
}();
|
|
|
|
|
|
|
|
MOZ_ASSERT(global);
|
|
|
|
|
2021-05-31 20:44:19 +03:00
|
|
|
// We do not have an mBlob but do have a DatabaseFileInfo.
|
2020-03-19 14:35:03 +03:00
|
|
|
//
|
|
|
|
// If we are creating an index, we do need a real-looking Blob/File instance
|
|
|
|
// because the index's key path can reference their properties. Rather than
|
|
|
|
// create a fake-looking object, create a real Blob.
|
|
|
|
//
|
|
|
|
// If we are in a schema upgrade, we don't strictly need that, but we do not
|
|
|
|
// need to optimize for that, and create it anyway.
|
|
|
|
const nsCOMPtr<nsIFile> file = aFile.FileInfo().GetFileForFileInfo();
|
|
|
|
if (!file) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto impl = MakeRefPtr<FileBlobImpl>(file);
|
|
|
|
impl->SetFileId(aFile.FileInfo().Id());
|
|
|
|
return File::Create(global, impl);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
class ValueDeserializationHelper<StructuredCloneFileChild>
|
|
|
|
: public ValueDeserializationHelperBase {
|
|
|
|
public:
|
|
|
|
static bool CreateAndWrapMutableFile(JSContext* aCx,
|
|
|
|
StructuredCloneFileChild& aFile,
|
|
|
|
const MutableFileData& aData,
|
|
|
|
JS::MutableHandle<JSObject*> aResult) {
|
|
|
|
MOZ_ASSERT(aCx);
|
|
|
|
MOZ_ASSERT(aFile.Type() == StructuredCloneFileBase::eMutableFile);
|
|
|
|
|
|
|
|
// If either MutableFile is disabled (via a pref) and we don't have a
|
|
|
|
// mutable file here, or we are on a DOM worker and MutableFile is not
|
|
|
|
// supported on workers, return false to indicate that.
|
|
|
|
if (!aFile.HasMutableFile() || !NS_IsMainThread()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aFile.MutableMutableFile().SetLazyData(aData.name, aData.type);
|
|
|
|
|
|
|
|
return WrapAsJSObject(aCx, aFile.MutableMutableFile(), aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
static RefPtr<Blob> GetBlob(JSContext* aCx, IDBDatabase* aDatabase,
|
|
|
|
const StructuredCloneFileChild& aFile) {
|
|
|
|
if (aFile.HasBlob()) {
|
|
|
|
return aFile.BlobPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_CRASH("Expected a StructuredCloneFile with a Blob");
|
|
|
|
}
|
2020-03-17 14:47:22 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
template <typename StructuredCloneReadInfo>
|
2020-03-17 14:47:22 +03:00
|
|
|
JSObject* CommonStructuredCloneReadCallback(
|
|
|
|
JSContext* aCx, JSStructuredCloneReader* aReader,
|
|
|
|
const JS::CloneDataPolicy& aCloneDataPolicy, uint32_t aTag, uint32_t aData,
|
|
|
|
StructuredCloneReadInfo* aCloneReadInfo, IDBDatabase* aDatabase) {
|
|
|
|
// We need to statically assert that our tag values are what we expect
|
|
|
|
// so that if people accidentally change them they notice.
|
|
|
|
static_assert(SCTAG_DOM_BLOB == 0xffff8001 &&
|
|
|
|
SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 &&
|
|
|
|
SCTAG_DOM_MUTABLEFILE == 0xffff8004 &&
|
|
|
|
SCTAG_DOM_FILE == 0xffff8005 &&
|
|
|
|
SCTAG_DOM_WASM_MODULE == 0xffff8006,
|
|
|
|
"You changed our structured clone tag values and just ate "
|
|
|
|
"everyone's IndexedDB data. I hope you are happy.");
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
using StructuredCloneFile =
|
|
|
|
typename StructuredCloneReadInfo::StructuredCloneFile;
|
|
|
|
|
2020-03-17 14:47:22 +03:00
|
|
|
if (aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE ||
|
|
|
|
aTag == SCTAG_DOM_BLOB || aTag == SCTAG_DOM_FILE ||
|
|
|
|
aTag == SCTAG_DOM_MUTABLEFILE || aTag == SCTAG_DOM_WASM_MODULE) {
|
|
|
|
JS::Rooted<JSObject*> result(aCx);
|
|
|
|
|
|
|
|
if (aTag == SCTAG_DOM_WASM_MODULE) {
|
|
|
|
WasmModuleData data(aData);
|
|
|
|
if (NS_WARN_IF(!ReadWasmModule(aReader, &data))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(data.compiledIndex == data.bytecodeIndex + 1);
|
|
|
|
MOZ_ASSERT(!data.flags);
|
|
|
|
|
|
|
|
const auto& files = aCloneReadInfo->Files();
|
|
|
|
if (data.bytecodeIndex >= files.Length() ||
|
|
|
|
data.compiledIndex >= files.Length()) {
|
|
|
|
MOZ_ASSERT(false, "Bad index value!");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
const auto& file = files[data.bytecodeIndex];
|
2020-03-17 14:47:22 +03:00
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
if (NS_WARN_IF(!ValueDeserializationHelper<StructuredCloneFile>::
|
|
|
|
CreateAndWrapWasmModule(aCx, file, data, &result))) {
|
2020-03-17 14:47:22 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aData >= aCloneReadInfo->Files().Length()) {
|
|
|
|
MOZ_ASSERT(false, "Bad index value!");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
auto& file = aCloneReadInfo->MutableFile(aData);
|
2020-03-17 14:47:22 +03:00
|
|
|
|
|
|
|
if (aTag == SCTAG_DOM_MUTABLEFILE) {
|
|
|
|
MutableFileData data;
|
|
|
|
if (NS_WARN_IF(!ReadFileHandle(aReader, &data))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
if (NS_WARN_IF(!ValueDeserializationHelper<StructuredCloneFile>::
|
|
|
|
CreateAndWrapMutableFile(aCx, file, data, &result))) {
|
2020-03-17 14:47:22 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobOrFileData data;
|
|
|
|
if (NS_WARN_IF(!ReadBlobOrFile(aReader, aTag, &data))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
if (NS_WARN_IF(!ValueDeserializationHelper<
|
|
|
|
StructuredCloneFile>::CreateAndWrapBlobOrFile(aCx, aDatabase,
|
|
|
|
file, data,
|
|
|
|
&result))) {
|
2020-03-17 14:47:22 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return StructuredCloneHolder::ReadFullySerializableObjects(aCx, aReader,
|
|
|
|
aTag);
|
|
|
|
}
|
2020-03-19 14:35:03 +03:00
|
|
|
|
|
|
|
template JSObject* CommonStructuredCloneReadCallback(
|
|
|
|
JSContext* aCx, JSStructuredCloneReader* aReader,
|
|
|
|
const JS::CloneDataPolicy& aCloneDataPolicy, uint32_t aTag, uint32_t aData,
|
|
|
|
StructuredCloneReadInfoChild* aCloneReadInfo, IDBDatabase* aDatabase);
|
|
|
|
|
|
|
|
template JSObject* CommonStructuredCloneReadCallback(
|
|
|
|
JSContext* aCx, JSStructuredCloneReader* aReader,
|
|
|
|
const JS::CloneDataPolicy& aCloneDataPolicy, uint32_t aTag, uint32_t aData,
|
|
|
|
StructuredCloneReadInfoParent* aCloneReadInfo, IDBDatabase* aDatabase);
|
2020-03-17 14:47:22 +03:00
|
|
|
} // namespace mozilla::dom::indexedDB
|