Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/plugins/ipc/PluginScriptableObjectChild.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: sw=2 ts=2 et :
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 "PluginScriptableObjectChild.h"
8
#include "PluginScriptableObjectUtils.h"
9
#include "mozilla/plugins/PluginTypes.h"
10
11
using namespace mozilla::plugins;
12
13
/**
14
 * NPIdentifiers in the plugin process use a tagged representation. The low bit
15
 * stores the tag. If it's zero, the identifier is a string, and the value is a
16
 * pointer to a StoredIdentifier. If the tag bit is 1, then the rest of the
17
 * NPIdentifier value is the integer itself. Like the JSAPI, we require that all
18
 * integers stored in NPIdentifier be non-negative.
19
 *
20
 * String identifiers are stored in the sIdentifiers hashtable to ensure
21
 * uniqueness. The lifetime of these identifiers is only as long as the incoming
22
 * IPC call from the chrome process. If the plugin wants to retain an
23
 * identifier, it needs to call NPN_GetStringIdentifier, which causes the
24
 * mPermanent flag to be set on the identifier. When this flag is set, the
25
 * identifier is saved until the plugin process exits.
26
 *
27
 * The StackIdentifier RAII class is used to manage ownership of
28
 * identifiers. Any identifier obtained from this class should not be used
29
 * outside its scope, except when the MakePermanent() method has been called on
30
 * it.
31
 *
32
 * The lifetime of an NPIdentifier in the plugin process is totally divorced
33
 * from the lifetime of an NPIdentifier in the chrome process (where an
34
 * NPIdentifier is stored as a jsid). The JS GC in the chrome process is able to
35
 * trace through the entire heap, unlike in the plugin process, so there is no
36
 * reason to retain identifiers there.
37
 */
38
39
PluginScriptableObjectChild::IdentifierTable PluginScriptableObjectChild::sIdentifiers;
40
41
/* static */ PluginScriptableObjectChild::StoredIdentifier*
42
PluginScriptableObjectChild::HashIdentifier(const nsCString& aIdentifier)
43
0
{
44
0
  StoredIdentifier* stored = sIdentifiers.Get(aIdentifier).get();
45
0
  if (stored) {
46
0
    return stored;
47
0
  }
48
0
49
0
  stored = new StoredIdentifier(aIdentifier);
50
0
  sIdentifiers.Put(aIdentifier, stored);
51
0
  return stored;
52
0
}
53
54
/* static */ void
55
PluginScriptableObjectChild::UnhashIdentifier(StoredIdentifier* aStored)
56
0
{
57
0
  MOZ_ASSERT(sIdentifiers.Get(aStored->mIdentifier));
58
0
  sIdentifiers.Remove(aStored->mIdentifier);
59
0
}
60
61
/* static */ void
62
PluginScriptableObjectChild::ClearIdentifiers()
63
0
{
64
0
  sIdentifiers.Clear();
65
0
}
66
67
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier)
68
: mIdentifier(aIdentifier),
69
  mStored(nullptr)
70
0
{
71
0
  if (aIdentifier.type() == PluginIdentifier::TnsCString) {
72
0
    mStored = PluginScriptableObjectChild::HashIdentifier(mIdentifier.get_nsCString());
73
0
  }
74
0
}
75
76
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(NPIdentifier aIdentifier)
77
: mStored(nullptr)
78
0
{
79
0
  uintptr_t bits = reinterpret_cast<uintptr_t>(aIdentifier);
80
0
  if (bits & 1) {
81
0
    int32_t num = int32_t(bits >> 1);
82
0
    mIdentifier = PluginIdentifier(num);
83
0
  } else {
84
0
    mStored = static_cast<StoredIdentifier*>(aIdentifier);
85
0
    mIdentifier = mStored->mIdentifier;
86
0
  }
87
0
}
88
89
PluginScriptableObjectChild::StackIdentifier::~StackIdentifier()
90
0
{
91
0
  if (!mStored) {
92
0
    return;
93
0
  }
94
0
95
0
  // Each StackIdentifier owns one reference to its StoredIdentifier. In
96
0
  // addition, the sIdentifiers table owns a reference. If mPermanent is false
97
0
  // and sIdentifiers has the last reference, then we want to remove the
98
0
  // StoredIdentifier from the table (and destroy it).
99
0
  StoredIdentifier *stored = mStored;
100
0
  mStored = nullptr;
101
0
  if (stored->mRefCnt == 1 && !stored->mPermanent) {
102
0
    PluginScriptableObjectChild::UnhashIdentifier(stored);
103
0
  }
104
0
}
105
106
NPIdentifier
107
PluginScriptableObjectChild::StackIdentifier::ToNPIdentifier() const
108
0
{
109
0
  if (mStored) {
110
0
    MOZ_ASSERT(mIdentifier.type() == PluginIdentifier::TnsCString);
111
0
    MOZ_ASSERT((reinterpret_cast<uintptr_t>(mStored.get()) & 1) == 0);
112
0
    return mStored;
113
0
  }
114
0
115
0
  int32_t num = mIdentifier.get_int32_t();
116
0
  // The JS engine imposes this condition on int32s in jsids, so we assume it.
117
0
  MOZ_ASSERT(num >= 0);
118
0
  return reinterpret_cast<NPIdentifier>((num << 1) | 1);
119
0
}
120
121
static PluginIdentifier
122
FromNPIdentifier(NPIdentifier aIdentifier)
123
0
{
124
0
  PluginScriptableObjectChild::StackIdentifier stack(aIdentifier);
125
0
  return stack.GetIdentifier();
126
0
}
127
128
// static
129
NPObject*
130
PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
131
                                                NPClass* aClass)
