Home | History | Annotate | Download | only in js
      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