1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "NPRemoteObjectMap.h"
28
29#if ENABLE(NETSCAPE_PLUGIN_API)
30
31#include "NPObjectMessageReceiver.h"
32#include "NPObjectProxy.h"
33#include "NPRuntimeUtilities.h"
34#include "NPVariantData.h"
35
36namespace WebKit {
37
38static uint64_t generateNPObjectID()
39{
40 static uint64_t generateNPObjectID;
41 return ++generateNPObjectID;
42}
43
44Ref<NPRemoteObjectMap> NPRemoteObjectMap::create(IPC::Connection* connection)
45{
46 return adoptRef(*new NPRemoteObjectMap(connection));
47}
48
49NPRemoteObjectMap::NPRemoteObjectMap(IPC::Connection* connection)
50 : m_connection(connection)
51{
52}
53
54NPRemoteObjectMap::~NPRemoteObjectMap()
55{
56 ASSERT(m_npObjectProxies.isEmpty());
57 ASSERT(m_registeredNPObjects.isEmpty());
58}
59
60NPObject* NPRemoteObjectMap::createNPObjectProxy(uint64_t remoteObjectID, Plugin* plugin)
61{
62 NPObjectProxy* npObjectProxy = NPObjectProxy::create(this, plugin, remoteObjectID);
63
64 m_npObjectProxies.add(npObjectProxy);
65
66 return npObjectProxy;
67}
68
69void NPRemoteObjectMap::npObjectProxyDestroyed(NPObject* npObject)
70{
71 NPObjectProxy* npObjectProxy = NPObjectProxy::toNPObjectProxy(npObject);
72 ASSERT(m_npObjectProxies.contains(npObjectProxy));
73
74 m_npObjectProxies.remove(npObjectProxy);
75}
76
77uint64_t NPRemoteObjectMap::registerNPObject(NPObject* npObject, Plugin* plugin)
78{
79 uint64_t npObjectID = generateNPObjectID();
80 m_registeredNPObjects.set(npObjectID, std::make_unique<NPObjectMessageReceiver>(this, plugin, npObjectID, npObject).release());
81
82 return npObjectID;
83}
84
85void NPRemoteObjectMap::unregisterNPObject(uint64_t npObjectID)
86{
87 m_registeredNPObjects.remove(npObjectID);
88}
89
90static uint64_t remoteNPObjectID(Plugin* plugin, NPObject* npObject)
91{
92 if (!NPObjectProxy::isNPObjectProxy(npObject))
93 return 0;
94
95 NPObjectProxy* npObjectProxy = NPObjectProxy::toNPObjectProxy(npObject);
96 if (npObjectProxy->plugin() != plugin)
97 return 0;
98
99 return npObjectProxy->npObjectID();
100}
101
102NPVariantData NPRemoteObjectMap::npVariantToNPVariantData(const NPVariant& variant, Plugin* plugin)
103{
104 switch (variant.type) {
105 case NPVariantType_Void:
106 return NPVariantData::makeVoid();
107
108 case NPVariantType_Null:
109 return NPVariantData::makeNull();
110
111 case NPVariantType_Bool:
112 return NPVariantData::makeBool(variant.value.boolValue);
113
114 case NPVariantType_Int32:
115 return NPVariantData::makeInt32(variant.value.intValue);
116
117 case NPVariantType_Double:
118 return NPVariantData::makeDouble(variant.value.doubleValue);
119
120 case NPVariantType_String:
121 return NPVariantData::makeString(variant.value.stringValue.UTF8Characters, variant.value.stringValue.UTF8Length);
122
123 case NPVariantType_Object: {
124 NPObject* npObject = variant.value.objectValue;
125
126 if (uint64_t npObjectID = remoteNPObjectID(plugin, npObject)) {
127 // FIXME: Under some circumstances, this might leak the NPObjectProxy object.
128 // Figure out how to avoid that.
129 retainNPObject(npObject);
130 return NPVariantData::makeRemoteNPObjectID(npObjectID);
131 }
132
133 uint64_t npObjectID = registerNPObject(npObject, plugin);
134 return NPVariantData::makeLocalNPObjectID(npObjectID);
135 }
136
137 }
138
139 ASSERT_NOT_REACHED();
140 return NPVariantData::makeVoid();
141}
142
143NPVariant NPRemoteObjectMap::npVariantDataToNPVariant(const NPVariantData& npVariantData, Plugin* plugin)
144{
145 NPVariant npVariant;
146
147 switch (npVariantData.type()) {
148 case NPVariantData::Void:
149 VOID_TO_NPVARIANT(npVariant);
150 break;
151 case NPVariantData::Null:
152 NULL_TO_NPVARIANT(npVariant);
153 break;
154 case NPVariantData::Bool:
155 BOOLEAN_TO_NPVARIANT(npVariantData.boolValue(), npVariant);
156 break;
157 case NPVariantData::Int32:
158 INT32_TO_NPVARIANT(npVariantData.int32Value(), npVariant);
159 break;
160 case NPVariantData::Double:
161 DOUBLE_TO_NPVARIANT(npVariantData.doubleValue(), npVariant);
162 break;
163 case NPVariantData::String: {
164 NPString npString = createNPString(npVariantData.stringValue());
165 STRINGN_TO_NPVARIANT(npString.UTF8Characters, npString.UTF8Length, npVariant);
166 break;
167 }
168 case NPVariantData::LocalNPObjectID: {
169 uint64_t npObjectID = npVariantData.localNPObjectIDValue();
170 ASSERT(npObjectID);
171
172 NPObjectMessageReceiver* npObjectMessageReceiver = m_registeredNPObjects.get(npObjectID);
173 if (!npObjectMessageReceiver) {
174 ASSERT_NOT_REACHED();
175 VOID_TO_NPVARIANT(npVariant);
176 break;
177 }
178
179 NPObject* npObject = npObjectMessageReceiver->npObject();
180 ASSERT(npObject);
181
182 retainNPObject(npObject);
183 OBJECT_TO_NPVARIANT(npObject, npVariant);
184 break;
185 }
186 case NPVariantData::RemoteNPObjectID: {
187 NPObject* npObjectProxy = createNPObjectProxy(npVariantData.remoteNPObjectIDValue(), plugin);
188 OBJECT_TO_NPVARIANT(npObjectProxy, npVariant);
189 break;
190 }
191 }
192
193 return npVariant;
194}
195
196void NPRemoteObjectMap::pluginDestroyed(Plugin* plugin)
197{
198 // Gather and delete the receivers associated with this plug-in.
199 Vector<NPObjectMessageReceiver*> receivers;
200 for (auto* receiver : m_registeredNPObjects.values()) {
201 if (receiver->plugin() == plugin)
202 receivers.append(receiver);
203 }
204 for (auto* receiver : receivers)
205 delete receiver;
206
207 // Invalidate and remove all proxies associated with this plug-in.
208 Vector<NPObjectProxy*> proxies;
209 for (auto* proxy : m_npObjectProxies) {
210 if (proxy->plugin() == plugin)
211 proxies.append(proxy);
212 }
213 for (auto* proxy : proxies) {
214 proxy->invalidate();
215 ASSERT(m_npObjectProxies.contains(proxy));
216 m_npObjectProxies.remove(proxy);
217 }
218}
219
220void NPRemoteObjectMap::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
221{
222 NPObjectMessageReceiver* messageReceiver = m_registeredNPObjects.get(decoder.destinationID());
223 if (!messageReceiver)
224 return;
225
226 messageReceiver->didReceiveSyncNPObjectMessageReceiverMessage(connection, decoder, replyEncoder);
227}
228
229} // namespace WebKit
230
231#endif // ENABLE(NETSCAPE_PLUGIN_API)
232