132
0
{
133
0
  AssertPluginThread();
134
0
135
0
  if (aClass != GetClass()) {
136
0
    MOZ_CRASH("Huh?! Wrong class!");
137
0
  }
138
0
139
0
  return new ChildNPObject();
140
0
}
141
142
// static
143
void
144
PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject)
145
0
{
146
0
  AssertPluginThread();
147
0
148
0
  if (aObject->_class != GetClass()) {
149
0
    MOZ_CRASH("Don't know what kind of object this is!");
150
0
  }
151
0
152
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
153
0
  if (object->invalidated) {
154
0
    // This can happen more than once, and is just fine.
155
0
    return;
156
0
  }
157
0
158
0
  object->invalidated = true;
159
0
}
160
161
// static
162
void
163
PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject)
164
0
{
165
0
  AssertPluginThread();
166
0
167
0
  if (aObject->_class != GetClass()) {
168
0
    MOZ_CRASH("Don't know what kind of object this is!");
169
0
  }
170
0
171
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
172
0
  PluginScriptableObjectChild* actor = object->parent;
173
0
  if (actor) {
174
0
    NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
175
0
    actor->DropNPObject();
176
0
  }
177
0
178
0
  delete object;
179
0
}
180
181
// static
182
bool
183
PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject,
184
                                                 NPIdentifier aName)
185
0
{
186
0
  AssertPluginThread();
187
0
188
0
  if (aObject->_class != GetClass()) {
189
0
    MOZ_CRASH("Don't know what kind of object this is!");
190
0
  }
191
0
192
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
193
0
  if (object->invalidated) {
194
0
    NS_WARNING("Calling method on an invalidated object!");
195
0
    return false;
196
0
  }
197
0
198
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
199
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
200
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
201
0
202
0
  bool result;
203
0
  actor->CallHasMethod(FromNPIdentifier(aName), &result);
204
0
205
0
  return result;
206
0
}
207
208
// static
209
bool
210
PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
211
                                              NPIdentifier aName,
212
                                              const NPVariant* aArgs,
213
                                              uint32_t aArgCount,
214
                                              NPVariant* aResult)
215
0
{
216
0
  AssertPluginThread();
217
0
218
0
  if (aObject->_class != GetClass()) {
219
0
    MOZ_CRASH("Don't know what kind of object this is!");
220
0
  }
221
0
222
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
223
0
  if (object->invalidated) {
224
0
    NS_WARNING("Calling method on an invalidated object!");
225
0
    return false;
226
0
  }
227
0
228
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
229
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
230
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
231
0
232
0
  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
233
0
  if (!args.IsOk()) {
234
0
    NS_ERROR("Failed to convert arguments!");
235
0
    return false;
236
0
  }
237
0
238
0
  Variant remoteResult;
239
0
  bool success;
240
0
  actor->CallInvoke(FromNPIdentifier(aName), args,
241
0
                    &remoteResult, &success);
242
0
243
0
  if (!success) {
244
0
    return false;
245
0
  }
246
0
247
0
  ConvertToVariant(remoteResult, *aResult);
248
0
  return true;
249
0
}
250
251
// static
252
bool
253
PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject,
254
                                                     const NPVariant* aArgs,
255
                                                     uint32_t aArgCount,
256
                                                     NPVariant* aResult)
257
0
{
258
0
  AssertPluginThread();
259
0
260
0
  if (aObject->_class != GetClass()) {
261
0
    MOZ_CRASH("Don't know what kind of object this is!");
262
0
  }
263
0
264
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
265
0
  if (object->invalidated) {
266
0
    NS_WARNING("Calling method on an invalidated object!");
267
0
    return false;
268
0
  }
269
0
270
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
271
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
272
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
273
0
274
0
  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
275
0
  if (!args.IsOk()) {
276
0
    NS_ERROR("Failed to convert arguments!");
277
0
    return false;
278
0
  }
279
0
280
0
  Variant remoteResult;
281
0
  bool success;
282
0
  actor->CallInvokeDefault(args, &remoteResult, &success);
283
0
284
0
  if (!success) {
285
0
    return false;
286
0
  }
287
0
288
0
  ConvertToVariant(remoteResult, *aResult);
289
0
  return true;
290
0
}
291
292
// static
293
bool
294
PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject,
295
                                                   NPIdentifier aName)
296
0
{
297
0
  AssertPluginThread();
298
0
299
0
  if (aObject->_class != GetClass()) {
300
0
    MOZ_CRASH("Don't know what kind of object this is!");
301
0
  }
302
0
303
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
304
0
  if (object->invalidated) {
305
0
    NS_WARNING("Calling method on an invalidated object!");
306
0
    return false;
307
0
  }
308
0
309
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
310
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
311
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
312
0
313
0
  bool result;
314
0
  actor->CallHasProperty(FromNPIdentifier(aName), &result);
315
0
316
0
  return result;
317
0
}
318
319
// static
320
bool
321
PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
322
                                                   NPIdentifier aName,
323
                                                   NPVariant* aResult)
