Line data Source code
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 "nsContentUtils.h"
11 :
12 : namespace mozilla {
13 : namespace dom {
14 :
15 : template<typename M>
16 : /* static */ IPCBlobInputStreamParent*
17 0 : IPCBlobInputStreamParent::Create(nsIInputStream* aInputStream, uint64_t aSize,
18 : uint64_t aChildID, nsresult* aRv, M* aManager)
19 : {
20 0 : MOZ_ASSERT(aInputStream);
21 0 : MOZ_ASSERT(aRv);
22 :
23 : nsID id;
24 0 : *aRv = nsContentUtils::GenerateUUIDInPlace(id);
25 0 : if (NS_WARN_IF(NS_FAILED(*aRv))) {
26 0 : return nullptr;
27 : }
28 :
29 0 : IPCBlobInputStreamStorage::Get()->AddStream(aInputStream, id, aChildID);
30 :
31 0 : return new IPCBlobInputStreamParent(id, aSize, aManager);
32 : }
33 :
34 : /* static */ IPCBlobInputStreamParent*
35 0 : IPCBlobInputStreamParent::Create(const nsID& aID, uint64_t aSize,
36 : PBackgroundParent* aManager)
37 : {
38 : IPCBlobInputStreamParent* actor =
39 0 : new IPCBlobInputStreamParent(aID, aSize, aManager);
40 :
41 0 : actor->mCallback = IPCBlobInputStreamStorage::Get()->TakeCallback(aID);
42 :
43 0 : return actor;
44 : }
45 :
46 0 : IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID,
47 : uint64_t aSize,
48 0 : nsIContentParent* aManager)
49 : : mID(aID)
50 : , mSize(aSize)
51 : , mContentManager(aManager)
52 : , mPBackgroundManager(nullptr)
53 0 : , mMigrating(false)
54 0 : {}
55 :
56 0 : IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID,
57 : uint64_t aSize,
58 0 : PBackgroundParent* aManager)
59 : : mID(aID)
60 : , mSize(aSize)
61 : , mContentManager(nullptr)
62 : , mPBackgroundManager(aManager)
63 0 : , mMigrating(false)
64 0 : {}
65 :
66 : void
67 0 : IPCBlobInputStreamParent::ActorDestroy(IProtocol::ActorDestroyReason aReason)
68 : {
69 0 : MOZ_ASSERT(mContentManager || mPBackgroundManager);
70 :
71 0 : mContentManager = nullptr;
72 0 : mPBackgroundManager = nullptr;
73 :
74 0 : RefPtr<IPCBlobInputStreamParentCallback> callback;
75 0 : mCallback.swap(callback);
76 :
77 0 : RefPtr<IPCBlobInputStreamStorage> storage = IPCBlobInputStreamStorage::Get();
78 :
79 0 : if (mMigrating) {
80 0 : if (callback && storage) {
81 : // We need to assign this callback to the next parent.
82 0 : IPCBlobInputStreamStorage::Get()->StoreCallback(mID, callback);
83 : }
84 0 : return;
85 : }
86 :
87 0 : if (storage) {
88 0 : storage->ForgetStream(mID);
89 : }
90 :
91 0 : if (callback) {
92 0 : callback->ActorDestroyed(mID);
93 : }
94 : }
95 :
96 : void
97 0 : IPCBlobInputStreamParent::SetCallback(
98 : IPCBlobInputStreamParentCallback* aCallback)
99 : {
100 0 : MOZ_ASSERT(aCallback);
101 0 : MOZ_ASSERT(!mCallback);
102 :
103 0 : mCallback = aCallback;
104 0 : }
105 :
106 : mozilla::ipc::IPCResult
107 0 : IPCBlobInputStreamParent::RecvStreamNeeded()
108 : {
109 0 : MOZ_ASSERT(mContentManager || mPBackgroundManager);
110 :
111 0 : nsCOMPtr<nsIInputStream> stream;
112 0 : IPCBlobInputStreamStorage::Get()->GetStream(mID, getter_AddRefs(stream));
113 0 : if (!stream) {
114 0 : if (!SendStreamReady(void_t())) {
115 0 : return IPC_FAIL(this, "SendStreamReady failed");
116 : }
117 :
118 0 : return IPC_OK();
119 : }
120 :
121 0 : mozilla::ipc::AutoIPCStream ipcStream;
122 0 : bool ok = false;
123 :
124 0 : if (mContentManager) {
125 0 : MOZ_ASSERT(NS_IsMainThread());
126 0 : ok = ipcStream.Serialize(stream, mContentManager);
127 : } else {
128 0 : MOZ_ASSERT(mPBackgroundManager);
129 0 : ok = ipcStream.Serialize(stream, mPBackgroundManager);
130 : }
131 :
132 0 : if (NS_WARN_IF(!ok)) {
133 0 : return IPC_FAIL(this, "SendStreamReady failed");
134 : }
135 :
136 0 : if (!SendStreamReady(ipcStream.TakeValue())) {
137 0 : return IPC_FAIL(this, "SendStreamReady failed");
138 : }
139 :
140 0 : return IPC_OK();
141 : }
142 :
143 : mozilla::ipc::IPCResult
144 0 : IPCBlobInputStreamParent::RecvClose()
145 : {
146 0 : MOZ_ASSERT(mContentManager || mPBackgroundManager);
147 :
148 0 : Unused << Send__delete__(this);
149 0 : return IPC_OK();
150 : }
151 :
152 : mozilla::ipc::IPCResult
153 0 : IPCBlobInputStreamParent::Recv__delete__()
154 : {
155 0 : MOZ_ASSERT(mContentManager || mPBackgroundManager);
156 0 : mMigrating = true;
157 0 : return IPC_OK();
158 : }
159 :
160 : bool
161 0 : IPCBlobInputStreamParent::HasValidStream() const
162 : {
163 0 : nsCOMPtr<nsIInputStream> stream;
164 0 : IPCBlobInputStreamStorage::Get()->GetStream(mID, getter_AddRefs(stream));
165 0 : return !!stream;
166 : }
167 :
168 : } // namespace dom
169 : } // namespace mozilla
|