• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "JSDOMWindowCustom.h"
32 #include "JSNode.h"
33 #include "Logging.h"
34 #include "Page.h"
35 #include "ScriptController.h"
36 #include "SecurityOrigin.h"
37 #include "Settings.h"
38 #include "WebCoreJSClientData.h"
39 #include <wtf/Threading.h>
40 #include <wtf/text/StringConcatenate.h>
41 
42 using namespace JSC;
43 
44 namespace WebCore {
45 
46 const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 };
47 
JSDOMWindowBase(JSGlobalData & globalData,Structure * structure,PassRefPtr<DOMWindow> window,JSDOMWindowShell * shell)48 JSDOMWindowBase::JSDOMWindowBase(JSGlobalData& globalData, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
49     : JSDOMGlobalObject(globalData, structure, shell->world(), shell)
50     , m_impl(window)
51     , m_shell(shell)
52 {
53     ASSERT(inherits(&s_info));
54 
55     GlobalPropertyInfo staticGlobals[] = {
56         GlobalPropertyInfo(Identifier(globalExec(), "document"), jsNull(), DontDelete | ReadOnly),
57         GlobalPropertyInfo(Identifier(globalExec(), "window"), m_shell, DontDelete | ReadOnly)
58     };
59 
60     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
61 }
62 
updateDocument()63 void JSDOMWindowBase::updateDocument()
64 {
65     ASSERT(m_impl->document());
66     ExecState* exec = globalExec();
67     symbolTablePutWithAttributes(exec->globalData(), Identifier(exec, "document"), toJS(exec, this, m_impl->document()), DontDelete | ReadOnly);
68 }
69 
scriptExecutionContext() const70 ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
71 {
72     return m_impl->document();
73 }
74 
crossDomainAccessErrorMessage(const JSGlobalObject * other) const75 String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const
76 {
77     return m_shell->window()->impl()->crossDomainAccessErrorMessage(asJSDOMWindow(other)->impl());
78 }
79 
printErrorMessage(const String & message) const80 void JSDOMWindowBase::printErrorMessage(const String& message) const
81 {
82     printErrorMessageForFrame(impl()->frame(), message);
83 }
84 
globalExec()85 ExecState* JSDOMWindowBase::globalExec()
86 {
87     // We need to make sure that any script execution happening in this
88     // frame does not destroy it
89     if (Frame *frame = impl()->frame())
90         frame->keepAlive();
91     return Base::globalExec();
92 }
93 
supportsProfiling() const94 bool JSDOMWindowBase::supportsProfiling() const
95 {
96 #if !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR)
97     return false;
98 #else
99     Frame* frame = impl()->frame();
100     if (!frame)
101         return false;
102 
103     Page* page = frame->page();
104     if (!page)
105         return false;
106 
107     return page->inspectorController()->profilerEnabled();
108 #endif
109 }
110 
supportsRichSourceInfo() const111 bool JSDOMWindowBase::supportsRichSourceInfo() const
112 {
113 #if PLATFORM(ANDROID)
114     return true;
115 #elif !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR)
116     return false;
117 #else
118     Frame* frame = impl()->frame();
119     if (!frame)
120         return false;
121 
122     Page* page = frame->page();
123     if (!page)
124         return false;
125 
126     bool enabled = page->inspectorController()->enabled();
127     ASSERT(enabled || !debugger());
128     ASSERT(enabled || !supportsProfiling());
129     return enabled;
130 #endif
131 }
132 
shouldInterruptScript() const133 bool JSDOMWindowBase::shouldInterruptScript() const
134 {
135     ASSERT(impl()->frame());
136     Page* page = impl()->frame()->page();
137 
138     // See <rdar://problem/5479443>. We don't think that page can ever be NULL
139     // in this case, but if it is, we've gotten into a state where we may have
140     // hung the UI, with no way to ask the client whether to cancel execution.
141     // For now, our solution is just to cancel execution no matter what,
142     // ensuring that we never hang. We might want to consider other solutions
143     // if we discover problems with this one.
144     ASSERT(page);
145     if (!page)
146         return true;
147 
148     return page->chrome()->shouldInterruptJavaScript();
149 }
150 
willRemoveFromWindowShell()151 void JSDOMWindowBase::willRemoveFromWindowShell()
152 {
153     setCurrentEvent(0);
154 }
155 
toThisObject(ExecState *) const156 JSObject* JSDOMWindowBase::toThisObject(ExecState*) const
157 {
158     return shell();
159 }
160 
toStrictThisObject(ExecState *) const161 JSValue JSDOMWindowBase::toStrictThisObject(ExecState*) const
162 {
163     return shell();
164 }
165 
shell() const166 JSDOMWindowShell* JSDOMWindowBase::shell() const
167 {
168     return m_shell;
169 }
170 
commonJSGlobalData()171 JSGlobalData* JSDOMWindowBase::commonJSGlobalData()
172 {
173     ASSERT(isMainThread());
174 
175     static JSGlobalData* globalData = 0;
176     if (!globalData) {
177         globalData = JSGlobalData::createLeaked(ThreadStackTypeLarge).releaseRef();
178         globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds
179 #ifndef NDEBUG
180         globalData->exclusiveThread = currentThread();
181 #endif
182         initNormalWorldClientData(globalData);
183     }
184 
185     return globalData;
186 }
187 
188 // JSDOMGlobalObject* is ignored, accessing a window in any context will
189 // use that DOMWindow's prototype chain.
toJS(ExecState * exec,JSDOMGlobalObject *,DOMWindow * domWindow)190 JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow)
191 {
192     return toJS(exec, domWindow);
193 }
194 
toJS(ExecState * exec,DOMWindow * domWindow)195 JSValue toJS(ExecState* exec, DOMWindow* domWindow)
196 {
197     if (!domWindow)
198         return jsNull();
199     Frame* frame = domWindow->frame();
200     if (!frame)
201         return jsNull();
202     return frame->script()->windowShell(currentWorld(exec));
203 }
204 
toJSDOMWindow(Frame * frame,DOMWrapperWorld * world)205 JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world)
206 {
207     if (!frame)
208         return 0;
209     return frame->script()->windowShell(world)->window();
210 }
211 
toJSDOMWindow(JSValue value)212 JSDOMWindow* toJSDOMWindow(JSValue value)
213 {
214     if (!value.isObject())
215         return 0;
216     const ClassInfo* classInfo = asObject(value)->classInfo();
217     if (classInfo == &JSDOMWindow::s_info)
218         return static_cast<JSDOMWindow*>(asObject(value));
219     if (classInfo == &JSDOMWindowShell::s_info)
220         return static_cast<JSDOMWindowShell*>(asObject(value))->window();
221     return 0;
222 }
223 
224 } // namespace WebCore
225