1 /* 2 * Copyright (C) 2000 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2006 Jon Shier (jshier (at) iastate.edu) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reseved. 5 * Copyright (C) 2006 Alexey Proskuryakov (ap (at) 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 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 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 70 ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const 71 { 72 return m_impl->document(); 73 } 74 75 String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const 76 { 77 return m_shell->window()->impl()->crossDomainAccessErrorMessage(asJSDOMWindow(other)->impl()); 78 } 79 80 void JSDOMWindowBase::printErrorMessage(const String& message) const 81 { 82 printErrorMessageForFrame(impl()->frame(), message); 83 } 84 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 94 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 111 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 133 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 151 void JSDOMWindowBase::willRemoveFromWindowShell() 152 { 153 setCurrentEvent(0); 154 } 155 156 JSObject* JSDOMWindowBase::toThisObject(ExecState*) const 157 { 158 return shell(); 159 } 160 161 JSValue JSDOMWindowBase::toStrictThisObject(ExecState*) const 162 { 163 return shell(); 164 } 165 166 JSDOMWindowShell* JSDOMWindowBase::shell() const 167 { 168 return m_shell; 169 } 170 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. 190 JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) 191 { 192 return toJS(exec, domWindow); 193 } 194 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 205 JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world) 206 { 207 if (!frame) 208 return 0; 209 return frame->script()->windowShell(world)->window(); 210 } 211 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