1/*
2 * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef ScriptController_h
32#define ScriptController_h
33
34#include "ScriptInstance.h"
35#include "ScriptValue.h"
36
37#include "V8Proxy.h"
38
39#include <v8.h>
40
41#include <wtf/HashMap.h>
42#include <wtf/RefCounted.h>
43#include <wtf/Vector.h>
44
45struct NPObject;
46
47namespace WebCore {
48
49class DOMWrapperWorld;
50class Event;
51class Frame;
52class HTMLPlugInElement;
53class ScriptSourceCode;
54class String;
55class Widget;
56class XSSAuditor;
57
58class ScriptController {
59public:
60    ScriptController(Frame*);
61    ~ScriptController();
62
63    // FIXME: V8Proxy should either be folded into ScriptController
64    // or this accessor should be made JSProxy*
65    V8Proxy* proxy() { return m_proxy.get(); }
66
67    ScriptValue executeScript(const ScriptSourceCode&);
68    ScriptValue executeScript(const String& script, bool forceUserGesture = false);
69
70    // Returns true if argument is a JavaScript URL.
71    bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true);
72
73    // This function must be called from the main thread. It is safe to call it repeatedly.
74    static void initializeThreading();
75
76    // Evaluate a script file in the environment of this proxy.
77    // If succeeded, 'succ' is set to true and result is returned
78    // as a string.
79    ScriptValue evaluate(const ScriptSourceCode&);
80
81    void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
82
83    // Executes JavaScript in an isolated world. The script gets its own global scope,
84    // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on),
85    // and its own wrappers for all DOM nodes and DOM constructors.
86    //
87    // If an isolated world with the specified ID already exists, it is reused.
88    // Otherwise, a new world is created.
89    //
90    // If the worldID is 0, a new world is always created.
91    //
92    // FIXME: Get rid of extensionGroup here.
93    void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup);
94
95    // Masquerade 'this' as the windowShell.
96    // This is a bit of a hack, but provides reasonable compatibility
97    // with what JSC does as well.
98    ScriptController* windowShell(DOMWrapperWorld*) { return this; }
99    ScriptController* existingWindowShell(DOMWrapperWorld*) { return this; }
100
101    XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); }
102
103    void collectGarbage();
104
105    // Notify V8 that the system is running low on memory.
106    void lowMemoryNotification();
107
108    // Creates a property of the global object of a frame.
109    void bindToWindowObject(Frame*, const String& key, NPObject*);
110
111    PassScriptInstance createScriptInstanceForWidget(Widget*);
112
113    // Check if the javascript engine has been initialized.
114    bool haveInterpreter() const;
115
116    bool canExecuteScripts();
117
118    // FIXME: void* is a compile hack.
119    void attachDebugger(void*);
120
121    // --- Static methods assume we are running VM in single thread, ---
122    // --- and there is only one VM instance.                        ---
123
124    // Returns the frame for the entered context. See comments in
125    // V8Proxy::retrieveFrameForEnteredContext() for more information.
126    static Frame* retrieveFrameForEnteredContext();
127
128    // Returns the frame for the current context. See comments in
129    // V8Proxy::retrieveFrameForEnteredContext() for more information.
130    static Frame* retrieveFrameForCurrentContext();
131
132    // Check whether it is safe to access a frame in another domain.
133    static bool isSafeScript(Frame*);
134
135    // Pass command-line flags to the JS engine.
136    static void setFlags(const char* string, int length);
137
138    // Protect and unprotect the JS wrapper from garbage collected.
139    static void gcProtectJSWrapper(void*);
140    static void gcUnprotectJSWrapper(void*);
141
142    void finishedWithEvent(Event*);
143    void setEventHandlerLineNumber(int lineNumber);
144
145    void setProcessingTimerCallback(bool processingTimerCallback) { m_processingTimerCallback = processingTimerCallback; }
146    // FIXME: Currently we don't use the parameter world at all.
147    // See http://trac.webkit.org/changeset/54182
148    bool processingUserGesture(DOMWrapperWorld* world = 0) const;
149    bool anyPageIsProcessingUserGesture() const;
150
151    void setPaused(bool paused) { m_paused = paused; }
152    bool isPaused() const { return m_paused; }
153
154    const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script.
155
156    void clearWindowShell();
157    void updateDocument();
158
159    void updateSecurityOrigin();
160    void clearScriptObjects();
161    void updatePlatformScriptObjects();
162    void cleanupScriptObjectsForPlugin(Widget*);
163
164#if ENABLE(NETSCAPE_PLUGIN_API)
165    NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*);
166    NPObject* windowScriptNPObject();
167#endif
168
169    // Dummy method to avoid a bunch of ifdef's in WebCore.
170    void evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*);
171    static void getAllWorlds(Vector<DOMWrapperWorld*>& worlds);
172
173private:
174    Frame* m_frame;
175    const String* m_sourceURL;
176
177    bool m_inExecuteScript;
178
179    bool m_processingTimerCallback;
180    bool m_paused;
181
182    OwnPtr<V8Proxy> m_proxy;
183    typedef HashMap<Widget*, NPObject*> PluginObjectMap;
184
185    // A mapping between Widgets and their corresponding script object.
186    // This list is used so that when the plugin dies, we can immediately
187    // invalidate all sub-objects which are associated with that plugin.
188    // The frame keeps a NPObject reference for each item on the list.
189    PluginObjectMap m_pluginObjects;
190#if ENABLE(NETSCAPE_PLUGIN_API)
191    NPObject* m_windowScriptNPObject;
192#endif
193    // The XSSAuditor associated with this ScriptController.
194    OwnPtr<XSSAuditor> m_XSSAuditor;
195};
196
197} // namespace WebCore
198
199#endif // ScriptController_h
200