324
0
{
325
0
  AssertPluginThread();
326
0
327
0
  if (aObject->_class != GetClass()) {
328
0
    MOZ_CRASH("Don't know what kind of object this is!");
329
0
  }
330
0
331
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
332
0
  if (object->invalidated) {
333
0
    NS_WARNING("Calling method on an invalidated object!");
334
0
    return false;
335
0
  }
336
0
337
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
338
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
339
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
340
0
341
0
  PluginInstanceChild::AutoStackHelper guard(actor->mInstance);
342
0
343
0
  Variant result;
344
0
  bool success;
345
0
  actor->CallGetParentProperty(FromNPIdentifier(aName),
346
0
                               &result, &success);
347
0
348
0
  if (!success) {
349
0
    return false;
350
0
  }
351
0
352
0
  ConvertToVariant(result, *aResult);
353
0
  return true;
354
0
}
355
356
// static
357
bool
358
PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject,
359
                                                   NPIdentifier aName,
360
                                                   const NPVariant* aValue)
361
0
{
362
0
  AssertPluginThread();
363
0
364
0
  if (aObject->_class != GetClass()) {
365
0
    MOZ_CRASH("Don't know what kind of object this is!");
366
0
  }
367
0
368
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
369
0
  if (object->invalidated) {
370
0
    NS_WARNING("Calling method on an invalidated object!");
371
0
    return false;
372
0
  }
373
0
374
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
375
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
376
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
377
0
378
0
  ProtectedVariant value(*aValue, actor->GetInstance());
379
0
  if (!value.IsOk()) {
380
0
    NS_WARNING("Failed to convert variant!");
381
0
    return false;
382
0
  }
383
0
384
0
  bool success;
385
0
  actor->CallSetProperty(FromNPIdentifier(aName), value,
386
0
                         &success);
387
0
388
0
  return success;
389
0
}
390
391
// static
392
bool
393
PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
394
                                                      NPIdentifier aName)
395
0
{
396
0
  AssertPluginThread();
397
0
398
0
  if (aObject->_class != GetClass()) {
399
0
    MOZ_CRASH("Don't know what kind of object this is!");
400
0
  }
401
0
402
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
403
0
  if (object->invalidated) {
404
0
    NS_WARNING("Calling method on an invalidated object!");
405
0
    return false;
406
0
  }
407
0
408
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
409
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
410
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
411
0
412
0
  bool success;
413
0
  actor->CallRemoveProperty(FromNPIdentifier(aName),
414
0
                            &success);
415
0
416
0
  return success;
417
0
}
418
419
// static
420
bool
421
PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
422
                                                 NPIdentifier** aIdentifiers,
423
                                                 uint32_t* aCount)
424
0
{
425
0
  AssertPluginThread();
426
0
427
0
  if (aObject->_class != GetClass()) {
428
0
    MOZ_CRASH("Don't know what kind of object this is!");
429
0
  }
430
0
431
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
432
0
  if (object->invalidated) {
433
0
    NS_WARNING("Calling method on an invalidated object!");
434
0
    return false;
435
0
  }
436
0
437
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
438
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
439
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
440
0
441
0
  AutoTArray<PluginIdentifier, 10> identifiers;
442
0
  bool success;
443
0
  actor->CallEnumerate(&identifiers, &success);
444
0
445
0
  if (!success) {
446
0
    return false;
447
0
  }
448
0
449
0
  *aCount = identifiers.Length();
450
0
  if (!*aCount) {
451
0
    *aIdentifiers = nullptr;
452
0
    return true;
453
0
  }
454
0
455
0
  *aIdentifiers = reinterpret_cast<NPIdentifier*>(
456
0
      PluginModuleChild::sBrowserFuncs.memalloc(*aCount * sizeof(NPIdentifier)));
457
0
  if (!*aIdentifiers) {
458
0
    NS_ERROR("Out of memory!");
459
0
    return false;
460
0
  }
461
0
462
0
  for (uint32_t index = 0; index < *aCount; index++) {
463
0
    StackIdentifier id(identifiers[index]);
464
0
    // Make the id permanent in case the plugin retains it.
465
0
    id.MakePermanent();
466
0
    (*aIdentifiers)[index] = id.ToNPIdentifier();
467
0
  }
468
0
  return true;
469
0
}
470
471
// static
472
bool
473
PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject,
474
                                                 const NPVariant* aArgs,
475
                                                 uint32_t aArgCount,
476
                                                 NPVariant* aResult)
477
0
{
478
0
  AssertPluginThread();
479
0
480
0
  if (aObject->_class != GetClass()) {
481
0
    MOZ_CRASH("Don't know what kind of object this is!");
482
0
  }
483
0
484
0
  ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
485
0
  if (object->invalidated) {
486
0
    NS_WARNING("Calling method on an invalidated object!");
487
0
    return false;
488
0
  }
489
0
490
0
  ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
491
0
  NS_ASSERTION(actor, "This shouldn't ever be null!");
492
0
  NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
493
0
494
0
  ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
495
0
  if (!args.IsOk()) {
496
0
    NS_ERROR("Failed to convert arguments!");
497
0
    return false;
498
0
  }
499
0
500
0
  Variant remoteResult;
501
0
  bool success;
502
0
  actor->CallConstruct(args, &remoteResult, &success);
503
0
504
0
  if (!success) {
505
0
    return false;
506
0
  }
507
0
508
0
  ConvertToVariant(remoteResult, *aResult);
509
0
  return true;
510
0
}
511
512
const NPClass PluginScriptableObjectChild::sNPClass = {
513
  NP_CLASS_STRUCT_VERSION,
514
  PluginScriptableObjectChild::ScriptableAllocate,
515
  PluginScriptableObjectChild::ScriptableDeallocate,
516
  PluginScriptableObjectChild::ScriptableInvalidate,
517
  PluginScriptableObjectChild::ScriptableHasMethod,
518
  PluginScriptableObjectChild::ScriptableInvoke,
519
  PluginScriptableObjectChild::ScriptableInvokeDefault,
520
  PluginScriptableObjectChild::ScriptableHasProperty,
521
  PluginScriptableObjectChild::ScriptableGetProperty,
522
  PluginScriptableObjectChild::ScriptableSetProperty,
523
  PluginScriptableObjectChild::ScriptableRemoveProperty,
524
  PluginScriptableObjectChild::ScriptableEnumerate,
525
  PluginScriptableObjectChild::ScriptableConstruct
526
};
527
528
PluginScriptableObjectChild::PluginScriptableObjectChild(
529
                                                     ScriptableObjectType aType)
