Bug 1520150 - Single InputStreams can serialize themselves as IPCRemoteStreams (pipe) - part 3 - pipe for string and storage streams, r=smaug

This commit is contained in:
Andrea Marchesini 2019-01-28 10:49:28 +01:00
Родитель c0dfa196ce
Коммит 931c1560cf
5 изменённых файлов: 84 добавлений и 40 удалений

Просмотреть файл

@ -100,44 +100,15 @@ bool SerializeInputStream(nsIInputStream* aStream, IPCStream& aValue,
MOZ_ASSERT(aStream);
MOZ_ASSERT(aManager);
// Let's try to take the length using InputStreamLengthHelper. If the length
// cannot be taken synchronously, and its length is needed, the stream needs
// to be fully copied in memory on the deserialization side.
int64_t length;
if (!InputStreamLengthHelper::GetSyncLength(aStream, &length)) {
length = -1;
InputStreamParams params;
InputStreamHelper::SerializeInputStreamAsPipe(aStream, params, aDelayedStart,
aManager);
if (params.type() == InputStreamParams::T__None) {
return false;
}
// As a fallback, attempt to stream the data across using a IPCStream
// actor. For blocking streams, create a nonblocking pipe instead,
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
if (!asyncStream) {
const uint32_t kBufferSize = 32768; // matches IPCStream buffer size.
nsCOMPtr<nsIAsyncOutputStream> sink;
nsresult rv = NS_NewPipe2(getter_AddRefs(asyncStream), getter_AddRefs(sink),
true, false, kBufferSize, UINT32_MAX);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
rv = NS_AsyncCopy(aStream, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
kBufferSize);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
}
MOZ_ASSERT(asyncStream);
IPCRemoteStreamParams remoteStream;
remoteStream.delayedStart() = aDelayedStart;
remoteStream.stream() = IPCStreamSource::Create(asyncStream, aManager);
remoteStream.length() = length;
aValue.stream() = remoteStream;
aValue.stream() = params;
aValue.optionalFds() = void_t();
return true;

Просмотреть файл

@ -70,6 +70,49 @@ void SerializeInputStreamInternal(nsIInputStream* aInputStream,
}
}
template <typename M>
void SerializeInputStreamAsPipeInternal(nsIInputStream* aInputStream,
InputStreamParams& aParams,
bool aDelayedStart, M* aManager) {
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aManager);
// Let's try to take the length using InputStreamLengthHelper. If the length
// cannot be taken synchronously, and its length is needed, the stream needs
// to be fully copied in memory on the deserialization side.
int64_t length;
if (!InputStreamLengthHelper::GetSyncLength(aInputStream, &length)) {
length = -1;
}
// As a fallback, attempt to stream the data across using a IPCStream
// actor. For blocking streams, create a nonblocking pipe instead,
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aInputStream);
if (!asyncStream) {
const uint32_t kBufferSize = 32768; // matches IPCStream buffer size.
nsCOMPtr<nsIAsyncOutputStream> sink;
nsresult rv = NS_NewPipe2(getter_AddRefs(asyncStream), getter_AddRefs(sink),
true, false, kBufferSize, UINT32_MAX);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
rv = NS_AsyncCopy(aInputStream, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
kBufferSize);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
MOZ_ASSERT(asyncStream);
aParams = IPCRemoteStreamParams(
aDelayedStart, IPCStreamSource::Create(asyncStream, aManager), length);
}
} // namespace
void InputStreamHelper::SerializeInputStream(

Просмотреть файл

@ -51,6 +51,26 @@ class InputStreamHelper {
bool aDelayedStart,
PBackgroundParent* aManager);
// When a stream wants to serialize itself as IPCRemoteStream, it uses one of
// these methods.
static void SerializeInputStreamAsPipe(
nsIInputStream* aInputStream, InputStreamParams& aParams,
bool aDelayedStart, mozilla::dom::nsIContentChild* aManager);
static void SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
InputStreamParams& aParams,
bool aDelayedStart,
PBackgroundChild* aManager);
static void SerializeInputStreamAsPipe(
nsIInputStream* aInputStream, InputStreamParams& aParams,
bool aDelayedStart, mozilla::dom::nsIContentParent* aManager);
static void SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
InputStreamParams& aParams,
bool aDelayedStart,
PBackgroundParent* aManager);
// After the sending of the inputStream into the IPC pipe, some of the
// InputStreamParams data struct needs to be activated (IPCRemoteStream).
// These 2 methods do that.

Просмотреть файл

@ -581,8 +581,13 @@ void nsStorageInputStream::SerializeInternal(InputStreamParams& aParams,
nsresult rv = Available(&remaining);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (remaining > 0) {
// TODO
// If the string is known to be larger than 1MB, prefer sending it in chunks.
const uint64_t kTooLargeStream = 1024 * 1024;
if (remaining > kTooLargeStream) {
InputStreamHelper::SerializeInputStreamAsPipe(this, aParams, aDelayedStart,
aManager);
return;
}
nsCString combined;

Просмотреть файл

@ -346,8 +346,13 @@ void nsStringInputStream::Serialize(InputStreamParams& aParams,
template <typename M>
void nsStringInputStream::SerializeInternal(InputStreamParams& aParams,
bool aDelayedStart, M* aManager) {
if (Length() > 0) {
// TODO
// If the string is known to be larger than 1MB, prefer sending it in chunks.
const uint64_t kTooLargeStream = 1024 * 1024;
if (Length() > kTooLargeStream) {
InputStreamHelper::SerializeInputStreamAsPipe(this, aParams, aDelayedStart,
aManager);
return;
}
StringInputStreamParams params;