• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "config.h"
21 #include "JSPluginElementFunctions.h"
22 
23 #include "BridgeJSC.h"
24 #include "HTMLNames.h"
25 #include "HTMLPlugInElement.h"
26 #include "JSHTMLElement.h"
27 #include "PluginViewBase.h"
28 
29 using namespace JSC;
30 
31 namespace WebCore {
32 
33 using namespace Bindings;
34 using namespace HTMLNames;
35 
36 // Runtime object support code for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement.
37 
isPluginElement(Node * node)38 static inline bool isPluginElement(Node* node)
39 {
40     return node->hasTagName(objectTag) || node->hasTagName(embedTag) || node->hasTagName(appletTag);
41 }
42 
pluginInstance(Node * node)43 Instance* pluginInstance(Node* node)
44 {
45     if (!node)
46         return 0;
47     if (!isPluginElement(node))
48         return 0;
49 
50     HTMLPlugInElement* plugInElement = static_cast<HTMLPlugInElement*>(node);
51     // The plugin element holds an owning reference, so we don't have to.
52     Instance* instance = plugInElement->getInstance().get();
53     if (!instance || !instance->rootObject())
54         return 0;
55     return instance;
56 }
57 
pluginScriptObjectFromPluginViewBase(HTMLPlugInElement * pluginElement,JSGlobalObject * globalObject)58 static JSObject* pluginScriptObjectFromPluginViewBase(HTMLPlugInElement* pluginElement, JSGlobalObject* globalObject)
59 {
60     Widget* pluginWidget = pluginElement->pluginWidget();
61     if (!pluginWidget)
62         return 0;
63 
64     if (!pluginWidget->isPluginViewBase())
65         return 0;
66 
67     PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(pluginWidget);
68     return pluginViewBase->scriptObject(globalObject);
69 }
70 
pluginScriptObjectFromPluginViewBase(JSHTMLElement * jsHTMLElement)71 static JSObject* pluginScriptObjectFromPluginViewBase(JSHTMLElement* jsHTMLElement)
72 {
73     HTMLElement* element = jsHTMLElement->impl();
74     if (!isPluginElement(element))
75         return 0;
76 
77     HTMLPlugInElement* pluginElement = static_cast<HTMLPlugInElement*>(element);
78     return pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject());
79 }
80 
pluginScriptObject(ExecState * exec,JSHTMLElement * jsHTMLElement)81 JSObject* pluginScriptObject(ExecState* exec, JSHTMLElement* jsHTMLElement)
82 {
83     HTMLElement* element = jsHTMLElement->impl();
84     if (!isPluginElement(element))
85         return 0;
86 
87     HTMLPlugInElement* pluginElement = static_cast<HTMLPlugInElement*>(element);
88 
89     // First, see if we can ask the plug-in view for its script object.
90     if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()))
91         return scriptObject;
92 
93     // Otherwise, fall back to getting the object from the instance.
94 
95     // The plugin element holds an owning reference, so we don't have to.
96     Instance* instance = pluginElement->getInstance().get();
97     if (!instance || !instance->rootObject())
98         return 0;
99 
100     return instance->createRuntimeObject(exec);
101 }
102 
runtimeObjectPropertyGetter(ExecState * exec,JSValue slotBase,const Identifier & propertyName)103 JSValue runtimeObjectPropertyGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
104 {
105     JSHTMLElement* element = static_cast<JSHTMLElement*>(asObject(slotBase));
106     JSObject* scriptObject = pluginScriptObject(exec, element);
107     if (!scriptObject)
108         return jsUndefined();
109 
110     return scriptObject->get(exec, propertyName);
111 }
112 
runtimeObjectCustomGetOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot,JSHTMLElement * element)113 bool runtimeObjectCustomGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, JSHTMLElement* element)
114 {
115     JSObject* scriptObject = pluginScriptObject(exec, element);
116     if (!scriptObject)
117         return false;
118 
119     if (!scriptObject->hasProperty(exec, propertyName))
120         return false;
121     slot.setCustom(element, runtimeObjectPropertyGetter);
122     return true;
123 }
124 
runtimeObjectCustomGetOwnPropertyDescriptor(ExecState * exec,const Identifier & propertyName,PropertyDescriptor & descriptor,JSHTMLElement * element)125 bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element)
126 {
127     JSObject* scriptObject = pluginScriptObject(exec, element);
128     if (!scriptObject)
129         return false;
130     if (!scriptObject->hasProperty(exec, propertyName))
131         return false;
132     PropertySlot slot;
133     slot.setCustom(element, runtimeObjectPropertyGetter);
134     // While we don't know what the plugin allows, we do know that we prevent
135     // enumeration or deletion of properties, so we mark plugin properties
136     // as DontEnum | DontDelete
137     descriptor.setDescriptor(slot.getValue(exec, propertyName), DontEnum | DontDelete);
138     return true;
139 }
140 
runtimeObjectCustomPut(ExecState * exec,const Identifier & propertyName,JSValue value,JSHTMLElement * element,PutPropertySlot & slot)141 bool runtimeObjectCustomPut(ExecState* exec, const Identifier& propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot)
142 {
143     JSObject* scriptObject = pluginScriptObject(exec, element);
144     if (!scriptObject)
145         return 0;
146     if (!scriptObject->hasProperty(exec, propertyName))
147         return false;
148     scriptObject->put(exec, propertyName, value, slot);
149     return true;
150 }
151 
callPlugin(ExecState * exec)152 static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec)
153 {
154     JSHTMLElement* element = static_cast<JSHTMLElement*>(exec->callee());
155 
156     // Get the plug-in script object.
157     JSObject* scriptObject = pluginScriptObject(exec, element);
158     ASSERT(scriptObject);
159 
160     size_t argumentCount = exec->argumentCount();
161     MarkedArgumentBuffer argumentList;
162     for (size_t i = 0; i < argumentCount; i++)
163         argumentList.append(exec->argument(i));
164 
165     CallData callData;
166     CallType callType = getCallData(scriptObject, callData);
167     ASSERT(callType == CallTypeHost);
168 
169     // Call the object.
170     JSValue result = call(exec, scriptObject, callType, callData, exec->hostThisValue(), argumentList);
171     return JSValue::encode(result);
172 }
173 
runtimeObjectGetCallData(JSHTMLElement * element,CallData & callData)174 CallType runtimeObjectGetCallData(JSHTMLElement* element, CallData& callData)
175 {
176     // First, ask the plug-in view base for its runtime object.
177     if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(element)) {
178         CallData scriptObjectCallData;
179 
180         if (scriptObject->getCallData(scriptObjectCallData) == CallTypeNone)
181             return CallTypeNone;
182 
183         callData.native.function = callPlugin;
184         return CallTypeHost;
185     }
186 
187     Instance* instance = pluginInstance(element->impl());
188     if (!instance || !instance->supportsInvokeDefaultMethod())
189         return CallTypeNone;
190     callData.native.function = callPlugin;
191     return CallTypeHost;
192 }
193 
194 } // namespace WebCore
195