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
44PassRefPtr<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::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& 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