Remove ENABLE(JAVASCRIPT_DEBUGGER) guards
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMWindowBase.cpp
1 /*
2  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reseved.
5  *  Copyright (C) 2006 Alexey Proskuryakov (ap@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
20  *  USA
21  */
22
23 #include "config.h"
24 #include "JSDOMWindowBase.h"
25
26 #include "Chrome.h"
27 #include "Console.h"
28 #include "DOMWindow.h"
29 #include "Frame.h"
30 #include "InspectorController.h"
31 #include "JSDOMGlobalObjectTask.h"
32 #include "JSDOMWindowCustom.h"
33 #include "JSNode.h"
34 #include "Logging.h"
35 #include "Page.h"
36 #include "ScriptController.h"
37 #include "SecurityOrigin.h"
38 #include "Settings.h"
39 #include "WebCoreJSClientData.h"
40 #include <runtime/Microtask.h>
41 #include <wtf/MainThread.h>
42
43 #if PLATFORM(IOS)
44 #include "ChromeClient.h"
45 #include "WebSafeGCActivityCallbackIOS.h"
46 #include "WebSafeIncrementalSweeperIOS.h"
47 #endif
48
49 using namespace JSC;
50
51 namespace WebCore {
52
53 static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec)
54 {
55     return BindingSecurity::shouldAllowAccessToDOMWindow(exec, asJSDOMWindow(thisObject)->impl());
56 }
57
58 const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) };
59
60 const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &shouldAllowAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout };
61
62 JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
63     : JSDOMGlobalObject(vm, structure, &shell->world(), &s_globalObjectMethodTable)
64     , m_impl(window)
65     , m_shell(shell)
66 {
67 }
68
69 void JSDOMWindowBase::finishCreation(VM& vm, JSDOMWindowShell* shell)
70 {
71     Base::finishCreation(vm, shell);
72     ASSERT(inherits(info()));
73
74     GlobalPropertyInfo staticGlobals[] = {
75         GlobalPropertyInfo(vm.propertyNames->document, jsNull(), DontDelete | ReadOnly),
76         GlobalPropertyInfo(vm.propertyNames->window, m_shell, DontDelete | ReadOnly)
77     };
78     
79     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
80 }
81
82 void JSDOMWindowBase::destroy(JSCell* cell)
83 {
84     static_cast<JSDOMWindowBase*>(cell)->JSDOMWindowBase::~JSDOMWindowBase();
85 }
86
87 void JSDOMWindowBase::updateDocument()
88 {
89     ASSERT(m_impl->document());
90     ExecState* exec = globalExec();
91     symbolTablePutWithAttributes(this, exec->vm(), exec->vm().propertyNames->document, toJS(exec, this, m_impl->document()), DontDelete | ReadOnly);
92 }
93
94 ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
95 {
96     return m_impl->document();
97 }
98
99 void JSDOMWindowBase::printErrorMessage(const String& message) const
100 {
101     printErrorMessageForFrame(impl().frame(), message);
102 }
103
104 bool JSDOMWindowBase::supportsProfiling(const JSGlobalObject* object)
105 {
106 #if !ENABLE(INSPECTOR)
107     UNUSED_PARAM(object);
108     return false;
109 #else
110     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
111     Frame* frame = thisObject->impl().frame();
112     if (!frame)
113         return false;
114
115     Page* page = frame->page();
116     if (!page)
117         return false;
118
119 #if ENABLE(INSPECTOR)
120     return page->inspectorController().profilerEnabled();
121 #else
122     return false;
123 #endif // ENABLE(INSPECTOR)
124 #endif
125 }
126
127 bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object)
128 {
129 #if !ENABLE(INSPECTOR)
130     UNUSED_PARAM(object);
131     return false;
132 #else
133     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
134     Frame* frame = thisObject->impl().frame();
135     if (!frame)
136         return false;
137
138     Page* page = frame->page();
139     if (!page)
140         return false;
141
142     bool enabled = page->inspectorController().enabled();
143     ASSERT(enabled || !thisObject->debugger());
144     ASSERT(enabled || !supportsProfiling(thisObject));
145     return enabled;
146 #endif
147 }
148
149 static inline bool shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(Page* page)
150 {
151     // See <rdar://problem/5479443>. We don't think that page can ever be NULL
152     // in this case, but if it is, we've gotten into a state where we may have
153     // hung the UI, with no way to ask the client whether to cancel execution.
154     // For now, our solution is just to cancel execution no matter what,
155     // ensuring that we never hang. We might want to consider other solutions
156     // if we discover problems with this one.
157     ASSERT(page);
158     return !page;
159 }
160
161 bool JSDOMWindowBase::shouldInterruptScript(const JSGlobalObject* object)
162 {
163     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
164     ASSERT(thisObject->impl().frame());
165     Page* page = thisObject->impl().frame()->page();
166     return shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page) || page->chrome().shouldInterruptJavaScript();
167 }
168
169 bool JSDOMWindowBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* object)
170 {
171     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
172     ASSERT(thisObject->impl().frame());
173     Page* page = thisObject->impl().frame()->page();
174
175     if (shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page))
176         return true;
177
178 #if PLATFORM(IOS)
179     if (page->chrome().client().isStopping())
180         return true;
181 #endif
182
183     return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object);
184 }
185
186 bool JSDOMWindowBase::javaScriptExperimentsEnabled(const JSGlobalObject* object)
187 {
188     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
189     Frame* frame = thisObject->impl().frame();
190     if (!frame)
191         return false;
192     return frame->settings().javaScriptExperimentsEnabled();
193 }
194
195 void JSDOMWindowBase::queueTaskToEventLoop(const JSGlobalObject* object, PassRefPtr<Microtask> task)
196 {
197     const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
198     thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask::create((JSDOMWindowBase*)thisObject, task));
199 }
200
201 void JSDOMWindowBase::willRemoveFromWindowShell()
202 {
203     setCurrentEvent(0);
204 }
205
206 JSDOMWindowShell* JSDOMWindowBase::shell() const
207 {
208     return m_shell;
209 }
210
211 VM* JSDOMWindowBase::commonVM()
212 {
213     ASSERT(isMainThread());
214
215 #if !PLATFORM(IOS)
216     static VM* vm = 0;
217 #else
218     VM*& vm = commonVMInternal();
219 #endif
220     if (!vm) {
221         ScriptController::initializeThreading();
222         vm = VM::createLeaked(LargeHeap).leakRef();
223 #if PLATFORM(IOS)
224         PassOwnPtr<WebSafeGCActivityCallback> activityCallback = WebSafeGCActivityCallback::create(&vm->heap);
225         vm->heap.setActivityCallback(activityCallback);
226         PassOwnPtr<WebSafeIncrementalSweeper> incrementalSweeper = WebSafeIncrementalSweeper::create(&vm->heap);
227         vm->heap.setIncrementalSweeper(incrementalSweeper);
228         vm->makeUsableFromMultipleThreads();
229         vm->heap.machineThreads().addCurrentThread();
230 #else
231         vm->exclusiveThread = currentThread();
232 #endif // !PLATFORM(IOS)
233         initNormalWorldClientData(vm);
234     }
235
236     return vm;
237 }
238
239 #if PLATFORM(IOS)
240 bool JSDOMWindowBase::commonVMExists()
241 {
242     return commonVMInternal();
243 }
244
245 VM*& JSDOMWindowBase::commonVMInternal()
246 {
247     ASSERT(isMainThread());
248     static VM* commonVM;
249     return commonVM;
250 }
251 #endif
252
253 // JSDOMGlobalObject* is ignored, accessing a window in any context will
254 // use that DOMWindow's prototype chain.
255 JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow)
256 {
257     return toJS(exec, domWindow);
258 }
259
260 JSValue toJS(ExecState* exec, DOMWindow* domWindow)
261 {
262     if (!domWindow)
263         return jsNull();
264     Frame* frame = domWindow->frame();
265     if (!frame)
266         return jsNull();
267     return frame->script().windowShell(currentWorld(exec));
268 }
269
270 JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld& world)
271 {
272     if (!frame)
273         return 0;
274     return frame->script().windowShell(world)->window();
275 }
276
277 JSDOMWindow* toJSDOMWindow(JSValue value)
278 {
279     if (!value.isObject())
280         return 0;
281     const ClassInfo* classInfo = asObject(value)->classInfo();
282     if (classInfo == JSDOMWindow::info())
283         return jsCast<JSDOMWindow*>(asObject(value));
284     if (classInfo == JSDOMWindowShell::info())
285         return jsCast<JSDOMWindowShell*>(asObject(value))->window();
286     return 0;
287 }
288
289 } // namespace WebCore