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