WebCore/bindings/js/JSDOMWindowCustom.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,1064 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "JSDOMWindowCustom.h"
+
+#include "AtomicString.h"
+#include "Chrome.h"
+#include "Database.h"
+#include "DOMWindow.h"
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "FloatRect.h"
+#include "Frame.h"
+#include "FrameLoadRequest.h"
+#include "FrameLoader.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+#include "HTMLCollection.h"
+#include "HTMLDocument.h"
+#include "History.h"
+#include "JSAudioConstructor.h"
+#if ENABLE(DATABASE)
+#include "JSDatabase.h"
+#include "JSDatabaseCallback.h"
+#endif
+#include "JSDOMWindowShell.h"
+#include "JSEvent.h"
+#include "JSEventListener.h"
+#include "JSEventSource.h"
+#include "JSHTMLCollection.h"
+#include "JSHistory.h"
+#include "JSImageConstructor.h"
+#include "JSLocation.h"
+#include "JSMessageChannel.h"
+#include "JSMessagePort.h"
+#include "JSMessagePortCustom.h"
+#include "JSOptionConstructor.h"
+
+#if ENABLE(SHARED_WORKERS)
+#include "JSSharedWorker.h"
+#endif
+
+#if ENABLE(3D_CANVAS)
+#include "JSArrayBuffer.h"
+#include "JSInt8Array.h"
+#include "JSUint8Array.h"
+#include "JSInt32Array.h"
+#include "JSUint32Array.h"
+#include "JSInt16Array.h"
+#include "JSUint16Array.h"
+#include "JSFloat32Array.h"
+#endif
+#include "JSWebKitCSSMatrix.h"
+#include "JSWebKitPoint.h"
+#if ENABLE(WEB_SOCKETS)
+#include "JSWebSocket.h"
+#endif
+#include "JSWorker.h"
+#include "JSXMLHttpRequest.h"
+#include "JSXSLTProcessor.h"
+#include "Location.h"
+#include "MediaPlayer.h"
+#include "MessagePort.h"
+#include "NotificationCenter.h"
+#include "Page.h"
+#include "PlatformScreen.h"
+#include "RegisteredEventListener.h"
+#include "ScheduledAction.h"
+#include "ScriptController.h"
+#include "SerializedScriptValue.h"
+#include "Settings.h"
+#include "SharedWorkerRepository.h"
+#include "WindowFeatures.h"
+#include <runtime/Error.h>
+#include <runtime/JSFunction.h>
+#include <runtime/JSObject.h>
+#include <runtime/PrototypeFunction.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSDOMWindow::markChildren(MarkStack& markStack)
+{
+    Base::markChildren(markStack);
+
+    impl()->markJSEventListeners(markStack);
+
+    JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalConsole());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalHistory());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocationbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalMenubar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalPersonalbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalScreen());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalScrollbars());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalSelection());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalMedia());
+#if ENABLE(DOM_STORAGE)
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage());
+#endif
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache());
+#endif
+}
+
+template<NativeFunction nativeFunction, int length>
+JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName)
+{
+    return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction);
+}
+
+static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+{
+    return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(identifierToAtomicString(propertyName))->domWindow());
+}
+
+static JSValue indexGetter(ExecState* exec, JSValue slotBase, unsigned index)
+{
+    return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(index)->domWindow());
+}
+
+static JSValue namedItemGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+{
+    JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slotBase));
+    Document* document = thisObj->impl()->frame()->document();
+
+    ASSERT(thisObj->allowsAccessFrom(exec));
+    ASSERT(document);
+    ASSERT(document->isHTMLDocument());
+
+    RefPtr<HTMLCollection> collection = document->windowNamedItems(identifierToString(propertyName));
+    if (collection->length() == 1)
+        return toJS(exec, collection->firstItem());
+    return toJS(exec, collection.get());
+}
+
+bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    // When accessing a Window cross-domain, functions are always the native built-in ones, and they
+    // are not affected by properties changed on the Window or anything in its prototype chain.
+    // This is consistent with the behavior of Firefox.
+
+    const HashEntry* entry;
+
+    // We don't want any properties other than "close" and "closed" on a closed window.
+    if (!impl()->frame()) {
+        // The following code is safe for cross-domain and same domain use.
+        // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
+        entry = s_info.propHashTable(exec)->entry(exec, propertyName);
+        if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
+            slot.setCustom(this, entry->propertyGetter());
+            return true;
+        }
+        entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+        if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
+            slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+            return true;
+        }
+
+        // FIXME: We should have a message here that explains why the property access/function call was
+        // not allowed. 
+        slot.setUndefined();
+        return true;
+    }
+
+    // We need to check for cross-domain access here without printing the generic warning message
+    // because we always allow access to some function, just different ones depending whether access
+    // is allowed.
+    String errorMessage;
+    bool allowsAccess = allowsAccessFrom(exec, errorMessage);
+
+    // Look for overrides before looking at any of our own properties, but ignore overrides completely
+    // if this is cross-domain access.
+    if (allowsAccess && JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot))
+        return true;
+
+    // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
+    // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
+    // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
+    // what prototype is actually set on this object.
+    entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+    if (entry) {
+        if (entry->attributes() & Function) {
+            if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
+                if (!allowsAccess) {
+                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
+                    return true;
+                }
+            } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
+                if (!allowsAccess) {
+                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+                    return true;
+                }
+            } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
+                if (!allowsAccess) {
+                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
+                    return true;
+                }
+            } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
+                if (!allowsAccess) {
+                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
+                    return true;
+                }
+            } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
+                if (!DOMWindow::canShowModalDialog(impl()->frame())) {
+                    slot.setUndefined();
+                    return true;
+                }
+            }
+        }
+    } else {
+        // Allow access to toString() cross-domain, but always Object.prototype.toString.
+        if (propertyName == exec->propertyNames().toString) {
+            if (!allowsAccess) {
+                slot.setCustom(this, objectToStringFunctionGetter);
+                return true;
+            }
+        }
+    }
+
+    entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
+    if (entry) {
+        slot.setCustom(this, entry->propertyGetter());
+        return true;
+    }
+
+    // Check for child frames by name before built-in properties to
+    // match Mozilla. This does not match IE, but some sites end up
+    // naming frames things that conflict with window properties that
+    // are in Moz but not IE. Since we have some of these, we have to do
+    // it the Moz way.
+    if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) {
+        slot.setCustom(this, childFrameGetter);
+        return true;
+    }
+
+    // Do prototype lookup early so that functions and attributes in the prototype can have
+    // precedence over the index and name getters.  
+    JSValue proto = prototype();
+    if (proto.isObject()) {
+        if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
+            if (!allowsAccess) {
+                printErrorMessage(errorMessage);
+                slot.setUndefined();
+            }
+            return true;
+        }
+    }
+
+    // FIXME: Search the whole frame hierarchy somewhere around here.
+    // We need to test the correct priority order.
+
+    // allow window[1] or parent[1] etc. (#56983)
+    bool ok;
+    unsigned i = propertyName.toArrayIndex(&ok);
+    if (ok && i < impl()->frame()->tree()->childCount()) {
+        slot.setCustomIndex(this, i, indexGetter);
+        return true;
+    }
+
+    if (!allowsAccess) {
+        printErrorMessage(errorMessage);
+        slot.setUndefined();
+        return true;
+    }
+
+    // Allow shortcuts like 'Image1' instead of document.images.Image1
+    Document* document = impl()->frame()->document();
+    if (document->isHTMLDocument()) {
+        AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
+        if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
+            slot.setCustom(this, namedItemGetter);
+            return true;
+        }
+    }
+
+    return Base::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    // Never allow cross-domain getOwnPropertyDescriptor
+    if (!allowsAccessFrom(exec))
+        return false;
+
+    const HashEntry* entry;
+    
+    // We don't want any properties other than "close" and "closed" on a closed window.
+    if (!impl()->frame()) {
+        // The following code is safe for cross-domain and same domain use.
+        // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
+        entry = s_info.propHashTable(exec)->entry(exec, propertyName);
+        if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
+            descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
+            return true;
+        }
+        entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+        if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
+            PropertySlot slot;
+            slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+            descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+            return true;
+        }
+        descriptor.setUndefined();
+        return true;
+    }
+
+    entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
+    if (entry) {
+        PropertySlot slot;
+        slot.setCustom(this, entry->propertyGetter());
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+        return true;
+    }
+    
+    // Check for child frames by name before built-in properties to
+    // match Mozilla. This does not match IE, but some sites end up
+    // naming frames things that conflict with window properties that
+    // are in Moz but not IE. Since we have some of these, we have to do
+    // it the Moz way.
+    if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) {
+        PropertySlot slot;
+        slot.setCustom(this, childFrameGetter);
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+        return true;
+    }
+    
+    bool ok;
+    unsigned i = propertyName.toArrayIndex(&ok);
+    if (ok && i < impl()->frame()->tree()->childCount()) {
+        PropertySlot slot;
+        slot.setCustomIndex(this, i, indexGetter);
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+        return true;
+    }
+
+    // Allow shortcuts like 'Image1' instead of document.images.Image1
+    Document* document = impl()->frame()->document();
+    if (document->isHTMLDocument()) {
+        AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
+        if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
+            PropertySlot slot;
+            slot.setCustom(this, namedItemGetter);
+            descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+            return true;
+        }
+    }
+    
+    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+    if (!impl()->frame())
+        return;
+
+    // Optimization: access JavaScript global variables directly before involving the DOM.
+    if (JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
+        if (allowsAccessFrom(exec))
+            JSGlobalObject::put(exec, propertyName, value, slot);
+        return;
+    }
+
+    if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), this))
+        return;
+
+    if (allowsAccessFrom(exec))
+        Base::put(exec, propertyName, value, slot);
+}
+
+bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+    // Only allow deleting properties by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return false;
+    return Base::deleteProperty(exec, propertyName);
+}
+
+void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    // Only allow the window to enumerated by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return;
+    Base::getPropertyNames(exec, propertyNames, mode);
+}
+
+void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    // Only allow the window to enumerated by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return;
+    Base::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
+{
+    // Only allow defining getters by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return;
+
+    // Don't allow shadowing location using defineGetter.
+    if (propertyName == "location")
+        return;
+
+    Base::defineGetter(exec, propertyName, getterFunction, attributes);
+}
+
+void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
+{
+    // Only allow defining setters by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return;
+    Base::defineSetter(exec, propertyName, setterFunction, attributes);
+}
+
+bool JSDOMWindow::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
+{
+    // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
+    if (!allowsAccessFrom(exec))
+        return false;
+    return Base::defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
+}
+
+JSValue JSDOMWindow::lookupGetter(ExecState* exec, const Identifier& propertyName)
+{
+    // Only allow looking-up getters by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return jsUndefined();
+    return Base::lookupGetter(exec, propertyName);
+}
+
+JSValue JSDOMWindow::lookupSetter(ExecState* exec, const Identifier& propertyName)
+{
+    // Only allow looking-up setters by frames in the same origin.
+    if (!allowsAccessFrom(exec))
+        return jsUndefined();
+    return Base::lookupSetter(exec, propertyName);
+}
+
+// Custom Attributes
+
+JSValue JSDOMWindow::history(ExecState* exec) const
+{
+    History* history = impl()->history();
+    if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, history))
+        return wrapper;
+
+    JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
+    JSHistory* jsHistory = new (exec) JSHistory(getDOMStructure<JSHistory>(exec, window), window, history);
+    cacheDOMObjectWrapper(exec, history, jsHistory);
+    return jsHistory;
+}
+
+JSValue JSDOMWindow::location(ExecState* exec) const
+{
+    Location* location = impl()->location();
+    if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, location))
+        return wrapper;
+
+    JSDOMWindow* window = const_cast<JSDOMWindow*>(this);
+    JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, window), window, location);
+    cacheDOMObjectWrapper(exec, location, jsLocation);
+    return jsLocation;
+}
+
+void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
+{
+    Frame* lexicalFrame = toLexicalFrame(exec);
+    if (!lexicalFrame)
+        return;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+    // To avoid breaking old widgets, make "var location =" in a top-level frame create
+    // a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
+    if (Settings* settings = lexicalFrame->settings()) {
+        if (settings->usesDashboardBackwardCompatibilityMode() && !lexicalFrame->tree()->parent()) {
+            if (allowsAccessFrom(exec))
+                putDirect(Identifier(exec, "location"), value);
+            return;
+        }
+    }
+#endif
+
+    Frame* frame = impl()->frame();
+    ASSERT(frame);
+
+    KURL url = completeURL(exec, ustringToString(value.toString(exec)));
+    if (url.isNull())
+        return;
+
+    if (!shouldAllowNavigation(exec, frame))
+        return;
+
+    if (!protocolIsJavaScript(url) || allowsAccessFrom(exec)) {
+        // We want a new history item if this JS was called via a user gesture
+        frame->redirectScheduler()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture(exec));
+    }
+}
+
+JSValue JSDOMWindow::crypto(ExecState*) const
+{
+    return jsUndefined();
+}
+
+JSValue JSDOMWindow::event(ExecState* exec) const
+{
+    Event* event = currentEvent();
+    if (!event)
+        return jsUndefined();
+    return toJS(exec, event);
+}
+
+#if ENABLE(EVENTSOURCE)
+JSValue JSDOMWindow::eventSource(ExecState* exec) const
+{
+    return getDOMConstructor<JSEventSourceConstructor>(exec, this);
+}
+#endif
+
+JSValue JSDOMWindow::image(ExecState* exec) const
+{
+    return getDOMConstructor<JSImageConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::option(ExecState* exec) const
+{
+    return getDOMConstructor<JSOptionConstructor>(exec, this);
+}
+
+#if ENABLE(VIDEO)
+JSValue JSDOMWindow::audio(ExecState* exec) const
+{
+    if (!MediaPlayer::isAvailable())
+        return jsUndefined();
+    return getDOMConstructor<JSAudioConstructor>(exec, this);
+}
+#endif
+
+JSValue JSDOMWindow::webKitPoint(ExecState* exec) const
+{
+    return getDOMConstructor<JSWebKitPointConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const
+{
+    return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this);
+}
+ 
+#if ENABLE(3D_CANVAS)
+JSValue JSDOMWindow::arrayBuffer(ExecState* exec) const
+{
+    return getDOMConstructor<JSArrayBufferConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::int8Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt8ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::uint8Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint8ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::int32Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt32ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::uint32Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint32ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::int16Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt16ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::uint16Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint16ArrayConstructor>(exec, this);
+}
+ 
+JSValue JSDOMWindow::float32Array(ExecState* exec) const
+{
+    return getDOMConstructor<JSFloat32ArrayConstructor>(exec, this);
+}
+
+// Temporary aliases to keep current WebGL content working during transition period to TypedArray spec.
+// To be removed before WebGL spec is finalized. (FIXME)
+JSValue JSDOMWindow::webGLArrayBuffer(ExecState* exec) const
+{
+    return getDOMConstructor<JSArrayBufferConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLByteArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt8ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLUnsignedByteArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint8ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLIntArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt32ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLUnsignedIntArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint32ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLShortArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSInt16ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLUnsignedShortArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSUint16ArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::webGLFloatArray(ExecState* exec) const
+{
+    return getDOMConstructor<JSFloat32ArrayConstructor>(exec, this);
+}
+#endif
+ 
+JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const
+{
+    return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
+}
+
+#if ENABLE(XSLT)
+JSValue JSDOMWindow::xsltProcessor(ExecState* exec) const
+{
+    return getDOMConstructor<JSXSLTProcessorConstructor>(exec, this);
+}
+#endif
+
+#if ENABLE(CHANNEL_MESSAGING)
+JSValue JSDOMWindow::messageChannel(ExecState* exec) const
+{
+    return getDOMConstructor<JSMessageChannelConstructor>(exec, this);
+}
+#endif
+
+#if ENABLE(WORKERS)
+JSValue JSDOMWindow::worker(ExecState* exec) const
+{
+    return getDOMConstructor<JSWorkerConstructor>(exec, this);
+}
+#endif
+
+#if ENABLE(SHARED_WORKERS)
+JSValue JSDOMWindow::sharedWorker(ExecState* exec) const
+{
+    if (SharedWorkerRepository::isAvailable())
+        return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
+    return jsUndefined();
+}
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+JSValue JSDOMWindow::webSocket(ExecState* exec) const
+{
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return jsUndefined();
+    Settings* settings = frame->settings();
+    if (!settings)
+        return jsUndefined();
+    return getDOMConstructor<JSWebSocketConstructor>(exec, this);
+}
+#endif
+
+// Custom functions
+
+// Helper for window.open() and window.showModalDialog()
+static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicFrame,
+                           Frame* openerFrame, const String& url, const String& frameName, 
+                           const WindowFeatures& windowFeatures, JSValue dialogArgs)
+{
+    ASSERT(lexicalFrame);
+    ASSERT(dynamicFrame);
+
+    ResourceRequest request;
+
+    // For whatever reason, Firefox uses the dynamicGlobalObject to determine
+    // the outgoingReferrer.  We replicate that behavior here.
+    String referrer = dynamicFrame->loader()->outgoingReferrer();
+    request.setHTTPReferrer(referrer);
+    FrameLoader::addHTTPOriginIfNeeded(request, dynamicFrame->loader()->outgoingOrigin());
+    FrameLoadRequest frameRequest(request, frameName);
+
+    // FIXME: It's much better for client API if a new window starts with a URL, here where we
+    // know what URL we are going to open. Unfortunately, this code passes the empty string
+    // for the URL, but there's a reason for that. Before loading we have to set up the opener,
+    // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently
+    // do an allowsAccessFrom call using the window we create, which can't be done before creating it.
+    // We'd have to resolve all those issues to pass the URL instead of "".
+
+    bool created;
+    // We pass in the opener frame here so it can be used for looking up the frame name, in case the active frame
+    // is different from the opener frame, and the name references a frame relative to the opener frame, for example
+    // "_self" or "_parent".
+    Frame* newFrame = lexicalFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created);
+    if (!newFrame)
+        return 0;
+
+    newFrame->loader()->setOpener(openerFrame);
+    newFrame->page()->setOpenedByDOM();
+
+    // FIXME: If a window is created from an isolated world, what are the consequences of this? 'dialogArguments' only appears back in the normal world?
+    JSDOMWindow* newWindow = toJSDOMWindow(newFrame, normalWorld(exec->globalData()));
+
+    if (dialogArgs)
+        newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);
+
+    if (!protocolIsJavaScript(url) || newWindow->allowsAccessFrom(exec)) {
+        KURL completedURL = url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(exec, url);
+        bool userGesture = processingUserGesture(exec);
+
+        if (created)
+            newFrame->loader()->changeLocation(completedURL, referrer, false, false, userGesture);
+        else if (!url.isEmpty())
+            newFrame->redirectScheduler()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
+    }
+
+    return newFrame;
+}
+
+static bool domWindowAllowPopUp(Frame* activeFrame, ExecState* exec)
+{
+    ASSERT(activeFrame);
+    if (activeFrame->script()->processingUserGesture(currentWorld(exec)))
+        return true;
+    return DOMWindow::allowPopUp(activeFrame);
+}
+
+JSValue JSDOMWindow::open(ExecState* exec)
+{
+    String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
+    AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(exec->argument(1).toString(exec));
+    WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)));
+
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return jsUndefined();
+    Frame* lexicalFrame = toLexicalFrame(exec);
+    if (!lexicalFrame)
+        return jsUndefined();
+    Frame* dynamicFrame = toDynamicFrame(exec);
+    if (!dynamicFrame)
+        return jsUndefined();
+
+    Page* page = frame->page();
+
+    // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
+    // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
+    if (!domWindowAllowPopUp(dynamicFrame, exec) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
+        return jsUndefined();
+
+    // Get the target frame for the special cases of _top and _parent.  In those
+    // cases, we can schedule a location change right now and return early.
+    bool topOrParent = false;
+    if (frameName == "_top") {
+        frame = frame->tree()->top();
+        topOrParent = true;
+    } else if (frameName == "_parent") {
+        if (Frame* parent = frame->tree()->parent())
+            frame = parent;
+        topOrParent = true;
+    }
+    if (topOrParent) {
+        String completedURL;
+        if (!urlString.isEmpty())
+            completedURL = completeURL(exec, urlString).string();
+
+        if (!shouldAllowNavigation(exec, frame))
+            return jsUndefined();
+
+        const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec));
+        if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
+            bool userGesture = processingUserGesture(exec);
+
+            // For whatever reason, Firefox uses the dynamicGlobalObject to
+            // determine the outgoingReferrer.  We replicate that behavior
+            // here.
+            String referrer = dynamicFrame->loader()->outgoingReferrer();
+
+            frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
+        }
+        return toJS(exec, frame->domWindow());
+    }
+
+    // In the case of a named frame or a new window, we'll use the createWindow() helper
+    FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
+                         windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
+    DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
+
+    windowFeatures.x = windowRect.x();
+    windowFeatures.y = windowRect.y();
+    windowFeatures.height = windowRect.height();
+    windowFeatures.width = windowRect.width();
+
+    frame = createWindow(exec, lexicalFrame, dynamicFrame, frame, urlString, frameName, windowFeatures, JSValue());
+
+    if (!frame)
+        return jsUndefined();
+
+    return toJS(exec, frame->domWindow());
+}
+
+JSValue JSDOMWindow::showModalDialog(ExecState* exec)
+{
+    String url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
+    JSValue dialogArgs = exec->argument(1);
+    String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
+
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return jsUndefined();
+    Frame* lexicalFrame = toLexicalFrame(exec);
+    if (!lexicalFrame)
+        return jsUndefined();
+    Frame* dynamicFrame = toDynamicFrame(exec);
+    if (!dynamicFrame)
+        return jsUndefined();
+
+    if (!DOMWindow::canShowModalDialogNow(frame) || !domWindowAllowPopUp(dynamicFrame, exec))
+        return jsUndefined();
+
+    HashMap<String, String> features;
+    DOMWindow::parseModalDialogFeatures(featureArgs, features);
+
+    const bool trusted = false;
+
+    // The following features from Microsoft's documentation are not implemented:
+    // - default font settings
+    // - width, height, left, and top specified in units other than "px"
+    // - edge (sunken or raised, default is raised)
+    // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
+    // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
+    // - unadorned: trusted && boolFeature(features, "unadorned");
+
+    FloatRect screenRect = screenAvailableRect(frame->view());
+
+    WindowFeatures wargs;
+    wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
+    wargs.widthSet = true;
+    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
+    wargs.heightSet = true;
+
+    wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);
+    wargs.xSet = wargs.x > 0;
+    wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);
+    wargs.ySet = wargs.y > 0;
+
+    if (WindowFeatures::boolFeature(features, "center", true)) {
+        if (!wargs.xSet) {
+            wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;
+            wargs.xSet = true;
+        }
+        if (!wargs.ySet) {
+            wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;
+            wargs.ySet = true;
+        }
+    }
+
+    wargs.dialog = true;
+    wargs.resizable = WindowFeatures::boolFeature(features, "resizable");
+    wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);
+    wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);
+    wargs.menuBarVisible = false;
+    wargs.toolBarVisible = false;
+    wargs.locationBarVisible = false;
+    wargs.fullscreen = false;
+
+    Frame* dialogFrame = createWindow(exec, lexicalFrame, dynamicFrame, frame, url, "", wargs, dialogArgs);
+    if (!dialogFrame)
+        return jsUndefined();
+
+    JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec));
+    dialogFrame->page()->chrome()->runModal();
+
+    Identifier returnValue(exec, "returnValue");
+    if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) {
+        PropertySlot slot;
+        // This is safe, we have already performed the origin security check and we are
+        // not interested in any of the DOM properties of the window.
+        if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot))
+            return slot.getValue(exec, returnValue);
+    }
+    return jsUndefined();
+}
+
+JSValue JSDOMWindow::postMessage(ExecState* exec)
+{
+    DOMWindow* window = impl();
+
+    DOMWindow* source = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
+    PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0));
+
+    if (exec->hadException())
+        return jsUndefined();
+
+    MessagePortArray messagePorts;
+    if (exec->argumentCount() > 2)
+        fillMessagePortArray(exec, exec->argument(1), messagePorts);
+    if (exec->hadException())
+        return jsUndefined();
+
+    String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, exec->argument((exec->argumentCount() == 2) ? 1 : 2));
+    if (exec->hadException())
+        return jsUndefined();
+
+    ExceptionCode ec = 0;
+    window->postMessage(message, &messagePorts, targetOrigin, source, ec);
+    setDOMException(exec, ec);
+
+    return jsUndefined();
+}
+
+JSValue JSDOMWindow::setTimeout(ExecState* exec)
+{
+    OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+    if (exec->hadException())
+        return jsUndefined();
+    int delay = exec->argument(1).toInt32(exec);
+
+    ExceptionCode ec = 0;
+    int result = impl()->setTimeout(action.release(), delay, ec);
+    setDOMException(exec, ec);
+
+    return jsNumber(exec, result);
+}
+
+JSValue JSDOMWindow::setInterval(ExecState* exec)
+{
+    OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec));
+    if (exec->hadException())
+        return jsUndefined();
+    int delay = exec->argument(1).toInt32(exec);
+
+    ExceptionCode ec = 0;
+    int result = impl()->setInterval(action.release(), delay, ec);
+    setDOMException(exec, ec);
+
+    return jsNumber(exec, result);
+}
+
+JSValue JSDOMWindow::addEventListener(ExecState* exec)
+{
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue listener = exec->argument(1);
+    if (!listener.isObject())
+        return jsUndefined();
+
+    impl()->addEventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), exec->argument(2).toBoolean(exec));
+    return jsUndefined();
+}
+
+JSValue JSDOMWindow::removeEventListener(ExecState* exec)
+{
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return jsUndefined();
+
+    JSValue listener = exec->argument(1);
+    if (!listener.isObject())
+        return jsUndefined();
+
+    impl()->removeEventListener(ustringToAtomicString(exec->argument(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), exec->argument(2).toBoolean(exec));
+    return jsUndefined();
+}
+
+#if ENABLE(DATABASE)
+JSValue JSDOMWindow::openDatabase(ExecState* exec)
+{
+    if (!allowsAccessFrom(exec) || (exec->argumentCount() < 4)) {
+        setDOMException(exec, SYNTAX_ERR);
+        return jsUndefined();
+    }
+
+    String name = ustringToString(exec->argument(0).toString(exec));
+    if (exec->hadException())
+        return jsUndefined();
+
+    String version = ustringToString(exec->argument(1).toString(exec));
+    if (exec->hadException())
+        return jsUndefined();
+
+    String displayName = ustringToString(exec->argument(2).toString(exec));
+    if (exec->hadException())
+        return jsUndefined();
+
+    // exec->argument(3) = estimated size
+    unsigned long estimatedSize = exec->argument(3).toUInt32(exec);
+    if (exec->hadException())
+        return jsUndefined();
+
+    RefPtr<DatabaseCallback> creationCallback;
+    if (exec->argumentCount() >= 5) {
+        if (!exec->argument(4).isObject()) {
+            setDOMException(exec, TYPE_MISMATCH_ERR);
+            return jsUndefined();
+        }
+
+        creationCallback = JSDatabaseCallback::create(asObject(exec->argument(4)), globalObject());
+    }
+
+    ExceptionCode ec = 0;
+    JSValue result = toJS(exec, globalObject(), WTF::getPtr(impl()->openDatabase(name, version, displayName, estimatedSize, creationCallback.release(), ec)));
+
+    setDOMException(exec, ec);
+    return result;
+}
+#endif
+
+DOMWindow* toDOMWindow(JSValue value)
+{
+    if (!value.isObject())
+        return 0;
+    JSObject* object = asObject(value);
+    if (object->inherits(&JSDOMWindow::s_info))
+        return static_cast<JSDOMWindow*>(object)->impl();
+    if (object->inherits(&JSDOMWindowShell::s_info))
+        return static_cast<JSDOMWindowShell*>(object)->impl();
+    return 0;
+}
+
+} // namespace WebCore