530
: mInstance(nullptr),
531
  mObject(nullptr),
532
  mInvalidated(false),
533
  mProtectCount(0),
534
  mType(aType)
535
0
{
536
0
  AssertPluginThread();
537
0
}
538
539
PluginScriptableObjectChild::~PluginScriptableObjectChild()
540
0
{
541
0
  AssertPluginThread();
542
0
543
0
  if (mObject) {
544
0
    UnregisterActor(mObject);
545
0
546
0
    if (mObject->_class == GetClass()) {
547
0
      NS_ASSERTION(mType == Proxy, "Wrong type!");
548
0
      static_cast<ChildNPObject*>(mObject)->parent = nullptr;
549
0
    }
550
0
    else {
551
0
      NS_ASSERTION(mType == LocalObject, "Wrong type!");
552
0
      PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
553
0
    }
554
0
  }
555
0
}
556
557
bool
558
PluginScriptableObjectChild::InitializeProxy()
559
0
{
560
0
  AssertPluginThread();
561
0
  NS_ASSERTION(mType == Proxy, "Bad type!");
562
0
  NS_ASSERTION(!mObject, "Calling Initialize more than once!");
563
0
  NS_ASSERTION(!mInvalidated, "Already invalidated?!");
564
0
565
0
  mInstance = static_cast<PluginInstanceChild*>(Manager());
566
0
  NS_ASSERTION(mInstance, "Null manager?!");
567
0
568
0
  NPObject* object = CreateProxyObject();
569
0
  if (!object) {
570
0
    NS_ERROR("Failed to create object!");
571
0
    return false;
572
0
  }
573
0
574
0
  if (!RegisterActor(object)) {
575
0
    NS_ERROR("RegisterActor failed");
576
0
    return false;
577
0
  }
578
0
579
0
  mObject = object;
580
0
  return true;
581
0
}
582
583
void
584
PluginScriptableObjectChild::InitializeLocal(NPObject* aObject)
585
0
{
586
0
  AssertPluginThread();
587
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
588
0
  NS_ASSERTION(!mObject, "Calling Initialize more than once!");
589
0
  NS_ASSERTION(!mInvalidated, "Already invalidated?!");
590
0
591
0
  mInstance = static_cast<PluginInstanceChild*>(Manager());
592
0
  NS_ASSERTION(mInstance, "Null manager?!");
593
0
594
0
  PluginModuleChild::sBrowserFuncs.retainobject(aObject);
595
0
596
0
  NS_ASSERTION(!mProtectCount, "Should be zero!");
597
0
  mProtectCount++;
598
0
599
0
  if (!RegisterActor(aObject)) {
600
0
    NS_ERROR("RegisterActor failed");
601
0
  }
602
0
603
0
  mObject = aObject;
604
0
}
605
606
NPObject*
607
PluginScriptableObjectChild::CreateProxyObject()
608
0
{
609
0
  NS_ASSERTION(mInstance, "Must have an instance!");
610
0
  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
611
0
612
0
  NPClass* proxyClass = const_cast<NPClass*>(GetClass());
613
0
  NPObject* npobject =
614
0
    PluginModuleChild::sBrowserFuncs.createobject(mInstance->GetNPP(),
615
0
                                                  proxyClass);
616
0
  NS_ASSERTION(npobject, "Failed to create object?!");
617
0
  NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
618
0
  NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
619
0
620
0
  ChildNPObject* object = static_cast<ChildNPObject*>(npobject);
621
0
  NS_ASSERTION(!object->invalidated, "Bad object!");
622
0
  NS_ASSERTION(!object->parent, "Bad object!");
623
0
624
0
  // We don't want to have the actor own this object but rather let the object
625
0
  // own this actor. Set the reference count to 0 here so that when the object
626
0
  // dies we will send the destructor message to the child.
627
0
  object->referenceCount = 0;
628
0
  NS_LOG_RELEASE(object, 0, "NPObject");
629
0
630
0
  object->parent = const_cast<PluginScriptableObjectChild*>(this);
631
0
  return object;
632
0
}
633
634
bool
635
PluginScriptableObjectChild::ResurrectProxyObject()
636
0
{
637
0
  NS_ASSERTION(mInstance, "Must have an instance already!");
638
0
  NS_ASSERTION(!mObject, "Should not have an object already!");
639
0
  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
640
0
641
0
  if (!InitializeProxy()) {
642
0
    NS_ERROR("Initialize failed!");
643
0
    return false;
644
0
  }
645
0
646
0
  SendProtect();
647
0
  return true;
648
0
}
649
650
NPObject*
651
PluginScriptableObjectChild::GetObject(bool aCanResurrect)
652
0
{
653
0
  if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
654
0
    NS_ERROR("Null object!");
655
0
    return nullptr;
656
0
  }
