| /* |
| * Copyright (C) 2000 Harri Porten (porten@kde.org) |
| * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) |
| * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reseved. |
| * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
| * USA |
| */ |
| |
| #include "config.h" |
| #include "JSDOMWindowBase.h" |
| |
| #include "BindingSecurity.h" |
| #include "Chrome.h" |
| #include "Console.h" |
| #include "DOMWindow.h" |
| #include "Frame.h" |
| #include "InspectorController.h" |
| #include "JSDOMWindowCustom.h" |
| #include "JSNode.h" |
| #include "Logging.h" |
| #include "Page.h" |
| #include "ScriptController.h" |
| #include "SecurityOrigin.h" |
| #include "Settings.h" |
| #include "WebCoreJSClientData.h" |
| #include <wtf/MainThread.h> |
| |
| using namespace JSC; |
| |
| namespace WebCore { |
| |
| static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec) |
| { |
| return BindingSecurity::shouldAllowAccessToDOMWindow(exec, asJSDOMWindow(thisObject)->impl()); |
| } |
| |
| const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) }; |
| |
| const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &shouldAllowAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled }; |
| |
| JSDOMWindowBase::JSDOMWindowBase(JSGlobalData& globalData, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) |
| : JSDOMGlobalObject(globalData, structure, shell->world(), &s_globalObjectMethodTable) |
| , m_impl(window) |
| , m_shell(shell) |
| { |
| } |
| |
| void JSDOMWindowBase::finishCreation(JSGlobalData& globalData, JSDOMWindowShell* shell) |
| { |
| Base::finishCreation(globalData, shell); |
| ASSERT(inherits(&s_info)); |
| |
| GlobalPropertyInfo staticGlobals[] = { |
| GlobalPropertyInfo(Identifier(globalExec(), "document"), jsNull(), DontDelete | ReadOnly), |
| GlobalPropertyInfo(Identifier(globalExec(), "window"), m_shell, DontDelete | ReadOnly) |
| }; |
| |
| addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); |
| } |
| |
| void JSDOMWindowBase::destroy(JSCell* cell) |
| { |
| static_cast<JSDOMWindowBase*>(cell)->JSDOMWindowBase::~JSDOMWindowBase(); |
| } |
| |
| void JSDOMWindowBase::updateDocument() |
| { |
| ASSERT(m_impl->document()); |
| ExecState* exec = globalExec(); |
| symbolTablePutWithAttributes(this, exec->globalData(), Identifier(exec, "document"), toJS(exec, this, m_impl->document()), DontDelete | ReadOnly); |
| } |
| |
| ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const |
| { |
| return m_impl->document(); |
| } |
| |
| void JSDOMWindowBase::printErrorMessage(const String& message) const |
| { |
| printErrorMessageForFrame(impl()->frame(), message); |
| } |
| |
| bool JSDOMWindowBase::supportsProfiling(const JSGlobalObject* object) |
| { |
| #if !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR) |
| return false; |
| #else |
| const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); |
| Frame* frame = thisObject->impl()->frame(); |
| if (!frame) |
| return false; |
| |
| Page* page = frame->page(); |
| if (!page) |
| return false; |
| |
| return page->inspectorController()->profilerEnabled(); |
| #endif |
| } |
| |
| bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object) |
| { |
| #if !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR) |
| return false; |
| #else |
| const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); |
| Frame* frame = thisObject->impl()->frame(); |
| if (!frame) |
| return false; |
| |
| Page* page = frame->page(); |
| if (!page) |
| return false; |
| |
| bool enabled = page->inspectorController()->enabled(); |
| ASSERT(enabled || !thisObject->debugger()); |
| ASSERT(enabled || !supportsProfiling(thisObject)); |
| return enabled; |
| #endif |
| } |
| |
| bool JSDOMWindowBase::shouldInterruptScript(const JSGlobalObject* object) |
| { |
| const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); |
| ASSERT(thisObject->impl()->frame()); |
| Page* page = thisObject->impl()->frame()->page(); |
| |
| // See <rdar://problem/5479443>. We don't think that page can ever be NULL |
| // in this case, but if it is, we've gotten into a state where we may have |
| // hung the UI, with no way to ask the client whether to cancel execution. |
| // For now, our solution is just to cancel execution no matter what, |
| // ensuring that we never hang. We might want to consider other solutions |
| // if we discover problems with this one. |
| ASSERT(page); |
| if (!page) |
| return true; |
| |
| return page->chrome()->shouldInterruptJavaScript(); |
| } |
| |
| bool JSDOMWindowBase::javaScriptExperimentsEnabled(const JSGlobalObject* object) |
| { |
| const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); |
| Frame* frame = thisObject->impl()->frame(); |
| if (!frame) |
| return false; |
| Settings* settings = frame->settings(); |
| if (!settings) |
| return false; |
| return settings->javaScriptExperimentsEnabled(); |
| } |
| |
| void JSDOMWindowBase::willRemoveFromWindowShell() |
| { |
| setCurrentEvent(0); |
| } |
| |
| JSDOMWindowShell* JSDOMWindowBase::shell() const |
| { |
| return m_shell; |
| } |
| |
| JSGlobalData* JSDOMWindowBase::commonJSGlobalData() |
| { |
| ASSERT(isMainThread()); |
| |
| static JSGlobalData* globalData = 0; |
| if (!globalData) { |
| ScriptController::initializeThreading(); |
| globalData = JSGlobalData::createLeaked(LargeHeap).leakRef(); |
| globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds |
| #ifndef NDEBUG |
| globalData->exclusiveThread = currentThread(); |
| #endif |
| initNormalWorldClientData(globalData); |
| } |
| |
| return globalData; |
| } |
| |
| // JSDOMGlobalObject* is ignored, accessing a window in any context will |
| // use that DOMWindow's prototype chain. |
| JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) |
| { |
| return toJS(exec, domWindow); |
| } |
| |
| JSValue toJS(ExecState* exec, DOMWindow* domWindow) |
| { |
| if (!domWindow) |
| return jsNull(); |
| Frame* frame = domWindow->frame(); |
| if (!frame) |
| return jsNull(); |
| return frame->script()->windowShell(currentWorld(exec)); |
| } |
| |
| JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world) |
| { |
| if (!frame) |
| return 0; |
| return frame->script()->windowShell(world)->window(); |
| } |
| |
| JSDOMWindow* toJSDOMWindow(JSValue value) |
| { |
| if (!value.isObject()) |
| return 0; |
| const ClassInfo* classInfo = asObject(value)->classInfo(); |
| if (classInfo == &JSDOMWindow::s_info) |
| return jsCast<JSDOMWindow*>(asObject(value)); |
| if (classInfo == &JSDOMWindowShell::s_info) |
| return jsCast<JSDOMWindowShell*>(asObject(value))->window(); |
| return 0; |
| } |
| |
| } // namespace WebCore |