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(PLUGIN_PROCESS)
30
31#include "NPObjectMessageReceiver.h"
32#include "NPObjectProxy.h"
33#include "NPRuntimeUtilities.h"
34#include "NPVariantData.h"
35#include <WebCore/NotImplemented.h>
36#include <wtf/OwnPtr.h>
37
38namespace WebKit {
39
40static uint64_t generateNPObjectID()
41{
42    static uint64_t generateNPObjectID;
43    return ++generateNPObjectID;
44}
45
46PassRefPtr<NPRemoteObjectMap> NPRemoteObjectMap::create(CoreIPC::Connection* connection)
47{
48    return adoptRef(new NPRemoteObjectMap(connection));
49}
50
51NPRemoteObjectMap::NPRemoteObjectMap(CoreIPC::Connection* connection)
52    : m_connection(connection)
53{
54}
55
56NPRemoteObjectMap::~NPRemoteObjectMap()
57{
58    ASSERT(m_npObjectProxies.isEmpty());
59    ASSERT(m_registeredNPObjects.isEmpty());
60}
61
62NPObject* NPRemoteObjectMap::createNPObjectProxy(uint64_t remoteObjectID, Plugin* plugin)
63{
64    NPObjectProxy* npObjectProxy = NPObjectProxy::create(this, plugin, remoteObjectID);
65
66    m_npObjectProxies.add(npObjectProxy);
67
68    return npObjectProxy;
69}
70
71void NPRemoteObjectMap::npObjectProxyDestroyed(NPObject* npObject)
72{
73    NPObjectProxy* npObjectProxy = NPObjectProxy::toNPObjectProxy(npObject);
74    ASSERT(m_npObjectProxies.contains(npObjectProxy));
75
76    m_npObjectProxies.remove(npObjectProxy);
77}
78
79uint64_t NPRemoteObjectMap::registerNPObject(NPObject* npObject, Plugin* plugin)
80{
81    uint64_t npObjectID = generateNPObjectID();
82    m_registeredNPObjects.set(npObjectID, NPObjectMessageReceiver::create(this, plugin, npObjectID, npObject).leakPtr());
83
84    return npObjectID;
85}
86
87void NPRemoteObjectMap::unregisterNPObject(uint64_t npObjectID)
88{
89    m_registeredNPObjects.remove(npObjectID);
90}
91
92NPVariantData NPRemoteObjectMap::npVariantToNPVariantData(const NPVariant& variant, Plugin* plugin)
93{
94    switch (variant.type) {
95    case NPVariantType_Void:
96        return NPVariantData::makeVoid();
97
98    case NPVariantType_Null:
99        return NPVariantData::makeNull();
100
101    case NPVariantType_Bool:
102        return NPVariantData::makeBool(variant.value.boolValue);
103
104    case NPVariantType_Int32:
105        return NPVariantData::makeInt32(variant.value.intValue);
106
107    case NPVariantType_Double:
108        return NPVariantData::makeDouble(variant.value.doubleValue);
109
110    case NPVariantType_String:
111        return NPVariantData::makeString(variant.value.stringValue.UTF8Characters, variant.value.stringValue.UTF8Length);
112
113    case NPVariantType_Object: {
114        NPObject* npObject = variant.value.objectValue;
115        if (NPObjectProxy::isNPObjectProxy(npObject)) {
116            NPObjectProxy* npObjectProxy = NPObjectProxy::toNPObjectProxy(npObject);
117
118            uint64_t npObjectID = npObjectProxy->npObjectID();
119
120            // FIXME: Under some circumstances, this might leak the NPObjectProxy object.
121            // Figure out how to avoid that.
122            retainNPObject(npObjectProxy);
123            return NPVariantData::makeRemoteNPObjectID(npObjectID);
124        }
125
126        uint64_t npObjectID = registerNPObject(npObject, plugin);
127        return NPVariantData::makeLocalNPObjectID(npObjectID);
128    }
129
130    }
131
132    ASSERT_NOT_REACHED();
133    return NPVariantData::makeVoid();
134}
135
136NPVariant NPRemoteObjectMap::npVariantDataToNPVariant(const NPVariantData& npVariantData, Plugin* plugin)
137{
138    NPVariant npVariant;
139
140    switch (npVariantData.type()) {
141    case NPVariantData::Void:
142        VOID_TO_NPVARIANT(npVariant);
143        break;
144    case NPVariantData::Null:
145        NULL_TO_NPVARIANT(npVariant);
146        break;
147    case NPVariantData::Bool:
148        BOOLEAN_TO_NPVARIANT(npVariantData.boolValue(), npVariant);
149        break;
150    case NPVariantData::Int32:
151        INT32_TO_NPVARIANT(npVariantData.int32Value(), npVariant);
152        break;
153    case NPVariantData::Double:
154        DOUBLE_TO_NPVARIANT(npVariantData.doubleValue(), npVariant);
155        break;
156    case NPVariantData::String: {
157        NPString npString = createNPString(npVariantData.stringValue());
158        STRINGN_TO_NPVARIANT(npString.UTF8Characters, npString.UTF8Length, npVariant);
159        break;
160    }
161    case NPVariantData::LocalNPObjectID: {
162        uint64_t npObjectID = npVariantData.localNPObjectIDValue();
163        ASSERT(npObjectID);
164
165        NPObjectMessageReceiver* npObjectMessageReceiver = m_registeredNPObjects.get(npObjectID);
166        if (!npObjectMessageReceiver) {
167            ASSERT_NOT_REACHED();
168            VOID_TO_NPVARIANT(npVariant);
169            break;
170        }
171
172        NPObject* npObject = npObjectMessageReceiver->npObject();
173        ASSERT(npObject);
174
175        retainNPObject(npObject);
176        OBJECT_TO_NPVARIANT(npObject, npVariant);
177        break;
178    }
179    case NPVariantData::RemoteNPObjectID: {
180        NPObject* npObjectProxy = createNPObjectProxy(npVariantData.remoteNPObjectIDValue(), plugin);
181        OBJECT_TO_NPVARIANT(npObjectProxy, npVariant);
182        break;
183    }
184    }
185
186    return npVariant;
187}
188
189void NPRemoteObjectMap::pluginDestroyed(Plugin* plugin)
190{
191    Vector<NPObjectMessageReceiver*> messageReceivers;
192
193    // Gather the receivers associated with this plug-in.
194    for (HashMap<uint64_t, NPObjectMessageReceiver*>::const_iterator it = m_registeredNPObjects.begin(), end = m_registeredNPObjects.end(); it != end; ++it) {
195        NPObjectMessageReceiver* npObjectMessageReceiver = it->second;
196        if (npObjectMessageReceiver->plugin() == plugin)
197            messageReceivers.append(npObjectMessageReceiver);
198    }
199
200    // Now delete all the receivers.
201    deleteAllValues(messageReceivers);
202
203    Vector<NPObjectProxy*> objectProxies;
204    for (HashSet<NPObjectProxy*>::const_iterator it = m_npObjectProxies.begin(), end = m_npObjectProxies.end(); it != end; ++it) {
205        NPObjectProxy* npObjectProxy = *it;
206
207        if (npObjectProxy->plugin() == plugin)
208            objectProxies.append(npObjectProxy);
209    }
210
211    // Invalidate and remove all proxies associated with this plug-in.
212    for (size_t i = 0; i < objectProxies.size(); ++i) {
213        NPObjectProxy* npObjectProxy = objectProxies[i];
214
215        npObjectProxy->invalidate();
216
217        ASSERT(m_npObjectProxies.contains(npObjectProxy));
218        m_npObjectProxies.remove(npObjectProxy);
219    }
220}
221
222CoreIPC::SyncReplyMode NPRemoteObjectMap::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
223{
224    NPObjectMessageReceiver* messageReceiver = m_registeredNPObjects.get(arguments->destinationID());
225    if (!messageReceiver)
226        return CoreIPC::AutomaticReply;
227
228    return messageReceiver->didReceiveSyncNPObjectMessageReceiverMessage(connection, messageID, arguments, reply);
229}
230
231} // namespace WebKit
232
233#endif // ENABLE(PLUGIN_PROCESS)
234