657
0
  return mObject;
658
0
}
659
660
void
661
PluginScriptableObjectChild::Protect()
662
0
{
663
0
  NS_ASSERTION(mObject, "No object!");
664
0
  NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
665
0
666
0
  if (mType == LocalObject) {
667
0
    ++mProtectCount;
668
0
  }
669
0
}
670
671
void
672
PluginScriptableObjectChild::Unprotect()
673
0
{
674
0
  NS_ASSERTION(mObject, "Bad state!");
675
0
  NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
676
0
677
0
  if (mType == LocalObject) {
678
0
    if (--mProtectCount == 0) {
679
0
      PluginScriptableObjectChild::Send__delete__(this);
680
0
    }
681
0
  }
682
0
}
683
684
void
685
PluginScriptableObjectChild::DropNPObject()
686
0
{
687
0
  NS_ASSERTION(mObject, "Invalidated object!");
688
0
  NS_ASSERTION(mObject->_class == GetClass(), "Wrong type of object!");
689
0
  NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
690
0
691
0
  // We think we're about to be deleted, but we could be racing with the other
692
0
  // process.
693
0
  UnregisterActor(mObject);
694
0
  mObject = nullptr;
695
0
696
0
  SendUnprotect();
697
0
}
698
699
void
700
PluginScriptableObjectChild::NPObjectDestroyed()
701
0
{
702
0
  NS_ASSERTION(LocalObject == mType,
703
0
               "ScriptableDeallocate should have handled this for proxies");
704
0
  mInvalidated = true;
705
0
  mObject = nullptr;
706
0
}
707
708
mozilla::ipc::IPCResult
709
PluginScriptableObjectChild::AnswerInvalidate()
710
0
{
711
0
  AssertPluginThread();
712
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
713
0
714
0
  if (mInvalidated) {
715
0
    return IPC_OK();
716
0
  }
717
0
718
0
  mInvalidated = true;
719
0
720
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
721
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
722
0
723
0
  if (mObject->_class && mObject->_class->invalidate) {
724
0
    mObject->_class->invalidate(mObject);
725
0
  }
726
0
727
0
  Unprotect();
728
0
729
0
  return IPC_OK();
730
0
}
731
732
mozilla::ipc::IPCResult
733
PluginScriptableObjectChild::AnswerHasMethod(const PluginIdentifier& aId,
734
                                             bool* aHasMethod)
735
0
{
736
0
  AssertPluginThread();
737
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
738
0
739
0
  if (mInvalidated) {
740
0
    NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
741
0
    *aHasMethod = false;
742
0
    return IPC_OK();
743
0
  }
744
0
745
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
746
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
747
0
748
0
  if (!(mObject->_class && mObject->_class->hasMethod)) {
749
0
    *aHasMethod = false;
750
0
    return IPC_OK();
751
0
  }
752
0
753
0
  StackIdentifier id(aId);
754
0
  *aHasMethod = mObject->_class->hasMethod(mObject, id.ToNPIdentifier());
755
0
  return IPC_OK();
756
0
}
757
758
mozilla::ipc::IPCResult
759
PluginScriptableObjectChild::AnswerInvoke(const PluginIdentifier& aId,
760
                                          InfallibleTArray<Variant>&& aArgs,
761
                                          Variant* aResult,
762
                                          bool* aSuccess)
763
0
{
764
0
  AssertPluginThread();
765
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
766
0
767
0
  if (mInvalidated) {
768
0
    NS_WARNING("Calling AnswerInvoke with an invalidated object!");
769
0
    *aResult = void_t();
770
0
    *aSuccess = false;
771
0
    return IPC_OK();
772
0
  }
773
0
774
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
775
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
776
0
777
0
  if (!(mObject->_class && mObject->_class->invoke)) {
778
0
    *aResult = void_t();
779
0
    *aSuccess = false;
780
0
    return IPC_OK();
781
0
  }
782
0
783
0
  AutoTArray<NPVariant, 10> convertedArgs;
784
0
  uint32_t argCount = aArgs.Length();
785
0
786
0
  if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
787
0
    *aResult = void_t();
788
0
    *aSuccess = false;
789
0
    return IPC_OK();
790
0
  }
791
0
792
0
  for (uint32_t index = 0; index < argCount; index++) {
793
0
    ConvertToVariant(aArgs[index], convertedArgs[index]);
794
0
  }
795
0
796
0
  NPVariant result;
797
0
  VOID_TO_NPVARIANT(result);
798
0
  StackIdentifier id(aId);
799
0
  bool success = mObject->_class->invoke(mObject, id.ToNPIdentifier(),
800
0
                                         convertedArgs.Elements(), argCount,
801
0
                                         &result);
802
0
803
0
  for (uint32_t index = 0; index < argCount; index++) {
804
0
    PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
805
0
  }
806
0
807
0
  if (!success) {
808
0
    *aResult = void_t();
809
0
    *aSuccess = false;
810
0
    return IPC_OK();
811
0
  }
812
0
813
0
  Variant convertedResult;
814
0
  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
815
0
                                   false);
816
0
817
0
  DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
818
0
819
0
  if (!success) {
820
0
    *aResult = void_t();
821
0
    *aSuccess = false;
822
0
    return IPC_OK();
823
0
  }
824
0
825
0
  *aSuccess = true;
826
0
  *aResult = convertedResult;
827
0
  return IPC_OK();
