Index: webkit/port/bindings/js/ScriptControllerChromium.cpp |
=================================================================== |
--- webkit/port/bindings/js/ScriptControllerChromium.cpp (revision 0) |
+++ webkit/port/bindings/js/ScriptControllerChromium.cpp (working copy) |
@@ -30,350 +30,14 @@ |
#include "config.h" |
#include "ScriptController.h" |
-#include "CString.h" |
-#include "Document.h" |
-#include "DOMWindow.h" |
-#include "Event.h" |
-#include "EventListener.h" |
-#include "EventNames.h" |
-#include "Frame.h" |
-#include "Node.h" |
-#include "NotImplemented.h" |
-#include "npruntime_priv.h" |
-#include "np_v8object.h" |
-#include "PausedTimeouts.h" |
-#include "Widget.h" |
+#include "bindings/npruntime.h" |
+#include "c_instance.h" |
-#include "v8_proxy.h" |
-#include "v8_binding.h" |
-#include "v8_npobject.h" |
- |
-//TODO(eseidel): We should remove this glue dependency |
#undef LOG // glue defines its own LOG macro |
#include "webkit/glue/webplugin_impl.h" |
-NPRuntimeFunctions npruntime_functions = { |
- NPN_GetStringIdentifier, |
- NPN_GetStringIdentifiers, |
- NPN_GetIntIdentifier, |
- NPN_IdentifierIsString, |
- NPN_UTF8FromIdentifier, |
- NPN_IntFromIdentifier, |
- NPN_CreateObject, |
- NPN_RetainObject, |
- NPN_ReleaseObject, |
- NPN_Invoke, |
- NPN_InvokeDefault, |
- NPN_Evaluate, |
- NPN_GetProperty, |
- NPN_SetProperty, |
- NPN_RemoveProperty, |
- NPN_HasProperty, |
- NPN_HasMethod, |
- NPN_ReleaseVariantValue, |
- NPN_SetException |
-}; |
- |
- |
namespace WebCore { |
-bool ScriptController::m_recordPlaybackMode = false; |
- |
-void ScriptController::setFlags(const char* str, int length) |
-{ |
- v8::V8::SetFlagsFromString(str, length); |
-} |
- |
-void ScriptController::setDomain(Frame* frame, const String&) |
-{ |
- V8Proxy::DomainChanged(frame); |
-} |
- |
-Frame* ScriptController::retrieveActiveFrame() |
-{ |
- return V8Proxy::retrieveActiveFrame(); |
-} |
- |
-bool ScriptController::isSafeScript(Frame* target) |
-{ |
- return V8Proxy::CanAccessFrame(target, true); |
-} |
- |
-void ScriptController::gcProtectJSWrapper(void* dom_object) |
-{ |
- V8Proxy::GCProtect(static_cast<Peerable*>(dom_object)); |
-} |
- |
-void ScriptController::gcUnprotectJSWrapper(void* dom_object) |
-{ |
- V8Proxy::GCUnprotect(static_cast<Peerable*>(dom_object)); |
-} |
- |
-void ScriptController::pauseTimeouts(OwnPtr<PausedTimeouts>& result) |
-{ |
- DOMWindow* window = m_frame->domWindow(); |
- if (!window) { |
- result.clear(); |
- return; |
- } |
- window->pauseTimeouts(result); |
-} |
- |
-void ScriptController::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts) |
-{ |
- DOMWindow* window = m_frame->domWindow(); |
- if (!window) { |
- timeouts.clear(); |
- return; |
- } |
- window->resumeTimeouts(timeouts); |
-} |
- |
-ScriptController::ScriptController(Frame* frame) |
- : m_frame(frame) |
- , m_sourceURL(0) |
- , m_processingTimerCallback(false) |
- , m_paused(false) |
- , m_proxy(new V8Proxy(frame)) |
-#if ENABLE(NETSCAPE_PLUGIN_API) |
- , m_windowScriptNPObject(0) |
-#endif |
-{ |
-} |
- |
-ScriptController::~ScriptController() |
-{ |
-} |
- |
-void ScriptController::clearScriptObjects() |
-{ |
- // TODO(eseidel): JSC handles binding root objects here, why don't we? |
- |
-#if ENABLE(NETSCAPE_PLUGIN_API) |
- if (m_windowScriptNPObject) { |
- // Call _NPN_DeallocateObject() instead of _NPN_ReleaseObject() so that we don't leak if a plugin fails to release the window |
- // script object properly. |
- // This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point. |
- _NPN_DeallocateObject(m_windowScriptNPObject); |
- m_windowScriptNPObject = 0; |
- } |
-#endif |
-} |
- |
-void ScriptController::clearPluginObjects() |
-{ |
- PluginObjectMap::iterator it = m_pluginObjects.begin(); |
- for (; it != m_pluginObjects.end(); ++it) { |
- _NPN_UnregisterObject(it->second); |
- NPN_ReleaseObject(it->second); |
- } |
- m_pluginObjects.clear(); |
-} |
- |
-// Disconnect the proxy from its owner frame; |
-void ScriptController::disconnectFrame() |
-{ |
- m_proxy->disconnectFrame(); |
-} |
- |
-bool ScriptController::processingUserGesture() const |
-{ |
- Frame* active_frame = V8Proxy::retrieveActiveFrame(); |
- // No script is running, must be run by users. |
- if (!active_frame) |
- return true; |
- |
- V8Proxy* active_proxy = active_frame->script()->proxy(); |
- |
- v8::HandleScope handle_scope; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(active_frame); |
- // TODO(fqian): find all cases context can be empty: |
- // 1) JS is disabled; |
- // 2) page is NULL; |
- if (context.IsEmpty()) |
- return true; |
- |
- v8::Context::Scope scope(context); |
- |
- v8::Handle<v8::Object> global = context->Global(); |
- v8::Handle<v8::Value> jsevent = global->Get(v8::String::NewSymbol("event")); |
- Event* event = V8Proxy::ToNativeEvent(jsevent); |
- |
- // Based on code from kjs_bindings.cpp. |
- // Note: This is more liberal than Firefox's implementation. |
- if (event) { |
- const AtomicString& type = event->type(); |
- bool event_ok = |
- // mouse events |
- type == EventNames::clickEvent || |
- type == EventNames::mousedownEvent || |
- type == EventNames::mouseupEvent || |
- type == EventNames::dblclickEvent || |
- // keyboard events |
- type == EventNames::keydownEvent || |
- type == EventNames::keypressEvent || |
- type == EventNames::keyupEvent || |
- // other accepted events |
- type == EventNames::selectEvent || |
- type == EventNames::changeEvent || |
- type == EventNames::focusEvent || |
- type == EventNames::blurEvent || |
- type == EventNames::submitEvent; |
- |
- if (event_ok) |
- return true; |
- } else if (active_proxy->inlineCode() && !active_proxy->timerCallback()) |
- // This is the <a href="javascript:window.open('...')> case -> we let it |
- // through |
- return true; |
- |
- // This is the <script>window.open(...)</script> case or a timer callback -> |
- // block it |
- return false; |
-} |
- |
- |
-// Evaluate a script file in the environment of this proxy. |
-String ScriptController::evaluate(const String& filename, int baseLine, |
- const String& code, Node* node, bool* succ) |
-{ |
- if (succ) |
- *succ = false; |
- String result; |
- |
- v8::HandleScope hs; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); |
- if (context.IsEmpty()) |
- return result; |
- |
- v8::Context::Scope scope(context); |
- |
- // HTMLTokenizer used to use base zero line numbers for scripts, now it |
- // uses base 1. This confuses v8, which uses line offsets from the |
- // first line. |
- v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine - 1, code, |
- node); |
- |
- if (obj.IsEmpty() || obj->IsUndefined()) |
- return result; |
- |
- // If the return value is not a string, return 0 (what KJS does). |
- if (!obj->IsString()) { |
- v8::TryCatch exception_block; |
- obj = obj->ToString(); |
- if (exception_block.HasCaught()) |
- obj = v8::String::New(""); |
- } |
- |
- result = ToWebCoreString(obj); |
- if (succ) |
- *succ = true; |
- |
- return result; |
-} |
- |
-v8::Persistent<v8::Value> ScriptController::evaluate(const String& filename, |
- int baseLine, |
- const String& code, |
- Node* node) |
-{ |
- v8::HandleScope hs; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); |
- if (context.IsEmpty()) |
- return v8::Persistent<v8::Value>(); |
- |
- v8::Context::Scope scope(context); |
- |
- v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine, code, node); |
- |
- if (obj.IsEmpty()) |
- return v8::Persistent<v8::Value>(); |
- |
- // TODO(fqian): keep track the global handle created. |
- return v8::Persistent<v8::Value>::New(obj); |
-} |
- |
-void ScriptController::disposeJSResult(v8::Persistent<v8::Value> result) |
-{ |
- result.Dispose(); |
- result.Clear(); |
-} |
- |
-PassRefPtr<EventListener> ScriptController::createHTMLEventHandler( |
- const String& functionName, const String& code, Node* node) |
-{ |
- return m_proxy->createHTMLEventHandler(functionName, code, node); |
-} |
- |
-#if ENABLE(SVG) |
-PassRefPtr<EventListener> ScriptController::createSVGEventHandler( |
- const String& functionName, const String& code, Node* node) |
-{ |
- return m_proxy->createSVGEventHandler(functionName, code, node); |
-} |
-#endif |
- |
-void ScriptController::setEventHandlerLineno(int lineno) |
-{ |
- m_proxy->setEventHandlerLineno(lineno); |
-} |
- |
-void ScriptController::finishedWithEvent(Event* evt) |
-{ |
- m_proxy->finishedWithEvent(evt); |
-} |
- |
-void ScriptController::clearDocumentWrapper() |
-{ |
- m_proxy->clearDocumentWrapper(); |
-} |
- |
-// Create a V8 object with an interceptor of NPObjectPropertyGetter |
-void ScriptController::BindToWindowObject(Frame* frame, const String& key, NPObject* object) |
-{ |
- v8::HandleScope handle_scope; |
- |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); |
- if (context.IsEmpty()) |
- return; |
- |
- v8::Context::Scope scope(context); |
- |
- v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, NULL); |
- |
- // Attach to the global object |
- v8::Handle<v8::Object> global = context->Global(); |
- global->Set(v8String(key), value); |
-} |
- |
-void ScriptController::collectGarbage() |
-{ |
- v8::HandleScope hs; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); |
- if (context.IsEmpty()) |
- return; |
- |
- v8::Context::Scope scope(context); |
- |
- m_proxy->Evaluate("", 0, "if (window.gc) void(gc());", NULL); |
-} |
- |
-NPRuntimeFunctions* ScriptController::functions() |
-{ |
- return &npruntime_functions; |
-} |
- |
- |
-bool ScriptController::haveInterpreter() const |
-{ |
- return m_proxy->ContextInitialized(); |
-} |
- |
-bool ScriptController::isEnabled() const |
-{ |
- return m_proxy->isEnabled(); |
-} |
- |
JSInstanceHandle ScriptController::createScriptInstanceForWidget(Widget* widget) |
{ |
ASSERT(widget != 0); |
@@ -392,197 +56,15 @@ |
if (!npObject) |
return JSInstanceHolder::EmptyInstance(); |
-#if USE(JSC) |
// Register 'widget' with the frame so that we can teardown |
// subobjects when the container goes away. |
- RefPtr<KJS::Bindings::RootObject> root = script()->createRootObject(widget); |
- KJS::Bindings::Instance* instance = |
- KJS::Bindings::Instance::createBindingForLanguageInstance( |
- KJS::Bindings::Instance::CLanguage, npObject, |
- root.release()); |
+ RefPtr<JSC::Bindings::RootObject> root = createRootObject(widget); |
+ RefPtr<JSC::Bindings::Instance> instance = |
+ JSC::Bindings::CInstance::create(npObject, root.release()); |
// GetPluginScriptableObject returns a retained NPObject. |
// The caller is expected to release it. |
NPN_ReleaseObject(npObject); |
- return instance; |
-#elif USE(V8) |
- // Frame Memory Management for NPObjects |
- // ------------------------------------- |
- // NPObjects are treated differently than other objects wrapped by JS. |
- // NPObjects are not Peerable, and cannot be made peerable, since NPObjects |
- // can be created either by the browser (e.g. the main window object) or by |
- // the plugin (the main plugin object for a HTMLEmbedElement). Further, |
- // unlike most DOM Objects, the frame is especially careful to ensure |
- // NPObjects terminate at frame teardown because if a plugin leaks a |
- // reference, it could leak its objects (or the browser's objects). |
- // |
- // The Frame maintains a list of plugin objects (m_pluginObjects) |
- // which it can use to quickly find the wrapped embed object. |
- // |
- // Inside the NPRuntime, we've added a few methods for registering |
- // wrapped NPObjects. The purpose of the registration is because |
- // javascript garbage collection is non-deterministic, yet we need to |
- // be able to tear down the plugin objects immediately. When an object |
- // is registered, javascript can use it. When the object is destroyed, |
- // or when the object's "owning" object is destroyed, the object will |
- // be un-registered, and the javascript engine must not use it. |
- // |
- // Inside the javascript engine, the engine can keep a reference to the |
- // NPObject as part of its wrapper. However, before accessing the object |
- // it must consult the NPN_Registry. |
- |
- v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, NULL); |
- |
- // Track the plugin object. We've been given a reference to the object. |
- m_pluginObjects.set(widget, npObject); |
- |
- JSInstance instance = wrapper; |
- return instance; |
-#endif |
+ return instance.release(); |
} |
-void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) |
-{ |
- PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); |
- if (it == m_pluginObjects.end()) |
- return; |
- _NPN_UnregisterObject(it->second); |
- NPN_ReleaseObject(it->second); |
- m_pluginObjects.remove(it); |
-} |
- |
-static NPObject* createNoScriptObject() |
-{ |
- notImplemented(); |
- return 0; |
-} |
- |
-static NPObject* createScriptObject(Frame* frame) |
-{ |
- v8::HandleScope handleScope; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); |
- if (context.IsEmpty()) |
- return createNoScriptObject(); |
- |
- v8::Context::Scope scope(context); |
- DOMWindow* window = frame->domWindow(); |
- v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); |
- ASSERT(global->IsObject()); |
- return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(global), window); |
-} |
- |
-NPObject* ScriptController::windowScriptNPObject() |
-{ |
- if (m_windowScriptNPObject) |
- return m_windowScriptNPObject; |
- |
- if (isEnabled()) { |
- // JavaScript is enabled, so there is a JavaScript window object. |
- // Return an NPObject bound to the window object. |
- m_windowScriptNPObject = createScriptObject(m_frame); |
- _NPN_RegisterObject(m_windowScriptNPObject, NULL); |
- } else { |
- // JavaScript is not enabled, so we cannot bind the NPObject to the |
- // JavaScript window object. Instead, we create an NPObject of a |
- // different class, one which is not bound to a JavaScript object. |
- m_windowScriptNPObject = createNoScriptObject(); |
- } |
- return m_windowScriptNPObject; |
-} |
- |
-NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) |
-{ |
- // Can't create NPObjects when JavaScript is disabled |
- if (!isEnabled()) |
- return createNoScriptObject(); |
- |
- v8::HandleScope handleScope; |
- v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); |
- if (context.IsEmpty()) |
- return createNoScriptObject(); |
- v8::Context::Scope scope(context); |
- |
- DOMWindow* window = m_frame->domWindow(); |
- v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); |
- if (!v8plugin->IsObject()) |
- return createNoScriptObject(); |
- |
- return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window); |
-} |
- |
- |
-void ScriptController::clearWindowShell() |
-{ |
- m_proxy->clearForNavigation(); |
-} |
- |
-void ScriptController::attachDebugger(void*) |
-{ |
- notImplemented(); |
-} |
- |
-void ScriptController::updateDocument() |
-{ |
- // TODO(eseidel): Should update document property on current window object |
- // and all previous window objects which may still be alive. |
- notImplemented(); |
-} |
- |
- |
-JSInstanceHolder::JSInstanceHolder() |
-{ |
-} |
- |
-JSInstanceHolder::JSInstanceHolder(JSInstanceHandle instance) |
-{ |
- *this = instance; |
-} |
- |
-JSInstanceHolder::~JSInstanceHolder() |
-{ |
- Clear(); |
-} |
- |
-bool JSInstanceHolder::IsEmpty() |
-{ |
- return m_instance.IsEmpty(); |
-} |
- |
-JSInstance JSInstanceHolder::Get() |
-{ |
- return v8::Local<v8::Object>::New(m_instance); |
-} |
- |
-void JSInstanceHolder::Clear() |
-{ |
- if (m_instance.IsEmpty()) |
- return; |
- v8::HandleScope scope; |
- v8::Persistent<v8::Object> handle(m_instance); |
-#ifndef NDEBUG |
- V8Proxy::UnregisterGlobalHandle(this, handle); |
-#endif |
- handle.Dispose(); |
- m_instance.Clear(); |
-} |
- |
-JSInstance JSInstanceHolder::EmptyInstance() |
-{ |
- return v8::Local<v8::Object>(); |
-} |
- |
-JSInstanceHolder& JSInstanceHolder::operator=(JSInstanceHandle instance) |
-{ |
- Clear(); |
- if (instance.IsEmpty()) |
- return *this; |
- |
- v8::Persistent<v8::Object> handle = |
- v8::Persistent<v8::Object>::New(instance); |
- m_instance = handle; |
-#ifndef NDEBUG |
- V8Proxy::RegisterGlobalHandle(JSINSTANCE, this, handle); |
-#endif |
- return *this; |
-} |
- |
} // namespace WebCpre |