зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1422335 - Using a sandbox on main-thread when deserializing data for IDB - part 1 - Deserialize on main-thread using a sandbox, r=asuth
This commit is contained in:
Родитель
c05fed43cf
Коммит
f3cbbe9985
|
@ -8028,14 +8028,8 @@ class CreateIndexOp final
|
|||
{
|
||||
friend class VersionChangeTransaction;
|
||||
|
||||
class ThreadLocalJSContext;
|
||||
class UpdateIndexDataValuesFunction;
|
||||
|
||||
static const unsigned int kBadThreadLocalIndex =
|
||||
static_cast<unsigned int>(-1);
|
||||
|
||||
static unsigned int sThreadLocalIndex;
|
||||
|
||||
const IndexMetadata mMetadata;
|
||||
Maybe<UniqueIndexTable> mMaybeUniqueIndexTable;
|
||||
RefPtr<FileManager> mFileManager;
|
||||
|
@ -8110,47 +8104,21 @@ protected:
|
|||
Init();
|
||||
};
|
||||
|
||||
class CreateIndexOp::ThreadLocalJSContext final
|
||||
: public NormalJSContext
|
||||
{
|
||||
friend class CreateIndexOp;
|
||||
friend class nsAutoPtr<ThreadLocalJSContext>;
|
||||
|
||||
public:
|
||||
static ThreadLocalJSContext*
|
||||
GetOrCreate();
|
||||
|
||||
private:
|
||||
ThreadLocalJSContext()
|
||||
{
|
||||
MOZ_COUNT_CTOR(CreateIndexOp::ThreadLocalJSContext);
|
||||
}
|
||||
|
||||
~ThreadLocalJSContext()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CreateIndexOp::ThreadLocalJSContext);
|
||||
}
|
||||
};
|
||||
|
||||
class CreateIndexOp::UpdateIndexDataValuesFunction final
|
||||
: public mozIStorageFunction
|
||||
{
|
||||
RefPtr<CreateIndexOp> mOp;
|
||||
RefPtr<DatabaseConnection> mConnection;
|
||||
JSContext* mCx;
|
||||
|
||||
public:
|
||||
UpdateIndexDataValuesFunction(CreateIndexOp* aOp,
|
||||
DatabaseConnection* aConnection,
|
||||
JSContext* aCx)
|
||||
DatabaseConnection* aConnection)
|
||||
: mOp(aOp)
|
||||
, mConnection(aConnection)
|
||||
, mCx(aCx)
|
||||
{
|
||||
MOZ_ASSERT(aOp);
|
||||
MOZ_ASSERT(aConnection);
|
||||
aConnection->AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(aCx);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -10154,24 +10122,6 @@ SerializeStructuredCloneFiles(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
GetFileForFileInfo(FileInfo* aFileInfo)
|
||||
{
|
||||
FileManager* fileManager = aFileInfo->Manager();
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
if (NS_WARN_IF(!directory)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file = fileManager->GetFileForId(directory,
|
||||
aFileInfo->Id());
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Globals
|
||||
******************************************************************************/
|
||||
|
@ -19880,7 +19830,7 @@ DatabaseOperationBase::GetStructuredCloneReadInfoFromExternalBlob(
|
|||
MOZ_ASSERT(file.mFileInfo);
|
||||
MOZ_ASSERT(file.mType == StructuredCloneFile::eStructuredClone);
|
||||
|
||||
nsCOMPtr<nsIFile> nativeFile = GetFileForFileInfo(file.mFileInfo);
|
||||
nsCOMPtr<nsIFile> nativeFile = FileInfo::GetFileForFileInfo(file.mFileInfo);
|
||||
if (NS_WARN_IF(!nativeFile)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -24243,7 +24193,7 @@ CreateFileOp::CreateFileOp(Database* aDatabase,
|
|||
nsresult
|
||||
CreateFileOp::CreateMutableFile(MutableFile** aMutableFile)
|
||||
{
|
||||
nsCOMPtr<nsIFile> file = GetFileForFileInfo(mFileInfo);
|
||||
nsCOMPtr<nsIFile> file = FileInfo::GetFileForFileInfo(mFileInfo);
|
||||
if (NS_WARN_IF(!file)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
@ -24830,8 +24780,6 @@ CreateIndexOp::CreateIndexOp(VersionChangeTransaction* aTransaction,
|
|||
MOZ_ASSERT(!mDatabaseId.IsEmpty());
|
||||
}
|
||||
|
||||
unsigned int CreateIndexOp::sThreadLocalIndex = kBadThreadLocalIndex;
|
||||
|
||||
nsresult
|
||||
CreateIndexOp::InsertDataFromObjectStore(DatabaseConnection* aConnection)
|
||||
{
|
||||
|
@ -24846,18 +24794,8 @@ CreateIndexOp::InsertDataFromObjectStore(DatabaseConnection* aConnection)
|
|||
aConnection->GetStorageConnection();
|
||||
MOZ_ASSERT(storageConnection);
|
||||
|
||||
ThreadLocalJSContext* context = ThreadLocalJSContext::GetOrCreate();
|
||||
if (NS_WARN_IF(!context)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
JSContext* cx = context->Context();
|
||||
JSAutoRequest ar(cx);
|
||||
JSAutoCompartment ac(cx, context->Global());
|
||||
|
||||
RefPtr<UpdateIndexDataValuesFunction> updateFunction =
|
||||
new UpdateIndexDataValuesFunction(this, aConnection, cx);
|
||||
new UpdateIndexDataValuesFunction(this, aConnection);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(updateFunctionName, "update_index_data_values");
|
||||
|
||||
|
@ -24923,25 +24861,6 @@ CreateIndexOp::Init(TransactionBase* aTransaction)
|
|||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aTransaction);
|
||||
|
||||
struct MOZ_STACK_CLASS Helper final
|
||||
{
|
||||
static void
|
||||
Destroy(void* aThreadLocal)
|
||||
{
|
||||
delete static_cast<ThreadLocalJSContext*>(aThreadLocal);
|
||||
}
|
||||
};
|
||||
|
||||
if (sThreadLocalIndex == kBadThreadLocalIndex) {
|
||||
if (NS_WARN_IF(PR_SUCCESS !=
|
||||
PR_NewThreadPrivateIndex(&sThreadLocalIndex,
|
||||
&Helper::Destroy))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
|
||||
|
||||
nsresult rv =
|
||||
GetUniqueIndexTableForObjectStore(aTransaction,
|
||||
mObjectStoreId,
|
||||
|
@ -25154,34 +25073,6 @@ NormalJSContext::Create()
|
|||
return newContext.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
auto
|
||||
CreateIndexOp::
|
||||
ThreadLocalJSContext::GetOrCreate() -> ThreadLocalJSContext*
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(CreateIndexOp::kBadThreadLocalIndex !=
|
||||
CreateIndexOp::sThreadLocalIndex);
|
||||
|
||||
auto* context = static_cast<ThreadLocalJSContext*>(
|
||||
PR_GetThreadPrivate(CreateIndexOp::sThreadLocalIndex));
|
||||
if (context) {
|
||||
return context;
|
||||
}
|
||||
|
||||
nsAutoPtr<ThreadLocalJSContext> newContext(new ThreadLocalJSContext());
|
||||
|
||||
if (NS_WARN_IF(!newContext->Init())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DebugOnly<PRStatus> status =
|
||||
PR_SetThreadPrivate(CreateIndexOp::sThreadLocalIndex, newContext);
|
||||
MOZ_ASSERT(status == PR_SUCCESS);
|
||||
|
||||
return newContext.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(CreateIndexOp::UpdateIndexDataValuesFunction,
|
||||
mozIStorageFunction);
|
||||
|
||||
|
@ -25195,7 +25086,6 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
|
|||
MOZ_ASSERT(mConnection);
|
||||
mConnection->AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(mOp);
|
||||
MOZ_ASSERT(mCx);
|
||||
|
||||
AUTO_PROFILER_LABEL(
|
||||
"CreateIndexOp::UpdateIndexDataValuesFunction::OnFunctionCall", STORAGE);
|
||||
|
@ -25235,25 +25125,18 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
|
|||
return rv;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> clone(mCx);
|
||||
if (NS_WARN_IF(!IDBObjectStore::DeserializeIndexValue(mCx,
|
||||
cloneInfo,
|
||||
&clone))) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
const IndexMetadata& metadata = mOp->mMetadata;
|
||||
const int64_t& objectStoreId = mOp->mObjectStoreId;
|
||||
|
||||
AutoTArray<IndexUpdateInfo, 32> updateInfos;
|
||||
rv = IDBObjectStore::AppendIndexUpdateInfo(metadata.id(),
|
||||
metadata.keyPath(),
|
||||
metadata.unique(),
|
||||
metadata.multiEntry(),
|
||||
metadata.locale(),
|
||||
mCx,
|
||||
clone,
|
||||
updateInfos);
|
||||
rv = IDBObjectStore::DeserializeIndexValueToUpdateInfos(
|
||||
metadata.id(),
|
||||
metadata.keyPath(),
|
||||
metadata.unique(),
|
||||
metadata.multiEntry(),
|
||||
metadata.locale(),
|
||||
cloneInfo,
|
||||
updateInfos);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -256,6 +256,24 @@ CleanupFileRunnable::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
FileInfo::GetFileForFileInfo(FileInfo* aFileInfo)
|
||||
{
|
||||
FileManager* fileManager = aFileInfo->Manager();
|
||||
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
|
||||
if (NS_WARN_IF(!directory)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file = fileManager->GetFileForId(directory,
|
||||
aFileInfo->Id());
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
} // namespace indexedDB
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -69,6 +69,9 @@ public:
|
|||
virtual int64_t
|
||||
Id() const = 0;
|
||||
|
||||
static already_AddRefed<nsIFile>
|
||||
GetFileForFileInfo(FileInfo* aFileInfo);
|
||||
|
||||
protected:
|
||||
virtual ~FileInfo();
|
||||
|
||||
|
|
|
@ -23,14 +23,18 @@
|
|||
#include "js/Date.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "KeyPath.h"
|
||||
#include "NullPrincipal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/JSObjectHolder.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/DOMStringList.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileBlobImpl.h"
|
||||
#include "mozilla/dom/IDBMutableFileBinding.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
|
@ -41,6 +45,7 @@
|
|||
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsStreamUtils.h"
|
||||
|
@ -900,7 +905,26 @@ public:
|
|||
aData.tag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE ||
|
||||
aData.tag == SCTAG_DOM_BLOB);
|
||||
MOZ_ASSERT(aFile.mType == StructuredCloneFile::eBlob);
|
||||
MOZ_ASSERT(aFile.mBlob);
|
||||
|
||||
RefPtr<Blob> blob = aFile.mBlob;
|
||||
|
||||
/* If we are creating an index, we do not have an mBlob but do have an
|
||||
* mInfo. Unlike other index or upgrade cases, 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 (!blob) {
|
||||
MOZ_ASSERT(aFile.mFileInfo);
|
||||
nsCOMPtr<nsIFile> file = FileInfo::GetFileForFileInfo(aFile.mFileInfo);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
RefPtr<FileBlobImpl> impl = new FileBlobImpl(file);
|
||||
impl->SetFileId(aFile.mFileInfo->Id());
|
||||
blob = File::Create(nullptr, impl);
|
||||
}
|
||||
|
||||
// It can happen that this IDB is chrome code, so there is no parent, but
|
||||
// still we want to set a correct parent for the new File object.
|
||||
|
@ -924,22 +948,22 @@ public:
|
|||
MOZ_ASSERT(parent);
|
||||
|
||||
if (aData.tag == SCTAG_DOM_BLOB) {
|
||||
aFile.mBlob->Impl()->SetLazyData(
|
||||
blob->Impl()->SetLazyData(
|
||||
VoidString(), aData.type, aData.size, INT64_MAX);
|
||||
MOZ_ASSERT(!aFile.mBlob->IsFile());
|
||||
MOZ_ASSERT(!blob->IsFile());
|
||||
|
||||
// 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 'aFile.mBlob' still has the WebIDL
|
||||
// DOM File wrapping.
|
||||
// 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.
|
||||
|
||||
RefPtr<Blob> blob =
|
||||
Blob::Create(aFile.mBlob->GetParentObject(), aFile.mBlob->Impl());
|
||||
MOZ_ASSERT(blob);
|
||||
RefPtr<Blob> exposedBlob =
|
||||
Blob::Create(blob->GetParentObject(), blob->Impl());
|
||||
MOZ_ASSERT(exposedBlob);
|
||||
JS::Rooted<JS::Value> wrappedBlob(aCx);
|
||||
if (!ToJSValue(aCx, blob, &wrappedBlob)) {
|
||||
if (!ToJSValue(aCx, exposedBlob, &wrappedBlob)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -947,12 +971,12 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
aFile.mBlob->Impl()->SetLazyData(
|
||||
blob->Impl()->SetLazyData(
|
||||
aData.name, aData.type, aData.size,
|
||||
aData.lastModifiedDate * PR_USEC_PER_MSEC);
|
||||
|
||||
MOZ_ASSERT(aFile.mBlob->IsFile());
|
||||
RefPtr<File> file = aFile.mBlob->ToFile();
|
||||
MOZ_ASSERT(blob->IsFile());
|
||||
RefPtr<File> file = blob->ToFile();
|
||||
MOZ_ASSERT(file);
|
||||
|
||||
JS::Rooted<JS::Value> wrappedFile(aCx);
|
||||
|
@ -985,114 +1009,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class IndexDeserializationHelper
|
||||
{
|
||||
public:
|
||||
static bool
|
||||
CreateAndWrapMutableFile(JSContext* aCx,
|
||||
StructuredCloneFile& aFile,
|
||||
const MutableFileData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
// MutableFile can't be used in index creation, so just make a dummy object.
|
||||
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
||||
if (NS_WARN_IF(!obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateAndWrapBlobOrFile(JSContext* aCx,
|
||||
IDBDatabase* aDatabase,
|
||||
StructuredCloneFile& aFile,
|
||||
const BlobOrFileData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
MOZ_ASSERT(aData.tag == SCTAG_DOM_FILE ||
|
||||
aData.tag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE ||
|
||||
aData.tag == SCTAG_DOM_BLOB);
|
||||
|
||||
// The following properties are available for use in index creation
|
||||
// Blob.size
|
||||
// Blob.type
|
||||
// File.name
|
||||
// File.lastModifiedDate
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
||||
if (NS_WARN_IF(!obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Technically these props go on the proto, but this detail won't change
|
||||
// the results of index creation.
|
||||
|
||||
JS::Rooted<JSString*> type(aCx,
|
||||
JS_NewUCStringCopyN(aCx, aData.type.get(), aData.type.Length()));
|
||||
if (NS_WARN_IF(!type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_DefineProperty(aCx,
|
||||
obj,
|
||||
"size",
|
||||
double(aData.size),
|
||||
0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "type", type, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aData.tag == SCTAG_DOM_BLOB) {
|
||||
aResult.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> name(aCx,
|
||||
JS_NewUCStringCopyN(aCx, aData.name.get(), aData.name.Length()));
|
||||
if (NS_WARN_IF(!name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::ClippedTime time = JS::TimeClip(aData.lastModifiedDate);
|
||||
JS::Rooted<JSObject*> date(aCx, JS::NewDateObject(aCx, time));
|
||||
if (NS_WARN_IF(!date)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "name", name, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "lastModifiedDate", date, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateAndWrapWasmModule(JSContext* aCx,
|
||||
StructuredCloneFile& aFile,
|
||||
const WasmModuleData& aData,
|
||||
JS::MutableHandle<JSObject*> aResult)
|
||||
{
|
||||
// Wasm module can't be used in index creation, so just make a dummy object.
|
||||
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
||||
if (NS_WARN_IF(!obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult.set(obj);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// We don't need to upgrade database on B2G. See the comment in ActorsParent.cpp,
|
||||
// UpgradeSchemaFrom18_0To19_0()
|
||||
class UpgradeDeserializationHelper
|
||||
|
@ -1460,37 +1376,217 @@ IDBObjectStore::DeserializeValue(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// This class helps to create only 1 sandbox.
|
||||
class SandboxHolder final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(SandboxHolder)
|
||||
|
||||
static JSObject*
|
||||
GetSandbox(JSContext* aCx)
|
||||
{
|
||||
SandboxHolder* holder = GetOrCreate();
|
||||
return holder->GetSandboxInternal(aCx);
|
||||
}
|
||||
|
||||
private:
|
||||
~SandboxHolder() = default;
|
||||
|
||||
static SandboxHolder*
|
||||
GetOrCreate()
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
static StaticRefPtr<SandboxHolder> sHolder;
|
||||
if (!sHolder) {
|
||||
sHolder = new SandboxHolder();
|
||||
ClearOnShutdown(&sHolder);
|
||||
}
|
||||
return sHolder;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
GetSandboxInternal(JSContext* aCx)
|
||||
{
|
||||
if (!mSandbox) {
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
MOZ_ASSERT(xpc, "This should never be null!");
|
||||
|
||||
// Let's use a null principal.
|
||||
nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
|
||||
|
||||
JS::Rooted<JSObject*> sandbox(aCx);
|
||||
nsresult rv = xpc->CreateSandbox(aCx, principal, sandbox.address());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mSandbox = new JSObjectHolder(aCx, sandbox);
|
||||
}
|
||||
|
||||
return mSandbox->GetJSObject();
|
||||
}
|
||||
|
||||
RefPtr<JSObjectHolder> mSandbox;
|
||||
};
|
||||
|
||||
class DeserializeIndexValueHelper final : public Runnable
|
||||
{
|
||||
public:
|
||||
DeserializeIndexValueHelper(int64_t aIndexID,
|
||||
const KeyPath& aKeyPath,
|
||||
bool aUnique,
|
||||
bool aMultiEntry,
|
||||
const nsCString& aLocale,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
|
||||
: Runnable("DeserializeIndexValueHelper")
|
||||
, mMonitor("DeserializeIndexValueHelper::mMonitor")
|
||||
, mIndexID(aIndexID)
|
||||
, mKeyPath(aKeyPath)
|
||||
, mUnique(aUnique)
|
||||
, mMultiEntry(aMultiEntry)
|
||||
, mLocale(aLocale)
|
||||
, mCloneReadInfo(aCloneReadInfo)
|
||||
, mUpdateInfoArray(aUpdateInfoArray)
|
||||
, mStatus(NS_ERROR_FAILURE)
|
||||
{}
|
||||
|
||||
nsresult
|
||||
DispatchAndWait()
|
||||
{
|
||||
// We don't need to go to the main-thread and use the sandbox. Let's create
|
||||
// the updateInfo data here.
|
||||
if (!mCloneReadInfo.mData.Size()) {
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
JS::Rooted<JS::Value> value(jsapi.cx());
|
||||
value.setUndefined();
|
||||
|
||||
return IDBObjectStore::AppendIndexUpdateInfo(mIndexID, mKeyPath, mUnique,
|
||||
mMultiEntry, mLocale,
|
||||
jsapi.cx(), value,
|
||||
mUpdateInfoArray);
|
||||
}
|
||||
|
||||
// The operation will continue on the main-thread.
|
||||
|
||||
MOZ_ASSERT(!(mCloneReadInfo.mData.Size() % sizeof(uint64_t)));
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
RefPtr<Runnable> self = this;
|
||||
nsresult rv = SystemGroup::Dispatch(TaskCategory::Other, self.forget());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
lock.Wait();
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, SandboxHolder::GetSandbox(cx));
|
||||
if (NS_WARN_IF(!global)) {
|
||||
OperationCompleted(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
nsresult rv = DeserializeIndexValue(cx, &value);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
OperationCompleted(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = IDBObjectStore::AppendIndexUpdateInfo(mIndexID, mKeyPath, mUnique,
|
||||
mMultiEntry, mLocale, cx,
|
||||
value, mUpdateInfoArray);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
OperationCompleted(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OperationCompleted(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult
|
||||
DeserializeIndexValue(JSContext* aCx, JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
static const JSStructuredCloneCallbacks callbacks = {
|
||||
CommonStructuredCloneReadCallback<ValueDeserializationHelper>,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, mCloneReadInfo.mData,
|
||||
JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
aValue, &callbacks, &mCloneReadInfo)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
OperationCompleted(nsresult aStatus)
|
||||
{
|
||||
mStatus = aStatus;
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
lock.Notify();
|
||||
}
|
||||
|
||||
Monitor mMonitor;
|
||||
|
||||
int64_t mIndexID;
|
||||
const KeyPath& mKeyPath;
|
||||
bool mUnique;
|
||||
bool mMultiEntry;
|
||||
const nsCString mLocale;
|
||||
StructuredCloneReadInfo& mCloneReadInfo;
|
||||
nsTArray<IndexUpdateInfo>& mUpdateInfoArray;
|
||||
nsresult mStatus;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
// static
|
||||
bool
|
||||
IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
nsresult
|
||||
IDBObjectStore::DeserializeIndexValueToUpdateInfos(int64_t aIndexID,
|
||||
const KeyPath& aKeyPath,
|
||||
bool aUnique,
|
||||
bool aMultiEntry,
|
||||
const nsCString& aLocale,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(aCx);
|
||||
|
||||
if (!aCloneReadInfo.mData.Size()) {
|
||||
aValue.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
static const JSStructuredCloneCallbacks callbacks = {
|
||||
CommonStructuredCloneReadCallback<IndexDeserializationHelper>,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
|
||||
JS::StructuredCloneScope::SameProcessSameThread,
|
||||
aValue, &callbacks, &aCloneReadInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
RefPtr<DeserializeIndexValueHelper> helper =
|
||||
new DeserializeIndexValueHelper(aIndexID, aKeyPath, aUnique, aMultiEntry,
|
||||
aLocale, aCloneReadInfo, aUpdateInfoArray);
|
||||
return helper->DispatchAndWait();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -88,6 +88,15 @@ public:
|
|||
JS::Handle<JS::Value> aObject,
|
||||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
|
||||
static nsresult
|
||||
DeserializeIndexValueToUpdateInfos(int64_t aIndexID,
|
||||
const KeyPath& aKeyPath,
|
||||
bool aUnique,
|
||||
bool aMultiEntry,
|
||||
const nsCString& aLocale,
|
||||
StructuredCloneReadInfo& aCloneInfo,
|
||||
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
|
||||
static void
|
||||
ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo);
|
||||
|
||||
|
@ -96,11 +105,6 @@ public:
|
|||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
static bool
|
||||
DeserializeIndexValue(JSContext* aCx,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
static bool
|
||||
DeserializeUpgradeValue(JSContext* aCx,
|
||||
StructuredCloneReadInfo& aCloneReadInfo,
|
||||
|
|
Загрузка…
Ссылка в новой задаче