828
0
}
829
830
mozilla::ipc::IPCResult
831
PluginScriptableObjectChild::AnswerInvokeDefault(InfallibleTArray<Variant>&& aArgs,
832
                                                 Variant* aResult,
833
                                                 bool* aSuccess)
834
0
{
835
0
  AssertPluginThread();
836
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
837
0
838
0
  if (mInvalidated) {
839
0
    NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!");
840
0
    *aResult = void_t();
841
0
    *aSuccess = false;
842
0
    return IPC_OK();
843
0
  }
844
0
845
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
846
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
847
0
848
0
  if (!(mObject->_class && mObject->_class->invokeDefault)) {
849
0
    *aResult = void_t();
850
0
    *aSuccess = false;
851
0
    return IPC_OK();
852
0
  }
853
0
854
0
  AutoTArray<NPVariant, 10> convertedArgs;
855
0
  uint32_t argCount = aArgs.Length();
856
0
857
0
  if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
858
0
    *aResult = void_t();
859
0
    *aSuccess = false;
860
0
    return IPC_OK();
861
0
  }
862
0
863
0
  for (uint32_t index = 0; index < argCount; index++) {
864
0
    ConvertToVariant(aArgs[index], convertedArgs[index]);
865
0
  }
866
0
867
0
  NPVariant result;
868
0
  VOID_TO_NPVARIANT(result);
869
0
  bool success = mObject->_class->invokeDefault(mObject,
870
0
                                                convertedArgs.Elements(),
871
0
                                                argCount, &result);
872
0
873
0
  for (uint32_t index = 0; index < argCount; index++) {
874
0
    PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
875
0
  }
876
0
877
0
  if (!success) {
878
0
    *aResult = void_t();
879
0
    *aSuccess = false;
880
0
    return IPC_OK();
881
0
  }
882
0
883
0
  Variant convertedResult;
884
0
  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
885
0
                                   false);
886
0
887
0
  DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
888
0
889
0
  if (!success) {
890
0
    *aResult = void_t();
891
0
    *aSuccess = false;
892
0
    return IPC_OK();
893
0
  }
894
0
895
0
  *aResult = convertedResult;
896
0
  *aSuccess = true;
897
0
  return IPC_OK();
898
0
}
899
900
mozilla::ipc::IPCResult
901
PluginScriptableObjectChild::AnswerHasProperty(const PluginIdentifier& aId,
902
                                               bool* aHasProperty)
903
0
{
904
0
  AssertPluginThread();
905
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
906
0
907
0
  if (mInvalidated) {
908
0
    NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
909
0
    *aHasProperty = false;
910
0
    return IPC_OK();
911
0
  }
912
0
913
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
914
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
915
0
916
0
  if (!(mObject->_class && mObject->_class->hasProperty)) {
917
0
    *aHasProperty = false;
918
0
    return IPC_OK();
919
0
  }
920
0
921
0
  StackIdentifier id(aId);
922
0
  *aHasProperty = mObject->_class->hasProperty(mObject, id.ToNPIdentifier());
923
0
  return IPC_OK();
924
0
}
925
926
mozilla::ipc::IPCResult
927
PluginScriptableObjectChild::AnswerGetChildProperty(const PluginIdentifier& aId,
928
                                                    bool* aHasProperty,
929
                                                    bool* aHasMethod,
930
                                                    Variant* aResult,
931
                                                    bool* aSuccess)
932
0
{
933
0
  AssertPluginThread();
934
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
935
0
936
0
  *aHasProperty = *aHasMethod = *aSuccess = false;
937
0
  *aResult = void_t();
938
0
939
0
  if (mInvalidated) {
940
0
    NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
941
0
    return IPC_OK();
942
0
  }
943
0
944
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
945
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
946
0
947
0
  if (!(mObject->_class && mObject->_class->hasProperty &&
948
0
        mObject->_class->hasMethod && mObject->_class->getProperty)) {
949
0
    return IPC_OK();
950
0
  }
951
0
952
0
  StackIdentifier stackID(aId);
953
0
  NPIdentifier id = stackID.ToNPIdentifier();
954
0
955
0
  *aHasProperty = mObject->_class->hasProperty(mObject, id);
956
0
  *aHasMethod = mObject->_class->hasMethod(mObject, id);
957
0
958
0
  if (*aHasProperty) {
959
0
    NPVariant result;
960
0
    VOID_TO_NPVARIANT(result);
961
0
962
0
    if (!mObject->_class->getProperty(mObject, id, &result)) {
963
0
      return IPC_OK();
964
0
    }
965
0
966
0
    Variant converted;
967
0
    if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
968
0
                                            false))) {
969
0
      DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
970
0
      *aResult = converted;
971
0
    }
972
0
  }
973
0
974
0
  return IPC_OK();
975
0
}
976
977
mozilla::ipc::IPCResult
978
PluginScriptableObjectChild::AnswerSetProperty(const PluginIdentifier& aId,
979
                                               const Variant& aValue,
980
                                               bool* aSuccess)
981
0
{
982
0
  AssertPluginThread();
983
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
984
0
985
0
  if (mInvalidated) {
986
0
    NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
987
0
    *aSuccess = false;
988
0
    return IPC_OK();
989
0
  }
990
0
991
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
992
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
993
0
994
0
  if (!(mObject->_class && mObject->_class->hasProperty &&
995
0
        mObject->_class->setProperty)) {
996
0
    *aSuccess = false;
997
0
    return IPC_OK();
998
0
  }
999
0
1000
0
  StackIdentifier stackID(aId);
1001
0
  NPIdentifier id = stackID.ToNPIdentifier();
1002
0
1003
0
  if (!mObject->_class->hasProperty(mObject, id)) {
1004
0
    *aSuccess = false;
1005
0
    return IPC_OK();
1006
0
  }
1007
0
1008
0
  NPVariant converted;
1009
0
  ConvertToVariant(aValue, converted);
1010
0
1011
0
  if ((*aSuccess = mObject->_class->setProperty(mObject, id, &converted))) {
1012
0
    PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted);
1013
0
  }
