summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/js/ScriptController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/js/ScriptController.cpp')
-rw-r--r--WebCore/bindings/js/ScriptController.cpp520
1 files changed, 0 insertions, 520 deletions
diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp
deleted file mode 100644
index cf55080..0000000
--- a/WebCore/bindings/js/ScriptController.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "ScriptController.h"
-
-#include "ScriptableDocumentParser.h"
-#include "Event.h"
-#include "EventNames.h"
-#include "Frame.h"
-#include "FrameLoaderClient.h"
-#include "GCController.h"
-#include "HTMLPlugInElement.h"
-#include "InspectorInstrumentation.h"
-#include "JSDocument.h"
-#include "JSMainThreadExecState.h"
-#include "NP_jsobject.h"
-#include "Page.h"
-#include "PageGroup.h"
-#include "ScriptSourceCode.h"
-#include "ScriptValue.h"
-#include "Settings.h"
-#include "StorageNamespace.h"
-#include "UserGestureIndicator.h"
-#include "WebCoreJSClientData.h"
-#include "XSSAuditor.h"
-#include "npruntime_impl.h"
-#include "runtime_root.h"
-#include <debugger/Debugger.h>
-#include <runtime/InitializeThreading.h>
-#include <runtime/JSLock.h>
-#include <wtf/Threading.h>
-
-using namespace JSC;
-using namespace std;
-
-namespace WebCore {
-
-void ScriptController::initializeThreading()
-{
- JSC::initializeThreading();
- WTF::initializeMainThread();
-}
-
-ScriptController::ScriptController(Frame* frame)
- : m_frame(frame)
- , m_sourceURL(0)
- , m_inExecuteScript(false)
- , m_processingTimerCallback(false)
- , m_paused(false)
- , m_allowPopupsFromPlugin(false)
-#if ENABLE(NETSCAPE_PLUGIN_API)
- , m_windowScriptNPObject(0)
-#endif
-#if PLATFORM(MAC)
- , m_windowScriptObject(0)
-#endif
- , m_XSSAuditor(new XSSAuditor(frame))
-{
-#if PLATFORM(MAC) && ENABLE(JAVA_BRIDGE)
- static bool initializedJavaJSBindings;
- if (!initializedJavaJSBindings) {
- initializedJavaJSBindings = true;
- initJavaJSBindings();
- }
-#endif
-}
-
-ScriptController::~ScriptController()
-{
- disconnectPlatformScriptObjects();
-
- if (m_cacheableBindingRootObject) {
- m_cacheableBindingRootObject->invalidate();
- m_cacheableBindingRootObject = 0;
- }
-
- // It's likely that destroying m_windowShells will create a lot of garbage.
- if (!m_windowShells.isEmpty()) {
- while (!m_windowShells.isEmpty())
- destroyWindowShell(m_windowShells.begin()->first.get());
- gcController().garbageCollectSoon();
- }
-}
-
-void ScriptController::destroyWindowShell(DOMWrapperWorld* world)
-{
- ASSERT(m_windowShells.contains(world));
- m_windowShells.remove(world);
- world->didDestroyWindowShell(this);
-}
-
-JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld* world)
-{
- ASSERT(!m_windowShells.contains(world));
- JSDOMWindowShell* windowShell = new JSDOMWindowShell(m_frame->domWindow(), world);
- m_windowShells.add(world, windowShell);
- world->didCreateWindowShell(this);
- return windowShell;
-}
-
-ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world, ShouldAllowXSS shouldAllowXSS)
-{
- const SourceCode& jsSourceCode = sourceCode.jsSourceCode();
- String sourceURL = ustringToString(jsSourceCode.provider()->url());
-
- if (shouldAllowXSS == DoNotAllowXSS && !m_XSSAuditor->canEvaluate(sourceCode.source())) {
- // This script is not safe to be evaluated.
- return JSValue();
- }
-
- // evaluate code. Returns the JS return value or 0
- // if there was none, an error occurred or the type couldn't be converted.
-
- // inlineCode is true for <a href="javascript:doSomething()">
- // and false for <script>doSomething()</script>. Check if it has the
- // expected value in all cases.
- // See smart window.open policy for where this is used.
- JSDOMWindowShell* shell = windowShell(world);
- ExecState* exec = shell->window()->globalExec();
- const String* savedSourceURL = m_sourceURL;
- m_sourceURL = &sourceURL;
-
- JSLock lock(SilenceAssertionsOnly);
-
- RefPtr<Frame> protect = m_frame;
-
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine());
-
- exec->globalData().timeoutChecker.start();
- Completion comp = JSMainThreadExecState::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell);
- exec->globalData().timeoutChecker.stop();
-
- InspectorInstrumentation::didEvaluateScript(cookie);
-
- // Evaluating the JavaScript could cause the frame to be deallocated
- // so we start the keep alive timer here.
- m_frame->keepAlive();
-
- if (comp.complType() == Normal || comp.complType() == ReturnValue) {
- m_sourceURL = savedSourceURL;
- return comp.value();
- }
-
- if (comp.complType() == Throw || comp.complType() == Interrupted)
- reportException(exec, comp.value());
-
- m_sourceURL = savedSourceURL;
- return JSValue();
-}
-
-ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ShouldAllowXSS shouldAllowXSS)
-{
- return evaluateInWorld(sourceCode, mainThreadNormalWorld(), shouldAllowXSS);
-}
-
-PassRefPtr<DOMWrapperWorld> ScriptController::createWorld()
-{
- return DOMWrapperWorld::create(JSDOMWindow::commonJSGlobalData());
-}
-
-void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds)
-{
- static_cast<WebCoreJSClientData*>(JSDOMWindow::commonJSGlobalData()->clientData)->getAllWorlds(worlds);
-}
-
-void ScriptController::clearWindowShell(bool goingIntoPageCache)
-{
- if (m_windowShells.isEmpty())
- return;
-
- JSLock lock(SilenceAssertionsOnly);
-
- for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) {
- JSDOMWindowShell* windowShell = iter->second;
-
- // Clear the debugger from the current window before setting the new window.
- attachDebugger(windowShell, 0);
-
- windowShell->window()->willRemoveFromWindowShell();
- windowShell->setWindow(m_frame->domWindow());
-
- // An m_cacheableBindingRootObject persists between page navigations
- // so needs to know about the new JSDOMWindow.
- if (m_cacheableBindingRootObject)
- m_cacheableBindingRootObject->updateGlobalObject(windowShell->window());
-
- if (Page* page = m_frame->page()) {
- attachDebugger(windowShell, page->debugger());
- windowShell->window()->setProfileGroup(page->group().identifier());
- }
- }
-
- // 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)
-{
- ASSERT(!m_windowShells.contains(world));
-
- JSLock lock(SilenceAssertionsOnly);
-
- JSDOMWindowShell* windowShell = createWindowShell(world);
-
- windowShell->window()->updateDocument();
-
- if (Page* page = m_frame->page()) {
- attachDebugger(windowShell, page->debugger());
- windowShell->window()->setProfileGroup(page->group().identifier());
- }
-
- m_frame->loader()->dispatchDidClearWindowObjectInWorld(world);
-
- return windowShell;
-}
-
-int ScriptController::eventHandlerLineNumber() const
-{
- // JSC expects 1-based line numbers, so we must add one here to get it right.
- ScriptableDocumentParser* parser = m_frame->document()->scriptableDocumentParser();
- if (parser)
- return parser->lineNumber() + 1;
- return 0;
-}
-
-bool ScriptController::processingUserGesture()
-{
- ExecState* exec = JSMainThreadExecState::currentState();
- Frame* frame = exec ? toDynamicFrame(exec) : 0;
- // No script is running, so it is user-initiated unless the gesture stack
- // explicitly says it is not.
- if (!frame)
- return UserGestureIndicator::getUserGestureState() != DefinitelyNotProcessingUserGesture;
-
- // FIXME: We check the plugin popup flag and javascript anchor navigation
- // from the dynamic frame becuase they should only be initiated on the
- // dynamic frame in which execution began if they do happen.
- ScriptController* scriptController = frame->script();
- ASSERT(scriptController);
- if (scriptController->allowPopupsFromPlugin() || scriptController->isJavaScriptAnchorNavigation())
- return true;
-
- // If a DOM event is being processed, check that it was initiated by the user
- // and that it is in the whitelist of event types allowed to generate pop-ups.
- if (JSDOMWindowShell* shell = scriptController->existingWindowShell(currentWorld(exec)))
- if (Event* event = shell->window()->currentEvent())
- return event->fromUserGesture();
-
- return UserGestureIndicator::processingUserGesture();
-}
-
-// FIXME: This seems like an insufficient check to verify a click on a javascript: anchor.
-bool ScriptController::isJavaScriptAnchorNavigation() const
-{
- // This is the <a href="javascript:window.open('...')> case -> we let it through
- if (m_sourceURL && m_sourceURL->isNull() && !m_processingTimerCallback)
- return true;
-
- // This is the <script>window.open(...)</script> case or a timer callback -> block it
- return false;
-}
-
-bool ScriptController::anyPageIsProcessingUserGesture() const
-{
- Page* page = m_frame->page();
- if (!page)
- return false;
-
- const HashSet<Page*>& pages = page->group().pages();
- HashSet<Page*>::const_iterator end = pages.end();
- for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
- for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
- ScriptController* script = frame->script();
-
- if (script->m_allowPopupsFromPlugin)
- return true;
-
- const ShellMap::const_iterator iterEnd = m_windowShells.end();
- for (ShellMap::const_iterator iter = m_windowShells.begin(); iter != iterEnd; ++iter) {
- JSDOMWindowShell* shell = iter->second.get();
- Event* event = shell->window()->currentEvent();
- if (event && event->fromUserGesture())
- return true;
- }
-
- if (isJavaScriptAnchorNavigation())
- return true;
- }
- }
-
- 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)
- attachDebugger(iter->second, debugger);
-}
-
-void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* debugger)
-{
- if (!shell)
- return;
-
- JSDOMWindow* globalObject = shell->window();
- if (debugger)
- debugger->attach(globalObject);
- else if (JSC::Debugger* currentDebugger = globalObject->debugger())
- currentDebugger->detach(globalObject);
-}
-
-void ScriptController::updateDocument()
-{
- if (!m_frame->document())
- return;
-
- JSLock lock(SilenceAssertionsOnly);
- for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter)
- iter->second->window()->updateDocument();
-}
-
-void ScriptController::updateSecurityOrigin()
-{
- // Our bindings do not do anything in this case.
-}
-
-Bindings::RootObject* ScriptController::cacheableBindingRootObject()
-{
- if (!canExecuteScripts(NotAboutToExecuteScript))
- return 0;
-
- if (!m_cacheableBindingRootObject) {
- JSLock lock(SilenceAssertionsOnly);
- m_cacheableBindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld()));
- }
- return m_cacheableBindingRootObject.get();
-}
-
-Bindings::RootObject* ScriptController::bindingRootObject()
-{
- if (!canExecuteScripts(NotAboutToExecuteScript))
- return 0;
-
- if (!m_bindingRootObject) {
- JSLock lock(SilenceAssertionsOnly);
- m_bindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld()));
- }
- return m_bindingRootObject.get();
-}
-
-PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* nativeHandle)
-{
- RootObjectMap::iterator it = m_rootObjects.find(nativeHandle);
- if (it != m_rootObjects.end())
- return it->second;
-
- RefPtr<Bindings::RootObject> rootObject = Bindings::RootObject::create(nativeHandle, globalObject(pluginWorld()));
-
- m_rootObjects.set(nativeHandle, rootObject);
- return rootObject.release();
-}
-
-#if ENABLE(INSPECTOR)
-void ScriptController::setCaptureCallStackForUncaughtExceptions(bool)
-{
-}
-#endif
-
-#if ENABLE(NETSCAPE_PLUGIN_API)
-
-NPObject* ScriptController::windowScriptNPObject()
-{
- if (!m_windowScriptNPObject) {
- if (canExecuteScripts(NotAboutToExecuteScript)) {
- // JavaScript is enabled, so there is a JavaScript window object.
- // Return an NPObject bound to the window object.
- JSC::JSLock lock(SilenceAssertionsOnly);
- JSObject* win = windowShell(pluginWorld())->window();
- ASSERT(win);
- Bindings::RootObject* root = bindingRootObject();
- m_windowScriptNPObject = _NPN_CreateScriptObject(0, win, root);
- } 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 = _NPN_CreateNoScriptObject();
- }
- }
-
- return m_windowScriptNPObject;
-}
-
-NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin)
-{
- JSObject* object = jsObjectForPluginElement(plugin);
- if (!object)
- return _NPN_CreateNoScriptObject();
-
- // Wrap the JSObject in an NPObject
- return _NPN_CreateScriptObject(0, object, bindingRootObject());
-}
-
-#endif
-
-JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin)
-{
- // Can't create JSObjects when JavaScript is disabled
- if (!canExecuteScripts(NotAboutToExecuteScript))
- return 0;
-
- // Create a JSObject bound to this element
- JSLock lock(SilenceAssertionsOnly);
- JSDOMWindow* globalObj = globalObject(pluginWorld());
- // FIXME: is normal okay? - used for NP plugins?
- JSValue jsElementValue = toJS(globalObj->globalExec(), globalObj, plugin);
- if (!jsElementValue || !jsElementValue.isObject())
- return 0;
-
- return jsElementValue.getObject();
-}
-
-#if !PLATFORM(MAC)
-
-void ScriptController::updatePlatformScriptObjects()
-{
-}
-
-void ScriptController::disconnectPlatformScriptObjects()
-{
-}
-
-#endif
-
-void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle)
-{
- RootObjectMap::iterator it = m_rootObjects.find(nativeHandle);
-
- if (it == m_rootObjects.end())
- return;
-
- it->second->invalidate();
- m_rootObjects.remove(it);
-}
-
-void ScriptController::clearScriptObjects()
-{
- JSLock lock(SilenceAssertionsOnly);
-
- RootObjectMap::const_iterator end = m_rootObjects.end();
- for (RootObjectMap::const_iterator it = m_rootObjects.begin(); it != end; ++it)
- it->second->invalidate();
-
- m_rootObjects.clear();
-
- if (m_bindingRootObject) {
- m_bindingRootObject->invalidate();
- m_bindingRootObject = 0;
- }
-
-#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
-}
-
-ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture, ShouldAllowXSS shouldAllowXSS)
-{
- ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->document()->url());
-
- if (!canExecuteScripts(AboutToExecuteScript) || isPaused())
- return ScriptValue();
-
- bool wasInExecuteScript = m_inExecuteScript;
- m_inExecuteScript = true;
-
- ScriptValue result = evaluateInWorld(sourceCode, world, shouldAllowXSS);
-
- if (!wasInExecuteScript) {
- m_inExecuteScript = false;
- Document::updateStyleForAllDocuments();
- }
-
- return result;
-}
-
-} // namespace WebCore