/src/mozilla-central/dom/file/ipc/IPCBlobInputStreamParent.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "IPCBlobInputStreamParent.h" |
8 | | #include "IPCBlobInputStreamStorage.h" |
9 | | #include "mozilla/ipc/IPCStreamUtils.h" |
10 | | #include "mozilla/InputStreamLengthHelper.h" |
11 | | #include "nsContentUtils.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace dom { |
15 | | |
16 | | template<typename M> |
17 | | /* static */ already_AddRefed<IPCBlobInputStreamParent> |
18 | | IPCBlobInputStreamParent::Create(nsIInputStream* aInputStream, uint64_t aSize, |
19 | | uint64_t aChildID, nsresult* aRv, M* aManager) |
20 | 0 | { |
21 | 0 | MOZ_ASSERT(aInputStream); |
22 | 0 | MOZ_ASSERT(aRv); |
23 | 0 |
|
24 | 0 | nsID id; |
25 | 0 | *aRv = nsContentUtils::GenerateUUIDInPlace(id); |
26 | 0 | if (NS_WARN_IF(NS_FAILED(*aRv))) { |
27 | 0 | return nullptr; |
28 | 0 | } |
29 | 0 | |
30 | 0 | IPCBlobInputStreamStorage::Get()->AddStream(aInputStream, id, aSize, aChildID); |
31 | 0 |
|
32 | 0 | RefPtr<IPCBlobInputStreamParent> parent = |
33 | 0 | new IPCBlobInputStreamParent(id, aSize, aManager); |
34 | 0 | return parent.forget(); |
35 | 0 | } Unexecuted instantiation: already_AddRefed<mozilla::dom::IPCBlobInputStreamParent> mozilla::dom::IPCBlobInputStreamParent::Create<mozilla::dom::nsIContentParent>(nsIInputStream*, unsigned long, unsigned long, nsresult*, mozilla::dom::nsIContentParent*) Unexecuted instantiation: already_AddRefed<mozilla::dom::IPCBlobInputStreamParent> mozilla::dom::IPCBlobInputStreamParent::Create<mozilla::ipc::PBackgroundParent>(nsIInputStream*, unsigned long, unsigned long, nsresult*, mozilla::ipc::PBackgroundParent*) |
36 | | |
37 | | /* static */ already_AddRefed<IPCBlobInputStreamParent> |
38 | | IPCBlobInputStreamParent::Create(const nsID& aID, uint64_t aSize, |
39 | | PBackgroundParent* aManager) |
40 | 0 | { |
41 | 0 | RefPtr<IPCBlobInputStreamParent> actor = |
42 | 0 | new IPCBlobInputStreamParent(aID, aSize, aManager); |
43 | 0 |
|
44 | 0 | actor->mCallback = IPCBlobInputStreamStorage::Get()->TakeCallback(aID); |
45 | 0 |
|
46 | 0 | return actor.forget(); |
47 | 0 | } |
48 | | |
49 | | IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID, |
50 | | uint64_t aSize, |
51 | | nsIContentParent* aManager) |
52 | | : mID(aID) |
53 | | , mSize(aSize) |
54 | | , mContentManager(aManager) |
55 | | , mPBackgroundManager(nullptr) |
56 | | , mMigrating(false) |
57 | 0 | {} |
58 | | |
59 | | IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID, |
60 | | uint64_t aSize, |
61 | | PBackgroundParent* aManager) |
62 | | : mID(aID) |
63 | | , mSize(aSize) |
64 | | , mContentManager(nullptr) |
65 | | , mPBackgroundManager(aManager) |
66 | | , mMigrating(false) |
67 | 0 | {} |
68 | | |
69 | | void |
70 | | IPCBlobInputStreamParent::ActorDestroy(IProtocol::ActorDestroyReason aReason) |
71 | 0 | { |
72 | 0 | MOZ_ASSERT(mContentManager || mPBackgroundManager); |
73 | 0 |
|
74 | 0 | mContentManager = nullptr; |
75 | 0 | mPBackgroundManager = nullptr; |
76 | 0 |
|
77 | 0 | RefPtr<IPCBlobInputStreamParentCallback> callback; |
78 | 0 | mCallback.swap(callback); |
79 | 0 |
|
80 | 0 | RefPtr<IPCBlobInputStreamStorage> storage = IPCBlobInputStreamStorage::Get(); |
81 | 0 |
|
82 | 0 | if (mMigrating) { |
83 | 0 | if (callback && storage) { |
84 | 0 | // We need to assign this callback to the next parent. |
85 | 0 | IPCBlobInputStreamStorage::Get()->StoreCallback(mID, callback); |
86 | 0 | } |
87 | 0 | return; |
88 | 0 | } |
89 | 0 |
|
90 | 0 | if (storage) { |
91 | 0 | storage->ForgetStream(mID); |
92 | 0 | } |
93 | 0 |
|
94 | 0 | if (callback) { |
95 | 0 | callback->ActorDestroyed(mID); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | void |
100 | | IPCBlobInputStreamParent::SetCallback( |
101 | | IPCBlobInputStreamParentCallback* aCallback) |
102 | 0 | { |
103 | 0 | MOZ_ASSERT(aCallback); |
104 | 0 | MOZ_ASSERT(!mCallback); |
105 | 0 |
|
106 | 0 | mCallback = aCallback; |
107 | 0 | } |
108 | | |
109 | | mozilla::ipc::IPCResult |
110 | | IPCBlobInputStreamParent::RecvStreamNeeded() |
111 | 0 | { |
112 | 0 | MOZ_ASSERT(mContentManager || mPBackgroundManager); |
113 | 0 |
|
114 | 0 | nsCOMPtr<nsIInputStream> stream; |
115 | 0 | IPCBlobInputStreamStorage::Get()->GetStream(mID, 0, mSize, getter_AddRefs(stream)); |
116 | 0 | if (!stream) { |
117 | 0 | if (!SendStreamReady(void_t())) { |
118 | 0 | return IPC_FAIL(this, "SendStreamReady failed"); |
119 | 0 | } |
120 | 0 |
|
121 | 0 | return IPC_OK(); |
122 | 0 | } |
123 | 0 |
|
124 | 0 | mozilla::ipc::AutoIPCStream ipcStream; |
125 | 0 | bool ok = false; |
126 | 0 |
|
127 | 0 | if (mContentManager) { |
128 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
129 | 0 | ok = ipcStream.Serialize(stream, mContentManager); |
130 | 0 | } else { |
131 | 0 | MOZ_ASSERT(mPBackgroundManager); |
132 | 0 | ok = ipcStream.Serialize(stream, mPBackgroundManager); |
133 | 0 | } |
134 | 0 |
|
135 | 0 | if (NS_WARN_IF(!ok)) { |
136 | 0 | return IPC_FAIL(this, "SendStreamReady failed"); |
137 | 0 | } |
138 | 0 |
|
139 | 0 | if (!SendStreamReady(ipcStream.TakeValue())) { |
140 | 0 | return IPC_FAIL(this, "SendStreamReady failed"); |
141 | 0 | } |
142 | 0 |
|
143 | 0 | return IPC_OK(); |
144 | 0 | } |
145 | | |
146 | | mozilla::ipc::IPCResult |
147 | | IPCBlobInputStreamParent::RecvLengthNeeded() |
148 | 0 | { |
149 | 0 | MOZ_ASSERT(mContentManager || mPBackgroundManager); |
150 | 0 |
|
151 | 0 | nsCOMPtr<nsIInputStream> stream; |
152 | 0 | IPCBlobInputStreamStorage::Get()->GetStream(mID, 0, mSize, getter_AddRefs(stream)); |
153 | 0 | if (!stream) { |
154 | 0 | if (!SendLengthReady(-1)) { |
155 | 0 | return IPC_FAIL(this, "SendLengthReady failed"); |
156 | 0 | } |
157 | 0 |
|
158 | 0 | return IPC_OK(); |
159 | 0 | } |
160 | 0 |
|
161 | 0 | int64_t length = -1; |
162 | 0 | if (InputStreamLengthHelper::GetSyncLength(stream, &length)) { |
163 | 0 | Unused << SendLengthReady(length); |
164 | 0 | return IPC_OK(); |
165 | 0 | } |
166 | 0 |
|
167 | 0 | RefPtr<IPCBlobInputStreamParent> self = this; |
168 | 0 | InputStreamLengthHelper::GetAsyncLength(stream, [self](int64_t aLength) { |
169 | 0 | if (self->mContentManager || self->mPBackgroundManager) { |
170 | 0 | Unused << self->SendLengthReady(aLength); |
171 | 0 | } |
172 | 0 | }); |
173 | 0 |
|
174 | 0 | return IPC_OK(); |
175 | 0 | } |
176 | | |
177 | | mozilla::ipc::IPCResult |
178 | | IPCBlobInputStreamParent::RecvClose() |
179 | 0 | { |
180 | 0 | MOZ_ASSERT(mContentManager || mPBackgroundManager); |
181 | 0 |
|
182 | 0 | Unused << Send__delete__(this); |
183 | 0 | return IPC_OK(); |
184 | 0 | } |
185 | | |
186 | | mozilla::ipc::IPCResult |
187 | | IPCBlobInputStreamParent::Recv__delete__() |
188 | 0 | { |
189 | 0 | MOZ_ASSERT(mContentManager || mPBackgroundManager); |
190 | 0 | mMigrating = true; |
191 | 0 | return IPC_OK(); |
192 | 0 | } |
193 | | |
194 | | bool |
195 | | IPCBlobInputStreamParent::HasValidStream() const |
196 | 0 | { |
197 | 0 | nsCOMPtr<nsIInputStream> stream; |
198 | 0 | IPCBlobInputStreamStorage::Get()->GetStream(mID, 0, mSize, getter_AddRefs(stream)); |
199 | 0 | return !!stream; |
200 | 0 | } |
201 | | |
202 | | } // namespace dom |
203 | | } // namespace mozilla |