1014
0
  return IPC_OK();
1015
0
}
1016
1017
mozilla::ipc::IPCResult
1018
PluginScriptableObjectChild::AnswerRemoveProperty(const PluginIdentifier& aId,
1019
                                                  bool* aSuccess)
1020
0
{
1021
0
  AssertPluginThread();
1022
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
1023
0
1024
0
  if (mInvalidated) {
1025
0
    NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
1026
0
    *aSuccess = false;
1027
0
    return IPC_OK();
1028
0
  }
1029
0
1030
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1031
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
1032
0
1033
0
  if (!(mObject->_class && mObject->_class->hasProperty &&
1034
0
        mObject->_class->removeProperty)) {
1035
0
    *aSuccess = false;
1036
0
    return IPC_OK();
1037
0
  }
1038
0
1039
0
  StackIdentifier stackID(aId);
1040
0
  NPIdentifier id = stackID.ToNPIdentifier();
1041
0
  *aSuccess = mObject->_class->hasProperty(mObject, id) ?
1042
0
              mObject->_class->removeProperty(mObject, id) :
1043
0
              true;
1044
0
1045
0
  return IPC_OK();
1046
0
}
1047
1048
mozilla::ipc::IPCResult
1049
PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
1050
                                             bool* aSuccess)
1051
0
{
1052
0
  AssertPluginThread();
1053
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
1054
0
1055
0
  if (mInvalidated) {
1056
0
    NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
1057
0
    *aSuccess = false;
1058
0
    return IPC_OK();
1059
0
  }
1060
0
1061
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1062
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
1063
0
1064
0
  if (!(mObject->_class && mObject->_class->enumerate)) {
1065
0
    *aSuccess = false;
1066
0
    return IPC_OK();
1067
0
  }
1068
0
1069
0
  NPIdentifier* ids;
1070
0
  uint32_t idCount;
1071
0
  if (!mObject->_class->enumerate(mObject, &ids, &idCount)) {
1072
0
    *aSuccess = false;
1073
0
    return IPC_OK();
1074
0
  }
1075
0
1076
0
  aProperties->SetCapacity(idCount);
1077
0
1078
0
  for (uint32_t index = 0; index < idCount; index++) {
1079
0
    aProperties->AppendElement(FromNPIdentifier(ids[index]));
1080
0
  }
1081
0
1082
0
  PluginModuleChild::sBrowserFuncs.memfree(ids);
1083
0
  *aSuccess = true;
1084
0
  return IPC_OK();
1085
0
}
1086
1087
mozilla::ipc::IPCResult
1088
PluginScriptableObjectChild::AnswerConstruct(InfallibleTArray<Variant>&& aArgs,
1089
                                             Variant* aResult,
1090
                                             bool* aSuccess)
1091
0
{
1092
0
  AssertPluginThread();
1093
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
1094
0
1095
0
  if (mInvalidated) {
1096
0
    NS_WARNING("Calling AnswerConstruct with an invalidated object!");
1097
0
    *aResult = void_t();
1098
0
    *aSuccess = false;
1099
0
    return IPC_OK();
1100
0
  }
1101
0
1102
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1103
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
1104
0
1105
0
  if (!(mObject->_class && mObject->_class->construct)) {
1106
0
    *aResult = void_t();
1107
0
    *aSuccess = false;
1108
0
    return IPC_OK();
1109
0
  }
1110
0
1111
0
  AutoTArray<NPVariant, 10> convertedArgs;
1112
0
  uint32_t argCount = aArgs.Length();
1113
0
1114
0
  if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
1115
0
    *aResult = void_t();
1116
0
    *aSuccess = false;
1117
0
    return IPC_OK();
1118
0
  }
1119
0
1120
0
  for (uint32_t index = 0; index < argCount; index++) {
1121
0
    ConvertToVariant(aArgs[index], convertedArgs[index]);
1122
0
  }
1123
0
1124
0
  NPVariant result;
1125
0
  VOID_TO_NPVARIANT(result);
1126
0
  bool success = mObject->_class->construct(mObject, convertedArgs.Elements(),
1127
0
                                            argCount, &result);
1128
0
1129
0
  for (uint32_t index = 0; index < argCount; index++) {
1130
0
    PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
1131
0
  }
1132
0
1133
0
  if (!success) {
1134
0
    *aResult = void_t();
1135
0
    *aSuccess = false;
1136
0
    return IPC_OK();
1137
0
  }
1138
0
1139
0
  Variant convertedResult;
1140
0
  success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
1141
0
                                   false);
1142
0
1143
0
  DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
1144
0
1145
0
  if (!success) {
1146
0
    *aResult = void_t();
1147
0
    *aSuccess = false;
1148
0
    return IPC_OK();
1149
0
  }
1150
0
1151
0
  *aResult = convertedResult;
1152
0
  *aSuccess = true;
1153
0
  return IPC_OK();
