зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
c0dfa196ce
Коммит
931c1560cf
|
@ -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);
|
||||
|
||||
// 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))) {
|
||||
if (params.type() == InputStreamParams::T__None) {
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче