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 "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