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 29using namespace JSC; 30 31namespace WebCore { 32 33using namespace Bindings; 34using namespace HTMLNames; 35 36// Runtime object support code for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. 37 38static inline bool isPluginElement(Node* node) 39{ 40 return node->hasTagName(objectTag) || node->hasTagName(embedTag) || node->hasTagName(appletTag); 41} 42 43Instance* 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 58static 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 71static 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 81JSObject* 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 103JSValue 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 113bool 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 125bool 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 141bool 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 152static 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 174CallType 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