1/*
2 *  Copyright (C) 1999 Harri Porten (porten@kde.org)
3 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 *  Copyright (C) 2008 Apple Inc. All rights reserved.
5 *  Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 *
7 *  This library is free software; you can redistribute it and/or
8 *  modify it under the terms of the GNU Lesser General Public
9 *  License as published by the Free Software Foundation; either
10 *  version 2 of the License, or (at your option) any later version.
11 *
12 *  This library is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 *  Lesser General Public License for more details.
16 *
17 *  You should have received a copy of the GNU Lesser General Public
18 *  License along with this library; if not, write to the Free Software
19 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22#ifndef ScriptController_h
23#define ScriptController_h
24
25#include "JSDOMWindowShell.h"
26#include "ScriptControllerBase.h"
27#include "ScriptInstance.h"
28#include <heap/Strong.h>
29#include <wtf/Forward.h>
30#include <wtf/RefPtr.h>
31
32#if PLATFORM(MAC)
33#include <wtf/RetainPtr.h>
34
35#ifdef __OBJC__
36@class WebScriptObject;
37#else
38class WebScriptObject;
39#endif
40#endif
41
42struct NPObject;
43
44namespace JSC {
45    class JSGlobalObject;
46
47    namespace Bindings {
48        class RootObject;
49    }
50}
51
52namespace WebCore {
53
54class Event;
55class EventListener;
56class HTMLPlugInElement;
57class Frame;
58class Node;
59class ScriptSourceCode;
60class ScriptValue;
61class Widget;
62
63typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject> > RootObjectMap;
64
65class ScriptController {
66    friend class ScriptCachedFrameData;
67    typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::Strong<JSDOMWindowShell> > ShellMap;
68
69public:
70    ScriptController(Frame*);
71    ~ScriptController();
72
73    static PassRefPtr<DOMWrapperWorld> createWorld();
74
75    JSDOMWindowShell* createWindowShell(DOMWrapperWorld*);
76    void destroyWindowShell(DOMWrapperWorld*);
77
78    JSDOMWindowShell* windowShell(DOMWrapperWorld* world)
79    {
80        ShellMap::iterator iter = m_windowShells.find(world);
81        return (iter != m_windowShells.end()) ? iter->second.get() : initScript(world);
82    }
83    JSDOMWindowShell* existingWindowShell(DOMWrapperWorld* world) const
84    {
85        ShellMap::const_iterator iter = m_windowShells.find(world);
86        return (iter != m_windowShells.end()) ? iter->second.get() : 0;
87    }
88    JSDOMWindow* globalObject(DOMWrapperWorld* world)
89    {
90        return windowShell(world)->window();
91    }
92
93    static void getAllWorlds(Vector<DOMWrapperWorld*>&);
94
95    ScriptValue executeScript(const ScriptSourceCode&);
96    ScriptValue executeScript(const String& script, bool forceUserGesture = false);
97    ScriptValue executeScriptInWorld(DOMWrapperWorld*, const String& script, bool forceUserGesture = false);
98
99    // Returns true if argument is a JavaScript URL.
100    bool executeIfJavaScriptURL(const KURL&, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL);
101
102    // This function must be called from the main thread. It is safe to call it repeatedly.
103    // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
104    static void initializeThreading();
105
106    ScriptValue evaluate(const ScriptSourceCode&);
107    ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*);
108
109    int eventHandlerLineNumber() const;
110
111    void setProcessingTimerCallback(bool b) { m_processingTimerCallback = b; }
112    static bool processingUserGesture();
113    bool anyPageIsProcessingUserGesture() const;
114
115    static bool canAccessFromCurrentOrigin(Frame*);
116    bool canExecuteScripts(ReasonForCallingCanExecuteScripts);
117
118    // Debugger can be 0 to detach any existing Debugger.
119    void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells.
120    void attachDebugger(JSDOMWindowShell*, JSC::Debugger*);
121
122    void setPaused(bool b) { m_paused = b; }
123    bool isPaused() const { return m_paused; }
124
125    void setAllowPopupsFromPlugin(bool allowPopupsFromPlugin) { m_allowPopupsFromPlugin = allowPopupsFromPlugin; }
126    bool allowPopupsFromPlugin() const { return m_allowPopupsFromPlugin; }
127
128    const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script
129
130    void clearWindowShell(bool goingIntoPageCache = false);
131    void updateDocument();
132
133    void namedItemAdded(HTMLDocument*, const AtomicString&) { }
134    void namedItemRemoved(HTMLDocument*, const AtomicString&) { }
135
136    // Notifies the ScriptController that the securityOrigin of the current
137    // document was modified.  For example, this method is called when
138    // document.domain is set.  This method is *not* called when a new document
139    // is attached to a frame because updateDocument() is called instead.
140    void updateSecurityOrigin();
141
142    void clearScriptObjects();
143    void cleanupScriptObjectsForPlugin(void*);
144
145    void updatePlatformScriptObjects();
146
147    PassScriptInstance createScriptInstanceForWidget(Widget*);
148    JSC::Bindings::RootObject* bindingRootObject();
149    JSC::Bindings::RootObject* cacheableBindingRootObject();
150
151    PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle);
152
153#if ENABLE(INSPECTOR)
154    static void setCaptureCallStackForUncaughtExceptions(bool);
155#endif
156
157#if PLATFORM(MAC)
158#if ENABLE(JAVA_BRIDGE)
159    static void initJavaJSBindings();
160#endif
161    WebScriptObject* windowScriptObject();
162#endif
163
164    JSC::JSObject* jsObjectForPluginElement(HTMLPlugInElement*);
165
166#if ENABLE(NETSCAPE_PLUGIN_API)
167    NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*);
168    NPObject* windowScriptNPObject();
169#endif
170
171private:
172    JSDOMWindowShell* initScript(DOMWrapperWorld* world);
173
174    void disconnectPlatformScriptObjects();
175
176    bool isJavaScriptAnchorNavigation() const;
177
178    ShellMap m_windowShells;
179    Frame* m_frame;
180    const String* m_sourceURL;
181
182    bool m_inExecuteScript;
183
184    bool m_processingTimerCallback;
185    bool m_paused;
186    bool m_allowPopupsFromPlugin;
187
188    // The root object used for objects bound outside the context of a plugin, such
189    // as NPAPI plugins. The plugins using these objects prevent a page from being cached so they
190    // are safe to invalidate() when WebKit navigates away from the page that contains them.
191    RefPtr<JSC::Bindings::RootObject> m_bindingRootObject;
192    // Unlike m_bindingRootObject these objects are used in pages that are cached, so they are not invalidate()'d.
193    // This ensures they are still available when the page is restored.
194    RefPtr<JSC::Bindings::RootObject> m_cacheableBindingRootObject;
195    RootObjectMap m_rootObjects;
196#if ENABLE(NETSCAPE_PLUGIN_API)
197    NPObject* m_windowScriptNPObject;
198#endif
199#if PLATFORM(MAC)
200    RetainPtr<WebScriptObject> m_windowScriptObject;
201#endif
202};
203
204} // namespace WebCore
205
206#endif // ScriptController_h
207