diff options
Diffstat (limited to 'WebCore/bindings')
52 files changed, 472 insertions, 439 deletions
diff --git a/WebCore/bindings/ScriptControllerBase.cpp b/WebCore/bindings/ScriptControllerBase.cpp index cbd4214..9bea8ae 100644 --- a/WebCore/bindings/ScriptControllerBase.cpp +++ b/WebCore/bindings/ScriptControllerBase.cpp @@ -44,12 +44,12 @@ bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reaso return allowed; } -ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) +ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture, ShouldAllowXSS shouldAllowXSS) { - return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url())); + return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()), shouldAllowXSS); } -ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) +ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode, ShouldAllowXSS shouldAllowXSS) { if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) return ScriptValue(); @@ -57,7 +57,7 @@ ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) bool wasInExecuteScript = m_inExecuteScript; m_inExecuteScript = true; - ScriptValue result = evaluate(sourceCode); + ScriptValue result = evaluate(sourceCode, shouldAllowXSS); if (!wasInExecuteScript) { m_inExecuteScript = false; @@ -80,10 +80,10 @@ bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, const int javascriptSchemeLength = sizeof("javascript:") - 1; - String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength)); + String decodedURL = decodeURLEscapeSequences(url.string()); ScriptValue result; - if (xssAuditor()->canEvaluateJavaScriptURL(script)) - result = executeScript(script, userGesture); + if (xssAuditor()->canEvaluateJavaScriptURL(decodedURL)) + result = executeScript(decodedURL.substring(javascriptSchemeLength), userGesture, AllowXSS); String scriptResult; #if USE(JSC) diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index d5a1789..f193b2e 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -61,7 +61,7 @@ GCController::GCController() void GCController::garbageCollectSoon() { if (!m_GCTimer.isActive()) - m_GCTimer.startOneShot(0.5); + m_GCTimer.startOneShot(0); } void GCController::gcTimerFired(Timer<GCController>*) diff --git a/WebCore/bindings/js/JSAttrCustom.cpp b/WebCore/bindings/js/JSAttrCustom.cpp index 4cd40ac..998ecad 100644 --- a/WebCore/bindings/js/JSAttrCustom.cpp +++ b/WebCore/bindings/js/JSAttrCustom.cpp @@ -31,9 +31,8 @@ #include "CSSHelper.h" #include "Document.h" -#include "HTMLFrameElementBase.h" +#include "Element.h" #include "HTMLNames.h" -#include "JSDOMBinding.h" using namespace JSC; @@ -41,20 +40,6 @@ namespace WebCore { using namespace HTMLNames; -void JSAttr::setValue(ExecState* exec, JSValue value) -{ - Attr* imp = static_cast<Attr*>(impl()); - String attrValue = valueToStringWithNullCheck(exec, value); - - Element* ownerElement = imp->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->name(), attrValue)) - return; - - ExceptionCode ec = 0; - imp->setValue(attrValue, ec); - setDOMException(exec, ec); -} - void JSAttr::markChildren(MarkStack& markStack) { Base::markChildren(markStack); diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index cd6ddfb..7a105ff 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -85,6 +85,7 @@ #include "JSJavaScriptCallFrameCustom.cpp" #include "JSLazyEventListener.cpp" #include "JSLocationCustom.cpp" +#include "JSMainThreadExecState.cpp" #include "JSMessageChannelConstructor.cpp" #include "JSMessageChannelCustom.cpp" #include "JSMessageEventCustom.cpp" diff --git a/WebCore/bindings/js/JSCallbackData.cpp b/WebCore/bindings/js/JSCallbackData.cpp index e128f27..e813da2 100644 --- a/WebCore/bindings/js/JSCallbackData.cpp +++ b/WebCore/bindings/js/JSCallbackData.cpp @@ -31,6 +31,7 @@ #include "Document.h" #include "JSDOMBinding.h" +#include "JSMainThreadExecState.h" using namespace JSC; @@ -59,7 +60,9 @@ JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedE } globalObject()->globalData()->timeoutChecker.start(); - JSValue result = JSC::call(exec, function, callType, callData, callback(), args); + JSValue result = globalObject()->scriptExecutionContext()->isDocument() + ? JSMainThreadExecState::call(exec, function, callType, callData, callback(), args) + : JSC::call(exec, function, callType, callData, callback(), args); globalObject()->globalData()->timeoutChecker.stop(); Document::updateStyleForAllDocuments(); diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index a4c3d6a..87d8cf7 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -686,7 +686,7 @@ KURL completeURL(ExecState* exec, const String& relativeURL) JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); } Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo) diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 209be3f..215e09a 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -58,7 +58,10 @@ namespace WebCore { // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { public: - JSDOMGlobalObject* globalObject() const { return static_cast<JSDOMGlobalObject*>(getAnonymousValue(GlobalObjectSlot).asCell()); } + JSDOMGlobalObject* globalObject() const + { + return static_cast<JSDOMGlobalObject*>(DOMObject::globalObject()); + } ScriptExecutionContext* scriptExecutionContext() const { @@ -72,19 +75,14 @@ namespace WebCore { } protected: - static const unsigned AnonymousSlotCount = 1 + DOMObject::AnonymousSlotCount; - static const unsigned GlobalObjectSlot = AnonymousSlotCount - 1; - DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) - : DOMObject(structure) + : DOMObject(globalObject, structure) { // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create // new JavaScript objects on detached windows due to DOMWindow::document() // needing to reach through the frame to get to the Document*. See bug 27640. // ASSERT(globalObject->scriptExecutionContext()); - putAnonymousValue(GlobalObjectSlot, globalObject); } - virtual ~DOMObjectWithGlobalPointer() { } }; // Base class for all constructor objects in the JSC bindings. diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index 656d580..343c8f9 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -130,7 +130,7 @@ void JSDOMWindow::markChildren(MarkStack& markStack) template<NativeFunction nativeFunction, int length> JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); } static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp index 1e82a49..65096b9 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -61,10 +61,11 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) RefPtr<Structure> prototypeStructure = JSDOMWindowPrototype::createStructure(jsNull()); - ProtectedPtr<JSDOMWindowPrototype> prototype = new JSDOMWindowPrototype(prototypeStructure.release()); + ProtectedPtr<JSDOMWindowPrototype> prototype = new JSDOMWindowPrototype(0, prototypeStructure.release()); RefPtr<Structure> structure = JSDOMWindow::createStructure(prototype); JSDOMWindow* jsDOMWindow = new (JSDOMWindow::commonJSGlobalData()) JSDOMWindow(structure.release(), domWindow, this); + prototype->putAnonymousValue(0, jsDOMWindow); setWindow(jsDOMWindow); } diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h index 1b986b8..888325d 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.h +++ b/WebCore/bindings/js/JSDOMWindowShell.h @@ -37,8 +37,8 @@ namespace WebCore { class DOMWindow; class Frame; - class JSDOMWindowShell : public DOMObject { - typedef DOMObject Base; + class JSDOMWindowShell : public JSC::JSObject { + typedef JSC::JSObject Base; public: JSDOMWindowShell(PassRefPtr<DOMWindow>, DOMWrapperWorld* world); virtual ~JSDOMWindowShell(); @@ -66,7 +66,7 @@ namespace WebCore { DOMWrapperWorld* world() { return m_world.get(); } private: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | DOMObject::StructureFlags; + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | Base::StructureFlags; virtual void markChildren(JSC::MarkStack&); virtual JSC::UString className() const; diff --git a/WebCore/bindings/js/JSDOMWrapper.h b/WebCore/bindings/js/JSDOMWrapper.h index 00594cf..2d09f01 100644 --- a/WebCore/bindings/js/JSDOMWrapper.h +++ b/WebCore/bindings/js/JSDOMWrapper.h @@ -22,15 +22,15 @@ #ifndef JSDOMWrapper_h #define JSDOMWrapper_h -#include <runtime/JSObject.h> +#include <runtime/JSObjectWithGlobalObject.h> namespace WebCore { -// Base class for all objects in this binding except Window. -class DOMObject : public JSC::JSObject { +// FIXME: Rename to JSDOMWrapper. +class DOMObject : public JSC::JSObjectWithGlobalObject { protected: - explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) - : JSObject(structure) + explicit DOMObject(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) + : JSObjectWithGlobalObject(globalObject, structure) { } diff --git a/WebCore/bindings/js/JSEventCustom.cpp b/WebCore/bindings/js/JSEventCustom.cpp index e5fdbe7..bc69323 100644 --- a/WebCore/bindings/js/JSEventCustom.cpp +++ b/WebCore/bindings/js/JSEventCustom.cpp @@ -32,11 +32,13 @@ #include "Clipboard.h" #include "CompositionEvent.h" #include "CustomEvent.h" +#include "DeviceOrientationEvent.h" #include "Event.h" #include "JSBeforeLoadEvent.h" #include "JSClipboard.h" #include "JSCustomEvent.h" #include "JSCompositionEvent.h" +#include "JSDeviceOrientationEvent.h" #include "JSErrorEvent.h" #if ENABLE(INDEXED_DATABASE) #include "JSIDBErrorEvent.h" @@ -171,6 +173,10 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, PopStateEvent, event); else if (event->isCustomEvent()) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CustomEvent, event); +#if ENABLE(DEVICE_ORIENTATION) + else if (event->isDeviceOrientationEvent()) + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, DeviceOrientationEvent, event); +#endif else wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Event, event); diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index c64aa29..e25a5d1 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -24,6 +24,7 @@ #include "Frame.h" #include "JSEvent.h" #include "JSEventTarget.h" +#include "JSMainThreadExecState.h" #include <runtime/JSLock.h> #include <wtf/RefCountedLeakCounter.h> @@ -111,9 +112,17 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); globalData->timeoutChecker.start(); - JSValue retval = handleEventFunction - ? JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args) - : JSC::call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args); + JSValue retval; + if (handleEventFunction) { + retval = scriptExecutionContext->isDocument() + ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, jsFunction, args) + : JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args); + } else { + JSValue currentTarget = toJS(exec, globalObject, event->currentTarget()); + retval = scriptExecutionContext->isDocument() + ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, currentTarget, args) + : JSC::call(exec, jsFunction, callType, callData, currentTarget, args); + } globalData->timeoutChecker.stop(); globalObject->setCurrentEvent(savedEvent); diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index c031b30..53b554f 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -40,17 +40,17 @@ namespace WebCore { static JSValue nonCachingStaticBackFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); } static JSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); } static JSValue nonCachingStaticGoFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); } bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index 1fedd7e..df191b7 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -36,6 +36,7 @@ #if ENABLE(INSPECTOR) #include "Console.h" +#include "JSMainThreadExecState.h" #if ENABLE(DATABASE) #include "Database.h" #include "JSDatabase.h" @@ -82,7 +83,7 @@ ScriptObject InjectedScriptHost::createInjectedScript(const String& source, Scri JSLock lock(SilenceAssertionsOnly); JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); JSValue globalThisValue = scriptState->globalThisValue(); - Completion comp = JSC::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); + Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) return ScriptObject(); JSValue functionValue = comp.value(); diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index e92a750..da35c23 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -41,17 +41,17 @@ namespace WebCore { static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); } static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); } static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); } bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/WebCore/bindings/js/JSMainThreadExecState.cpp b/WebCore/bindings/js/JSMainThreadExecState.cpp new file mode 100644 index 0000000..d679a58 --- /dev/null +++ b/WebCore/bindings/js/JSMainThreadExecState.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSMainThreadExecState.h" + +namespace WebCore { + +JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0; + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSMainThreadExecState.h b/WebCore/bindings/js/JSMainThreadExecState.h new file mode 100644 index 0000000..8193d7c --- /dev/null +++ b/WebCore/bindings/js/JSMainThreadExecState.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSMainThreadExecState_h +#define JSMainThreadExecState_h + +#include <JSDOMBinding.h> +#ifndef NDEBUG +#include <wtf/MainThread.h> +#endif +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class JSMainThreadExecState : public Noncopyable { +public: + static JSC::ExecState* currentState() + { + ASSERT(WTF::isMainThread()); + return s_mainThreadState; + }; + + static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args) + { + JSMainThreadExecState currentState(exec); + return JSC::call(exec, functionObject, callType, callData, thisValue, args); + }; + + static JSC::Completion evaluate(JSC::ExecState* exec, JSC::ScopeChain& chain, const JSC::SourceCode& source, JSC::JSValue thisValue) + { + JSMainThreadExecState currentState(exec); + return JSC::evaluate(exec, chain, source, thisValue); + }; + +protected: + explicit JSMainThreadExecState(JSC::ExecState* exec) + : m_previousState(s_mainThreadState) + { + ASSERT(WTF::isMainThread()); + s_mainThreadState = exec; + }; + + ~JSMainThreadExecState() + { + ASSERT(WTF::isMainThread()); + s_mainThreadState = m_previousState; + } + +private: + static JSC::ExecState* s_mainThreadState; + JSC::ExecState* m_previousState; +}; + +// Null state prevents origin security checks. +class JSMainThreadNullState : private JSMainThreadExecState { +public: + explicit JSMainThreadNullState() : JSMainThreadExecState(0) {}; +}; + +} // namespace WebCore + +#endif // JSMainThreadExecState_h diff --git a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp index e1c490e..8df9304 100644 --- a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp +++ b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp @@ -35,38 +35,6 @@ using namespace JSC; namespace WebCore { -JSValue JSNamedNodeMap::setNamedItem(ExecState* exec, const ArgList& args) -{ - NamedNodeMap* imp = static_cast<NamedNodeMap*>(impl()); - ExceptionCode ec = 0; - Node* newNode = toNode(args.at(0)); - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) - return jsNull(); - } - - JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItem(newNode, ec))); - setDOMException(exec, ec); - return result; -} - -JSValue JSNamedNodeMap::setNamedItemNS(ExecState* exec, const ArgList& args) -{ - NamedNodeMap* imp = static_cast<NamedNodeMap*>(impl()); - ExceptionCode ec = 0; - Node* newNode = toNode(args.at(0)); - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) - return jsNull(); - } - - JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItemNS(newNode, ec))); - setDOMException(exec, ec); - return result; -} - bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, const Identifier& propertyName) { return impl->getNamedItem(identifierToString(propertyName)); diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 9fbcffd..747f238 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -68,51 +68,9 @@ using namespace JSC; namespace WebCore { -static inline bool isAttrFrameSrc(Element *element, const String& name) -{ - return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); -} - -void JSNode::setNodeValue(JSC::ExecState* exec, JSC::JSValue value) -{ - Node* imp = static_cast<Node*>(impl()); - String nodeValue = valueToStringWithNullCheck(exec, value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element* ownerElement = static_cast<Attr*>(impl())->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setNodeValue(nodeValue, ec); - setDOMException(exec, ec); -} - -void JSNode::setTextContent(JSC::ExecState* exec, JSC::JSValue value) -{ - Node* imp = static_cast<Node*>(impl()); - String nodeValue = valueToStringWithNullCheck(exec, value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element* ownerElement = static_cast<Attr*>(impl())->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setTextContent(nodeValue, ec); - setDOMException(exec, ec); -} - JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); @@ -124,11 +82,6 @@ JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); @@ -140,11 +93,6 @@ JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->removeChild(toNode(args.at(0)), ec); setDOMException(exec, ec); @@ -156,11 +104,6 @@ JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) JSValue JSNode::appendChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->appendChild(toNode(args.at(0)), ec, true); setDOMException(exec, ec); diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index 8fc860b..8cafefe 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -30,6 +30,7 @@ #include "FrameLoader.h" #include "JSDOMBinding.h" #include "JSDOMWindow.h" +#include "JSMainThreadExecState.h" #include "ScriptController.h" #include "ScriptExecutionContext.h" #include "ScriptSourceCode.h" @@ -84,7 +85,7 @@ void ScheduledAction::execute(ScriptExecutionContext* context) #endif } -void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue) +void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext* context) { ASSERT(m_function); JSLock lock(SilenceAssertionsOnly); @@ -102,7 +103,10 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV args.append(m_args[i]); globalObject->globalData()->timeoutChecker.start(); - JSC::call(exec, m_function, callType, callData, thisValue, args); + if (context->isDocument()) + JSMainThreadExecState::call(exec, m_function, callType, callData, thisValue, args); + else + JSC::call(exec, m_function, callType, callData, thisValue, args); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) @@ -122,7 +126,7 @@ void ScheduledAction::execute(Document* document) frame->script()->setProcessingTimerCallback(true); if (m_function) { - executeFunctionInContext(window, window->shell()); + executeFunctionInContext(window, window->shell(), document); Document::updateStyleForAllDocuments(); } else frame->script()->executeScriptInWorld(m_isolatedWorld.get(), m_code); @@ -140,7 +144,7 @@ void ScheduledAction::execute(WorkerContext* workerContext) if (m_function) { JSWorkerContext* contextWrapper = scriptController->workerContextWrapper(); - executeFunctionInContext(contextWrapper, contextWrapper); + executeFunctionInContext(contextWrapper, contextWrapper, workerContext); } else { ScriptSourceCode code(m_code, workerContext->url()); scriptController->evaluate(code); diff --git a/WebCore/bindings/js/ScheduledAction.h b/WebCore/bindings/js/ScheduledAction.h index 3b7e001..313451a 100644 --- a/WebCore/bindings/js/ScheduledAction.h +++ b/WebCore/bindings/js/ScheduledAction.h @@ -55,7 +55,7 @@ namespace WebCore { { } - void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue); + void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext*); void execute(Document*); #if ENABLE(WORKERS) void execute(WorkerContext*); diff --git a/WebCore/bindings/js/ScriptCallStack.cpp b/WebCore/bindings/js/ScriptCallStack.cpp index 771141d..64600cf 100644 --- a/WebCore/bindings/js/ScriptCallStack.cpp +++ b/WebCore/bindings/js/ScriptCallStack.cpp @@ -33,7 +33,7 @@ #include <interpreter/CallFrame.h> #include <interpreter/Interpreter.h> -#include <runtime/InternalFunction.h> +#include <runtime/JSFunction.h> #include <runtime/JSValue.h> #include <runtime/UString.h> #include <runtime/JSGlobalData.h> @@ -57,7 +57,7 @@ ScriptCallStack::ScriptCallStack(ExecState* exec, const ArgList& args, unsigned unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0; if (function) { - m_caller = asInternalFunction(function); + m_caller = asFunction(function); m_frames.append(ScriptCallFrame(m_caller->name(m_exec), urlString, lineNumber, args, skipArgumentCount)); } else { // Caller is unknown, but we should still add the frame, because @@ -93,10 +93,10 @@ void ScriptCallStack::initialize() JSValue func = m_exec->interpreter()->retrieveCaller(m_exec, m_caller); while (!func.isNull()) { - InternalFunction* internalFunction = asInternalFunction(func); + JSFunction* jsFunction = asFunction(func); ArgList emptyArgList; - m_frames.append(ScriptCallFrame(internalFunction->name(m_exec), UString(), 0, emptyArgList, 0)); - func = m_exec->interpreter()->retrieveCaller(m_exec, internalFunction); + m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), UString(), 0, emptyArgList, 0)); + func = m_exec->interpreter()->retrieveCaller(m_exec, jsFunction); } m_initialized = true; } diff --git a/WebCore/bindings/js/ScriptCallStack.h b/WebCore/bindings/js/ScriptCallStack.h index e51d97a..7b66a97 100644 --- a/WebCore/bindings/js/ScriptCallStack.h +++ b/WebCore/bindings/js/ScriptCallStack.h @@ -61,7 +61,7 @@ namespace WebCore { JSC::ExecState* m_exec; Vector<ScriptCallFrame> m_frames; - JSC::InternalFunction* m_caller; + JSC::JSFunction* m_caller; }; } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 508b2f8..3dcbb0b 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -29,6 +29,7 @@ #include "HTMLPlugInElement.h" #include "InspectorTimelineAgent.h" #include "JSDocument.h" +#include "JSMainThreadExecState.h" #include "NP_jsobject.h" #include "Page.h" #include "PageGroup.h" @@ -110,12 +111,12 @@ JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld* world) return windowShell; } -ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world) +ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world, ShouldAllowXSS shouldAllowXSS) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = ustringToString(jsSourceCode.provider()->url()); - if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { + if (shouldAllowXSS == DoNotAllowXSS && !m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return JSValue(); } @@ -142,7 +143,7 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode #endif exec->globalData().timeoutChecker.start(); - Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell); + Completion comp = JSMainThreadExecState::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell); exec->globalData().timeoutChecker.stop(); #if ENABLE(INSPECTOR) @@ -166,9 +167,9 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode return JSValue(); } -ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ShouldAllowXSS shouldAllowXSS) { - return evaluateInWorld(sourceCode, mainThreadNormalWorld()); + return evaluateInWorld(sourceCode, mainThreadNormalWorld(), shouldAllowXSS); } PassRefPtr<DOMWrapperWorld> ScriptController::createWorld() @@ -181,7 +182,7 @@ void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds) static_cast<WebCoreJSClientData*>(JSDOMWindow::commonJSGlobalData()->clientData)->getAllWorlds(worlds); } -void ScriptController::clearWindowShell() +void ScriptController::clearWindowShell(bool goingIntoPageCache) { if (m_windowShells.isEmpty()) return; @@ -203,8 +204,10 @@ void ScriptController::clearWindowShell() } } - // It's likely that resetting our windows created a lot of garbage. - gcController().garbageCollectSoon(); + // It's likely that resetting our windows created a lot of garbage, unless + // it went in a back/forward cache. + if (!goingIntoPageCache) + gcController().garbageCollectSoon(); } JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) @@ -283,6 +286,16 @@ bool ScriptController::anyPageIsProcessingUserGesture() const return false; } +bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +{ + ExecState* exec = JSMainThreadExecState::currentState(); + if (exec) + return allowsAccessFromFrame(exec, frame); + // If the current state is 0 we're in a call path where the DOM security + // check doesn't apply (eg. parser). + return true; +} + void ScriptController::attachDebugger(JSC::Debugger* debugger) { for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) @@ -441,7 +454,7 @@ void ScriptController::clearScriptObjects() #endif } -ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture) +ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture, ShouldAllowXSS shouldAllowXSS) { ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); @@ -451,7 +464,7 @@ ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const bool wasInExecuteScript = m_inExecuteScript; m_inExecuteScript = true; - ScriptValue result = evaluateInWorld(sourceCode, world); + ScriptValue result = evaluateInWorld(sourceCode, world, shouldAllowXSS); if (!wasInExecuteScript) { m_inExecuteScript = false; diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index ed6c0a0..877eb9f 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -67,6 +67,12 @@ enum ReasonForCallingCanExecuteScripts { NotAboutToExecuteScript }; +// Whether to call the XSSAuditor to audit a script before passing it to the JavaScript engine. +enum ShouldAllowXSS { + AllowXSS, + DoNotAllowXSS +}; + class ScriptController { friend class ScriptCachedFrameData; typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::ProtectedPtr<JSDOMWindowShell> > ShellMap; @@ -97,9 +103,9 @@ public: static void getAllWorlds(Vector<DOMWrapperWorld*>&); - ScriptValue executeScript(const ScriptSourceCode&); - ScriptValue executeScript(const String& script, bool forceUserGesture = false); - ScriptValue executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture = false); + ScriptValue executeScript(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue executeScript(const String& script, bool forceUserGesture = false, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture = false, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); // Returns true if argument is a JavaScript URL. bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL); @@ -108,8 +114,8 @@ public: // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly. static void initializeThreading(); - ScriptValue evaluate(const ScriptSourceCode&); - ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*); + ScriptValue evaluate(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); void setEventHandlerLineNumber(int lineno) { m_handlerLineNumber = lineno; } int eventHandlerLineNumber() { return m_handlerLineNumber; } @@ -118,6 +124,7 @@ public: bool processingUserGesture(DOMWrapperWorld*) const; bool anyPageIsProcessingUserGesture() const; + static bool canAccessFromCurrentOrigin(Frame*); bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // Debugger can be 0 to detach any existing Debugger. @@ -132,7 +139,7 @@ public: const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script - void clearWindowShell(); + void clearWindowShell(bool goingIntoPageCache = false); void updateDocument(); // Notifies the ScriptController that the securityOrigin of the current diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index e9073b5..3784457 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -32,6 +32,7 @@ #include "ScriptFunctionCall.h" #include "JSDOMBinding.h" +#include "JSMainThreadExecState.h" #include "ScriptString.h" #include "ScriptValue.h" @@ -146,7 +147,7 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) if (callType == CallTypeNone) return ScriptValue(); - JSValue result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments); + JSValue result = JSMainThreadExecState::call(m_exec, function, callType, callData, thisObject, m_arguments); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index 85d6861..1d45dfa 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -71,22 +71,26 @@ void WorkerScriptController::initScript() // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(jsNull()); - ProtectedPtr<JSWorkerContextPrototype> workerContextPrototype = new (m_globalData.get()) JSWorkerContextPrototype(workerContextPrototypeStructure.release()); + ProtectedPtr<JSWorkerContextPrototype> workerContextPrototype = new (m_globalData.get()) JSWorkerContextPrototype(0, workerContextPrototypeStructure.release()); if (m_workerContext->isDedicatedWorkerContext()) { RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(workerContextPrototype); - ProtectedPtr<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype = new (m_globalData.get()) JSDedicatedWorkerContextPrototype(dedicatedContextPrototypeStructure.release()); + ProtectedPtr<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype = new (m_globalData.get()) JSDedicatedWorkerContextPrototype(0, dedicatedContextPrototypeStructure.release()); RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(dedicatedContextPrototype); m_workerContextWrapper = new (m_globalData.get()) JSDedicatedWorkerContext(structure.release(), m_workerContext->toDedicatedWorkerContext()); + workerContextPrototype->putAnonymousValue(0, m_workerContextWrapper); + dedicatedContextPrototype->putAnonymousValue(0, m_workerContextWrapper); #if ENABLE(SHARED_WORKERS) } else { ASSERT(m_workerContext->isSharedWorkerContext()); RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(workerContextPrototype); - ProtectedPtr<JSSharedWorkerContextPrototype> sharedContextPrototype = new (m_globalData.get()) JSSharedWorkerContextPrototype(sharedContextPrototypeStructure.release()); + ProtectedPtr<JSSharedWorkerContextPrototype> sharedContextPrototype = new (m_globalData.get()) JSSharedWorkerContextPrototype(0, sharedContextPrototypeStructure.release()); RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(sharedContextPrototype); m_workerContextWrapper = new (m_globalData.get()) JSSharedWorkerContext(structure.release(), m_workerContext->toSharedWorkerContext()); + workerContextPrototype->putAnonymousValue(0, m_workerContextWrapper); + sharedContextPrototype->putAnonymousValue(0, m_workerContextWrapper); #endif } } diff --git a/WebCore/bindings/objc/ObjCEventListener.mm b/WebCore/bindings/objc/ObjCEventListener.mm index d73ac30..c1b8aa5 100644 --- a/WebCore/bindings/objc/ObjCEventListener.mm +++ b/WebCore/bindings/objc/ObjCEventListener.mm @@ -32,6 +32,7 @@ #import "DOMEventListener.h" #import "Event.h" #import "EventListener.h" +#import "JSMainThreadExecState.h" #import <wtf/HashMap.h> namespace WebCore { diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm index 1cec41c..794fc69 100644 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ b/WebCore/bindings/objc/WebScriptObject.mm @@ -34,6 +34,7 @@ #import "JSDOMWindow.h" #import "JSDOMWindowCustom.h" #import "JSHTMLElement.h" +#import "JSMainThreadExecState.h" #import "JSPluginElementFunctions.h" #import "ObjCRuntimeObject.h" #import "PlatformString.h" @@ -304,7 +305,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root return nil; [self _rootObject]->globalObject()->globalData()->timeoutChecker.start(); - JSValue result = JSC::call(exec, function, callType, callData, [self _imp], argList); + JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList); [self _rootObject]->globalObject()->globalData()->timeoutChecker.stop(); if (exec->hadException()) { @@ -333,7 +334,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root JSLock lock(SilenceAssertionsOnly); [self _rootObject]->globalObject()->globalData()->timeoutChecker.start(); - Completion completion = JSC::evaluate([self _rootObject]->globalObject()->globalExec(), [self _rootObject]->globalObject()->globalScopeChain(), makeSource(String(script)), JSC::JSValue()); + Completion completion = JSMainThreadExecState::evaluate([self _rootObject]->globalObject()->globalExec(), [self _rootObject]->globalObject()->globalScopeChain(), makeSource(String(script)), JSC::JSValue()); [self _rootObject]->globalObject()->globalData()->timeoutChecker.stop(); ComplType type = completion.complType(); diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 46ac42d..3be997f 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -226,7 +226,7 @@ sub IndexGetterReturnsStrings { my $type = shift; - return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration"; + return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration" or $type eq "DOMStringList"; return 0; } @@ -643,6 +643,8 @@ sub GenerateHeader if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) { $headerIncludes{"$implClassName.h"} = 1; } + + $headerIncludes{"<runtime/JSObjectWithGlobalObject.h>"} = 1; $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; @@ -935,8 +937,8 @@ sub GenerateHeader # Add prototype declaration. %structureFlags = (); - push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n"); - push(@headerContent, " typedef JSC::JSObject Base;\n"); + push(@headerContent, "class ${className}Prototype : public JSC::JSObjectWithGlobalObject {\n"); + push(@headerContent, " typedef JSC::JSObjectWithGlobalObject Base;\n"); push(@headerContent, "public:\n"); if ($interfaceName eq "DOMWindow") { push(@headerContent, " void* operator new(size_t);\n"); @@ -970,7 +972,7 @@ sub GenerateHeader # Custom defineGetter function push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"}; - push(@headerContent, " ${className}Prototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n"); + push(@headerContent, " ${className}Prototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { }\n"); # structure flags push(@headerContent, "protected:\n"); @@ -985,7 +987,7 @@ sub GenerateHeader if ($numFunctions > 0) { push(@headerContent,"// Functions\n\n"); foreach my $function (@{$dataNode->functions}) { - next if $function->{overloadIndex} > 1; + next if $function->{overloadIndex} && $function->{overloadIndex} > 1; my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); push(@headerContent, "JSC::JSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);\n"); } @@ -1254,7 +1256,7 @@ sub GenerateImplementation } foreach my $function (@{$dataNode->functions}) { - next if $function->{overloadIndex} > 1; + next if $function->{overloadIndex} && $function->{overloadIndex} > 1; my $name = $function->signature->name; push(@hashKeys, $name); @@ -1440,9 +1442,9 @@ sub GenerateImplementation push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n"); push(@implContent, "{\n"); if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") { - push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n"); + push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n"); } else { - push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructure(globalObject->objectPrototype()));\n"); + push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(globalObject->objectPrototype()));\n"); } push(@implContent, "}\n\n"); } @@ -1781,7 +1783,7 @@ sub GenerateImplementation my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name); - if (@{$function->{overloads}} > 1) { + if ($function->{overloads} && @{$function->{overloads}} > 1) { # Append a number to an overloaded method's name to make it unique: $functionName = $functionName . $function->{overloadIndex}; } @@ -1953,7 +1955,7 @@ sub GenerateImplementation } push(@implContent, "}\n\n"); - if (@{$function->{overloads}} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { + if ($function->{overloads} && @{$function->{overloads}} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { # Generate a function dispatching call to the rest of the overloads. GenerateOverloadedPrototypeFunction($function, $dataNode, $implClassName); } diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index 7132e22..e06b274 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -80,6 +80,7 @@ my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4; my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5; my $exceptionInit = "WebCore::ExceptionCode ec = 0;"; +my $jsContextSetter = "WebCore::JSMainThreadNullState state;"; my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);"; my $assertMainThread = "{ DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }"; @@ -1056,6 +1057,7 @@ sub GenerateImplementation $implIncludes{"ExceptionHandlers.h"} = 1; $implIncludes{"ThreadCheck.h"} = 1; + $implIncludes{"JSMainThreadExecState.h"} = 1; $implIncludes{"WebScriptObjectPrivate.h"} = 1; $implIncludes{$classHeaderName . "Internal.h"} = 1; @@ -1268,6 +1270,7 @@ sub GenerateImplementation push(@implContent, $getterSig); push(@implContent, "{\n"); + push(@implContent, " $jsContextSetter\n"); push(@implContent, @customGetterContent); if ($hasGetterException) { # Differentiated between when the return type is a pointer and @@ -1308,6 +1311,7 @@ sub GenerateImplementation push(@implContent, $setterSig); push(@implContent, "{\n"); + push(@implContent, " $jsContextSetter\n"); unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) { push(@implContent, " ASSERT($argName);\n\n"); @@ -1523,6 +1527,7 @@ sub GenerateImplementation push(@implContent, "$functionSig\n"); push(@implContent, "{\n"); + push(@implContent, " $jsContextSetter\n"); push(@implContent, @functionContent); push(@implContent, "}\n\n"); @@ -1533,6 +1538,7 @@ sub GenerateImplementation push(@implContent, "$deprecatedFunctionSig\n"); push(@implContent, "{\n"); + push(@implContent, " $jsContextSetter\n"); push(@implContent, @functionContent); push(@implContent, "}\n\n"); } diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index f38e0d1..0167a4f 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -628,7 +628,10 @@ sub GenerateNormalAttrGetter my $getterStringUsesImp = $implClassName ne "float"; - # Getter + # Getter + my $conditionalString = GenerateConditionalString($attribute->signature); + push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString; + push(@implContentDecls, <<END); static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { @@ -671,6 +674,7 @@ END $implIncludes{"${namespace}.h"} = 1; push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n"); push(@implContentDecls, "}\n\n"); + push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; return; # Skip the rest of the function! } @@ -801,6 +805,7 @@ END push(@implContentDecls, " }\n"); push(@implContentDecls, " return wrapper;\n"); push(@implContentDecls, "}\n\n"); + push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; return; } } @@ -825,6 +830,7 @@ END } push(@implContentDecls, "}\n\n"); # end of getter + push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; } sub GenerateNormalAttrSetter @@ -836,6 +842,9 @@ sub GenerateNormalAttrSetter my $attrExt = $attribute->signature->extendedAttributes; + my $conditionalString = GenerateConditionalString($attribute->signature); + push(@implContentDecls, "#if ${conditionalString}\n\n") if $conditionalString; + push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n"); push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); @@ -875,6 +884,7 @@ END $implIncludes{"${namespace}.h"} = 1; push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n"); push(@implContentDecls, "}\n\n"); + push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; return; # Skip the rest of the function! } @@ -963,6 +973,7 @@ END push(@implContentDecls, " return;\n"); push(@implContentDecls, "}\n\n"); # end of setter + push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; } sub GetFunctionTemplateCallbackName diff --git a/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp b/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp index 233ba21..51eb4ec 100644 --- a/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp +++ b/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp @@ -44,13 +44,7 @@ static const HashTableValue JSTestInterfaceTableValues[2] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestInterfaceTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 0, JSTestInterfaceTableValues, 0 }; -#else - { 2, 1, JSTestInterfaceTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestInterfaceTable = { 2, 1, JSTestInterfaceTableValues, 0 }; /* Hash table for constructor */ #if ENABLE(JIT) #define THUNK_GENERATOR(generator) , generator @@ -64,13 +58,7 @@ static const HashTableValue JSTestInterfaceConstructorTableValues[1] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestInterfaceConstructorTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 0, JSTestInterfaceConstructorTableValues, 0 }; -#else - { 1, 0, JSTestInterfaceConstructorTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestInterfaceConstructorTable = { 1, 0, JSTestInterfaceConstructorTableValues, 0 }; class JSTestInterfaceConstructor : public DOMConstructorObject { public: JSTestInterfaceConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) @@ -129,13 +117,7 @@ static const HashTableValue JSTestInterfacePrototypeTableValues[1] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestInterfacePrototypeTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 0, JSTestInterfacePrototypeTableValues, 0 }; -#else - { 1, 0, JSTestInterfacePrototypeTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestInterfacePrototypeTable = { 1, 0, JSTestInterfacePrototypeTableValues, 0 }; const ClassInfo JSTestInterfacePrototype::s_info = { "TestInterfacePrototype", 0, &JSTestInterfacePrototypeTable, 0 }; JSObject* JSTestInterfacePrototype::self(ExecState* exec, JSGlobalObject* globalObject) diff --git a/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp index de5a171..926d137 100644 --- a/WebCore/bindings/scripts/test/JS/JSTestObj.cpp +++ b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp @@ -66,13 +66,7 @@ static const HashTableValue JSTestObjTableValues[15] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestObjTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 127, JSTestObjTableValues, 0 }; -#else - { 34, 31, JSTestObjTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestObjTable = { 34, 31, JSTestObjTableValues, 0 }; /* Hash table for constructor */ #if ENABLE(JIT) #define THUNK_GENERATOR(generator) , generator @@ -86,13 +80,7 @@ static const HashTableValue JSTestObjConstructorTableValues[1] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestObjConstructorTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 0, JSTestObjConstructorTableValues, 0 }; -#else - { 1, 0, JSTestObjConstructorTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestObjConstructorTable = { 1, 0, JSTestObjConstructorTableValues, 0 }; class JSTestObjConstructor : public DOMConstructorObject { public: JSTestObjConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) @@ -167,13 +155,7 @@ static const HashTableValue JSTestObjPrototypeTableValues[29] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestObjPrototypeTable = -#if ENABLE(PERFECT_HASH_SIZE) - { 8191, JSTestObjPrototypeTableValues, 0 }; -#else - { 69, 63, JSTestObjPrototypeTableValues, 0 }; -#endif - +static JSC_CONST_HASHTABLE HashTable JSTestObjPrototypeTable = { 69, 63, JSTestObjPrototypeTableValues, 0 }; const ClassInfo JSTestObjPrototype::s_info = { "TestObjPrototype", 0, &JSTestObjPrototypeTable, 0 }; JSObject* JSTestObjPrototype::self(ExecState* exec, JSGlobalObject* globalObject) diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm index 5201a91..e941eda 100644 --- a/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm @@ -50,6 +50,7 @@ #import "DOMStyleSheetInternal.h" #import "DOMTestCallbackInternal.h" #import "ExceptionHandlers.h" +#import "JSMainThreadExecState.h" #import "KURL.h" #import "TestCallback.h" #import "ThreadCheck.h" @@ -80,21 +81,25 @@ - (BOOL)callbackWithClass1Param:(DOMClass1 *)class1Param { + WebCore::JSMainThreadNullState state; return IMPL->callbackWithClass1Param(core(class1Param)); } - (BOOL)callbackWithClass2Param:(DOMClass2 *)class2Param strArg:(NSString *)strArg { + WebCore::JSMainThreadNullState state; return IMPL->callbackWithClass2Param(core(class2Param), strArg); } - (int)callbackWithNonBoolReturnType:(DOMClass3 *)class3Param { + WebCore::JSMainThreadNullState state; return IMPL->callbackWithNonBoolReturnType(core(class3Param)); } - (int)customCallback:(DOMClass5 *)class5Param class6Param:(DOMClass6 *)class6Param { + WebCore::JSMainThreadNullState state; return IMPL->customCallback(core(class5Param), core(class6Param)); } diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm index a88b366..8fd7791 100644 --- a/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm @@ -37,6 +37,7 @@ #import "DOMStyleSheetInternal.h" #import "DOMTestInterfaceInternal.h" #import "ExceptionHandlers.h" +#import "JSMainThreadExecState.h" #import "TestInterface.h" #import "ThreadCheck.h" #import "WebCoreObjCExtras.h" diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm index a24f6fe..0f3fb66 100644 --- a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm @@ -39,6 +39,7 @@ #import "DOMlogInternal.h" #import "EventListener.h" #import "ExceptionHandlers.h" +#import "JSMainThreadExecState.h" #import "KURL.h" #import "ObjCEventListener.h" #import "SerializedScriptValue.h" @@ -72,66 +73,79 @@ - (int)readOnlyIntAttr { + WebCore::JSMainThreadNullState state; return IMPL->readOnlyIntAttr(); } - (NSString *)readOnlyStringAttr { + WebCore::JSMainThreadNullState state; return IMPL->readOnlyStringAttr(); } - (DOMTestObj *)readOnlyTestObjAttr { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->readOnlyTestObjAttr())); } - (int)intAttr { + WebCore::JSMainThreadNullState state; return IMPL->intAttr(); } - (void)setIntAttr:(int)newIntAttr { + WebCore::JSMainThreadNullState state; IMPL->setIntAttr(newIntAttr); } - (long long)longLongAttr { + WebCore::JSMainThreadNullState state; return IMPL->longLongAttr(); } - (void)setLongLongAttr:(long long)newLongLongAttr { + WebCore::JSMainThreadNullState state; IMPL->setLongLongAttr(newLongLongAttr); } - (unsigned long long)unsignedLongLongAttr { + WebCore::JSMainThreadNullState state; return IMPL->unsignedLongLongAttr(); } - (void)setUnsignedLongLongAttr:(unsigned long long)newUnsignedLongLongAttr { + WebCore::JSMainThreadNullState state; IMPL->setUnsignedLongLongAttr(newUnsignedLongLongAttr); } - (NSString *)stringAttr { + WebCore::JSMainThreadNullState state; return IMPL->stringAttr(); } - (void)setStringAttr:(NSString *)newStringAttr { + WebCore::JSMainThreadNullState state; IMPL->setStringAttr(newStringAttr); } - (DOMTestObj *)testObjAttr { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->testObjAttr())); } - (void)setTestObjAttr:(DOMTestObj *)newTestObjAttr { + WebCore::JSMainThreadNullState state; ASSERT(newTestObjAttr); IMPL->setTestObjAttr(core(newTestObjAttr)); @@ -139,16 +153,19 @@ - (int)attrWithException { + WebCore::JSMainThreadNullState state; return IMPL->attrWithException(); } - (void)setAttrWithException:(int)newAttrWithException { + WebCore::JSMainThreadNullState state; IMPL->setAttrWithException(newAttrWithException); } - (int)attrWithSetterException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; int result = IMPL->attrWithSetterException(ec); WebCore::raiseOnDOMError(ec); @@ -157,6 +174,7 @@ - (void)setAttrWithSetterException:(int)newAttrWithSetterException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; IMPL->setAttrWithSetterException(newAttrWithSetterException, ec); WebCore::raiseOnDOMError(ec); @@ -164,11 +182,13 @@ - (int)attrWithGetterException { + WebCore::JSMainThreadNullState state; return IMPL->attrWithGetterException(); } - (void)setAttrWithGetterException:(int)newAttrWithGetterException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; IMPL->setAttrWithGetterException(newAttrWithGetterException, ec); WebCore::raiseOnDOMError(ec); @@ -176,56 +196,67 @@ - (int)customAttr { + WebCore::JSMainThreadNullState state; return IMPL->customAttr(); } - (void)setCustomAttr:(int)newCustomAttr { + WebCore::JSMainThreadNullState state; IMPL->setCustomAttr(newCustomAttr); } - (NSString *)scriptStringAttr { + WebCore::JSMainThreadNullState state; return IMPL->scriptStringAttr(); } - (void)voidMethod { + WebCore::JSMainThreadNullState state; IMPL->voidMethod(); } - (void)voidMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; IMPL->voidMethodWithArgs(intArg, strArg, core(objArg)); } - (int)intMethod { + WebCore::JSMainThreadNullState state; return IMPL->intMethod(); } - (int)intMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; return IMPL->intMethodWithArgs(intArg, strArg, core(objArg)); } - (DOMTestObj *)objMethod { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->objMethod())); } - (DOMTestObj *)objMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->objMethodWithArgs(intArg, strArg, core(objArg)))); } - (DOMTestObj *)methodThatRequiresAllArgs:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->methodThatRequiresAllArgs(strArg, core(objArg)))); } - (DOMTestObj *)methodThatRequiresAllArgsAndThrows:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; DOMTestObj *result = kit(WTF::getPtr(IMPL->methodThatRequiresAllArgsAndThrows(strArg, core(objArg), ec))); WebCore::raiseOnDOMError(ec); @@ -234,11 +265,13 @@ - (void)serializedValue:(NSString *)serializedArg { + WebCore::JSMainThreadNullState state; IMPL->serializedValue(WebCore::SerializedScriptValue::create(WebCore::String(serializedArg))); } - (void)methodWithException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; IMPL->methodWithException(ec); WebCore::raiseOnDOMError(ec); @@ -246,16 +279,19 @@ - (void)customMethod { + WebCore::JSMainThreadNullState state; IMPL->customMethod(); } - (void)customMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg { + WebCore::JSMainThreadNullState state; IMPL->customMethodWithArgs(intArg, strArg, core(objArg)); } - (void)customArgsAndException:(DOMlog *)intArg { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; IMPL->customArgsAndException(core(intArg), ec); WebCore::raiseOnDOMError(ec); @@ -263,53 +299,63 @@ - (void)addEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture { + WebCore::JSMainThreadNullState state; RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap(listener); IMPL->addEventListener(type, WTF::getPtr(nativeEventListener), useCapture); } - (void)removeEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture { + WebCore::JSMainThreadNullState state; RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap(listener); IMPL->removeEventListener(type, WTF::getPtr(nativeEventListener), useCapture); } - (void)withDynamicFrame { + WebCore::JSMainThreadNullState state; IMPL->withDynamicFrame(); } - (void)withDynamicFrameAndArg:(int)intArg { + WebCore::JSMainThreadNullState state; IMPL->withDynamicFrameAndArg(intArg); } - (void)withDynamicFrameAndOptionalArg:(int)intArg optionalArg:(int)optionalArg { + WebCore::JSMainThreadNullState state; IMPL->withDynamicFrameAndOptionalArg(intArg, optionalArg); } - (void)withDynamicFrameAndUserGesture:(int)intArg { + WebCore::JSMainThreadNullState state; IMPL->withDynamicFrameAndUserGesture(intArg); } - (void)withDynamicFrameAndUserGestureASAD:(int)intArg optionalArg:(int)optionalArg { + WebCore::JSMainThreadNullState state; IMPL->withDynamicFrameAndUserGestureASAD(intArg, optionalArg); } - (void)withScriptStateVoid { + WebCore::JSMainThreadNullState state; IMPL->withScriptStateVoid(); } - (DOMTestObj *)withScriptStateObj { + WebCore::JSMainThreadNullState state; return kit(WTF::getPtr(IMPL->withScriptStateObj())); } - (void)withScriptStateVoidException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; IMPL->withScriptStateVoidException(ec); WebCore::raiseOnDOMError(ec); @@ -317,6 +363,7 @@ - (DOMTestObj *)withScriptStateObjException { + WebCore::JSMainThreadNullState state; WebCore::ExceptionCode ec = 0; DOMTestObj *result = kit(WTF::getPtr(IMPL->withScriptStateObjException(ec))); WebCore::raiseOnDOMError(ec); @@ -325,16 +372,19 @@ - (void)methodWithOptionalArg:(int)opt { + WebCore::JSMainThreadNullState state; IMPL->methodWithOptionalArg(opt); } - (void)methodWithNonOptionalArgAndOptionalArg:(int)nonOpt opt:(int)opt { + WebCore::JSMainThreadNullState state; IMPL->methodWithNonOptionalArgAndOptionalArg(nonOpt, opt); } - (void)methodWithNonOptionalArgAndTwoOptionalArgs:(int)nonOpt opt1:(int)opt1 opt2:(int)opt2 { + WebCore::JSMainThreadNullState state; IMPL->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); } diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp index 56f9810..d8076f3 100644 --- a/WebCore/bindings/v8/NPV8Object.cpp +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -52,13 +52,7 @@ #include <v8.h> #include <wtf/StringExtras.h> -using WebCore::npObjectInternalFieldCount; -using WebCore::toV8Context; -using WebCore::toV8Proxy; -using WebCore::V8DOMWrapper; -using WebCore::V8GCController; -using WebCore::V8Proxy; -using WebCore::WrapperTypeInfo; +using namespace WebCore; namespace WebCore { @@ -68,8 +62,6 @@ WrapperTypeInfo* npObjectTypeInfo() return &typeInfo; } -} - // FIXME: Comments on why use malloc and free. static NPObject* allocV8NPObject(NPP, NPClass*) { @@ -110,7 +102,7 @@ static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object) { - return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperObjectIndex)); + return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); } static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, @@ -121,12 +113,12 @@ static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, // NPAPI's npruntime functions. NPClass* npScriptObjectClass = &V8NPObjectClass; -NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore::DOMWindow* root) +NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root) { // Check to see if this object is already wrapped. if (object->InternalFieldCount() == npObjectInternalFieldCount) { - WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperTypeIndex)); - if (typeInfo == WebCore::npObjectTypeInfo()) { + WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex)); + if (typeInfo == npObjectTypeInfo()) { NPObject* returnValue = v8ObjectToNPObject(object); _NPN_RetainObject(returnValue); @@ -137,12 +129,14 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); v8npObject->v8Object = v8::Persistent<v8::Object>::New(object); #ifndef NDEBUG - V8GCController::registerGlobalHandle(WebCore::NPOBJECT, v8npObject, v8npObject->v8Object); + V8GCController::registerGlobalHandle(NPOBJECT, v8npObject, v8npObject->v8Object); #endif v8npObject->rootObject = root; return reinterpret_cast<NPObject*>(v8npObject); } +} // namespace WebCore + bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) { if (!npObject) @@ -162,6 +156,14 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV if (!identifier->isString) return false; + if (!strcmp(identifier->value.string, "eval")) { + if (argumentCount != 1) + return false; + if (arguments[0].type != NPVariantType_String) + return false; + return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); + } + v8::HandleScope handleScope; // FIXME: should use the plugin's owner frame as the security context. v8::Handle<v8::Context> context = toV8Context(npp, npObject); @@ -169,14 +171,7 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV return false; v8::Context::Scope scope(context); - - if (methodName == _NPN_GetStringIdentifier("eval")) { - if (argumentCount != 1) - return false; - if (arguments[0].type != NPVariantType_String) - return false; - return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); - } + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String::New(identifier->value.string)); if (functionObject.IsEmpty() || functionObject->IsNull()) { @@ -229,6 +224,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; // Lookup the function object and call it. v8::Handle<v8::Object> functionObject(v8NpObject->v8Object); @@ -255,7 +251,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result) { - bool popupsAllowed = WebCore::PlatformBridge::popupsAllowed(npp); + bool popupsAllowed = PlatformBridge::popupsAllowed(npp); return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result); } @@ -277,13 +273,14 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri ASSERT(proxy); v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; - WebCore::String filename; + String filename; if (!popupsAllowed) filename = "npscript"; - WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); - v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(WebCore::ParsedURLString, filename)), 0); + String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); + v8::Local<v8::Value> v8result = proxy->evaluate(ScriptSourceCode(script, KURL(ParsedURLString, filename)), 0); if (v8result.IsEmpty()) return false; @@ -306,6 +303,7 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); @@ -340,6 +338,7 @@ bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, co return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); obj->Set(npIdentifierToV8Identifier(propertyName), @@ -367,6 +366,7 @@ bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) if (context.IsEmpty()) return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); // FIXME: Verify that setting to undefined is right. @@ -387,6 +387,7 @@ bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) if (context.IsEmpty()) return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); return obj->Has(npIdentifierToV8Identifier(propertyName)); @@ -410,6 +411,7 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) if (context.IsEmpty()) return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName)); @@ -439,6 +441,8 @@ void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) return; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; + V8Proxy::throwError(V8Proxy::GeneralError, message); } @@ -455,6 +459,7 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint if (context.IsEmpty()) return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj(object->v8Object); @@ -509,6 +514,7 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin if (context.IsEmpty()) return false; v8::Context::Scope scope(context); + ExceptionCatcher exceptionCatcher; // Lookup the constructor function. v8::Handle<v8::Object> ctorObj(object->v8Object); diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h index b6fecce..2a81181 100644 --- a/WebCore/bindings/v8/NPV8Object.h +++ b/WebCore/bindings/v8/NPV8Object.h @@ -45,12 +45,12 @@ #include <v8.h> namespace WebCore { - class DOMWindow; - static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; +class DOMWindow; - WrapperTypeInfo* npObjectTypeInfo(); -} +static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; + +WrapperTypeInfo* npObjectTypeInfo(); extern NPClass* npScriptObjectClass; @@ -59,7 +59,7 @@ extern NPClass* npScriptObjectClass; struct V8NPObject { NPObject object; v8::Persistent<v8::Object> v8Object; - WebCore::DOMWindow* rootObject; + DOMWindow* rootObject; }; struct PrivateIdentifier { @@ -70,8 +70,10 @@ struct PrivateIdentifier { bool isString; }; -NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, WebCore::DOMWindow*); +NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, DOMWindow*); NPObject* v8ObjectToNPObject(v8::Handle<v8::Object>); +} // namespace WebCore + #endif // NPV8Object_h diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 7748f75..41cb5a2 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -88,6 +88,11 @@ Frame* ScriptController::retrieveFrameForCurrentContext() return V8Proxy::retrieveFrameForCurrentContext(); } +bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +{ + return !v8::Context::InContext() || V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true); +} + bool ScriptController::isSafeScript(Frame* target) { return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, true); @@ -219,13 +224,13 @@ void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<Sc } // Evaluate a script file in the environment of this proxy. -ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ShouldAllowXSS shouldAllowXSS) { String sourceURL = sourceCode.url(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; - if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { + if (shouldAllowXSS == DoNotAllowXSS && !m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return ScriptValue(); } @@ -444,7 +449,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement } -void ScriptController::clearWindowShell() +void ScriptController::clearWindowShell(bool) { // V8 binding expects ScriptController::clearWindowShell only be called // when a frame is loading a new page. V8Proxy::clearForNavigation diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index 1400134..ee39e9a 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -60,6 +60,12 @@ enum ReasonForCallingCanExecuteScripts { NotAboutToExecuteScript }; +// Whether to call the XSSAuditor to audit a script before passing it to the JavaScript engine. +enum ShouldAllowXSS { + AllowXSS, + DoNotAllowXSS +}; + class ScriptController { public: ScriptController(Frame*); @@ -69,8 +75,8 @@ public: // or this accessor should be made JSProxy* V8Proxy* proxy() { return m_proxy.get(); } - ScriptValue executeScript(const ScriptSourceCode&); - ScriptValue executeScript(const String& script, bool forceUserGesture = false); + ScriptValue executeScript(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue executeScript(const String& script, bool forceUserGesture = false, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); // Returns true if argument is a JavaScript URL. bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL); @@ -81,7 +87,7 @@ public: // Evaluate a script file in the environment of this proxy. // If succeeded, 'succ' is set to true and result is returned // as a string. - ScriptValue evaluate(const ScriptSourceCode&); + ScriptValue evaluate(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&); @@ -118,6 +124,8 @@ public: // Check if the javascript engine has been initialized. bool haveInterpreter() const; + static bool canAccessFromCurrentOrigin(Frame*); + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // FIXME: void* is a compile hack. @@ -158,7 +166,7 @@ public: const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script. - void clearWindowShell(); + void clearWindowShell(bool = false); void updateDocument(); void updateSecurityOrigin(); diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index 84450e5..f9cc94a 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -45,7 +45,7 @@ #include "npruntime_priv.h" #include <wtf/OwnArrayPtr.h> -using namespace WebCore; +namespace WebCore { enum InvokeFunctionType { InvokeMethod = 1, @@ -409,3 +409,5 @@ void forgetV8ObjectForNPObject(NPObject* object) _NPN_ReleaseObject(object); } } + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8NPObject.h b/WebCore/bindings/v8/V8NPObject.h index 5924b3c..a540ca9 100644 --- a/WebCore/bindings/v8/V8NPObject.h +++ b/WebCore/bindings/v8/V8NPObject.h @@ -39,6 +39,8 @@ #include <v8.h> +namespace WebCore { + // These functions can be replaced by normal JS operation. // Getters v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo&); @@ -65,4 +67,6 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root); // cannot be referred to. void forgetV8ObjectForNPObject(NPObject*); +} // namespace WebCore + #endif // V8NPObject_h diff --git a/WebCore/bindings/v8/V8NPUtils.cpp b/WebCore/bindings/v8/V8NPUtils.cpp index 17855d7..8fa19d7 100644 --- a/WebCore/bindings/v8/V8NPUtils.cpp +++ b/WebCore/bindings/v8/V8NPUtils.cpp @@ -29,19 +29,18 @@ */ #include "config.h" - #include "V8NPUtils.h" #include "DOMWindow.h" #include "Frame.h" #include "PlatformString.h" -#undef LOG - +#include "npruntime_impl.h" +#include "npruntime_priv.h" #include "NPV8Object.h" #include "V8NPObject.h" #include "V8Proxy.h" -#include "npruntime_impl.h" -#include "npruntime_priv.h" + +namespace WebCore { void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result) { @@ -69,7 +68,7 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP char* utf8_chars = strdup(*utf8); STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result); } else if (object->IsObject()) { - WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext()); + DOMWindow* window = V8Proxy::retrieveWindow(V8Proxy::currentContext()); NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window); if (npobject) _NPN_RegisterObject(npobject, owner); @@ -77,7 +76,6 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP } } - v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* npobject) { NPVariantType type = variant->type; @@ -128,3 +126,45 @@ NPIdentifier getStringIdentifier(v8::Handle<v8::String> str) v8::String::Utf8Value utf8(str); return _NPN_GetStringIdentifier(*utf8); } + +struct ExceptionHandlerInfo { + ExceptionHandlerInfo* previous; + ExceptionHandler handler; + void* data; +}; + +static ExceptionHandlerInfo* topHandler; + +void pushExceptionHandler(ExceptionHandler handler, void* data) +{ + ExceptionHandlerInfo* info = new ExceptionHandlerInfo; + info->previous = topHandler; + info->handler = handler; + info->data = data; + topHandler = info; +} + +void popExceptionHandler() +{ + ASSERT(topHandler); + ExceptionHandlerInfo* doomed = topHandler; + topHandler = topHandler->previous; + delete doomed; +} + +ExceptionCatcher::ExceptionCatcher() +{ + if (!topHandler) + m_tryCatch.SetVerbose(true); +} + +ExceptionCatcher::~ExceptionCatcher() +{ + if (!m_tryCatch.HasCaught()) + return; + + if (topHandler) + topHandler->handler(topHandler->data, *v8::String::Utf8Value(m_tryCatch.Exception())); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8NPUtils.h b/WebCore/bindings/v8/V8NPUtils.h index c978d2b..78414b4 100644 --- a/WebCore/bindings/v8/V8NPUtils.h +++ b/WebCore/bindings/v8/V8NPUtils.h @@ -38,6 +38,8 @@ #include <v8.h> +namespace WebCore { + // Convert a V8 Value of any type (string, bool, object, etc) to a NPVariant. void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPObject*, NPVariant*); @@ -48,4 +50,22 @@ v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, NPObject*); // Helper function to create an NPN String Identifier from a v8 string. NPIdentifier getStringIdentifier(v8::Handle<v8::String>); +// The ExceptionHandler will be notified of any exceptions thrown while +// operating on a NPObject. +typedef void (*ExceptionHandler)(void* data, const NPUTF8* message); +void pushExceptionHandler(ExceptionHandler, void* data); +void popExceptionHandler(); + +// Upon destruction, an ExceptionCatcher will pass a caught exception to the +// current ExceptionHandler. +class ExceptionCatcher { +public: + ExceptionCatcher(); + ~ExceptionCatcher(); +private: + v8::TryCatch m_tryCatch; +}; + +} // namespace WebCore + #endif // V8NPUtils_h diff --git a/WebCore/bindings/v8/custom/V8AttrCustom.cpp b/WebCore/bindings/v8/custom/V8AttrCustom.cpp deleted file mode 100644 index 0da4ae4..0000000 --- a/WebCore/bindings/v8/custom/V8AttrCustom.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8Attr.h" - -#include "Attr.h" -#include "Element.h" -#include "ExceptionCode.h" -#include "V8Binding.h" -#include "V8BindingState.h" -#include "V8Proxy.h" - -namespace WebCore { - -void V8Attr::valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) -{ - Attr* imp = V8Attr::toNative(info.Holder()); - String attrValue = toWebCoreStringWithNullCheck(value); - Element* ownerElement = imp->ownerElement(); - - if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->name(), attrValue)) - return; - - ExceptionCode ec = 0; - imp->setValue(attrValue, ec); - if (ec) - throwError(ec); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 8a1a339..bce1561 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -40,6 +40,7 @@ #include "V8Clipboard.h" #include "V8CompositionEvent.h" #include "V8CustomEvent.h" +#include "V8DeviceOrientationEvent.h" #include "V8ErrorEvent.h" #include "V8IDBErrorEvent.h" #include "V8IDBSuccessEvent.h" @@ -153,6 +154,10 @@ v8::Handle<v8::Value> toV8(Event* impl) #endif if (impl->isBeforeLoadEvent()) return toV8(static_cast<BeforeLoadEvent*>(impl)); +#if ENABLE(DEVICE_ORIENTATION) + if (impl->isDeviceOrientationEvent()) + return toV8(static_cast<DeviceOrientationEvent*>(impl)); +#endif if (impl->isCustomEvent()) return toV8(static_cast<CustomEvent*>(impl)); return V8Event::wrap(impl); diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index 4e1dd21..d9e1de0 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -75,48 +75,6 @@ v8::Handle<v8::Value> V8NamedNodeMap::namedPropertyGetter(v8::Local<v8::String> return toV8(result.release()); } -v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemNSCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.NamedNodeMap.setNamedItemNS"); - NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); - Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) - return v8::Handle<v8::Value>(); - } - - ExceptionCode ec = 0; - RefPtr<Node> result = imp->setNamedItemNS(newNode, ec); - if (UNLIKELY(ec)) { - throwError(ec); - return v8::Handle<v8::Value>(); - } - - return toV8(result.release()); -} - -v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemCallback(const v8::Arguments & args) -{ - INC_STATS("DOM.NamedNodeMap.setNamedItem"); - NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); - Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) - return v8::Handle<v8::Value>(); - } - - ExceptionCode ec = 0; - RefPtr<Node> result = imp->setNamedItem(newNode, ec); - if (UNLIKELY(ec)) { - throwError(ec); - return v8::Handle<v8::Value>(); - } - - return toV8(result.release()); -} - v8::Handle<v8::Value> toV8(NamedNodeMap* impl) { if (!impl) diff --git a/WebCore/bindings/v8/custom/V8NamedNodesCollection.cpp b/WebCore/bindings/v8/custom/V8NamedNodesCollection.cpp index 0723498..905b23d 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodesCollection.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodesCollection.cpp @@ -31,7 +31,7 @@ #include "V8NamedNodesCollection.h" #include "Element.h" -#include "NamedAttrMap.h" +#include "NamedNodeMap.h" namespace WebCore { diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index 0a7198a..1f0c79b 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -57,57 +57,12 @@ namespace WebCore { -static inline bool isFrameSrc(Element *element, const String& name) -{ - return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); -} - -void V8Node::textContentAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) -{ - Node* imp = V8Node::toNative(info.Holder()); - String nodeValue = toWebCoreStringWithNullCheck(value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); - if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setTextContent(nodeValue, ec); - if (ec) - throwError(ec); -} - -void V8Node::nodeValueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) -{ - Node* imp = V8Node::toNative(info.Holder()); - String nodeValue = toWebCoreStringWithNullCheck(value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); - if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setNodeValue(nodeValue, ec); - if (ec) - throwError(ec); -} - // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach v8::Handle<v8::Value> V8Node::insertBeforeCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.insertBefore"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { - V8Proxy::setDOMException(NOT_SUPPORTED_ERR); - return v8::Handle<v8::Value>(); - } - ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* refChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -127,12 +82,6 @@ v8::Handle<v8::Value> V8Node::replaceChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.replaceChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { - V8Proxy::setDOMException(NOT_SUPPORTED_ERR); - return v8::Handle<v8::Value>(); - } - ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* oldChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -151,12 +100,6 @@ v8::Handle<v8::Value> V8Node::removeChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.removeChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { - V8Proxy::setDOMException(NOT_SUPPORTED_ERR); - return v8::Handle<v8::Value>(); - } - ExceptionCode ec = 0; Node* oldChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); @@ -175,12 +118,6 @@ v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.appendChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { - V8Proxy::setDOMException(NOT_SUPPORTED_ERR); - return v8::Handle<v8::Value>(); - } - ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); diff --git a/WebCore/bindings/v8/npruntime.cpp b/WebCore/bindings/v8/npruntime.cpp index 35015b0..12500a7 100644 --- a/WebCore/bindings/v8/npruntime.cpp +++ b/WebCore/bindings/v8/npruntime.cpp @@ -35,6 +35,8 @@ #include <wtf/HashSet.h> #include <wtf/Assertions.h> +using namespace WebCore; + // FIXME: Consider removing locks if we're singlethreaded already. // The static initializer here should work okay, but we want to avoid // static initialization in general. |