mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1076975 - Avoid serializing blobs when passed between threads in the same process, r=khuey.
This commit is contained in:
parent
3fd962194d
commit
e24fd2b2d7
@ -86,7 +86,7 @@ FileImplSnapshot::AssertSanity()
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, FileImpl)
|
||||
NS_IMPL_ISUPPORTS_INHERITED(FileImplSnapshot, FileImpl, PIFileImplSnapshot)
|
||||
|
||||
void
|
||||
FileImplSnapshot::Unlink()
|
||||
|
@ -11,6 +11,18 @@
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#define FILEIMPLSNAPSHOT_IID \
|
||||
{0x0dfc11b1, 0x75d3, 0x473b, {0x8c, 0x67, 0xb7, 0x23, 0xf4, 0x67, 0xd6, 0x73}}
|
||||
|
||||
class PIFileImplSnapshot : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(FILEIMPLSNAPSHOT_IID)
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(PIFileImplSnapshot, FILEIMPLSNAPSHOT_IID)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -23,6 +35,7 @@ class IDBFileHandle;
|
||||
|
||||
class FileImplSnapshot MOZ_FINAL
|
||||
: public FileImplBase
|
||||
, public PIFileImplSnapshot
|
||||
{
|
||||
typedef mozilla::dom::MetadataParameters MetadataParameters;
|
||||
|
||||
|
@ -19,6 +19,7 @@ support-files =
|
||||
unit/test_advance.js
|
||||
unit/test_autoIncrement.js
|
||||
unit/test_autoIncrement_indexes.js
|
||||
unit/test_blob_file_backed.js
|
||||
unit/test_blocked_order.js
|
||||
unit/test_clear.js
|
||||
unit/test_complex_keyPaths.js
|
||||
@ -111,6 +112,9 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_blob_archive.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_blob_file_backed.html]
|
||||
# This test can only run in the main process.
|
||||
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
|
||||
[test_blob_simple.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_blob_worker_crash.html]
|
||||
|
18
dom/indexedDB/test/test_blob_file_backed.html
Normal file
18
dom/indexedDB/test/test_blob_file_backed.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>IndexedDB Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="unit/test_blob_file_backed.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
95
dom/indexedDB/test/unit/test_blob_file_backed.js
Normal file
95
dom/indexedDB/test/unit/test_blob_file_backed.js
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
let testGenerator = testSteps();
|
||||
|
||||
function createFileReader() {
|
||||
return SpecialPowers.Cc["@mozilla.org/files/filereader;1"]
|
||||
.createInstance(SpecialPowers.Ci.nsIDOMFileReader);
|
||||
}
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const fileIOFlags = 0x02 | // PR_WRONLY
|
||||
0x08 | // PR_CREATEFILE
|
||||
0x20; // PR_TRUNCATE
|
||||
const filePerms = 0664;
|
||||
const fileData = "abcdefghijklmnopqrstuvwxyz";
|
||||
const fileType = "text/plain";
|
||||
|
||||
const databaseName =
|
||||
("window" in this) ? window.location.pathname : "Test";
|
||||
const objectStoreName = "foo";
|
||||
const objectStoreKey = "10";
|
||||
|
||||
info("Creating temp file");
|
||||
|
||||
let dirSvc =
|
||||
SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
let testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
testFile.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, filePerms);
|
||||
|
||||
info("Writing temp file");
|
||||
|
||||
let outStream =
|
||||
SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, fileIOFlags, filePerms, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
let file = SpecialPowers.createDOMFile(testFile.path, { type: fileType });
|
||||
ok(file instanceof File, "Got a File object");
|
||||
is(file.size, fileData.length, "Correct size");
|
||||
is(file.type, fileType, "Correct type");
|
||||
|
||||
let fileReader = createFileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(file);
|
||||
|
||||
let event = yield undefined;
|
||||
|
||||
is(fileReader.result, fileData, "Correct data");
|
||||
|
||||
let request = indexedDB.open(databaseName, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
let db = event.target.result;
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.put(file, objectStoreKey);
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
db = event.target.result;
|
||||
|
||||
file = null;
|
||||
testFile.remove(false);
|
||||
|
||||
objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(objectStoreKey).onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
file = event.target.result;
|
||||
|
||||
ok(file instanceof File, "Got a File object");
|
||||
is(file.size, fileData.length, "Correct size");
|
||||
is(file.type, fileType, "Correct type");
|
||||
|
||||
fileReader = createFileReader();
|
||||
fileReader.onload = grabEventAndContinueHandler;
|
||||
fileReader.readAsText(file);
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(fileReader.result, fileData, "Correct data");
|
||||
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
@ -46,7 +46,7 @@ if (!this.runTest) {
|
||||
enableExperimental();
|
||||
}
|
||||
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
Cu.importGlobalProperties(["indexedDB", "Blob", "File"]);
|
||||
|
||||
do_test_pending();
|
||||
testGenerator.next();
|
||||
@ -332,5 +332,21 @@ var SpecialPowers = {
|
||||
var prefService =
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
||||
return prefService.getBranch(null);
|
||||
}
|
||||
},
|
||||
|
||||
get Cc() {
|
||||
return Cc;
|
||||
},
|
||||
|
||||
get Ci() {
|
||||
return Ci;
|
||||
},
|
||||
|
||||
get Cu() {
|
||||
return Cu;
|
||||
},
|
||||
|
||||
createDOMFile: function(file, options) {
|
||||
return new File(file, options);
|
||||
},
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ support-files =
|
||||
|
||||
[include:xpcshell-shared.ini]
|
||||
|
||||
[test_blob_file_backed.js]
|
||||
[test_bug1056939.js]
|
||||
[test_globalObjects_ipc.js]
|
||||
[test_invalidate.js]
|
||||
|
509
dom/ipc/Blob.cpp
509
dom/ipc/Blob.cpp
@ -21,6 +21,7 @@
|
||||
#include "mozilla/dom/nsIContentChild.h"
|
||||
#include "mozilla/dom/PBlobStreamChild.h"
|
||||
#include "mozilla/dom/PBlobStreamParent.h"
|
||||
#include "mozilla/dom/indexedDB/FileSnapshot.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
@ -837,13 +838,13 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata MOZ_FINAL
|
||||
uint64_t mLength;
|
||||
uint64_t mLastModifiedDate;
|
||||
bool mHasRecursed;
|
||||
bool mIsSameProcessActor;
|
||||
const bool mIsSameProcessActor;
|
||||
|
||||
CreateBlobImplMetadata()
|
||||
CreateBlobImplMetadata(bool aIsSameProcessActor)
|
||||
: mLength(0)
|
||||
, mLastModifiedDate(0)
|
||||
, mHasRecursed(false)
|
||||
, mIsSameProcessActor(false)
|
||||
, mIsSameProcessActor(aIsSameProcessActor)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CreateBlobImplMetadata);
|
||||
|
||||
@ -863,10 +864,30 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata MOZ_FINAL
|
||||
};
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
||||
CreateBlobImpl(const nsID& aKnownBlobIDData,
|
||||
const CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
static_assert(sizeof(aParams.data().Length()) <= sizeof(size_t),
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(aMetadata.mHasRecursed);
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl = BlobParent::GetBlobImplForID(aKnownBlobIDData);
|
||||
if (NS_WARN_IF(!blobImpl)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DebugOnly<bool> isMutable;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)));
|
||||
MOZ_ASSERT(!isMutable);
|
||||
|
||||
return blobImpl.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImpl(const nsTArray<uint8_t>& aMemoryData,
|
||||
const CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
static_assert(sizeof(aMemoryData.Length()) <= sizeof(size_t),
|
||||
"String length won't fit in size_t!");
|
||||
static_assert(sizeof(size_t) <= sizeof(uint64_t),
|
||||
"size_t won't fit in uint64_t!");
|
||||
@ -875,19 +896,22 @@ CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl;
|
||||
|
||||
if (auto length = static_cast<size_t>(aParams.data().Length())) {
|
||||
if (auto length = static_cast<size_t>(aMemoryData.Length())) {
|
||||
static MOZ_CONSTEXPR_VAR size_t elementSizeMultiplier =
|
||||
sizeof(aMemoryData[0]) / sizeof(char);
|
||||
|
||||
if (!aMetadata.mHasRecursed &&
|
||||
NS_WARN_IF(aMetadata.mLength != uint64_t(length))) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* buffer = moz_malloc(aParams.data().Length());
|
||||
void* buffer = moz_malloc(length * elementSizeMultiplier);
|
||||
if (NS_WARN_IF(!buffer)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(buffer, aParams.data().get(), length);
|
||||
memcpy(buffer, aMemoryData.Elements(), length * elementSizeMultiplier);
|
||||
|
||||
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
||||
blobImpl =
|
||||
@ -915,36 +939,16 @@ CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const RemoteInputStreamParams& aParams,
|
||||
const CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(aMetadata.mHasRecursed);
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl = BlobParent::GetBlobImplForID(aParams.id());
|
||||
if (NS_WARN_IF(!blobImpl)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DebugOnly<bool> isMutable;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)));
|
||||
MOZ_ASSERT(!isMutable);
|
||||
|
||||
return blobImpl.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const SameProcessInputStreamParams& aParams,
|
||||
CreateBlobImpl(intptr_t aAddRefedInputStream,
|
||||
const CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(aMetadata.mIsSameProcessActor);
|
||||
MOZ_ASSERT(aParams.addRefedInputStream());
|
||||
MOZ_ASSERT(aAddRefedInputStream);
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream =
|
||||
dont_AddRef(
|
||||
reinterpret_cast<nsIInputStream*>(aParams.addRefedInputStream()));
|
||||
reinterpret_cast<nsIInputStream*>(aAddRefedInputStream));
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl;
|
||||
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
||||
@ -969,73 +973,35 @@ CreateBlobImplFromParams(const SameProcessInputStreamParams& aParams,
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
||||
CreateBlobImpl(const nsTArray<BlobData>& aBlobData,
|
||||
CreateBlobImplMetadata& aMetadata);
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromInputStreamParams(const InputStreamParams& aParams,
|
||||
CreateBlobImplFromBlobData(const BlobData& aBlobData,
|
||||
CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl;
|
||||
|
||||
switch (aParams.type()) {
|
||||
case InputStreamParams::TStringInputStreamParams: {
|
||||
const StringInputStreamParams& params =
|
||||
aParams.get_StringInputStreamParams();
|
||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
||||
switch (aBlobData.type()) {
|
||||
case BlobData::TnsID: {
|
||||
blobImpl = CreateBlobImpl(aBlobData.get_nsID(), aMetadata);
|
||||
break;
|
||||
}
|
||||
|
||||
case InputStreamParams::TFileInputStreamParams: {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case InputStreamParams::TPartialFileInputStreamParams: {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case InputStreamParams::TBufferedInputStreamParams: {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case InputStreamParams::TMIMEInputStreamParams: {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case InputStreamParams::TMultiplexInputStreamParams: {
|
||||
const MultiplexInputStreamParams& params =
|
||||
aParams.get_MultiplexInputStreamParams();
|
||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
||||
case BlobData::TArrayOfuint8_t: {
|
||||
blobImpl = CreateBlobImpl(aBlobData.get_ArrayOfuint8_t(), aMetadata);
|
||||
break;
|
||||
}
|
||||
|
||||
case InputStreamParams::TRemoteInputStreamParams: {
|
||||
if (NS_WARN_IF(!aMetadata.mHasRecursed)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RemoteInputStreamParams& params =
|
||||
aParams.get_RemoteInputStreamParams();
|
||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
||||
case BlobData::Tintptr_t: {
|
||||
blobImpl = CreateBlobImpl(aBlobData.get_intptr_t(), aMetadata);
|
||||
break;
|
||||
}
|
||||
|
||||
case InputStreamParams::TSameProcessInputStreamParams: {
|
||||
if (NS_WARN_IF(!aMetadata.mIsSameProcessActor)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SameProcessInputStreamParams& params =
|
||||
aParams.get_SameProcessInputStreamParams();
|
||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
||||
case BlobData::TArrayOfBlobData: {
|
||||
blobImpl = CreateBlobImpl(aBlobData.get_ArrayOfBlobData(), aMetadata);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1047,34 +1013,17 @@ CreateBlobImplFromInputStreamParams(const InputStreamParams& aParams,
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
||||
CreateBlobImpl(const nsTArray<BlobData>& aBlobDatas,
|
||||
CreateBlobImplMetadata& aMetadata)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
if (NS_WARN_IF(aParams.currentStream())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(aParams.status()))) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aParams.startedReadingCurrent())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const nsTArray<InputStreamParams>& streams = aParams.streams();
|
||||
|
||||
// Special case for a multipart blob with only one part.
|
||||
if (streams.Length() == 1) {
|
||||
const InputStreamParams& params = streams[0];
|
||||
if (aBlobDatas.Length() == 1) {
|
||||
const BlobData& blobData = aBlobDatas[0];
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl =
|
||||
CreateBlobImplFromInputStreamParams(params, aMetadata);
|
||||
CreateBlobImplFromBlobData(blobData, aMetadata);
|
||||
if (NS_WARN_IF(!blobImpl)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1087,7 +1036,7 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
||||
}
|
||||
|
||||
FallibleTArray<nsRefPtr<FileImpl>> fallibleBlobImpls;
|
||||
if (NS_WARN_IF(!fallibleBlobImpls.SetLength(streams.Length()))) {
|
||||
if (NS_WARN_IF(!fallibleBlobImpls.SetLength(aBlobDatas.Length()))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1097,11 +1046,13 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
||||
const bool hasRecursed = aMetadata.mHasRecursed;
|
||||
aMetadata.mHasRecursed = true;
|
||||
|
||||
for (uint32_t count = streams.Length(), index = 0; index < count; index++) {
|
||||
const InputStreamParams& params = streams[index];
|
||||
for (uint32_t count = aBlobDatas.Length(), index = 0;
|
||||
index < count;
|
||||
index++) {
|
||||
const BlobData& blobData = aBlobDatas[index];
|
||||
nsRefPtr<FileImpl>& blobImpl = blobImpls[index];
|
||||
|
||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
||||
blobImpl = CreateBlobImplFromBlobData(blobData, aMetadata);
|
||||
if (NS_WARN_IF(!blobImpl)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1126,7 +1077,8 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
||||
}
|
||||
|
||||
already_AddRefed<FileImpl>
|
||||
CreateBlobImplFromParams(const ParentBlobConstructorParams& aParams,
|
||||
CreateBlobImpl(const ParentBlobConstructorParams& aParams,
|
||||
const BlobData& aBlobData,
|
||||
bool aIsSameProcessActor)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
@ -1134,10 +1086,8 @@ CreateBlobImplFromParams(const ParentBlobConstructorParams& aParams,
|
||||
AnyBlobConstructorParams::TNormalBlobConstructorParams ||
|
||||
aParams.blobParams().type() ==
|
||||
AnyBlobConstructorParams::TFileBlobConstructorParams);
|
||||
MOZ_ASSERT(aParams.optionalInputStreamParams().type() ==
|
||||
OptionalInputStreamParams::TInputStreamParams);
|
||||
|
||||
CreateBlobImplMetadata metadata;
|
||||
CreateBlobImplMetadata metadata(aIsSameProcessActor);
|
||||
|
||||
if (aParams.blobParams().type() ==
|
||||
AnyBlobConstructorParams::TNormalBlobConstructorParams) {
|
||||
@ -1171,16 +1121,71 @@ CreateBlobImplFromParams(const ParentBlobConstructorParams& aParams,
|
||||
metadata.mLastModifiedDate = params.modDate();
|
||||
}
|
||||
|
||||
metadata.mIsSameProcessActor = aIsSameProcessActor;
|
||||
|
||||
const InputStreamParams& inputStreamParams =
|
||||
aParams.optionalInputStreamParams().get_InputStreamParams();
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl =
|
||||
CreateBlobImplFromInputStreamParams(inputStreamParams, metadata);
|
||||
CreateBlobImplFromBlobData(aBlobData, metadata);
|
||||
return blobImpl.forget();
|
||||
}
|
||||
|
||||
void
|
||||
BlobDataFromBlobImpl(FileImpl* aBlobImpl, BlobData& aBlobData)
|
||||
{
|
||||
MOZ_ASSERT(gProcessType != GeckoProcessType_Default);
|
||||
MOZ_ASSERT(aBlobImpl);
|
||||
|
||||
const nsTArray<nsRefPtr<FileImpl>>* subBlobs = aBlobImpl->GetSubBlobImpls();
|
||||
|
||||
if (subBlobs) {
|
||||
aBlobData = nsTArray<BlobData>();
|
||||
|
||||
nsTArray<BlobData>& subBlobDatas = aBlobData.get_ArrayOfBlobData();
|
||||
subBlobDatas.SetLength(subBlobs->Length());
|
||||
|
||||
for (uint32_t count = subBlobs->Length(), index = 0;
|
||||
index < count;
|
||||
index++) {
|
||||
BlobDataFromBlobImpl(subBlobs->ElementAt(index), subBlobDatas[index]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlobImpl);
|
||||
if (remoteBlob) {
|
||||
BlobChild* actor = remoteBlob->GetBlobChild();
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
aBlobData = actor->ParentID();
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aBlobImpl->IsMemoryFile());
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
aBlobImpl->GetInternalStream(getter_AddRefs(inputStream))));
|
||||
|
||||
DebugOnly<bool> isNonBlocking;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(inputStream->IsNonBlocking(&isNonBlocking)));
|
||||
MOZ_ASSERT(isNonBlocking);
|
||||
|
||||
uint64_t available;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(inputStream->Available(&available)));
|
||||
|
||||
MOZ_ASSERT(available <= uint64_t(UINT32_MAX));
|
||||
|
||||
aBlobData = nsTArray<uint8_t>();
|
||||
|
||||
nsTArray<uint8_t>& blobData = aBlobData.get_ArrayOfuint8_t();
|
||||
|
||||
blobData.SetLength(size_t(available));
|
||||
|
||||
uint32_t readCount;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
inputStream->Read(reinterpret_cast<char*>(blobData.Elements()),
|
||||
uint32_t(available),
|
||||
&readCount)));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
StaticAutoPtr<BlobParent::IDTable> BlobParent::sIDTable;
|
||||
@ -1548,6 +1553,9 @@ protected:
|
||||
|
||||
BlobChild* mActor;
|
||||
nsCOMPtr<nsIEventTarget> mActorTarget;
|
||||
|
||||
nsRefPtr<FileImpl> mSameProcessFileImpl;
|
||||
|
||||
const bool mIsSlice;
|
||||
|
||||
public:
|
||||
@ -1563,6 +1571,20 @@ public:
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength);
|
||||
|
||||
// For same-process blobs.
|
||||
RemoteBlobImpl(BlobChild* aActor,
|
||||
FileImpl* aSameProcessBlobImpl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength,
|
||||
uint64_t aModDate);
|
||||
|
||||
// For same-process blobs.
|
||||
RemoteBlobImpl(BlobChild* aActor,
|
||||
FileImpl* aSameProcessBlobImpl,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength);
|
||||
|
||||
// For mystery blobs.
|
||||
explicit
|
||||
RemoteBlobImpl(BlobChild* aActor);
|
||||
@ -1853,6 +1875,38 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
||||
CommonInit(aActor);
|
||||
}
|
||||
|
||||
BlobChild::
|
||||
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
||||
FileImpl* aSameProcessBlobImpl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength,
|
||||
uint64_t aModDate)
|
||||
: FileImplBase(aName, aContentType, aLength, aModDate)
|
||||
, mSameProcessFileImpl(aSameProcessBlobImpl)
|
||||
, mIsSlice(false)
|
||||
{
|
||||
MOZ_ASSERT(aSameProcessBlobImpl);
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
CommonInit(aActor);
|
||||
}
|
||||
|
||||
BlobChild::
|
||||
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
||||
FileImpl* aSameProcessBlobImpl,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength)
|
||||
: FileImplBase(aContentType, aLength)
|
||||
, mSameProcessFileImpl(aSameProcessBlobImpl)
|
||||
, mIsSlice(false)
|
||||
{
|
||||
MOZ_ASSERT(aSameProcessBlobImpl);
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
CommonInit(aActor);
|
||||
}
|
||||
|
||||
BlobChild::
|
||||
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
|
||||
: FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
|
||||
@ -1954,6 +2008,13 @@ RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFilePath,
|
||||
MOZ_CRASH("Not implemented!");
|
||||
}
|
||||
|
||||
if (mSameProcessFileImpl) {
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
mSameProcessFileImpl->GetMozFullPathInternal(aFilePath, aRv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mActor) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
@ -1976,6 +2037,15 @@ RemoteBlobImpl::CreateSlice(uint64_t aStart,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// May be called on any thread.
|
||||
if (mSameProcessFileImpl) {
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
return mSameProcessFileImpl->CreateSlice(aStart,
|
||||
aLength,
|
||||
aContentType,
|
||||
aRv);
|
||||
}
|
||||
|
||||
nsRefPtr<RemoteBlobSliceImpl> slice =
|
||||
new RemoteBlobSliceImpl(this, aStart, aLength, aContentType);
|
||||
return slice.forget();
|
||||
@ -1986,6 +2056,22 @@ BlobChild::
|
||||
RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream)
|
||||
{
|
||||
// May be called on any thread.
|
||||
if (mSameProcessFileImpl) {
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
nsCOMPtr<nsIInputStream> realStream;
|
||||
nsresult rv =
|
||||
mSameProcessFileImpl->GetInternalStream(getter_AddRefs(realStream));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<BlobInputStreamTether> tether =
|
||||
new BlobInputStreamTether(realStream, mSameProcessFileImpl);
|
||||
tether.forget(aStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<CreateStreamHelper> helper = new CreateStreamHelper(this);
|
||||
return helper->GetStream(aStream);
|
||||
}
|
||||
@ -1998,6 +2084,12 @@ RemoteBlobImpl::GetFileId()
|
||||
MOZ_CRASH("Not implemented!");
|
||||
}
|
||||
|
||||
if (mSameProcessFileImpl) {
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
return mSameProcessFileImpl->GetFileId();
|
||||
}
|
||||
|
||||
int64_t fileId;
|
||||
if (mActor && mActor->SendGetFileId(&fileId)) {
|
||||
return fileId;
|
||||
@ -2209,8 +2301,7 @@ RemoteBlobSliceImpl::GetBlobChild()
|
||||
id /* id */,
|
||||
mStart /* begin */,
|
||||
mStart + mLength /* end */,
|
||||
mContentType /* contentType */),
|
||||
void_t() /* optionalInputStream */);
|
||||
mContentType /* contentType */));
|
||||
|
||||
if (nsIContentChild* contentManager = baseActor->GetContentManager()) {
|
||||
mActor = SendSliceConstructor(contentManager, this, params);
|
||||
@ -2648,6 +2739,8 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
||||
|
||||
AnyBlobConstructorParams::Type paramsType = blobParams.type();
|
||||
MOZ_ASSERT(paramsType != AnyBlobConstructorParams::T__None &&
|
||||
paramsType !=
|
||||
AnyBlobConstructorParams::TSlicedBlobConstructorParams &&
|
||||
paramsType !=
|
||||
AnyBlobConstructorParams::TKnownBlobConstructorParams);
|
||||
|
||||
@ -2673,6 +2766,44 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
||||
break;
|
||||
}
|
||||
|
||||
case AnyBlobConstructorParams::TSameProcessBlobConstructorParams: {
|
||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||
|
||||
const SameProcessBlobConstructorParams& params =
|
||||
blobParams.get_SameProcessBlobConstructorParams();
|
||||
MOZ_ASSERT(params.addRefedFileImpl());
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl =
|
||||
dont_AddRef(reinterpret_cast<FileImpl*>(params.addRefedFileImpl()));
|
||||
|
||||
ErrorResult rv;
|
||||
uint64_t size = blobImpl->GetSize(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
nsString contentType;
|
||||
blobImpl->GetType(contentType);
|
||||
|
||||
if (blobImpl->IsFile()) {
|
||||
nsString name;
|
||||
blobImpl->GetName(name);
|
||||
|
||||
uint64_t lastModifiedDate = blobImpl->GetLastModified(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
remoteBlob =
|
||||
new RemoteBlobImpl(this,
|
||||
blobImpl,
|
||||
name,
|
||||
contentType,
|
||||
size,
|
||||
lastModifiedDate);
|
||||
} else {
|
||||
remoteBlob = new RemoteBlobImpl(this, blobImpl, contentType, size);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
||||
remoteBlob = new RemoteBlobImpl(this);
|
||||
break;
|
||||
@ -2798,7 +2929,7 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
||||
}
|
||||
}
|
||||
|
||||
// All blobs shared between processes must be immutable.
|
||||
// All blobs shared between threads or processes must be immutable.
|
||||
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2808,6 +2939,31 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
||||
|
||||
AnyBlobConstructorParams blobParams;
|
||||
|
||||
nsCOMPtr<nsIInputStream> snapshotInputStream;
|
||||
|
||||
if (gProcessType == GeckoProcessType_Default) {
|
||||
nsCOMPtr<PIFileImplSnapshot> snapshot = do_QueryInterface(aBlobImpl);
|
||||
if (snapshot) {
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
aBlobImpl->GetInternalStream(getter_AddRefs(snapshotInputStream))));
|
||||
}
|
||||
}
|
||||
|
||||
if (gProcessType == GeckoProcessType_Default && !snapshotInputStream) {
|
||||
nsRefPtr<FileImpl> sameProcessImpl = aBlobImpl;
|
||||
auto addRefedFileImpl =
|
||||
reinterpret_cast<intptr_t>(sameProcessImpl.forget().take());
|
||||
|
||||
blobParams = SameProcessBlobConstructorParams(addRefedFileImpl);
|
||||
} else {
|
||||
BlobData blobData;
|
||||
if (snapshotInputStream) {
|
||||
blobData =
|
||||
reinterpret_cast<intptr_t>(snapshotInputStream.forget().take());
|
||||
} else {
|
||||
BlobDataFromBlobImpl(aBlobImpl, blobData);
|
||||
}
|
||||
|
||||
nsString contentType;
|
||||
aBlobImpl->GetType(contentType);
|
||||
|
||||
@ -2815,10 +2971,6 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
||||
uint64_t length = aBlobImpl->GetSize(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
aBlobImpl->GetInternalStream(getter_AddRefs(stream))));
|
||||
|
||||
if (aBlobImpl->IsFile()) {
|
||||
nsString name;
|
||||
aBlobImpl->GetName(name);
|
||||
@ -2826,22 +2978,16 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
||||
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
blobParams = FileBlobConstructorParams(name, contentType, length, modDate);
|
||||
blobParams =
|
||||
FileBlobConstructorParams(name, contentType, length, modDate, blobData);
|
||||
} else {
|
||||
blobParams = NormalBlobConstructorParams(contentType, length);
|
||||
blobParams = NormalBlobConstructorParams(contentType, length, blobData);
|
||||
}
|
||||
}
|
||||
|
||||
InputStreamParams inputStreamParams;
|
||||
|
||||
nsTArray<FileDescriptor> fds;
|
||||
SerializeInputStream(stream, inputStreamParams, fds);
|
||||
|
||||
MOZ_ASSERT(inputStreamParams.type() != InputStreamParams::T__None);
|
||||
MOZ_ASSERT(fds.IsEmpty());
|
||||
|
||||
BlobChild* actor = new BlobChild(aManager, aBlobImpl);
|
||||
|
||||
ParentBlobConstructorParams params(blobParams, inputStreamParams);
|
||||
ParentBlobConstructorParams params(blobParams);
|
||||
|
||||
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
||||
BlobChild::Destroy(actor);
|
||||
@ -2865,6 +3011,7 @@ BlobChild::CreateFromParams(ChildManagerType* aManager,
|
||||
switch (blobParams.type()) {
|
||||
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
||||
case AnyBlobConstructorParams::TFileBlobConstructorParams:
|
||||
case AnyBlobConstructorParams::TSameProcessBlobConstructorParams:
|
||||
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
||||
return new BlobChild(aManager, aParams);
|
||||
}
|
||||
@ -2896,8 +3043,6 @@ BlobChild::SendSliceConstructor(ChildManagerType* aManager,
|
||||
MOZ_ASSERT(aRemoteBlobSliceImpl);
|
||||
MOZ_ASSERT(aParams.blobParams().type() ==
|
||||
AnyBlobConstructorParams::TSlicedBlobConstructorParams);
|
||||
MOZ_ASSERT(aParams.optionalInputStreamParams().type() ==
|
||||
OptionalInputStreamParams::Tvoid_t);
|
||||
|
||||
const nsID& id = aParams.blobParams().get_SlicedBlobConstructorParams().id();
|
||||
|
||||
@ -2933,8 +3078,7 @@ BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
||||
actor = new BlobChild(aManager, actor);
|
||||
|
||||
ParentBlobConstructorParams params(
|
||||
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
||||
void_t() /* optionalInputStream */);
|
||||
KnownBlobConstructorParams(actor->ParentID()));
|
||||
|
||||
aManager->SendPBlobConstructor(actor, params);
|
||||
|
||||
@ -2963,8 +3107,7 @@ BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
||||
actor = new BlobChild(aManager, actor);
|
||||
|
||||
ParentBlobConstructorParams params(
|
||||
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
||||
void_t() /* optionalInputStream */);
|
||||
KnownBlobConstructorParams(actor->ParentID()));
|
||||
|
||||
aManager->SendPBlobConstructor(actor, params);
|
||||
|
||||
@ -3019,8 +3162,11 @@ BlobChild::SetMysteryBlobInfo(const nsString& aName,
|
||||
|
||||
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
|
||||
|
||||
FileBlobConstructorParams params(aName, aContentType, aLength,
|
||||
aLastModifiedDate);
|
||||
FileBlobConstructorParams params(aName,
|
||||
aContentType,
|
||||
aLength,
|
||||
aLastModifiedDate,
|
||||
void_t() /* optionalBlobData */);
|
||||
return SendResolveMystery(params);
|
||||
}
|
||||
|
||||
@ -3036,7 +3182,9 @@ BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
|
||||
|
||||
mBlobImpl->SetLazyData(voidString, aContentType, aLength, UINT64_MAX);
|
||||
|
||||
NormalBlobConstructorParams params(aContentType, aLength);
|
||||
NormalBlobConstructorParams params(aContentType,
|
||||
aLength,
|
||||
void_t() /* optionalBlobData */);
|
||||
return SendResolveMystery(params);
|
||||
}
|
||||
|
||||
@ -3326,17 +3474,35 @@ BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
|
||||
}
|
||||
}
|
||||
|
||||
// All blobs shared between processes must be immutable.
|
||||
// All blobs shared between threads or processes must be immutable.
|
||||
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bool isSameProcessActor = ActorManagerIsSameProcess(aManager);
|
||||
|
||||
AnyBlobConstructorParams blobParams;
|
||||
|
||||
bool isSnapshot;
|
||||
|
||||
if (isSameProcessActor) {
|
||||
nsCOMPtr<PIFileImplSnapshot> snapshot = do_QueryInterface(aBlobImpl);
|
||||
isSnapshot = !!snapshot;
|
||||
} else {
|
||||
isSnapshot = false;
|
||||
}
|
||||
|
||||
if (isSameProcessActor && !isSnapshot) {
|
||||
nsRefPtr<FileImpl> sameProcessImpl = aBlobImpl;
|
||||
auto addRefedFileImpl =
|
||||
reinterpret_cast<intptr_t>(sameProcessImpl.forget().take());
|
||||
|
||||
blobParams = SameProcessBlobConstructorParams(addRefedFileImpl);
|
||||
} else {
|
||||
if (aBlobImpl->IsSizeUnknown() || aBlobImpl->IsDateUnknown()) {
|
||||
// We don't want to call GetSize or GetLastModifiedDate yet since that may
|
||||
// stat a file on the this thread. Instead we'll learn the size lazily from
|
||||
// the other side.
|
||||
// stat a file on the this thread. Instead we'll learn the size lazily
|
||||
// from the other side.
|
||||
blobParams = MysteryBlobConstructorParams();
|
||||
} else {
|
||||
nsString contentType;
|
||||
@ -3354,9 +3520,10 @@ BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
|
||||
blobParams =
|
||||
FileBlobConstructorParams(name, contentType, length, modDate);
|
||||
FileBlobConstructorParams(name, contentType, length, modDate, void_t());
|
||||
} else {
|
||||
blobParams = NormalBlobConstructorParams(contentType, length);
|
||||
blobParams = NormalBlobConstructorParams(contentType, length, void_t());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3397,14 +3564,21 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
||||
|
||||
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
||||
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
||||
if (aParams.optionalInputStreamParams().type() !=
|
||||
OptionalInputStreamParams::TInputStreamParams) {
|
||||
const OptionalBlobData& optionalBlobData =
|
||||
blobParams.type() ==
|
||||
AnyBlobConstructorParams::TNormalBlobConstructorParams ?
|
||||
blobParams.get_NormalBlobConstructorParams().optionalBlobData() :
|
||||
blobParams.get_FileBlobConstructorParams().optionalBlobData();
|
||||
|
||||
if (NS_WARN_IF(optionalBlobData.type() != OptionalBlobData::TBlobData)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl =
|
||||
CreateBlobImplFromParams(aParams, ActorManagerIsSameProcess(aManager));
|
||||
CreateBlobImpl(aParams,
|
||||
optionalBlobData.get_BlobData(),
|
||||
ActorManagerIsSameProcess(aManager));
|
||||
if (NS_WARN_IF(!blobImpl)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
@ -3424,12 +3598,6 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
||||
}
|
||||
|
||||
case AnyBlobConstructorParams::TSlicedBlobConstructorParams: {
|
||||
if (aParams.optionalInputStreamParams().type() !=
|
||||
OptionalInputStreamParams::Tvoid_t) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SlicedBlobConstructorParams& params =
|
||||
blobParams.get_SlicedBlobConstructorParams();
|
||||
|
||||
@ -3472,12 +3640,6 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
||||
}
|
||||
|
||||
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
||||
if (aParams.optionalInputStreamParams().type() !=
|
||||
OptionalInputStreamParams::Tvoid_t) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const KnownBlobConstructorParams& params =
|
||||
blobParams.get_KnownBlobConstructorParams();
|
||||
|
||||
@ -3494,6 +3656,29 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
||||
return new BlobParent(aManager, blobImpl, idTableEntry);
|
||||
}
|
||||
|
||||
case AnyBlobConstructorParams::TSameProcessBlobConstructorParams: {
|
||||
if (NS_WARN_IF(!ActorManagerIsSameProcess(aManager))) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SameProcessBlobConstructorParams& params =
|
||||
blobParams.get_SameProcessBlobConstructorParams();
|
||||
|
||||
nsRefPtr<FileImpl> blobImpl =
|
||||
dont_AddRef(reinterpret_cast<FileImpl*>(params.addRefedFileImpl()));
|
||||
MOZ_ASSERT(blobImpl);
|
||||
|
||||
nsID id;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(gUUIDGenerator->GenerateUUIDInPlace(&id)));
|
||||
|
||||
nsRefPtr<IDTableEntry> idTableEntry =
|
||||
IDTableEntry::Create(id, ActorManagerProcessID(aManager), blobImpl);
|
||||
MOZ_ASSERT(idTableEntry);
|
||||
|
||||
return new BlobParent(aManager, blobImpl, idTableEntry);
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown params!");
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBlob;
|
||||
include InputStreamParams;
|
||||
|
||||
using struct mozilla::void_t
|
||||
from "ipc/IPCMessageUtils.h";
|
||||
@ -13,6 +12,9 @@ using struct mozilla::void_t
|
||||
using struct mozilla::SerializedStructuredCloneBuffer
|
||||
from "ipc/IPCMessageUtils.h";
|
||||
|
||||
using struct nsID
|
||||
from "nsID.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -28,10 +30,35 @@ struct ClonedMessageData
|
||||
PBlob[] blobs;
|
||||
};
|
||||
|
||||
union BlobData
|
||||
{
|
||||
// For remote blobs.
|
||||
nsID;
|
||||
|
||||
// For memory-backed blobs.
|
||||
uint8_t[];
|
||||
|
||||
// For file snapshots, this is an nsIInputStream.
|
||||
intptr_t;
|
||||
|
||||
// For multiplex blobs.
|
||||
BlobData[];
|
||||
};
|
||||
|
||||
union OptionalBlobData
|
||||
{
|
||||
BlobData;
|
||||
void_t;
|
||||
};
|
||||
|
||||
struct NormalBlobConstructorParams
|
||||
{
|
||||
nsString contentType;
|
||||
uint64_t length;
|
||||
|
||||
// This must be of type BlobData in a child->parent message, and will always
|
||||
// be of type void_t in a parent->child message.
|
||||
OptionalBlobData optionalBlobData;
|
||||
};
|
||||
|
||||
struct FileBlobConstructorParams
|
||||
@ -40,6 +67,10 @@ struct FileBlobConstructorParams
|
||||
nsString contentType;
|
||||
uint64_t length;
|
||||
uint64_t modDate;
|
||||
|
||||
// This must be of type BlobData in a child->parent message, and will always
|
||||
// be of type void_t in a parent->child message.
|
||||
OptionalBlobData optionalBlobData;
|
||||
};
|
||||
|
||||
struct SlicedBlobConstructorParams
|
||||
@ -61,11 +92,20 @@ struct KnownBlobConstructorParams
|
||||
nsID id;
|
||||
};
|
||||
|
||||
// This may only be used for same-process inter-thread communication!
|
||||
struct SameProcessBlobConstructorParams
|
||||
{
|
||||
// This member should be reinterpret_cast'd to mozilla::dom::FileImpl. It
|
||||
// carries a reference.
|
||||
intptr_t addRefedFileImpl;
|
||||
};
|
||||
|
||||
union AnyBlobConstructorParams
|
||||
{
|
||||
// These types may be sent to/from parent and child.
|
||||
NormalBlobConstructorParams;
|
||||
FileBlobConstructorParams;
|
||||
SameProcessBlobConstructorParams;
|
||||
|
||||
// This type may only be sent from parent to child.
|
||||
MysteryBlobConstructorParams;
|
||||
@ -87,14 +127,6 @@ struct ParentBlobConstructorParams
|
||||
{
|
||||
// May not be MysteryBlobConstructorParams.
|
||||
AnyBlobConstructorParams blobParams;
|
||||
|
||||
// This must be of type void_t for:
|
||||
// - SlicedBlobConstructorParams
|
||||
// - KnownBlobConstructorParams
|
||||
// This must be of type InputStreamParams for:
|
||||
// - NormalBlobConstructorParams
|
||||
// - FileBlobConstructorParams
|
||||
OptionalInputStreamParams optionalInputStreamParams;
|
||||
};
|
||||
|
||||
union BlobConstructorParams
|
||||
|
@ -2,13 +2,13 @@
|
||||
* 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/. */
|
||||
|
||||
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
include protocol PBlob;
|
||||
include protocol PFileDescriptorSet;
|
||||
|
||||
using struct nsID
|
||||
from "nsID.h";
|
||||
include DOMTypes;
|
||||
|
||||
using struct mozilla::void_t
|
||||
from "ipc/IPCMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
@ -18,6 +18,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
Cu.importGlobalProperties(["File"]);
|
||||
|
||||
// Allow stuff from this scope to be accessed from non-privileged scopes. This
|
||||
// would crash if used outside of automation.
|
||||
Cu.forcePermissiveCOWs();
|
||||
@ -1877,6 +1879,10 @@ SpecialPowersAPI.prototype = {
|
||||
let msg = { op: op, uri: uri, appId: appId, inBrowser: inBrowser, id: id };
|
||||
this._sendAsyncMessage(messageTopic, msg);
|
||||
},
|
||||
|
||||
createDOMFile: function(path, options) {
|
||||
return new File(path, options);
|
||||
},
|
||||
};
|
||||
|
||||
this.SpecialPowersAPI = SpecialPowersAPI;
|
||||
|
Loading…
Reference in New Issue
Block a user