mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1167730 - Make nsTemporaryFileStream serializable. r=baku
This commit is contained in:
parent
4d94ead59d
commit
ee501c8947
20
dom/ipc/tests/blob_verify.sjs
Normal file
20
dom/ipc/tests/blob_verify.sjs
Normal file
@ -0,0 +1,20 @@
|
||||
const CC = Components.Constructor;
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
|
||||
"nsIBinaryOutputStream",
|
||||
"setOutputStream");
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var bodyStream = new BinaryInputStream(request.bodyInputStream);
|
||||
var bodyBytes = [];
|
||||
while ((bodyAvail = bodyStream.available()) > 0)
|
||||
Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
|
||||
|
||||
var bos = new BinaryOutputStream(response.bodyOutputStream);
|
||||
|
||||
response.processAsync();
|
||||
bos.writeByteArray(bodyBytes, bodyBytes.length);
|
||||
response.finish();
|
||||
}
|
@ -53,3 +53,7 @@ support-files =
|
||||
test_permission_helper.js
|
||||
test_permission_embed.html
|
||||
test_permission_framescript.js
|
||||
[test_temporaryfile_stream.html]
|
||||
support-files =
|
||||
blob_verify.sjs
|
||||
!/dom/canvas/test/captureStream_common.js
|
80
dom/ipc/tests/test_temporaryfile_stream.html
Normal file
80
dom/ipc/tests/test_temporaryfile_stream.html
Normal file
@ -0,0 +1,80 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Send an nsTemporaryFileInputStream cross-process</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/dom/canvas/test/captureStream_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<div id="content">
|
||||
</div>
|
||||
<script class="testbody" type="text/javascript">
|
||||
function startTest() {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = canvas.height = 100;
|
||||
document.getElementById("content").appendChild(canvas);
|
||||
|
||||
var helper = new CaptureStreamTestHelper2D(100, 100);
|
||||
helper.drawColor(canvas, helper.red);
|
||||
|
||||
var stream = canvas.captureStream(0);
|
||||
|
||||
var blob;
|
||||
|
||||
mediaRecorder = new MediaRecorder(stream);
|
||||
is(mediaRecorder.stream, stream,
|
||||
"Media recorder stream = canvas stream at the start of recording");
|
||||
|
||||
mediaRecorder.onwarning = () => ok(false, "warning unexpectedly fired");
|
||||
|
||||
mediaRecorder.onerror = () => ok(false, "Recording failed");
|
||||
|
||||
mediaRecorder.ondataavailable = ev => {
|
||||
is(blob, undefined, "Should only get one dataavailable event");
|
||||
blob = ev.data;
|
||||
};
|
||||
|
||||
mediaRecorder.onstart = () => {
|
||||
info("Got 'start' event");
|
||||
// We just want one frame encoded, to see that the recorder produces something readable.
|
||||
mediaRecorder.stop();
|
||||
};
|
||||
|
||||
mediaRecorder.onstop = () => {
|
||||
info("Got 'stop' event");
|
||||
ok(blob, "Should have gotten a data blob");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'blob_verify.sjs', true);
|
||||
xhr.onload = () => {
|
||||
var video = document.createElement("video");
|
||||
video.id = "recorded-video";
|
||||
video.src = URL.createObjectURL(xhr.response);
|
||||
video.play();
|
||||
video.onerror = err => {
|
||||
ok(false, "Should be able to play the recording. Got error. code=" + video.error.code);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
document.getElementById("content").appendChild(video);
|
||||
helper.waitForPixelColor(video, helper.red, 128, "Should become red")
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
ok(false, "XHR error");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
xhr.responseType = "blob";
|
||||
xhr.send(blob);
|
||||
};
|
||||
|
||||
mediaRecorder.start();
|
||||
is(mediaRecorder.state, "recording", "Media recorder should be recording");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({set:[["media.recorder.max_memory", 1]]}, startTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -30,6 +30,13 @@ struct PartialFileInputStreamParams
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
struct TemporaryFileInputStreamParams
|
||||
{
|
||||
uint32_t fileDescriptorIndex;
|
||||
uint64_t startPos;
|
||||
uint64_t endPos;
|
||||
};
|
||||
|
||||
struct MultiplexInputStreamParams
|
||||
{
|
||||
InputStreamParams[] streams;
|
||||
@ -56,6 +63,7 @@ union InputStreamParams
|
||||
StringInputStreamParams;
|
||||
FileInputStreamParams;
|
||||
PartialFileInputStreamParams;
|
||||
TemporaryFileInputStreamParams;
|
||||
BufferedInputStreamParams;
|
||||
MIMEInputStreamParams;
|
||||
MultiplexInputStreamParams;
|
||||
|
@ -93,6 +93,10 @@ DeserializeInputStream(const InputStreamParams& aParams,
|
||||
serializable = do_CreateInstance(kPartialFileInputStreamCID);
|
||||
break;
|
||||
|
||||
case InputStreamParams::TTemporaryFileInputStreamParams:
|
||||
serializable = new nsTemporaryFileInputStream();
|
||||
break;
|
||||
|
||||
case InputStreamParams::TBufferedInputStreamParams:
|
||||
serializable = do_CreateInstance(kBufferedInputStreamCID);
|
||||
break;
|
||||
|
@ -7,7 +7,12 @@
|
||||
#include "nsStreamUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsTemporaryFileInputStream, nsIInputStream, nsISeekableStream)
|
||||
typedef mozilla::ipc::FileDescriptor::PlatformHandleType FileHandleType;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsTemporaryFileInputStream,
|
||||
nsIInputStream,
|
||||
nsISeekableStream,
|
||||
nsIIPCSerializableInputStream)
|
||||
|
||||
nsTemporaryFileInputStream::nsTemporaryFileInputStream(FileDescOwner* aFileDescOwner, uint64_t aStartPos, uint64_t aEndPos)
|
||||
: mFileDescOwner(aFileDescOwner),
|
||||
@ -19,6 +24,14 @@ nsTemporaryFileInputStream::nsTemporaryFileInputStream(FileDescOwner* aFileDescO
|
||||
NS_ASSERTION(aStartPos <= aEndPos, "StartPos should less equal than EndPos!");
|
||||
}
|
||||
|
||||
nsTemporaryFileInputStream::nsTemporaryFileInputStream()
|
||||
: mStartPos(0),
|
||||
mCurPos(0),
|
||||
mEndPos(0),
|
||||
mClosed(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTemporaryFileInputStream::Close()
|
||||
{
|
||||
@ -164,3 +177,65 @@ nsTemporaryFileInputStream::SetEOF()
|
||||
|
||||
return Close();
|
||||
}
|
||||
|
||||
void
|
||||
nsTemporaryFileInputStream::Serialize(InputStreamParams& aParams,
|
||||
FileDescriptorArray& aFileDescriptors)
|
||||
{
|
||||
TemporaryFileInputStreamParams params;
|
||||
|
||||
MutexAutoLock lock(mFileDescOwner->FileMutex());
|
||||
MOZ_ASSERT(mFileDescOwner->mFD);
|
||||
if (!mClosed) {
|
||||
FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFileDescOwner->mFD));
|
||||
NS_ASSERTION(fd, "This should never be null!");
|
||||
|
||||
DebugOnly<FileDescriptor*> dbgFD = aFileDescriptors.AppendElement(fd);
|
||||
NS_ASSERTION(dbgFD->IsValid(), "Sending an invalid file descriptor!");
|
||||
|
||||
params.fileDescriptorIndex() = aFileDescriptors.Length() - 1;
|
||||
|
||||
Close();
|
||||
} else {
|
||||
NS_WARNING("The stream is already closed. "
|
||||
"Sending an invalid file descriptor to the other process!");
|
||||
|
||||
params.fileDescriptorIndex() = UINT32_MAX;
|
||||
}
|
||||
params.startPos() = mCurPos;
|
||||
params.endPos() = mEndPos;
|
||||
aParams = params;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemporaryFileInputStream::Deserialize(const InputStreamParams& aParams,
|
||||
const FileDescriptorArray& aFileDescriptors)
|
||||
{
|
||||
const TemporaryFileInputStreamParams& params = aParams.get_TemporaryFileInputStreamParams();
|
||||
|
||||
uint32_t fileDescriptorIndex = params.fileDescriptorIndex();
|
||||
FileDescriptor fd;
|
||||
if (fileDescriptorIndex < aFileDescriptors.Length()) {
|
||||
fd = aFileDescriptors[fileDescriptorIndex];
|
||||
NS_WARNING_ASSERTION(fd.IsValid(),
|
||||
"Received an invalid file descriptor!");
|
||||
} else {
|
||||
NS_WARNING("Received a bad file descriptor index!");
|
||||
}
|
||||
|
||||
if (fd.IsValid()) {
|
||||
auto rawFD = fd.ClonePlatformHandle();
|
||||
PRFileDesc* fileDesc = PR_ImportFile(PROsfd(rawFD.release()));
|
||||
if (!fileDesc) {
|
||||
NS_WARNING("Failed to import file handle!");
|
||||
return false;
|
||||
}
|
||||
mFileDescOwner = new FileDescOwner(fileDesc);
|
||||
} else {
|
||||
mClosed = true;
|
||||
}
|
||||
|
||||
mStartPos = mCurPos = params.startPos();
|
||||
mEndPos = params.endPos();
|
||||
return true;
|
||||
}
|
||||
|
@ -9,11 +9,13 @@
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "prio.h"
|
||||
|
||||
class nsTemporaryFileInputStream : public nsIInputStream
|
||||
, public nsISeekableStream
|
||||
, public nsIIPCSerializableInputStream
|
||||
{
|
||||
public:
|
||||
//used to release a PRFileDesc
|
||||
@ -42,10 +44,12 @@ public:
|
||||
};
|
||||
|
||||
nsTemporaryFileInputStream(FileDescOwner* aFileDescOwner, uint64_t aStartPos, uint64_t aEndPos);
|
||||
nsTemporaryFileInputStream();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIINPUTSTREAM
|
||||
NS_DECL_NSISEEKABLESTREAM
|
||||
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
|
||||
|
||||
private:
|
||||
virtual ~nsTemporaryFileInputStream() { }
|
||||
|
Loading…
Reference in New Issue
Block a user