Coverage Report

Created: 2018-09-25 14:53

/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