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 "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 46 JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) 47 : JSDOMGlobalObjectData(shell->world(), destroyJSDOMWindowBaseData) 48 , impl(window) 49 , shell(shell) 50 { 51 } 52 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 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 71 ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const 72 { 73 return d()->impl->document(); 74 } 75 76 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 88 void JSDOMWindowBase::printErrorMessage(const String& message) const 89 { 90 printErrorMessageForFrame(impl()->frame(), message); 91 } 92 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 102 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 119 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 137 void JSDOMWindowBase::willRemoveFromWindowShell() 138 { 139 setCurrentEvent(0); 140 } 141 142 JSObject* JSDOMWindowBase::toThisObject(ExecState*) const 143 { 144 return shell(); 145 } 146 147 JSDOMWindowShell* JSDOMWindowBase::shell() const 148 { 149 return d()->shell; 150 } 151 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 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. 176 JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) 177 { 178 return toJS(exec, domWindow); 179 } 180 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 191 JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world) 192 { 193 if (!frame) 194 return 0; 195 return frame->script()->windowShell(world)->window(); 196 } 197 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