• 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 "CString.h"
27 #include "Chrome.h"
28 #include "Console.h"
29 #include "DOMWindow.h"
30 #include "Frame.h"
31 #include "InspectorController.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 
40 using namespace JSC;
41 
42 namespace WebCore {
43 
44 const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 };
45 
JSDOMWindowBaseData(PassRefPtr<DOMWindow> window,JSDOMWindowShell * shell)46 JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
47     : JSDOMGlobalObjectData(shell->world(), destroyJSDOMWindowBaseData)
48     , impl(window)
49     , shell(shell)
50 {
51 }
52 
JSDOMWindowBase(NonNullPassRefPtr<Structure> structure,PassRefPtr<DOMWindow> window,JSDOMWindowShell * shell)53 JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
54     : JSDOMGlobalObject(structure, new JSDOMWindowBaseData(window, shell), shell)
55 {
56     GlobalPropertyInfo staticGlobals[] = {
57         GlobalPropertyInfo(Identifier(globalExec(), "document"), jsNull(), DontDelete | ReadOnly),
58         GlobalPropertyInfo(Identifier(globalExec(), "window"), d()->shell, DontDelete | ReadOnly)
59     };
60 
61     addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
62 }
63 
updateDocument()64 void JSDOMWindowBase::updateDocument()
65 {
66     ASSERT(d()->impl->document());
67     ExecState* exec = globalExec();
68     symbolTablePutWithAttributes(Identifier(exec, "document"), toJS(exec, this, d()->impl->document()), DontDelete | ReadOnly);
69 }
70 
scriptExecutionContext() const71 ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
72 {
73     return d()->impl->document();
74 }
75 
crossDomainAccessErrorMessage(const JSGlobalObject * other) const76 String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const
77 {
78     KURL originURL = asJSDOMWindow(other)->impl()->url();
79     KURL targetURL = d()->shell->window()->impl()->url();
80     if (originURL.isNull() || targetURL.isNull())
81         return String();
82 
83     // FIXME: this error message should contain more specifics of why the same origin check has failed.
84     return String::format("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains, protocols and ports must match.\n",
85         targetURL.string().utf8().data(), originURL.string().utf8().data());
86 }
87 
printErrorMessage(const String & message) const88 void JSDOMWindowBase::printErrorMessage(const String& message) const
89 {
90     printErrorMessageForFrame(impl()->frame(), message);
91 }
92 
globalExec()93 ExecState* JSDOMWindowBase::globalExec()
94 {
95     // We need to make sure that any script execution happening in this
96     // frame does not destroy it
97     if (Frame *frame = impl()->frame())
98         frame->keepAlive();
99     return Base::globalExec();
100 }
101 
supportsProfiling() const102 bool JSDOMWindowBase::supportsProfiling() const
103 {
104 #if !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR)
105     return false;
106 #else
107     Frame* frame = impl()->frame();
108     if (!frame)
109         return false;
110 
111     Page* page = frame->page();
112     if (!page)
113         return false;
114 
115     return page->inspectorController()->profilerEnabled();
116 #endif
117 }
118 
shouldInterruptScript() const119 bool JSDOMWindowBase::shouldInterruptScript() const
120 {
121     ASSERT(impl()->frame());
122     Page* page = impl()->frame()->page();
123 
124     // See <rdar://problem/5479443>. We don't think that page can ever be NULL
125     // in this case, but if it is, we've gotten into a state where we may have
126     // hung the UI, with no way to ask the client whether to cancel execution.
127     // For now, our solution is just to cancel execution no matter what,
128     // ensuring that we never hang. We might want to consider other solutions
129     // if we discover problems with this one.
130     ASSERT(page);
131     if (!page)
132         return true;
133 
134     return page->chrome()->shouldInterruptJavaScript();
135 }
136 
willRemoveFromWindowShell()137 void JSDOMWindowBase::willRemoveFromWindowShell()
138 {
139     setCurrentEvent(0);
140 }
141 
toThisObject(ExecState *) const142 JSObject* JSDOMWindowBase::toThisObject(ExecState*) const
143 {
144     return shell();
145 }
146 
shell() const147 JSDOMWindowShell* JSDOMWindowBase::shell() const
148 {
149     return d()->shell;
150 }
151 
commonJSGlobalData()152 JSGlobalData* JSDOMWindowBase::commonJSGlobalData()
153 {
154     ASSERT(isMainThread());
155 
156     static JSGlobalData* globalData = 0;
157     if (!globalData) {
158         globalData = JSGlobalData::createLeaked().releaseRef();
159         globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds
160 #ifndef NDEBUG
161         globalData->mainThreadOnly = true;
162 #endif
163         globalData->clientData = new WebCoreJSClientData(globalData);
164     }
165 
166     return globalData;
167 }
168 
destroyJSDOMWindowBaseData(void * jsDOMWindowBaseData)169 void JSDOMWindowBase::destroyJSDOMWindowBaseData(void* jsDOMWindowBaseData)
170 {
171     delete static_cast<JSDOMWindowBaseData*>(jsDOMWindowBaseData);
172 }
173 
174 // JSDOMGlobalObject* is ignored, accessing a window in any context will
175 // use that DOMWindow's prototype chain.
toJS(ExecState * exec,JSDOMGlobalObject *,DOMWindow * domWindow)176 JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow)
177 {
178     return toJS(exec, domWindow);
179 }
180 
toJS(ExecState * exec,DOMWindow * domWindow)181 JSValue toJS(ExecState* exec, DOMWindow* domWindow)
182 {
183     if (!domWindow)
184         return jsNull();
185     Frame* frame = domWindow->frame();
186     if (!frame)
187         return jsNull();
188     return frame->script()->windowShell(currentWorld(exec));
189 }
190 
toJSDOMWindow(Frame * frame,DOMWrapperWorld * world)191 JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world)
192 {
193     if (!frame)
194         return 0;
195     return frame->script()->windowShell(world)->window();
196 }
197 
toJSDOMWindow(JSValue value)198 JSDOMWindow* toJSDOMWindow(JSValue value)
199 {
200     if (!value.isObject())
201         return 0;
202     const ClassInfo* classInfo = asObject(value)->classInfo();
203     if (classInfo == &JSDOMWindow::s_info)
204         return static_cast<JSDOMWindow*>(asObject(value));
205     if (classInfo == &JSDOMWindowShell::s_info)
206         return static_cast<JSDOMWindowShell*>(asObject(value))->window();
207     return 0;
208 }
209 
210 } // namespace WebCore
211