1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "mozilla/ipc/SendStream.h"
#include "mozilla/Unused.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIPipe.h"
namespace mozilla {
namespace ipc {
namespace {
class SendStreamParentImpl final : public SendStreamParent
{
public:
SendStreamParentImpl(nsIAsyncInputStream* aReader,
nsIAsyncOutputStream* aWriter);
~SendStreamParentImpl();
private:
// PSendStreamParentImpl methods
virtual void
ActorDestroy(ActorDestroyReason aReason) override;
// SendStreamparent methods
already_AddRefed<nsIInputStream>
TakeReader() override;
virtual bool
RecvBuffer(const nsCString& aBuffer) override;
virtual bool
RecvClose(const nsresult& aRv) override;
nsCOMPtr<nsIAsyncInputStream> mReader;
nsCOMPtr<nsIAsyncOutputStream> mWriter;
NS_DECL_OWNINGTHREAD
};
SendStreamParentImpl::~SendStreamParentImpl()
{
}
already_AddRefed<nsIInputStream>
SendStreamParentImpl::TakeReader()
{
MOZ_ASSERT(mReader);
return mReader.forget();
}
void
SendStreamParentImpl::ActorDestroy(ActorDestroyReason aReason)
{
// If we were gracefully closed we should have gotten RecvClose(). In
// that case, the writer will already be closed and this will have no
// effect. This just aborts the writer in the case where the child process
// crashes.
mWriter->CloseWithStatus(NS_ERROR_ABORT);
}
bool
SendStreamParentImpl::RecvBuffer(const nsCString& aBuffer)
{
uint32_t numWritten = 0;
// This should only fail if we hit an OOM condition.
nsresult rv = mWriter->Write(aBuffer.get(), aBuffer.Length(), &numWritten);
if (NS_WARN_IF(NS_FAILED(rv))) {
Unused << SendRequestClose(rv);
}
return true;
}
bool
SendStreamParentImpl::RecvClose(const nsresult& aRv)
{
mWriter->CloseWithStatus(aRv);
Unused << Send__delete__(this);
return true;
}
SendStreamParentImpl::SendStreamParentImpl(nsIAsyncInputStream* aReader,
nsIAsyncOutputStream* aWriter)
: mReader(aReader)
, mWriter(aWriter)
{
MOZ_ASSERT(mReader);
MOZ_ASSERT(mWriter);
}
} // anonymous namespace
SendStreamParent::~SendStreamParent()
{
}
PSendStreamParent*
AllocPSendStreamParent()
{
// use async versions for both reader and writer even though we are
// opening the writer as an infinite stream. We want to be able to
// use CloseWithStatus() to communicate errors through the pipe.
nsCOMPtr<nsIAsyncInputStream> reader;
nsCOMPtr<nsIAsyncOutputStream> writer;
// Use an "infinite" pipe because we cannot apply back-pressure through
// the async IPC layer at the moment. Blocking the IPC worker thread
// is not desirable, either.
nsresult rv = NS_NewPipe2(getter_AddRefs(reader),
getter_AddRefs(writer),
true, true, // non-blocking
0, // segment size
UINT32_MAX); // "infinite" pipe
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return new SendStreamParentImpl(reader, writer);
}
void
DeallocPSendStreamParent(PSendStreamParent* aActor)
{
delete aActor;
}
} // namespace ipc
} // namespace mozilla
|