1154
0
}
1155
1156
mozilla::ipc::IPCResult
1157
PluginScriptableObjectChild::RecvProtect()
1158
0
{
1159
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1160
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
1161
0
1162
0
  Protect();
1163
0
  return IPC_OK();
1164
0
}
1165
1166
mozilla::ipc::IPCResult
1167
PluginScriptableObjectChild::RecvUnprotect()
1168
0
{
1169
0
  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1170
0
  NS_ASSERTION(mType == LocalObject, "Bad type!");
1171
0
1172
0
  Unprotect();
1173
0
  return IPC_OK();
1174
0
}
1175
1176
bool
1177
PluginScriptableObjectChild::Evaluate(NPString* aScript,
1178
                                      NPVariant* aResult)
1179
0
{
1180
0
  PluginInstanceChild::AutoStackHelper guard(mInstance);
1181
0
1182
0
  nsDependentCString script("");
1183
0
  if (aScript->UTF8Characters && aScript->UTF8Length) {
1184
0
    script.Rebind(aScript->UTF8Characters, aScript->UTF8Length);
1185
0
  }
1186
0
1187
0
  bool success;
1188
0
  Variant result;
1189
0
  CallNPN_Evaluate(script, &result, &success);
1190
0
1191
0
  if (!success) {
1192
0
    return false;
1193
0
  }
1194
0
1195
0
  ConvertToVariant(result, *aResult);
1196
0
  return true;
1197
0
}
1198
1199
nsTHashtable<PluginScriptableObjectChild::NPObjectData>* PluginScriptableObjectChild::sObjectMap;
1200
1201
bool
1202
PluginScriptableObjectChild::RegisterActor(NPObject* aObject)
1203
0
{
1204
0
  AssertPluginThread();
1205
0
  MOZ_ASSERT(aObject, "Null pointer!");
1206
0
1207
0
  NPObjectData* d = sObjectMap->GetEntry(aObject);
1208
0
  if (!d) {
1209
0
    NS_ERROR("NPObject not in object table");
1210
0
    return false;
1211
0
  }
1212
0
1213
0
  d->actor = this;
1214
0
  return true;
1215
0
}
1216
1217
void
1218
PluginScriptableObjectChild::UnregisterActor(NPObject* aObject)
1219
0
{
1220
0
  AssertPluginThread();
1221
0
  MOZ_ASSERT(aObject, "Null pointer!");
1222
0
1223
0
  NPObjectData* d = sObjectMap->GetEntry(aObject);
1224
0
  MOZ_ASSERT(d, "NPObject not in object table");
1225
0
  if (d) {
1226
0
    d->actor = nullptr;
1227
0
  }
1228
0
}
1229
1230
/* static */ PluginScriptableObjectChild*
1231
PluginScriptableObjectChild::GetActorForNPObject(NPObject* aObject)
1232
0
{
1233
0
  AssertPluginThread();
1234
0
  MOZ_ASSERT(aObject, "Null pointer!");
1235
0
1236
0
  NPObjectData* d = sObjectMap->GetEntry(aObject);
1237
0
  if (!d) {
1238
0
    NS_ERROR("Plugin using object not created with NPN_CreateObject?");
1239
0
    return nullptr;
1240
0
  }
1241
0
1242
0
  return d->actor;
1243
0
}
1244
1245
/* static */ void
1246
PluginScriptableObjectChild::RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance)
1247
0
{
1248
0
  AssertPluginThread();
1249
0
1250
0
  if (!sObjectMap) {
1251
0
    sObjectMap = new nsTHashtable<PluginScriptableObjectChild::NPObjectData>();
1252
0
  }
1253
0
1254
0
  NPObjectData* d = sObjectMap->PutEntry(aObject);
1255
0
  MOZ_ASSERT(!d->instance, "New NPObject already mapped?");
1256
0
  d->instance = aInstance;
1257
0
}
1258
1259
/* static */ void
1260
PluginScriptableObjectChild::UnregisterObject(NPObject* aObject)
1261
0
{
1262
0
  AssertPluginThread();
1263
0
1264
0
  sObjectMap->RemoveEntry(aObject);
1265
0
1266
0
  if (!sObjectMap->Count()) {
1267
0
    delete sObjectMap;
1268
0
    sObjectMap = nullptr;
1269
0
  }
1270
0
}
1271
1272
/* static */ PluginInstanceChild*
1273
PluginScriptableObjectChild::GetInstanceForNPObject(NPObject* aObject)
1274
0
{
1275
0
  AssertPluginThread();
1276
0
  if (!sObjectMap) {
1277
0
    // All PluginInstanceChilds have been destroyed
1278
0
    return nullptr;
1279
0
  }
1280
0
1281
0
  NPObjectData* d = sObjectMap->GetEntry(aObject);
1282
0
  if (!d) {
1283
0
    return nullptr;
1284
0
  }
1285
0
  return d->instance;
1286
0
}
1287
1288
/* static */ void
1289
PluginScriptableObjectChild::NotifyOfInstanceShutdown(PluginInstanceChild* aInstance)
1290
0
{
1291
0
  AssertPluginThread();
1292
0
  if (!sObjectMap) {
1293
0
    return;
1294
0
  }
1295
0
1296
0
  for (auto iter = sObjectMap->Iter(); !iter.Done(); iter.Next()) {
1297
0
    NPObjectData* d = iter.Get();
1298
0
    if (d->instance == aInstance) {
1299
0
        NPObject* o = d->GetKey();
1300
0
        aInstance->mDeletingHash->PutEntry(o);
1301
0
    }
1302
0
  }
1303
0
}