Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/gmp/GMPContentParent.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "GMPContentParent.h"
7
#include "GMPParent.h"
8
#include "GMPServiceChild.h"
9
#include "GMPVideoDecoderParent.h"
10
#include "GMPVideoEncoderParent.h"
11
#include "ChromiumCDMParent.h"
12
#include "mozIGeckoMediaPluginService.h"
13
#include "mozilla/Logging.h"
14
#include "mozilla/Unused.h"
15
#include "base/task.h"
16
17
namespace mozilla {
18
19
#ifdef LOG
20
#undef LOG
21
#endif
22
23
extern LogModule* GetGMPLog();
24
25
#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
26
#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)
27
28
#ifdef __CLASS__
29
#undef __CLASS__
30
#endif
31
#define __CLASS__ "GMPContentParent"
32
33
namespace gmp {
34
35
GMPContentParent::GMPContentParent(GMPParent* aParent)
36
  : mParent(aParent)
37
  , mPluginId(0)
38
0
{
39
0
  if (mParent) {
40
0
    SetDisplayName(mParent->GetDisplayName());
41
0
    SetPluginId(mParent->GetPluginId());
42
0
  }
43
0
}
44
45
GMPContentParent::~GMPContentParent()
46
0
{
47
0
}
48
49
class ReleaseGMPContentParent : public Runnable
50
{
51
public:
52
  explicit ReleaseGMPContentParent(GMPContentParent* aToRelease)
53
    : Runnable("gmp::ReleaseGMPContentParent")
54
    , mToRelease(aToRelease)
55
0
  {
56
0
  }
57
58
  NS_IMETHOD Run() override
59
0
  {
60
0
    return NS_OK;
61
0
  }
62
63
private:
64
  RefPtr<GMPContentParent> mToRelease;
65
};
66
67
void
68
GMPContentParent::ActorDestroy(ActorDestroyReason aWhy)
69
0
{
70
0
  MOZ_ASSERT(mVideoDecoders.IsEmpty() &&
71
0
             mVideoEncoders.IsEmpty() &&
72
0
             mChromiumCDMs.IsEmpty());
73
0
  NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this));
74
0
}
75
76
void
77
GMPContentParent::CheckThread()
78
0
{
79
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
80
0
}
81
82
void
83
GMPContentParent::ChromiumCDMDestroyed(ChromiumCDMParent* aDecoder)
84
0
{
85
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
86
0
87
0
  MOZ_ALWAYS_TRUE(mChromiumCDMs.RemoveElement(aDecoder));
88
0
  CloseIfUnused();
89
0
}
90
91
void
92
GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
93
0
{
94
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
95
0
96
0
  // If the constructor fails, we'll get called before it's added
97
0
  Unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder));
98
0
  CloseIfUnused();
99
0
}
100
101
void
102
GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder)
103
0
{
104
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
105
0
106
0
  // If the constructor fails, we'll get called before it's added
107
0
  Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder));
108
0
  CloseIfUnused();
109
0
}
110
111
void
112
GMPContentParent::AddCloseBlocker()
113
0
{
114
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
115
0
  ++mCloseBlockerCount;
116
0
}
117
118
void
119
GMPContentParent::RemoveCloseBlocker()
120
0
{
121
0
  MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread());
122
0
  --mCloseBlockerCount;
123
0
  CloseIfUnused();
