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// JavaScript access to plug-in-exported properties for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. 37 38static inline bool isPluginElement(HTMLElement& element) 39{ 40 return element.hasTagName(objectTag) || element.hasTagName(embedTag) || element.hasTagName(appletTag); 41} 42 43Instance* pluginInstance(HTMLElement& element) 44{ 45 // The plugin element holds an owning reference, so we don't have to. 46 if (!isPluginElement(element)) 47 return 0; 48 Instance* instance = toHTMLPlugInElement(element).getInstance().get(); 49 if (!instance || !instance->rootObject()) 50 return 0; 51 return instance; 52} 53 54static JSObject* pluginScriptObjectFromPluginViewBase(HTMLPlugInElement& pluginElement, JSGlobalObject* globalObject) 55{ 56 Widget* pluginWidget = pluginElement.pluginWidget(); 57 if (!pluginWidget) 58 return 0; 59 60 if (!pluginWidget->isPluginViewBase()) 61 return 0; 62 63 PluginViewBase* pluginViewBase = toPluginViewBase(pluginWidget); 64 return pluginViewBase->scriptObject(globalObject); 65} 66 67static JSObject* pluginScriptObjectFromPluginViewBase(JSHTMLElement* jsHTMLElement) 68{ 69 HTMLElement& element = jsHTMLElement->impl(); 70 if (!isPluginElement(element)) 71 return 0; 72 73 HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element); 74 return pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()); 75} 76 77JSObject* pluginScriptObject(ExecState* exec, JSHTMLElement* jsHTMLElement) 78{ 79 HTMLElement& element = jsHTMLElement->impl(); 80 if (!isPluginElement(element)) 81 return 0; 82 83 HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element); 84 85 // First, see if the element has a plug-in replacement with a script. 86 if (JSObject* scriptObject = pluginElement.scriptObjectForPluginReplacement()) 87 return scriptObject; 88 89 // Next, 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 103EncodedJSValue pluginElementPropertyGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName propertyName) 104{ 105 106 JSHTMLElement* thisObject = jsDynamicCast<JSHTMLElement*>(JSValue::decode(thisValue)); 107 if (!thisObject) 108 return throwVMTypeError(exec); 109 JSObject* scriptObject = pluginScriptObject(exec, thisObject); 110 if (!scriptObject) 111 return JSValue::encode(jsUndefined()); 112 113 return JSValue::encode(scriptObject->get(exec, propertyName)); 114} 115 116bool pluginElementCustomGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot, JSHTMLElement* element) 117{ 118 JSObject* scriptObject = pluginScriptObject(exec, element); 119 if (!scriptObject) 120 return false; 121 122 if (!scriptObject->hasProperty(exec, propertyName)) 123 return false; 124 slot.setCustom(element, DontDelete | DontEnum, pluginElementPropertyGetter); 125 return true; 126} 127 128bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot) 129{ 130 JSObject* scriptObject = pluginScriptObject(exec, element); 131 if (!scriptObject) 132 return 0; 133 if (!scriptObject->hasProperty(exec, propertyName)) 134 return false; 135 scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot); 136 return true; 137} 138 139static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec) 140{ 141 JSHTMLElement* element = jsCast<JSHTMLElement*>(exec->callee()); 142 143 // Get the plug-in script object. 144 JSObject* scriptObject = pluginScriptObject(exec, element); 145 ASSERT(scriptObject); 146 147 size_t argumentCount = exec->argumentCount(); 148 MarkedArgumentBuffer argumentList; 149 for (size_t i = 0; i < argumentCount; i++) 150 argumentList.append(exec->argument(i)); 151 152 CallData callData; 153 CallType callType = getCallData(scriptObject, callData); 154 ASSERT(callType == CallTypeHost); 155 156 // Call the object. 157 JSValue result = call(exec, scriptObject, callType, callData, exec->thisValue(), argumentList); 158 return JSValue::encode(result); 159} 160 161CallType pluginElementGetCallData(JSHTMLElement* element, CallData& callData) 162{ 163 // First, ask the plug-in view base for its runtime object. 164 if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(element)) { 165 CallData scriptObjectCallData; 166 167 if (scriptObject->methodTable()->getCallData(scriptObject, scriptObjectCallData) == CallTypeNone) 168 return CallTypeNone; 169 170 callData.native.function = callPlugin; 171 return CallTypeHost; 172 } 173 174 Instance* instance = pluginInstance(element->impl()); 175 if (!instance || !instance->supportsInvokeDefaultMethod()) 176 return CallTypeNone; 177 callData.native.function = callPlugin; 178 return CallTypeHost; 179} 180 181} // namespace WebCore 182