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 "PluginScriptableObjectUtils.h"
8 
9 namespace {
10 
11 template<class InstanceType>
12 class VariantTraits;
13 
14 template<>
15 class VariantTraits<mozilla::plugins::PluginInstanceParent>
16 {
17 public:
18   typedef mozilla::plugins::PluginScriptableObjectParent ScriptableObjectType;
19 };
20 
21 template<>
22 class VariantTraits<mozilla::plugins::PluginInstanceChild>
23 {
24 public:
25   typedef mozilla::plugins::PluginScriptableObjectChild ScriptableObjectType;
26 };
27 
28 } /* anonymous namespace */
29 
30 inline bool
ConvertToVariant(const Variant & aRemoteVariant,NPVariant & aVariant,PluginInstanceParent * aInstance)31 mozilla::plugins::ConvertToVariant(const Variant& aRemoteVariant,
32                                    NPVariant& aVariant,
33                                    PluginInstanceParent* aInstance)
34 {
35   switch (aRemoteVariant.type()) {
36     case Variant::Tvoid_t: {
37       VOID_TO_NPVARIANT(aVariant);
38       break;
39     }
40 
41     case Variant::Tnull_t: {
42       NULL_TO_NPVARIANT(aVariant);
43       break;
44     }
45 
46     case Variant::Tbool: {
47       BOOLEAN_TO_NPVARIANT(aRemoteVariant.get_bool(), aVariant);
48       break;
49     }
50 
51     case Variant::Tint: {
52       INT32_TO_NPVARIANT(aRemoteVariant.get_int(), aVariant);
53       break;
54     }
55 
56     case Variant::Tdouble: {
57       DOUBLE_TO_NPVARIANT(aRemoteVariant.get_double(), aVariant);
58       break;
59     }
60 
61     case Variant::TnsCString: {
62       const nsCString& string = aRemoteVariant.get_nsCString();
63       const size_t length = string.Length();
64       NPUTF8* buffer = static_cast<NPUTF8*>(::malloc(sizeof(NPUTF8) * (length + 1)));
65       if (!buffer) {
66         NS_ERROR("Out of memory!");
67         return false;
68       }
69 
70       std::copy(string.get(), string.get() + length, buffer);
71       buffer[length] = '\0';
72       STRINGN_TO_NPVARIANT(buffer, length, aVariant);
73       break;
74     }
75 
76     case Variant::TPPluginScriptableObjectParent: {
77       NS_ASSERTION(aInstance, "Must have an instance!");
78       NPObject* object = NPObjectFromVariant(aRemoteVariant);
79       if (!object) {
80         NS_ERROR("Er, this shouldn't fail!");
81         return false;
82       }
83 
84       const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
85       if (!npn) {
86         NS_ERROR("Null netscape funcs!");
87         return false;
88       }
89 
90       npn->retainobject(object);
91       OBJECT_TO_NPVARIANT(object, aVariant);
92       break;
93     }
94 
95     case Variant::TPPluginScriptableObjectChild: {
96       NS_ASSERTION(!aInstance, "No instance should be given!");
97       NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Plugin,
98                    "Should be running on child only!");
99 
100       NPObject* object = NPObjectFromVariant(aRemoteVariant);
101       NS_ASSERTION(object, "Null object?!");
102 
103       PluginModuleChild::sBrowserFuncs.retainobject(object);
104       OBJECT_TO_NPVARIANT(object, aVariant);
105       break;
106     }
107 
108     default:
109       NS_NOTREACHED("Shouldn't get here!");
110       return false;
111   }
112 
113   return true;
114 }
115 
116 template <class InstanceType>
117 bool
ConvertToRemoteVariant(const NPVariant & aVariant,Variant & aRemoteVariant,InstanceType * aInstance,bool aProtectActors)118 mozilla::plugins::ConvertToRemoteVariant(const NPVariant& aVariant,
119                                          Variant& aRemoteVariant,
120                                          InstanceType* aInstance,
121                                          bool aProtectActors)
122 {
123   if (NPVARIANT_IS_VOID(aVariant)) {
124     aRemoteVariant = mozilla::void_t();
125   }
126   else if (NPVARIANT_IS_NULL(aVariant)) {
127     aRemoteVariant = mozilla::null_t();
128   }
129   else if (NPVARIANT_IS_BOOLEAN(aVariant)) {
130     aRemoteVariant = NPVARIANT_TO_BOOLEAN(aVariant);
131   }
132   else if (NPVARIANT_IS_INT32(aVariant)) {
133     aRemoteVariant = NPVARIANT_TO_INT32(aVariant);
134   }
135   else if (NPVARIANT_IS_DOUBLE(aVariant)) {
136     aRemoteVariant = NPVARIANT_TO_DOUBLE(aVariant);
137   }
138   else if (NPVARIANT_IS_STRING(aVariant)) {
139     NPString str = NPVARIANT_TO_STRING(aVariant);
140     nsCString string(str.UTF8Characters, str.UTF8Length);
141     aRemoteVariant = string;
142   }
143   else if (NPVARIANT_IS_OBJECT(aVariant)) {
144     NPObject* object = NPVARIANT_TO_OBJECT(aVariant);
145 
146     typename VariantTraits<InstanceType>::ScriptableObjectType* actor =
147       aInstance->GetActorForNPObject(object);
148 
149     if (!actor) {
150       NS_ERROR("Null actor!");
151       return false;
152     }
153 
154     if (aProtectActors) {
155       actor->Protect();
156     }
157 
158     aRemoteVariant = actor;
159   }
160   else {
161     NS_NOTREACHED("Shouldn't get here!");
162     return false;
163   }
164 
165   return true;
166 }
167