124
0
}
125
126
void
127
GMPContentParent::CloseIfUnused()
128
0
{
129
0
  if (mVideoDecoders.IsEmpty() &&
130
0
      mVideoEncoders.IsEmpty() &&
131
0
      mChromiumCDMs.IsEmpty() &&
132
0
      mCloseBlockerCount == 0) {
133
0
    RefPtr<GMPContentParent> toClose;
134
0
    if (mParent) {
135
0
      toClose = mParent->ForgetGMPContentParent();
136
0
    } else {
137
0
      toClose = this;
138
0
      RefPtr<GeckoMediaPluginServiceChild> gmp(
139
0
        GeckoMediaPluginServiceChild::GetSingleton());
140
0
      gmp->RemoveGMPContentParent(toClose);
141
0
    }
142
0
    NS_DispatchToCurrentThread(NewRunnableMethod(
143
0
      "gmp::GMPContentParent::Close", toClose, &GMPContentParent::Close));
144
0
  }
145
0
}
146
147
nsCOMPtr<nsISerialEventTarget>
148
GMPContentParent::GMPEventTarget()
149
0
{
150
0
  if (!mGMPEventTarget) {
151
0
    nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
152
0
    MOZ_ASSERT(mps);
153
0
    if (!mps) {
154
0
      return nullptr;
155
0
    }
156
0
    // Not really safe if we just grab to the mGMPEventTarget, as we don't know
157
0
    // what thread we're running on and other threads may be trying to
158
0
    // access this without locks!  However, debug only, and primary failure
159
0
    // mode outside of compiler-helped TSAN is a leak.  But better would be
160
0
    // to use swap() under a lock.
161
0
    nsCOMPtr<nsIThread> gmpThread;
162
0
    mps->GetThread(getter_AddRefs(gmpThread));
163
0
    MOZ_ASSERT(gmpThread);
164
0
165
0
    mGMPEventTarget = gmpThread->SerialEventTarget();
166
0
  }
167
0
168
0
  return mGMPEventTarget;
169
0
}
170
171
already_AddRefed<ChromiumCDMParent>
172
GMPContentParent::GetChromiumCDM()
173
0
{
174
0
  PChromiumCDMParent* actor = SendPChromiumCDMConstructor();
175
0
  if (!actor) {
176
0
    return nullptr;
177
0
  }
178
0
  RefPtr<ChromiumCDMParent> parent = static_cast<ChromiumCDMParent*>(actor);
179
0
180
0
  // TODO: Remove parent from mChromiumCDMs in ChromiumCDMParent::Destroy().
181
0
  mChromiumCDMs.AppendElement(parent);
182
0
183
0
  return parent.forget();
184
0
}
185
186
nsresult
187
GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD,
188
                                     uint32_t aDecryptorId)
189
0
{
190
0
  // returned with one anonymous AddRef that locks it until Destroy
191
0
  PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor(aDecryptorId);
192
0
  if (!pvdp) {
193
0
    return NS_ERROR_FAILURE;
194
0
  }
195
0
  GMPVideoDecoderParent *vdp = static_cast<GMPVideoDecoderParent*>(pvdp);
196
0
  // This addref corresponds to the Proxy pointer the consumer is returned.
197
0
  // It's dropped by calling Close() on the interface.
198
0
  NS_ADDREF(vdp);
199
0
  *aGMPVD = vdp;
200
0
  mVideoDecoders.AppendElement(vdp);
201
0
202
0
  return NS_OK;
203
0
}
204
205
nsresult
206
GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE)
207
0
{
208
0
  // returned with one anonymous AddRef that locks it until Destroy
209
0
  PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor();
210
0
  if (!pvep) {
211
0
    return NS_ERROR_FAILURE;
212
0
  }
213
0
  GMPVideoEncoderParent *vep = static_cast<GMPVideoEncoderParent*>(pvep);
214
0
  // This addref corresponds to the Proxy pointer the consumer is returned.
215
0
  // It's dropped by calling Close() on the interface.
216
0
  NS_ADDREF(vep);
217
0
  *aGMPVE = vep;
218
0
  mVideoEncoders.AppendElement(vep);
219
0
220
0
  return NS_OK;
221
0
}
222
223
PChromiumCDMParent*
224
GMPContentParent::AllocPChromiumCDMParent()
225
0
{
226
0
  ChromiumCDMParent* parent = new ChromiumCDMParent(this, GetPluginId());
227
0
  NS_ADDREF(parent);
228
0
  return parent;
229
0
}
230
231
PGMPVideoDecoderParent*
232
GMPContentParent::AllocPGMPVideoDecoderParent(const uint32_t& aDecryptorId)
233
0
{
234
0
  GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this);
235
0
  NS_ADDREF(vdp);
236
0
  return vdp;
237
0
}
238
239
bool
240
GMPContentParent::DeallocPChromiumCDMParent(PChromiumCDMParent* aActor)
241
0
{
242
0
  ChromiumCDMParent* parent = static_cast<ChromiumCDMParent*>(aActor);
243
0
  NS_RELEASE(parent);
244
0
  return true;
245
0
}
246
247
bool
248
GMPContentParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor)
249
0
{
250
0
  GMPVideoDecoderParent* vdp = static_cast<GMPVideoDecoderParent*>(aActor);
251
0
  NS_RELEASE(vdp);
252
0
  return true;
253
0
}
254
255
PGMPVideoEncoderParent*
256
GMPContentParent::AllocPGMPVideoEncoderParent()
257
0
{
258
0
  GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this);
259
0
  NS_ADDREF(vep);
260
0
  return vep;
261
0
}
262
263
bool
264
GMPContentParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor)
265
0
{
266
0
  GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor);
267
0
  NS_RELEASE(vep);
268
0
  return true;
269
0
}
270
271
} // namespace gmp
272
} // namespace mozilla