Line data Source code
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 3 : PluginScriptableObjectChild::IdentifierTable PluginScriptableObjectChild::sIdentifiers;
40 :
41 : /* static */ PluginScriptableObjectChild::StoredIdentifier*
42 0 : PluginScriptableObjectChild::HashIdentifier(const nsCString& aIdentifier)
43 : {
44 0 : StoredIdentifier* stored = sIdentifiers.Get(aIdentifier).get();
45 0 : if (stored) {
46 0 : return stored;
47 : }
48 :
49 0 : stored = new StoredIdentifier(aIdentifier);
50 0 : sIdentifiers.Put(aIdentifier, stored);
51 0 : return stored;
52 : }
53 :
54 : /* static */ void
55 0 : PluginScriptableObjectChild::UnhashIdentifier(StoredIdentifier* aStored)
56 : {
57 0 : MOZ_ASSERT(sIdentifiers.Get(aStored->mIdentifier));
58 0 : sIdentifiers.Remove(aStored->mIdentifier);
59 0 : }
60 :
61 : /* static */ void
62 0 : PluginScriptableObjectChild::ClearIdentifiers()
63 : {
64 0 : sIdentifiers.Clear();
65 0 : }
66 :
67 0 : PluginScriptableObjectChild::StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier)
68 : : mIdentifier(aIdentifier),
69 0 : mStored(nullptr)
70 : {
71 0 : if (aIdentifier.type() == PluginIdentifier::TnsCString) {
72 0 : mStored = PluginScriptableObjectChild::HashIdentifier(mIdentifier.get_nsCString());
73 : }
74 0 : }
75 :
76 0 : PluginScriptableObjectChild::StackIdentifier::StackIdentifier(NPIdentifier aIdentifier)
77 0 : : mStored(nullptr)
78 : {
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 : } else {
84 0 : mStored = static_cast<StoredIdentifier*>(aIdentifier);
85 0 : mIdentifier = mStored->mIdentifier;
86 : }
87 0 : }
88 :
89 0 : PluginScriptableObjectChild::StackIdentifier::~StackIdentifier()
90 : {
91 0 : if (!mStored) {
92 0 : return;
93 : }
94 :
95 : // Each StackIdentifier owns one reference to its StoredIdentifier. In
96 : // addition, the sIdentifiers table owns a reference. If mPermanent is false
97 : // and sIdentifiers has the last reference, then we want to remove the
98 : // 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 : }
104 0 : }
105 :
106 : NPIdentifier
107 0 : PluginScriptableObjectChild::StackIdentifier::ToNPIdentifier() const
108 : {
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 : }
114 :
115 0 : int32_t num = mIdentifier.get_int32_t();
116 : // 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 : }
120 :
121 : static PluginIdentifier
122 0 : FromNPIdentifier(NPIdentifier aIdentifier)
123 : {
124 0 : PluginScriptableObjectChild::StackIdentifier stack(aIdentifier);
125 0 : return stack.GetIdentifier();
126 : }
127 :
128 : // static
129 : NPObject*
130 0 : PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
131 : NPClass* aClass)
132 : {
133 0 : AssertPluginThread();
134 :
135 0 : if (aClass != GetClass()) {
136 0 : MOZ_CRASH("Huh?! Wrong class!");
137 : }
138 :
139 0 : return new ChildNPObject();
140 : }
141 :
142 : // static
143 : void
144 0 : PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject)
145 : {
146 0 : AssertPluginThread();
147 :
148 0 : if (aObject->_class != GetClass()) {
149 0 : MOZ_CRASH("Don't know what kind of object this is!");
150 : }
151 :
152 0 : ChildNPObject* object = reinterpret_cast<ChildNPObject*>(aObject);
153 0 : if (object->invalidated) {
154 : // This can happen more than once, and is just fine.
155 0 : return;
156 : }
157 :
158 0 : object->invalidated = true;
159 : }
160 :
161 : // static
162 : void
163 0 : PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject)
164 : {
165 0 : AssertPluginThread();
166 :
167 0 : if (aObject->_class != GetClass()) {
168 0 : MOZ_CRASH("Don't know what kind of object this is!");
169 : }
170 :
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 : }
177 :
178 0 : delete object;
179 0 : }
180 :
181 : // static
182 : bool
183 0 : PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject,
184 : NPIdentifier aName)
185 : {
186 0 : AssertPluginThread();
187 :
188 0 : if (aObject->_class != GetClass()) {
189 0 : MOZ_CRASH("Don't know what kind of object this is!");
190 : }
191 :
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 : }
197 :
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 :
202 : bool result;
203 0 : actor->CallHasMethod(FromNPIdentifier(aName), &result);
204 :
205 0 : return result;
206 : }
207 :
208 : // static
209 : bool
210 0 : PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
211 : NPIdentifier aName,
212 : const NPVariant* aArgs,
213 : uint32_t aArgCount,
214 : NPVariant* aResult)
215 : {
216 0 : AssertPluginThread();
217 :
218 0 : if (aObject->_class != GetClass()) {
219 0 : MOZ_CRASH("Don't know what kind of object this is!");
220 : }
221 :
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 : }
227 :
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 :
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 : }
237 :
238 0 : Variant remoteResult;
239 : bool success;
240 0 : actor->CallInvoke(FromNPIdentifier(aName), args,
241 0 : &remoteResult, &success);
242 :
243 0 : if (!success) {
244 0 : return false;
245 : }
246 :
247 0 : ConvertToVariant(remoteResult, *aResult);
248 0 : return true;
249 : }
250 :
251 : // static
252 : bool
253 0 : PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject,
254 : const NPVariant* aArgs,
255 : uint32_t aArgCount,
256 : NPVariant* aResult)
257 : {
258 0 : AssertPluginThread();
259 :
260 0 : if (aObject->_class != GetClass()) {
261 0 : MOZ_CRASH("Don't know what kind of object this is!");
262 : }
263 :
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 : }
269 :
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 :
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 : }
279 :
280 0 : Variant remoteResult;
281 : bool success;
282 0 : actor->CallInvokeDefault(args, &remoteResult, &success);
283 :
284 0 : if (!success) {
285 0 : return false;
286 : }
287 :
288 0 : ConvertToVariant(remoteResult, *aResult);
289 0 : return true;
290 : }
291 :
292 : // static
293 : bool
294 0 : PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject,
295 : NPIdentifier aName)
296 : {
297 0 : AssertPluginThread();
298 :
299 0 : if (aObject->_class != GetClass()) {
300 0 : MOZ_CRASH("Don't know what kind of object this is!");
301 : }
302 :
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 : }
308 :
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 :
313 : bool result;
314 0 : actor->CallHasProperty(FromNPIdentifier(aName), &result);
315 :
316 0 : return result;
317 : }
318 :
319 : // static
320 : bool
321 0 : PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
322 : NPIdentifier aName,
323 : NPVariant* aResult)
324 : {
325 0 : AssertPluginThread();
326 :
327 0 : if (aObject->_class != GetClass()) {
328 0 : MOZ_CRASH("Don't know what kind of object this is!");
329 : }
330 :
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 : }
336 :
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 :
341 0 : PluginInstanceChild::AutoStackHelper guard(actor->mInstance);
342 :
343 0 : Variant result;
344 : bool success;
345 0 : actor->CallGetParentProperty(FromNPIdentifier(aName),
346 0 : &result, &success);
347 :
348 0 : if (!success) {
349 0 : return false;
350 : }
351 :
352 0 : ConvertToVariant(result, *aResult);
353 0 : return true;
354 : }
355 :
356 : // static
357 : bool
358 0 : PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject,
359 : NPIdentifier aName,
360 : const NPVariant* aValue)
361 : {
362 0 : AssertPluginThread();
363 :
364 0 : if (aObject->_class != GetClass()) {
365 0 : MOZ_CRASH("Don't know what kind of object this is!");
366 : }
367 :
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 : }
373 :
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 :
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 : }
383 :
384 : bool success;
385 0 : actor->CallSetProperty(FromNPIdentifier(aName), value,
386 0 : &success);
387 :
388 0 : return success;
389 : }
390 :
391 : // static
392 : bool
393 0 : PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
394 : NPIdentifier aName)
395 : {
396 0 : AssertPluginThread();
397 :
398 0 : if (aObject->_class != GetClass()) {
399 0 : MOZ_CRASH("Don't know what kind of object this is!");
400 : }
401 :
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 : }
407 :
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 :
412 : bool success;
413 0 : actor->CallRemoveProperty(FromNPIdentifier(aName),
414 0 : &success);
415 :
416 0 : return success;
417 : }
418 :
419 : // static
420 : bool
421 0 : PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
422 : NPIdentifier** aIdentifiers,
423 : uint32_t* aCount)
424 : {
425 0 : AssertPluginThread();
426 :
427 0 : if (aObject->_class != GetClass()) {
428 0 : MOZ_CRASH("Don't know what kind of object this is!");
429 : }
430 :
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 : }
436 :
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 :
441 0 : AutoTArray<PluginIdentifier, 10> identifiers;
442 : bool success;
443 0 : actor->CallEnumerate(&identifiers, &success);
444 :
445 0 : if (!success) {
446 0 : return false;
447 : }
448 :
449 0 : *aCount = identifiers.Length();
450 0 : if (!*aCount) {
451 0 : *aIdentifiers = nullptr;
452 0 : return true;
453 : }
454 :
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 : }
461 :
462 0 : for (uint32_t index = 0; index < *aCount; index++) {
463 0 : StackIdentifier id(identifiers[index]);
464 : // Make the id permanent in case the plugin retains it.
465 0 : id.MakePermanent();
466 0 : (*aIdentifiers)[index] = id.ToNPIdentifier();
467 : }
468 0 : return true;
469 : }
470 :
471 : // static
472 : bool
473 0 : PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject,
474 : const NPVariant* aArgs,
475 : uint32_t aArgCount,
476 : NPVariant* aResult)
477 : {
478 0 : AssertPluginThread();
479 :
480 0 : if (aObject->_class != GetClass()) {
481 0 : MOZ_CRASH("Don't know what kind of object this is!");
482 : }
483 :
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 : }
489 :
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 :
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 : }
499 :
500 0 : Variant remoteResult;
501 : bool success;
502 0 : actor->CallConstruct(args, &remoteResult, &success);
503 :
504 0 : if (!success) {
505 0 : return false;
506 : }
507 :
508 0 : ConvertToVariant(remoteResult, *aResult);
509 0 : return true;
510 : }
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 0 : PluginScriptableObjectChild::PluginScriptableObjectChild(
529 0 : ScriptableObjectType aType)
530 : : mInstance(nullptr),
531 : mObject(nullptr),
532 : mInvalidated(false),
533 : mProtectCount(0),
534 0 : mType(aType)
535 : {
536 0 : AssertPluginThread();
537 0 : }
538 :
539 0 : PluginScriptableObjectChild::~PluginScriptableObjectChild()
540 : {
541 0 : AssertPluginThread();
542 :
543 0 : if (mObject) {
544 0 : UnregisterActor(mObject);
545 :
546 0 : if (mObject->_class == GetClass()) {
547 0 : NS_ASSERTION(mType == Proxy, "Wrong type!");
548 0 : static_cast<ChildNPObject*>(mObject)->parent = nullptr;
549 : }
550 : else {
551 0 : NS_ASSERTION(mType == LocalObject, "Wrong type!");
552 0 : PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
553 : }
554 : }
555 0 : }
556 :
557 : bool
558 0 : PluginScriptableObjectChild::InitializeProxy()
559 : {
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 :
565 0 : mInstance = static_cast<PluginInstanceChild*>(Manager());
566 0 : NS_ASSERTION(mInstance, "Null manager?!");
567 :
568 0 : NPObject* object = CreateProxyObject();
569 0 : if (!object) {
570 0 : NS_ERROR("Failed to create object!");
571 0 : return false;
572 : }
573 :
574 0 : if (!RegisterActor(object)) {
575 0 : NS_ERROR("RegisterActor failed");
576 0 : return false;
577 : }
578 :
579 0 : mObject = object;
580 0 : return true;
581 : }
582 :
583 : void
584 0 : PluginScriptableObjectChild::InitializeLocal(NPObject* aObject)
585 : {
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 :
591 0 : mInstance = static_cast<PluginInstanceChild*>(Manager());
592 0 : NS_ASSERTION(mInstance, "Null manager?!");
593 :
594 0 : PluginModuleChild::sBrowserFuncs.retainobject(aObject);
595 :
596 0 : NS_ASSERTION(!mProtectCount, "Should be zero!");
597 0 : mProtectCount++;
598 :
599 0 : if (!RegisterActor(aObject)) {
600 0 : NS_ERROR("RegisterActor failed");
601 : }
602 :
603 0 : mObject = aObject;
604 0 : }
605 :
606 : NPObject*
607 0 : PluginScriptableObjectChild::CreateProxyObject()
608 : {
609 0 : NS_ASSERTION(mInstance, "Must have an instance!");
610 0 : NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
611 :
612 0 : NPClass* proxyClass = const_cast<NPClass*>(GetClass());
613 : 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 :
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 :
624 : // We don't want to have the actor own this object but rather let the object
625 : // own this actor. Set the reference count to 0 here so that when the object
626 : // dies we will send the destructor message to the child.
627 0 : object->referenceCount = 0;
628 0 : NS_LOG_RELEASE(object, 0, "NPObject");
629 :
630 0 : object->parent = const_cast<PluginScriptableObjectChild*>(this);
631 0 : return object;
632 : }
633 :
634 : bool
635 0 : PluginScriptableObjectChild::ResurrectProxyObject()
636 : {
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 :
641 0 : if (!InitializeProxy()) {
642 0 : NS_ERROR("Initialize failed!");
643 0 : return false;
644 : }
645 :
646 0 : SendProtect();
647 0 : return true;
648 : }
649 :
650 : NPObject*
651 0 : PluginScriptableObjectChild::GetObject(bool aCanResurrect)
652 : {
653 0 : if (!mObject && aCanResurrect && !ResurrectProxyObject()) {
654 0 : NS_ERROR("Null object!");
655 0 : return nullptr;
656 : }
657 0 : return mObject;
658 : }
659 :
660 : void
661 0 : PluginScriptableObjectChild::Protect()
662 : {
663 0 : NS_ASSERTION(mObject, "No object!");
664 0 : NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
665 :
666 0 : if (mType == LocalObject) {
667 0 : ++mProtectCount;
668 : }
669 0 : }
670 :
671 : void
672 0 : PluginScriptableObjectChild::Unprotect()
673 : {
674 0 : NS_ASSERTION(mObject, "Bad state!");
675 0 : NS_ASSERTION(mProtectCount >= 0, "Negative retain count?!");
676 :
677 0 : if (mType == LocalObject) {
678 0 : if (--mProtectCount == 0) {
679 0 : PluginScriptableObjectChild::Send__delete__(this);
680 : }
681 : }
682 0 : }
683 :
684 : void
685 0 : PluginScriptableObjectChild::DropNPObject()
686 : {
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 :
691 : // We think we're about to be deleted, but we could be racing with the other
692 : // process.
693 0 : UnregisterActor(mObject);
694 0 : mObject = nullptr;
695 :
696 0 : SendUnprotect();
697 0 : }
698 :
699 : void
700 0 : PluginScriptableObjectChild::NPObjectDestroyed()
701 : {
702 0 : NS_ASSERTION(LocalObject == mType,
703 : "ScriptableDeallocate should have handled this for proxies");
704 0 : mInvalidated = true;
705 0 : mObject = nullptr;
706 0 : }
707 :
708 : mozilla::ipc::IPCResult
709 0 : PluginScriptableObjectChild::AnswerInvalidate()
710 : {
711 0 : AssertPluginThread();
712 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
713 :
714 0 : if (mInvalidated) {
715 0 : return IPC_OK();
716 : }
717 :
718 0 : mInvalidated = true;
719 :
720 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
721 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
722 :
723 0 : if (mObject->_class && mObject->_class->invalidate) {
724 0 : mObject->_class->invalidate(mObject);
725 : }
726 :
727 0 : Unprotect();
728 :
729 0 : return IPC_OK();
730 : }
731 :
732 : mozilla::ipc::IPCResult
733 0 : PluginScriptableObjectChild::AnswerHasMethod(const PluginIdentifier& aId,
734 : bool* aHasMethod)
735 : {
736 0 : AssertPluginThread();
737 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
738 :
739 0 : if (mInvalidated) {
740 0 : NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
741 0 : *aHasMethod = false;
742 0 : return IPC_OK();
743 : }
744 :
745 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
746 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
747 :
748 0 : if (!(mObject->_class && mObject->_class->hasMethod)) {
749 0 : *aHasMethod = false;
750 0 : return IPC_OK();
751 : }
752 :
753 0 : StackIdentifier id(aId);
754 0 : *aHasMethod = mObject->_class->hasMethod(mObject, id.ToNPIdentifier());
755 0 : return IPC_OK();
756 : }
757 :
758 : mozilla::ipc::IPCResult
759 0 : PluginScriptableObjectChild::AnswerInvoke(const PluginIdentifier& aId,
760 : InfallibleTArray<Variant>&& aArgs,
761 : Variant* aResult,
762 : bool* aSuccess)
763 : {
764 0 : AssertPluginThread();
765 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
766 :
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 : }
773 :
774 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
775 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
776 :
777 0 : if (!(mObject->_class && mObject->_class->invoke)) {
778 0 : *aResult = void_t();
779 0 : *aSuccess = false;
780 0 : return IPC_OK();
781 : }
782 :
783 0 : AutoTArray<NPVariant, 10> convertedArgs;
784 0 : uint32_t argCount = aArgs.Length();
785 :
786 0 : if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
787 0 : *aResult = void_t();
788 0 : *aSuccess = false;
789 0 : return IPC_OK();
790 : }
791 :
792 0 : for (uint32_t index = 0; index < argCount; index++) {
793 0 : ConvertToVariant(aArgs[index], convertedArgs[index]);
794 : }
795 :
796 : 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 :
803 0 : for (uint32_t index = 0; index < argCount; index++) {
804 0 : PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
805 : }
806 :
807 0 : if (!success) {
808 0 : *aResult = void_t();
809 0 : *aSuccess = false;
810 0 : return IPC_OK();
811 : }
812 :
813 0 : Variant convertedResult;
814 0 : success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
815 0 : false);
816 :
817 0 : DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
818 :
819 0 : if (!success) {
820 0 : *aResult = void_t();
821 0 : *aSuccess = false;
822 0 : return IPC_OK();
823 : }
824 :
825 0 : *aSuccess = true;
826 0 : *aResult = convertedResult;
827 0 : return IPC_OK();
828 : }
829 :
830 : mozilla::ipc::IPCResult
831 0 : PluginScriptableObjectChild::AnswerInvokeDefault(InfallibleTArray<Variant>&& aArgs,
832 : Variant* aResult,
833 : bool* aSuccess)
834 : {
835 0 : AssertPluginThread();
836 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
837 :
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 : }
844 :
845 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
846 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
847 :
848 0 : if (!(mObject->_class && mObject->_class->invokeDefault)) {
849 0 : *aResult = void_t();
850 0 : *aSuccess = false;
851 0 : return IPC_OK();
852 : }
853 :
854 0 : AutoTArray<NPVariant, 10> convertedArgs;
855 0 : uint32_t argCount = aArgs.Length();
856 :
857 0 : if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
858 0 : *aResult = void_t();
859 0 : *aSuccess = false;
860 0 : return IPC_OK();
861 : }
862 :
863 0 : for (uint32_t index = 0; index < argCount; index++) {
864 0 : ConvertToVariant(aArgs[index], convertedArgs[index]);
865 : }
866 :
867 : 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 :
873 0 : for (uint32_t index = 0; index < argCount; index++) {
874 0 : PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
875 : }
876 :
877 0 : if (!success) {
878 0 : *aResult = void_t();
879 0 : *aSuccess = false;
880 0 : return IPC_OK();
881 : }
882 :
883 0 : Variant convertedResult;
884 0 : success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
885 0 : false);
886 :
887 0 : DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
888 :
889 0 : if (!success) {
890 0 : *aResult = void_t();
891 0 : *aSuccess = false;
892 0 : return IPC_OK();
893 : }
894 :
895 0 : *aResult = convertedResult;
896 0 : *aSuccess = true;
897 0 : return IPC_OK();
898 : }
899 :
900 : mozilla::ipc::IPCResult
901 0 : PluginScriptableObjectChild::AnswerHasProperty(const PluginIdentifier& aId,
902 : bool* aHasProperty)
903 : {
904 0 : AssertPluginThread();
905 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
906 :
907 0 : if (mInvalidated) {
908 0 : NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
909 0 : *aHasProperty = false;
910 0 : return IPC_OK();
911 : }
912 :
913 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
914 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
915 :
916 0 : if (!(mObject->_class && mObject->_class->hasProperty)) {
917 0 : *aHasProperty = false;
918 0 : return IPC_OK();
919 : }
920 :
921 0 : StackIdentifier id(aId);
922 0 : *aHasProperty = mObject->_class->hasProperty(mObject, id.ToNPIdentifier());
923 0 : return IPC_OK();
924 : }
925 :
926 : mozilla::ipc::IPCResult
927 0 : PluginScriptableObjectChild::AnswerGetChildProperty(const PluginIdentifier& aId,
928 : bool* aHasProperty,
929 : bool* aHasMethod,
930 : Variant* aResult,
931 : bool* aSuccess)
932 : {
933 0 : AssertPluginThread();
934 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
935 :
936 0 : *aHasProperty = *aHasMethod = *aSuccess = false;
937 0 : *aResult = void_t();
938 :
939 0 : if (mInvalidated) {
940 0 : NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
941 0 : return IPC_OK();
942 : }
943 :
944 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
945 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
946 :
947 0 : if (!(mObject->_class && mObject->_class->hasProperty &&
948 0 : mObject->_class->hasMethod && mObject->_class->getProperty)) {
949 0 : return IPC_OK();
950 : }
951 :
952 0 : StackIdentifier stackID(aId);
953 0 : NPIdentifier id = stackID.ToNPIdentifier();
954 :
955 0 : *aHasProperty = mObject->_class->hasProperty(mObject, id);
956 0 : *aHasMethod = mObject->_class->hasMethod(mObject, id);
957 :
958 0 : if (*aHasProperty) {
959 : NPVariant result;
960 0 : VOID_TO_NPVARIANT(result);
961 :
962 0 : if (!mObject->_class->getProperty(mObject, id, &result)) {
963 0 : return IPC_OK();
964 : }
965 :
966 0 : Variant converted;
967 0 : if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
968 : false))) {
969 0 : DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
970 0 : *aResult = converted;
971 : }
972 : }
973 :
974 0 : return IPC_OK();
975 : }
976 :
977 : mozilla::ipc::IPCResult
978 0 : PluginScriptableObjectChild::AnswerSetProperty(const PluginIdentifier& aId,
979 : const Variant& aValue,
980 : bool* aSuccess)
981 : {
982 0 : AssertPluginThread();
983 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
984 :
985 0 : if (mInvalidated) {
986 0 : NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
987 0 : *aSuccess = false;
988 0 : return IPC_OK();
989 : }
990 :
991 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
992 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
993 :
994 0 : if (!(mObject->_class && mObject->_class->hasProperty &&
995 0 : mObject->_class->setProperty)) {
996 0 : *aSuccess = false;
997 0 : return IPC_OK();
998 : }
999 :
1000 0 : StackIdentifier stackID(aId);
1001 0 : NPIdentifier id = stackID.ToNPIdentifier();
1002 :
1003 0 : if (!mObject->_class->hasProperty(mObject, id)) {
1004 0 : *aSuccess = false;
1005 0 : return IPC_OK();
1006 : }
1007 :
1008 : NPVariant converted;
1009 0 : ConvertToVariant(aValue, converted);
1010 :
1011 0 : if ((*aSuccess = mObject->_class->setProperty(mObject, id, &converted))) {
1012 0 : PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted);
1013 : }
1014 0 : return IPC_OK();
1015 : }
1016 :
1017 : mozilla::ipc::IPCResult
1018 0 : PluginScriptableObjectChild::AnswerRemoveProperty(const PluginIdentifier& aId,
1019 : bool* aSuccess)
1020 : {
1021 0 : AssertPluginThread();
1022 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
1023 :
1024 0 : if (mInvalidated) {
1025 0 : NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
1026 0 : *aSuccess = false;
1027 0 : return IPC_OK();
1028 : }
1029 :
1030 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1031 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1032 :
1033 0 : if (!(mObject->_class && mObject->_class->hasProperty &&
1034 0 : mObject->_class->removeProperty)) {
1035 0 : *aSuccess = false;
1036 0 : return IPC_OK();
1037 : }
1038 :
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 : true;
1044 :
1045 0 : return IPC_OK();
1046 : }
1047 :
1048 : mozilla::ipc::IPCResult
1049 0 : PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
1050 : bool* aSuccess)
1051 : {
1052 0 : AssertPluginThread();
1053 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
1054 :
1055 0 : if (mInvalidated) {
1056 0 : NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
1057 0 : *aSuccess = false;
1058 0 : return IPC_OK();
1059 : }
1060 :
1061 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1062 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1063 :
1064 0 : if (!(mObject->_class && mObject->_class->enumerate)) {
1065 0 : *aSuccess = false;
1066 0 : return IPC_OK();
1067 : }
1068 :
1069 : NPIdentifier* ids;
1070 : uint32_t idCount;
1071 0 : if (!mObject->_class->enumerate(mObject, &ids, &idCount)) {
1072 0 : *aSuccess = false;
1073 0 : return IPC_OK();
1074 : }
1075 :
1076 0 : aProperties->SetCapacity(idCount);
1077 :
1078 0 : for (uint32_t index = 0; index < idCount; index++) {
1079 0 : aProperties->AppendElement(FromNPIdentifier(ids[index]));
1080 : }
1081 :
1082 0 : PluginModuleChild::sBrowserFuncs.memfree(ids);
1083 0 : *aSuccess = true;
1084 0 : return IPC_OK();
1085 : }
1086 :
1087 : mozilla::ipc::IPCResult
1088 0 : PluginScriptableObjectChild::AnswerConstruct(InfallibleTArray<Variant>&& aArgs,
1089 : Variant* aResult,
1090 : bool* aSuccess)
1091 : {
1092 0 : AssertPluginThread();
1093 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
1094 :
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 : }
1101 :
1102 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1103 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1104 :
1105 0 : if (!(mObject->_class && mObject->_class->construct)) {
1106 0 : *aResult = void_t();
1107 0 : *aSuccess = false;
1108 0 : return IPC_OK();
1109 : }
1110 :
1111 0 : AutoTArray<NPVariant, 10> convertedArgs;
1112 0 : uint32_t argCount = aArgs.Length();
1113 :
1114 0 : if (!convertedArgs.SetLength(argCount, mozilla::fallible)) {
1115 0 : *aResult = void_t();
1116 0 : *aSuccess = false;
1117 0 : return IPC_OK();
1118 : }
1119 :
1120 0 : for (uint32_t index = 0; index < argCount; index++) {
1121 0 : ConvertToVariant(aArgs[index], convertedArgs[index]);
1122 : }
1123 :
1124 : NPVariant result;
1125 0 : VOID_TO_NPVARIANT(result);
1126 0 : bool success = mObject->_class->construct(mObject, convertedArgs.Elements(),
1127 0 : argCount, &result);
1128 :
1129 0 : for (uint32_t index = 0; index < argCount; index++) {
1130 0 : PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
1131 : }
1132 :
1133 0 : if (!success) {
1134 0 : *aResult = void_t();
1135 0 : *aSuccess = false;
1136 0 : return IPC_OK();
1137 : }
1138 :
1139 0 : Variant convertedResult;
1140 0 : success = ConvertToRemoteVariant(result, convertedResult, GetInstance(),
1141 0 : false);
1142 :
1143 0 : DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
1144 :
1145 0 : if (!success) {
1146 0 : *aResult = void_t();
1147 0 : *aSuccess = false;
1148 0 : return IPC_OK();
1149 : }
1150 :
1151 0 : *aResult = convertedResult;
1152 0 : *aSuccess = true;
1153 0 : return IPC_OK();
1154 : }
1155 :
1156 : mozilla::ipc::IPCResult
1157 0 : PluginScriptableObjectChild::RecvProtect()
1158 : {
1159 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1160 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1161 :
1162 0 : Protect();
1163 0 : return IPC_OK();
1164 : }
1165 :
1166 : mozilla::ipc::IPCResult
1167 0 : PluginScriptableObjectChild::RecvUnprotect()
1168 : {
1169 0 : NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
1170 0 : NS_ASSERTION(mType == LocalObject, "Bad type!");
1171 :
1172 0 : Unprotect();
1173 0 : return IPC_OK();
1174 : }
1175 :
1176 : bool
1177 0 : PluginScriptableObjectChild::Evaluate(NPString* aScript,
1178 : NPVariant* aResult)
1179 : {
1180 0 : PluginInstanceChild::AutoStackHelper guard(mInstance);
1181 :
1182 0 : nsDependentCString script("");
1183 0 : if (aScript->UTF8Characters && aScript->UTF8Length) {
1184 0 : script.Rebind(aScript->UTF8Characters, aScript->UTF8Length);
1185 : }
1186 :
1187 : bool success;
1188 0 : Variant result;
1189 0 : CallNPN_Evaluate(script, &result, &success);
1190 :
1191 0 : if (!success) {
1192 0 : return false;
1193 : }
1194 :
1195 0 : ConvertToVariant(result, *aResult);
1196 0 : return true;
1197 : }
1198 :
1199 : nsTHashtable<PluginScriptableObjectChild::NPObjectData>* PluginScriptableObjectChild::sObjectMap;
1200 :
1201 : bool
1202 0 : PluginScriptableObjectChild::RegisterActor(NPObject* aObject)
1203 : {
1204 0 : AssertPluginThread();
1205 0 : MOZ_ASSERT(aObject, "Null pointer!");
1206 :
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 : }
1212 :
1213 0 : d->actor = this;
1214 0 : return true;
1215 : }
1216 :
1217 : void
1218 0 : PluginScriptableObjectChild::UnregisterActor(NPObject* aObject)
1219 : {
1220 0 : AssertPluginThread();
1221 0 : MOZ_ASSERT(aObject, "Null pointer!");
1222 :
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 : }
1228 0 : }
1229 :
1230 : /* static */ PluginScriptableObjectChild*
1231 0 : PluginScriptableObjectChild::GetActorForNPObject(NPObject* aObject)
1232 : {
1233 0 : AssertPluginThread();
1234 0 : MOZ_ASSERT(aObject, "Null pointer!");
1235 :
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 : }
1241 :
1242 0 : return d->actor;
1243 : }
1244 :
1245 : /* static */ void
1246 0 : PluginScriptableObjectChild::RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance)
1247 : {
1248 0 : AssertPluginThread();
1249 :
1250 0 : if (!sObjectMap) {
1251 0 : sObjectMap = new nsTHashtable<PluginScriptableObjectChild::NPObjectData>();
1252 : }
1253 :
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 0 : PluginScriptableObjectChild::UnregisterObject(NPObject* aObject)
1261 : {
1262 0 : AssertPluginThread();
1263 :
1264 0 : sObjectMap->RemoveEntry(aObject);
1265 :
1266 0 : if (!sObjectMap->Count()) {
1267 0 : delete sObjectMap;
1268 0 : sObjectMap = nullptr;
1269 : }
1270 0 : }
1271 :
1272 : /* static */ PluginInstanceChild*
1273 0 : PluginScriptableObjectChild::GetInstanceForNPObject(NPObject* aObject)
1274 : {
1275 0 : AssertPluginThread();
1276 0 : NPObjectData* d = sObjectMap->GetEntry(aObject);
1277 0 : if (!d) {
1278 0 : return nullptr;
1279 : }
1280 0 : return d->instance;
1281 : }
1282 :
1283 : /* static */ void
1284 0 : PluginScriptableObjectChild::NotifyOfInstanceShutdown(PluginInstanceChild* aInstance)
1285 : {
1286 0 : AssertPluginThread();
1287 0 : if (!sObjectMap) {
1288 0 : return;
1289 : }
1290 :
1291 0 : for (auto iter = sObjectMap->Iter(); !iter.Done(); iter.Next()) {
1292 0 : NPObjectData* d = iter.Get();
1293 0 : if (d->instance == aInstance) {
1294 0 : NPObject* o = d->GetKey();
1295 0 : aInstance->mDeletingHash->PutEntry(o);
1296 : }
1297 : }
1298 : }
|