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
|
#endif // DEBUG
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(FileImplSnapshot, FileImpl)
|
NS_IMPL_ISUPPORTS_INHERITED(FileImplSnapshot, FileImpl, PIFileImplSnapshot)
|
||||||
|
|
||||||
void
|
void
|
||||||
FileImplSnapshot::Unlink()
|
FileImplSnapshot::Unlink()
|
||||||
|
@ -11,6 +11,18 @@
|
|||||||
#include "mozilla/dom/File.h"
|
#include "mozilla/dom/File.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsCOMPtr.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 mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@ -23,6 +35,7 @@ class IDBFileHandle;
|
|||||||
|
|
||||||
class FileImplSnapshot MOZ_FINAL
|
class FileImplSnapshot MOZ_FINAL
|
||||||
: public FileImplBase
|
: public FileImplBase
|
||||||
|
, public PIFileImplSnapshot
|
||||||
{
|
{
|
||||||
typedef mozilla::dom::MetadataParameters MetadataParameters;
|
typedef mozilla::dom::MetadataParameters MetadataParameters;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ support-files =
|
|||||||
unit/test_advance.js
|
unit/test_advance.js
|
||||||
unit/test_autoIncrement.js
|
unit/test_autoIncrement.js
|
||||||
unit/test_autoIncrement_indexes.js
|
unit/test_autoIncrement_indexes.js
|
||||||
|
unit/test_blob_file_backed.js
|
||||||
unit/test_blocked_order.js
|
unit/test_blocked_order.js
|
||||||
unit/test_clear.js
|
unit/test_clear.js
|
||||||
unit/test_complex_keyPaths.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
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_blob_archive.html]
|
[test_blob_archive.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
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]
|
[test_blob_simple.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_blob_worker_crash.html]
|
[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();
|
enableExperimental();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cu.importGlobalProperties(["indexedDB"]);
|
Cu.importGlobalProperties(["indexedDB", "Blob", "File"]);
|
||||||
|
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
testGenerator.next();
|
testGenerator.next();
|
||||||
@ -332,5 +332,21 @@ var SpecialPowers = {
|
|||||||
var prefService =
|
var prefService =
|
||||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
||||||
return prefService.getBranch(null);
|
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]
|
[include:xpcshell-shared.ini]
|
||||||
|
|
||||||
|
[test_blob_file_backed.js]
|
||||||
[test_bug1056939.js]
|
[test_bug1056939.js]
|
||||||
[test_globalObjects_ipc.js]
|
[test_globalObjects_ipc.js]
|
||||||
[test_invalidate.js]
|
[test_invalidate.js]
|
||||||
|
577
dom/ipc/Blob.cpp
577
dom/ipc/Blob.cpp
@ -21,6 +21,7 @@
|
|||||||
#include "mozilla/dom/nsIContentChild.h"
|
#include "mozilla/dom/nsIContentChild.h"
|
||||||
#include "mozilla/dom/PBlobStreamChild.h"
|
#include "mozilla/dom/PBlobStreamChild.h"
|
||||||
#include "mozilla/dom/PBlobStreamParent.h"
|
#include "mozilla/dom/PBlobStreamParent.h"
|
||||||
|
#include "mozilla/dom/indexedDB/FileSnapshot.h"
|
||||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
#include "mozilla/ipc/InputStreamUtils.h"
|
||||||
#include "mozilla/ipc/PBackgroundChild.h"
|
#include "mozilla/ipc/PBackgroundChild.h"
|
||||||
@ -837,13 +838,13 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata MOZ_FINAL
|
|||||||
uint64_t mLength;
|
uint64_t mLength;
|
||||||
uint64_t mLastModifiedDate;
|
uint64_t mLastModifiedDate;
|
||||||
bool mHasRecursed;
|
bool mHasRecursed;
|
||||||
bool mIsSameProcessActor;
|
const bool mIsSameProcessActor;
|
||||||
|
|
||||||
CreateBlobImplMetadata()
|
CreateBlobImplMetadata(bool aIsSameProcessActor)
|
||||||
: mLength(0)
|
: mLength(0)
|
||||||
, mLastModifiedDate(0)
|
, mLastModifiedDate(0)
|
||||||
, mHasRecursed(false)
|
, mHasRecursed(false)
|
||||||
, mIsSameProcessActor(false)
|
, mIsSameProcessActor(aIsSameProcessActor)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(CreateBlobImplMetadata);
|
MOZ_COUNT_CTOR(CreateBlobImplMetadata);
|
||||||
|
|
||||||
@ -863,10 +864,30 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata MOZ_FINAL
|
|||||||
};
|
};
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
CreateBlobImpl(const nsID& aKnownBlobIDData,
|
||||||
const CreateBlobImplMetadata& aMetadata)
|
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!");
|
"String length won't fit in size_t!");
|
||||||
static_assert(sizeof(size_t) <= sizeof(uint64_t),
|
static_assert(sizeof(size_t) <= sizeof(uint64_t),
|
||||||
"size_t won't fit in uint64_t!");
|
"size_t won't fit in uint64_t!");
|
||||||
@ -875,19 +896,22 @@ CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
|||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl;
|
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 &&
|
if (!aMetadata.mHasRecursed &&
|
||||||
NS_WARN_IF(aMetadata.mLength != uint64_t(length))) {
|
NS_WARN_IF(aMetadata.mLength != uint64_t(length))) {
|
||||||
ASSERT_UNLESS_FUZZING();
|
ASSERT_UNLESS_FUZZING();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* buffer = moz_malloc(aParams.data().Length());
|
void* buffer = moz_malloc(length * elementSizeMultiplier);
|
||||||
if (NS_WARN_IF(!buffer)) {
|
if (NS_WARN_IF(!buffer)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer, aParams.data().get(), length);
|
memcpy(buffer, aMemoryData.Elements(), length * elementSizeMultiplier);
|
||||||
|
|
||||||
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
||||||
blobImpl =
|
blobImpl =
|
||||||
@ -915,36 +939,16 @@ CreateBlobImplFromParams(const StringInputStreamParams& aParams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromParams(const RemoteInputStreamParams& aParams,
|
CreateBlobImpl(intptr_t aAddRefedInputStream,
|
||||||
const CreateBlobImplMetadata& aMetadata)
|
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,
|
|
||||||
const CreateBlobImplMetadata& aMetadata)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
MOZ_ASSERT(aMetadata.mIsSameProcessActor);
|
MOZ_ASSERT(aMetadata.mIsSameProcessActor);
|
||||||
MOZ_ASSERT(aParams.addRefedInputStream());
|
MOZ_ASSERT(aAddRefedInputStream);
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> inputStream =
|
nsCOMPtr<nsIInputStream> inputStream =
|
||||||
dont_AddRef(
|
dont_AddRef(
|
||||||
reinterpret_cast<nsIInputStream*>(aParams.addRefedInputStream()));
|
reinterpret_cast<nsIInputStream*>(aAddRefedInputStream));
|
||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl;
|
nsRefPtr<FileImpl> blobImpl;
|
||||||
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
|
||||||
@ -969,73 +973,35 @@ CreateBlobImplFromParams(const SameProcessInputStreamParams& aParams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
CreateBlobImpl(const nsTArray<BlobData>& aBlobData,
|
||||||
CreateBlobImplMetadata& aMetadata);
|
CreateBlobImplMetadata& aMetadata);
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromInputStreamParams(const InputStreamParams& aParams,
|
CreateBlobImplFromBlobData(const BlobData& aBlobData,
|
||||||
CreateBlobImplMetadata& aMetadata)
|
CreateBlobImplMetadata& aMetadata)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl;
|
nsRefPtr<FileImpl> blobImpl;
|
||||||
|
|
||||||
switch (aParams.type()) {
|
switch (aBlobData.type()) {
|
||||||
case InputStreamParams::TStringInputStreamParams: {
|
case BlobData::TnsID: {
|
||||||
const StringInputStreamParams& params =
|
blobImpl = CreateBlobImpl(aBlobData.get_nsID(), aMetadata);
|
||||||
aParams.get_StringInputStreamParams();
|
|
||||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case InputStreamParams::TFileInputStreamParams: {
|
case BlobData::TArrayOfuint8_t: {
|
||||||
ASSERT_UNLESS_FUZZING();
|
blobImpl = CreateBlobImpl(aBlobData.get_ArrayOfuint8_t(), aMetadata);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case InputStreamParams::TRemoteInputStreamParams: {
|
case BlobData::Tintptr_t: {
|
||||||
if (NS_WARN_IF(!aMetadata.mHasRecursed)) {
|
blobImpl = CreateBlobImpl(aBlobData.get_intptr_t(), aMetadata);
|
||||||
ASSERT_UNLESS_FUZZING();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RemoteInputStreamParams& params =
|
|
||||||
aParams.get_RemoteInputStreamParams();
|
|
||||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case InputStreamParams::TSameProcessInputStreamParams: {
|
case BlobData::TArrayOfBlobData: {
|
||||||
if (NS_WARN_IF(!aMetadata.mIsSameProcessActor)) {
|
blobImpl = CreateBlobImpl(aBlobData.get_ArrayOfBlobData(), aMetadata);
|
||||||
ASSERT_UNLESS_FUZZING();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SameProcessInputStreamParams& params =
|
|
||||||
aParams.get_SameProcessInputStreamParams();
|
|
||||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1047,34 +1013,17 @@ CreateBlobImplFromInputStreamParams(const InputStreamParams& aParams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
CreateBlobImpl(const nsTArray<BlobData>& aBlobDatas,
|
||||||
CreateBlobImplMetadata& aMetadata)
|
CreateBlobImplMetadata& aMetadata)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
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.
|
// Special case for a multipart blob with only one part.
|
||||||
if (streams.Length() == 1) {
|
if (aBlobDatas.Length() == 1) {
|
||||||
const InputStreamParams& params = streams[0];
|
const BlobData& blobData = aBlobDatas[0];
|
||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl =
|
nsRefPtr<FileImpl> blobImpl =
|
||||||
CreateBlobImplFromInputStreamParams(params, aMetadata);
|
CreateBlobImplFromBlobData(blobData, aMetadata);
|
||||||
if (NS_WARN_IF(!blobImpl)) {
|
if (NS_WARN_IF(!blobImpl)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1087,7 +1036,7 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
FallibleTArray<nsRefPtr<FileImpl>> fallibleBlobImpls;
|
FallibleTArray<nsRefPtr<FileImpl>> fallibleBlobImpls;
|
||||||
if (NS_WARN_IF(!fallibleBlobImpls.SetLength(streams.Length()))) {
|
if (NS_WARN_IF(!fallibleBlobImpls.SetLength(aBlobDatas.Length()))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,11 +1046,13 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
|||||||
const bool hasRecursed = aMetadata.mHasRecursed;
|
const bool hasRecursed = aMetadata.mHasRecursed;
|
||||||
aMetadata.mHasRecursed = true;
|
aMetadata.mHasRecursed = true;
|
||||||
|
|
||||||
for (uint32_t count = streams.Length(), index = 0; index < count; index++) {
|
for (uint32_t count = aBlobDatas.Length(), index = 0;
|
||||||
const InputStreamParams& params = streams[index];
|
index < count;
|
||||||
|
index++) {
|
||||||
|
const BlobData& blobData = aBlobDatas[index];
|
||||||
nsRefPtr<FileImpl>& blobImpl = blobImpls[index];
|
nsRefPtr<FileImpl>& blobImpl = blobImpls[index];
|
||||||
|
|
||||||
blobImpl = CreateBlobImplFromParams(params, aMetadata);
|
blobImpl = CreateBlobImplFromBlobData(blobData, aMetadata);
|
||||||
if (NS_WARN_IF(!blobImpl)) {
|
if (NS_WARN_IF(!blobImpl)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1126,18 +1077,17 @@ CreateBlobImplFromParams(const MultiplexInputStreamParams& aParams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<FileImpl>
|
already_AddRefed<FileImpl>
|
||||||
CreateBlobImplFromParams(const ParentBlobConstructorParams& aParams,
|
CreateBlobImpl(const ParentBlobConstructorParams& aParams,
|
||||||
bool aIsSameProcessActor)
|
const BlobData& aBlobData,
|
||||||
|
bool aIsSameProcessActor)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
MOZ_ASSERT(aParams.blobParams().type() ==
|
MOZ_ASSERT(aParams.blobParams().type() ==
|
||||||
AnyBlobConstructorParams::TNormalBlobConstructorParams ||
|
AnyBlobConstructorParams::TNormalBlobConstructorParams ||
|
||||||
aParams.blobParams().type() ==
|
aParams.blobParams().type() ==
|
||||||
AnyBlobConstructorParams::TFileBlobConstructorParams);
|
AnyBlobConstructorParams::TFileBlobConstructorParams);
|
||||||
MOZ_ASSERT(aParams.optionalInputStreamParams().type() ==
|
|
||||||
OptionalInputStreamParams::TInputStreamParams);
|
|
||||||
|
|
||||||
CreateBlobImplMetadata metadata;
|
CreateBlobImplMetadata metadata(aIsSameProcessActor);
|
||||||
|
|
||||||
if (aParams.blobParams().type() ==
|
if (aParams.blobParams().type() ==
|
||||||
AnyBlobConstructorParams::TNormalBlobConstructorParams) {
|
AnyBlobConstructorParams::TNormalBlobConstructorParams) {
|
||||||
@ -1171,16 +1121,71 @@ CreateBlobImplFromParams(const ParentBlobConstructorParams& aParams,
|
|||||||
metadata.mLastModifiedDate = params.modDate();
|
metadata.mLastModifiedDate = params.modDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.mIsSameProcessActor = aIsSameProcessActor;
|
|
||||||
|
|
||||||
const InputStreamParams& inputStreamParams =
|
|
||||||
aParams.optionalInputStreamParams().get_InputStreamParams();
|
|
||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl =
|
nsRefPtr<FileImpl> blobImpl =
|
||||||
CreateBlobImplFromInputStreamParams(inputStreamParams, metadata);
|
CreateBlobImplFromBlobData(aBlobData, metadata);
|
||||||
return blobImpl.forget();
|
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
|
} // anonymous namespace
|
||||||
|
|
||||||
StaticAutoPtr<BlobParent::IDTable> BlobParent::sIDTable;
|
StaticAutoPtr<BlobParent::IDTable> BlobParent::sIDTable;
|
||||||
@ -1548,6 +1553,9 @@ protected:
|
|||||||
|
|
||||||
BlobChild* mActor;
|
BlobChild* mActor;
|
||||||
nsCOMPtr<nsIEventTarget> mActorTarget;
|
nsCOMPtr<nsIEventTarget> mActorTarget;
|
||||||
|
|
||||||
|
nsRefPtr<FileImpl> mSameProcessFileImpl;
|
||||||
|
|
||||||
const bool mIsSlice;
|
const bool mIsSlice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1563,6 +1571,20 @@ public:
|
|||||||
const nsAString& aContentType,
|
const nsAString& aContentType,
|
||||||
uint64_t aLength);
|
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.
|
// For mystery blobs.
|
||||||
explicit
|
explicit
|
||||||
RemoteBlobImpl(BlobChild* aActor);
|
RemoteBlobImpl(BlobChild* aActor);
|
||||||
@ -1853,6 +1875,38 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
|
|||||||
CommonInit(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::
|
BlobChild::
|
||||||
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
|
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
|
||||||
: FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
|
: FileImplBase(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX)
|
||||||
@ -1954,6 +2008,13 @@ RemoteBlobImpl::GetMozFullPathInternal(nsAString& aFilePath,
|
|||||||
MOZ_CRASH("Not implemented!");
|
MOZ_CRASH("Not implemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSameProcessFileImpl) {
|
||||||
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
|
|
||||||
|
mSameProcessFileImpl->GetMozFullPathInternal(aFilePath, aRv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mActor) {
|
if (!mActor) {
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
return;
|
return;
|
||||||
@ -1976,9 +2037,18 @@ RemoteBlobImpl::CreateSlice(uint64_t aStart,
|
|||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// May be called on any thread.
|
// May be called on any thread.
|
||||||
nsRefPtr<RemoteBlobSliceImpl> slice =
|
if (mSameProcessFileImpl) {
|
||||||
new RemoteBlobSliceImpl(this, aStart, aLength, aContentType);
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
return slice.forget();
|
|
||||||
|
return mSameProcessFileImpl->CreateSlice(aStart,
|
||||||
|
aLength,
|
||||||
|
aContentType,
|
||||||
|
aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<RemoteBlobSliceImpl> slice =
|
||||||
|
new RemoteBlobSliceImpl(this, aStart, aLength, aContentType);
|
||||||
|
return slice.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -1986,6 +2056,22 @@ BlobChild::
|
|||||||
RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream)
|
RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream)
|
||||||
{
|
{
|
||||||
// May be called on any thread.
|
// 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);
|
nsRefPtr<CreateStreamHelper> helper = new CreateStreamHelper(this);
|
||||||
return helper->GetStream(aStream);
|
return helper->GetStream(aStream);
|
||||||
}
|
}
|
||||||
@ -1998,6 +2084,12 @@ RemoteBlobImpl::GetFileId()
|
|||||||
MOZ_CRASH("Not implemented!");
|
MOZ_CRASH("Not implemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSameProcessFileImpl) {
|
||||||
|
MOZ_ASSERT(gProcessType == GeckoProcessType_Default);
|
||||||
|
|
||||||
|
return mSameProcessFileImpl->GetFileId();
|
||||||
|
}
|
||||||
|
|
||||||
int64_t fileId;
|
int64_t fileId;
|
||||||
if (mActor && mActor->SendGetFileId(&fileId)) {
|
if (mActor && mActor->SendGetFileId(&fileId)) {
|
||||||
return fileId;
|
return fileId;
|
||||||
@ -2209,8 +2301,7 @@ RemoteBlobSliceImpl::GetBlobChild()
|
|||||||
id /* id */,
|
id /* id */,
|
||||||
mStart /* begin */,
|
mStart /* begin */,
|
||||||
mStart + mLength /* end */,
|
mStart + mLength /* end */,
|
||||||
mContentType /* contentType */),
|
mContentType /* contentType */));
|
||||||
void_t() /* optionalInputStream */);
|
|
||||||
|
|
||||||
if (nsIContentChild* contentManager = baseActor->GetContentManager()) {
|
if (nsIContentChild* contentManager = baseActor->GetContentManager()) {
|
||||||
mActor = SendSliceConstructor(contentManager, this, params);
|
mActor = SendSliceConstructor(contentManager, this, params);
|
||||||
@ -2648,6 +2739,8 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
|||||||
|
|
||||||
AnyBlobConstructorParams::Type paramsType = blobParams.type();
|
AnyBlobConstructorParams::Type paramsType = blobParams.type();
|
||||||
MOZ_ASSERT(paramsType != AnyBlobConstructorParams::T__None &&
|
MOZ_ASSERT(paramsType != AnyBlobConstructorParams::T__None &&
|
||||||
|
paramsType !=
|
||||||
|
AnyBlobConstructorParams::TSlicedBlobConstructorParams &&
|
||||||
paramsType !=
|
paramsType !=
|
||||||
AnyBlobConstructorParams::TKnownBlobConstructorParams);
|
AnyBlobConstructorParams::TKnownBlobConstructorParams);
|
||||||
|
|
||||||
@ -2673,6 +2766,44 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
|
|||||||
break;
|
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: {
|
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
||||||
remoteBlob = new RemoteBlobImpl(this);
|
remoteBlob = new RemoteBlobImpl(this);
|
||||||
break;
|
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)))) {
|
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -2808,40 +2939,55 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
|
|||||||
|
|
||||||
AnyBlobConstructorParams blobParams;
|
AnyBlobConstructorParams blobParams;
|
||||||
|
|
||||||
nsString contentType;
|
nsCOMPtr<nsIInputStream> snapshotInputStream;
|
||||||
aBlobImpl->GetType(contentType);
|
|
||||||
|
|
||||||
ErrorResult rv;
|
if (gProcessType == GeckoProcessType_Default) {
|
||||||
uint64_t length = aBlobImpl->GetSize(rv);
|
nsCOMPtr<PIFileImplSnapshot> snapshot = do_QueryInterface(aBlobImpl);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
if (snapshot) {
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||||
nsCOMPtr<nsIInputStream> stream;
|
aBlobImpl->GetInternalStream(getter_AddRefs(snapshotInputStream))));
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
}
|
||||||
aBlobImpl->GetInternalStream(getter_AddRefs(stream))));
|
|
||||||
|
|
||||||
if (aBlobImpl->IsFile()) {
|
|
||||||
nsString name;
|
|
||||||
aBlobImpl->GetName(name);
|
|
||||||
|
|
||||||
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
|
||||||
MOZ_ASSERT(!rv.Failed());
|
|
||||||
|
|
||||||
blobParams = FileBlobConstructorParams(name, contentType, length, modDate);
|
|
||||||
} else {
|
|
||||||
blobParams = NormalBlobConstructorParams(contentType, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStreamParams inputStreamParams;
|
if (gProcessType == GeckoProcessType_Default && !snapshotInputStream) {
|
||||||
|
nsRefPtr<FileImpl> sameProcessImpl = aBlobImpl;
|
||||||
|
auto addRefedFileImpl =
|
||||||
|
reinterpret_cast<intptr_t>(sameProcessImpl.forget().take());
|
||||||
|
|
||||||
nsTArray<FileDescriptor> fds;
|
blobParams = SameProcessBlobConstructorParams(addRefedFileImpl);
|
||||||
SerializeInputStream(stream, inputStreamParams, fds);
|
} else {
|
||||||
|
BlobData blobData;
|
||||||
|
if (snapshotInputStream) {
|
||||||
|
blobData =
|
||||||
|
reinterpret_cast<intptr_t>(snapshotInputStream.forget().take());
|
||||||
|
} else {
|
||||||
|
BlobDataFromBlobImpl(aBlobImpl, blobData);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(inputStreamParams.type() != InputStreamParams::T__None);
|
nsString contentType;
|
||||||
MOZ_ASSERT(fds.IsEmpty());
|
aBlobImpl->GetType(contentType);
|
||||||
|
|
||||||
|
ErrorResult rv;
|
||||||
|
uint64_t length = aBlobImpl->GetSize(rv);
|
||||||
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
|
if (aBlobImpl->IsFile()) {
|
||||||
|
nsString name;
|
||||||
|
aBlobImpl->GetName(name);
|
||||||
|
|
||||||
|
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
||||||
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
|
blobParams =
|
||||||
|
FileBlobConstructorParams(name, contentType, length, modDate, blobData);
|
||||||
|
} else {
|
||||||
|
blobParams = NormalBlobConstructorParams(contentType, length, blobData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BlobChild* actor = new BlobChild(aManager, aBlobImpl);
|
BlobChild* actor = new BlobChild(aManager, aBlobImpl);
|
||||||
|
|
||||||
ParentBlobConstructorParams params(blobParams, inputStreamParams);
|
ParentBlobConstructorParams params(blobParams);
|
||||||
|
|
||||||
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
if (NS_WARN_IF(!aManager->SendPBlobConstructor(actor, params))) {
|
||||||
BlobChild::Destroy(actor);
|
BlobChild::Destroy(actor);
|
||||||
@ -2865,6 +3011,7 @@ BlobChild::CreateFromParams(ChildManagerType* aManager,
|
|||||||
switch (blobParams.type()) {
|
switch (blobParams.type()) {
|
||||||
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
||||||
case AnyBlobConstructorParams::TFileBlobConstructorParams:
|
case AnyBlobConstructorParams::TFileBlobConstructorParams:
|
||||||
|
case AnyBlobConstructorParams::TSameProcessBlobConstructorParams:
|
||||||
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
case AnyBlobConstructorParams::TMysteryBlobConstructorParams: {
|
||||||
return new BlobChild(aManager, aParams);
|
return new BlobChild(aManager, aParams);
|
||||||
}
|
}
|
||||||
@ -2896,8 +3043,6 @@ BlobChild::SendSliceConstructor(ChildManagerType* aManager,
|
|||||||
MOZ_ASSERT(aRemoteBlobSliceImpl);
|
MOZ_ASSERT(aRemoteBlobSliceImpl);
|
||||||
MOZ_ASSERT(aParams.blobParams().type() ==
|
MOZ_ASSERT(aParams.blobParams().type() ==
|
||||||
AnyBlobConstructorParams::TSlicedBlobConstructorParams);
|
AnyBlobConstructorParams::TSlicedBlobConstructorParams);
|
||||||
MOZ_ASSERT(aParams.optionalInputStreamParams().type() ==
|
|
||||||
OptionalInputStreamParams::Tvoid_t);
|
|
||||||
|
|
||||||
const nsID& id = aParams.blobParams().get_SlicedBlobConstructorParams().id();
|
const nsID& id = aParams.blobParams().get_SlicedBlobConstructorParams().id();
|
||||||
|
|
||||||
@ -2933,8 +3078,7 @@ BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|||||||
actor = new BlobChild(aManager, actor);
|
actor = new BlobChild(aManager, actor);
|
||||||
|
|
||||||
ParentBlobConstructorParams params(
|
ParentBlobConstructorParams params(
|
||||||
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
KnownBlobConstructorParams(actor->ParentID()));
|
||||||
void_t() /* optionalInputStream */);
|
|
||||||
|
|
||||||
aManager->SendPBlobConstructor(actor, params);
|
aManager->SendPBlobConstructor(actor, params);
|
||||||
|
|
||||||
@ -2963,8 +3107,7 @@ BlobChild::MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
|
|||||||
actor = new BlobChild(aManager, actor);
|
actor = new BlobChild(aManager, actor);
|
||||||
|
|
||||||
ParentBlobConstructorParams params(
|
ParentBlobConstructorParams params(
|
||||||
KnownBlobConstructorParams(actor->ParentID()) /* blobParams */,
|
KnownBlobConstructorParams(actor->ParentID()));
|
||||||
void_t() /* optionalInputStream */);
|
|
||||||
|
|
||||||
aManager->SendPBlobConstructor(actor, params);
|
aManager->SendPBlobConstructor(actor, params);
|
||||||
|
|
||||||
@ -3019,8 +3162,11 @@ BlobChild::SetMysteryBlobInfo(const nsString& aName,
|
|||||||
|
|
||||||
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
|
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
|
||||||
|
|
||||||
FileBlobConstructorParams params(aName, aContentType, aLength,
|
FileBlobConstructorParams params(aName,
|
||||||
aLastModifiedDate);
|
aContentType,
|
||||||
|
aLength,
|
||||||
|
aLastModifiedDate,
|
||||||
|
void_t() /* optionalBlobData */);
|
||||||
return SendResolveMystery(params);
|
return SendResolveMystery(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3036,7 +3182,9 @@ BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
|
|||||||
|
|
||||||
mBlobImpl->SetLazyData(voidString, aContentType, aLength, UINT64_MAX);
|
mBlobImpl->SetLazyData(voidString, aContentType, aLength, UINT64_MAX);
|
||||||
|
|
||||||
NormalBlobConstructorParams params(aContentType, aLength);
|
NormalBlobConstructorParams params(aContentType,
|
||||||
|
aLength,
|
||||||
|
void_t() /* optionalBlobData */);
|
||||||
return SendResolveMystery(params);
|
return SendResolveMystery(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3326,37 +3474,56 @@ 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)))) {
|
if (NS_WARN_IF(NS_FAILED(aBlobImpl->SetMutable(false)))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isSameProcessActor = ActorManagerIsSameProcess(aManager);
|
||||||
|
|
||||||
AnyBlobConstructorParams blobParams;
|
AnyBlobConstructorParams blobParams;
|
||||||
|
|
||||||
if (aBlobImpl->IsSizeUnknown() || aBlobImpl->IsDateUnknown()) {
|
bool isSnapshot;
|
||||||
// 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
|
if (isSameProcessActor) {
|
||||||
// the other side.
|
nsCOMPtr<PIFileImplSnapshot> snapshot = do_QueryInterface(aBlobImpl);
|
||||||
blobParams = MysteryBlobConstructorParams();
|
isSnapshot = !!snapshot;
|
||||||
} else {
|
} else {
|
||||||
nsString contentType;
|
isSnapshot = false;
|
||||||
aBlobImpl->GetType(contentType);
|
}
|
||||||
|
|
||||||
ErrorResult rv;
|
if (isSameProcessActor && !isSnapshot) {
|
||||||
uint64_t length = aBlobImpl->GetSize(rv);
|
nsRefPtr<FileImpl> sameProcessImpl = aBlobImpl;
|
||||||
MOZ_ASSERT(!rv.Failed());
|
auto addRefedFileImpl =
|
||||||
|
reinterpret_cast<intptr_t>(sameProcessImpl.forget().take());
|
||||||
|
|
||||||
if (aBlobImpl->IsFile()) {
|
blobParams = SameProcessBlobConstructorParams(addRefedFileImpl);
|
||||||
nsString name;
|
} else {
|
||||||
aBlobImpl->GetName(name);
|
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.
|
||||||
|
blobParams = MysteryBlobConstructorParams();
|
||||||
|
} else {
|
||||||
|
nsString contentType;
|
||||||
|
aBlobImpl->GetType(contentType);
|
||||||
|
|
||||||
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
ErrorResult rv;
|
||||||
|
uint64_t length = aBlobImpl->GetSize(rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
blobParams =
|
if (aBlobImpl->IsFile()) {
|
||||||
FileBlobConstructorParams(name, contentType, length, modDate);
|
nsString name;
|
||||||
} else {
|
aBlobImpl->GetName(name);
|
||||||
blobParams = NormalBlobConstructorParams(contentType, length);
|
|
||||||
|
uint64_t modDate = aBlobImpl->GetLastModified(rv);
|
||||||
|
MOZ_ASSERT(!rv.Failed());
|
||||||
|
|
||||||
|
blobParams =
|
||||||
|
FileBlobConstructorParams(name, contentType, length, modDate, void_t());
|
||||||
|
} else {
|
||||||
|
blobParams = NormalBlobConstructorParams(contentType, length, void_t());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3397,14 +3564,21 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
|||||||
|
|
||||||
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
case AnyBlobConstructorParams::TNormalBlobConstructorParams:
|
||||||
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
case AnyBlobConstructorParams::TFileBlobConstructorParams: {
|
||||||
if (aParams.optionalInputStreamParams().type() !=
|
const OptionalBlobData& optionalBlobData =
|
||||||
OptionalInputStreamParams::TInputStreamParams) {
|
blobParams.type() ==
|
||||||
|
AnyBlobConstructorParams::TNormalBlobConstructorParams ?
|
||||||
|
blobParams.get_NormalBlobConstructorParams().optionalBlobData() :
|
||||||
|
blobParams.get_FileBlobConstructorParams().optionalBlobData();
|
||||||
|
|
||||||
|
if (NS_WARN_IF(optionalBlobData.type() != OptionalBlobData::TBlobData)) {
|
||||||
ASSERT_UNLESS_FUZZING();
|
ASSERT_UNLESS_FUZZING();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<FileImpl> blobImpl =
|
nsRefPtr<FileImpl> blobImpl =
|
||||||
CreateBlobImplFromParams(aParams, ActorManagerIsSameProcess(aManager));
|
CreateBlobImpl(aParams,
|
||||||
|
optionalBlobData.get_BlobData(),
|
||||||
|
ActorManagerIsSameProcess(aManager));
|
||||||
if (NS_WARN_IF(!blobImpl)) {
|
if (NS_WARN_IF(!blobImpl)) {
|
||||||
ASSERT_UNLESS_FUZZING();
|
ASSERT_UNLESS_FUZZING();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -3424,12 +3598,6 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AnyBlobConstructorParams::TSlicedBlobConstructorParams: {
|
case AnyBlobConstructorParams::TSlicedBlobConstructorParams: {
|
||||||
if (aParams.optionalInputStreamParams().type() !=
|
|
||||||
OptionalInputStreamParams::Tvoid_t) {
|
|
||||||
ASSERT_UNLESS_FUZZING();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SlicedBlobConstructorParams& params =
|
const SlicedBlobConstructorParams& params =
|
||||||
blobParams.get_SlicedBlobConstructorParams();
|
blobParams.get_SlicedBlobConstructorParams();
|
||||||
|
|
||||||
@ -3472,12 +3640,6 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
case AnyBlobConstructorParams::TKnownBlobConstructorParams: {
|
||||||
if (aParams.optionalInputStreamParams().type() !=
|
|
||||||
OptionalInputStreamParams::Tvoid_t) {
|
|
||||||
ASSERT_UNLESS_FUZZING();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const KnownBlobConstructorParams& params =
|
const KnownBlobConstructorParams& params =
|
||||||
blobParams.get_KnownBlobConstructorParams();
|
blobParams.get_KnownBlobConstructorParams();
|
||||||
|
|
||||||
@ -3494,6 +3656,29 @@ BlobParent::CreateFromParams(ParentManagerType* aManager,
|
|||||||
return new BlobParent(aManager, blobImpl, idTableEntry);
|
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:
|
default:
|
||||||
MOZ_CRASH("Unknown params!");
|
MOZ_CRASH("Unknown params!");
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
include protocol PBlob;
|
include protocol PBlob;
|
||||||
include InputStreamParams;
|
|
||||||
|
|
||||||
using struct mozilla::void_t
|
using struct mozilla::void_t
|
||||||
from "ipc/IPCMessageUtils.h";
|
from "ipc/IPCMessageUtils.h";
|
||||||
@ -13,6 +12,9 @@ using struct mozilla::void_t
|
|||||||
using struct mozilla::SerializedStructuredCloneBuffer
|
using struct mozilla::SerializedStructuredCloneBuffer
|
||||||
from "ipc/IPCMessageUtils.h";
|
from "ipc/IPCMessageUtils.h";
|
||||||
|
|
||||||
|
using struct nsID
|
||||||
|
from "nsID.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
@ -28,10 +30,35 @@ struct ClonedMessageData
|
|||||||
PBlob[] blobs;
|
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
|
struct NormalBlobConstructorParams
|
||||||
{
|
{
|
||||||
nsString contentType;
|
nsString contentType;
|
||||||
uint64_t length;
|
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
|
struct FileBlobConstructorParams
|
||||||
@ -40,6 +67,10 @@ struct FileBlobConstructorParams
|
|||||||
nsString contentType;
|
nsString contentType;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
uint64_t modDate;
|
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
|
struct SlicedBlobConstructorParams
|
||||||
@ -61,11 +92,20 @@ struct KnownBlobConstructorParams
|
|||||||
nsID id;
|
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
|
union AnyBlobConstructorParams
|
||||||
{
|
{
|
||||||
// These types may be sent to/from parent and child.
|
// These types may be sent to/from parent and child.
|
||||||
NormalBlobConstructorParams;
|
NormalBlobConstructorParams;
|
||||||
FileBlobConstructorParams;
|
FileBlobConstructorParams;
|
||||||
|
SameProcessBlobConstructorParams;
|
||||||
|
|
||||||
// This type may only be sent from parent to child.
|
// This type may only be sent from parent to child.
|
||||||
MysteryBlobConstructorParams;
|
MysteryBlobConstructorParams;
|
||||||
@ -87,14 +127,6 @@ struct ParentBlobConstructorParams
|
|||||||
{
|
{
|
||||||
// May not be MysteryBlobConstructorParams.
|
// May not be MysteryBlobConstructorParams.
|
||||||
AnyBlobConstructorParams blobParams;
|
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
|
union BlobConstructorParams
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 PBlob;
|
||||||
include protocol PFileDescriptorSet;
|
include protocol PFileDescriptorSet;
|
||||||
|
|
||||||
using struct nsID
|
include DOMTypes;
|
||||||
from "nsID.h";
|
|
||||||
|
using struct mozilla::void_t
|
||||||
|
from "ipc/IPCMessageUtils.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
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/PrivateBrowsingUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
Cu.importGlobalProperties(["File"]);
|
||||||
|
|
||||||
// Allow stuff from this scope to be accessed from non-privileged scopes. This
|
// Allow stuff from this scope to be accessed from non-privileged scopes. This
|
||||||
// would crash if used outside of automation.
|
// would crash if used outside of automation.
|
||||||
Cu.forcePermissiveCOWs();
|
Cu.forcePermissiveCOWs();
|
||||||
@ -1877,6 +1879,10 @@ SpecialPowersAPI.prototype = {
|
|||||||
let msg = { op: op, uri: uri, appId: appId, inBrowser: inBrowser, id: id };
|
let msg = { op: op, uri: uri, appId: appId, inBrowser: inBrowser, id: id };
|
||||||
this._sendAsyncMessage(messageTopic, msg);
|
this._sendAsyncMessage(messageTopic, msg);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createDOMFile: function(path, options) {
|
||||||
|
return new File(path, options);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
this.SpecialPowersAPI = SpecialPowersAPI;
|
this.SpecialPowersAPI = SpecialPowersAPI;
|
||||||
|
Loading…
Reference in New Issue
Block a user