PassRefPtr<JSLazyEventListener> JSLazyEventListener::createForDOMWindow(Frame& frame, const QualifiedName& attributeName, const AtomicString& attributeValue)
{
    if (attributeValue.isNull())
        return nullptr;

    if (!frame.script().canExecuteScripts(AboutToExecuteScript))
        return nullptr;

    return adoptRef(new JSLazyEventListener(attributeName.localName().string(),
        eventParameterName(frame.document()->isSVGDocument()), attributeValue,
        nullptr, frame.document()->url().string(), frame.script().eventHandlerPosition(),
        toJSDOMWindow(&frame, mainThreadNormalWorld()), mainThreadNormalWorld()));
}
Esempio n. 2
0
JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext)
{
    if (scriptExecutionContext->isDocument())
        return toJSDOMWindow(static_cast<Document*>(scriptExecutionContext)->frame());

#if ENABLE(WORKERS)
    if (scriptExecutionContext->isWorkerContext())
        return static_cast<WorkerContext*>(scriptExecutionContext)->script()->workerContextWrapper();
#endif

    ASSERT_NOT_REACHED();
    return 0;
}
void JSXMLHttpRequestUpload::setOnabort(ExecState* exec, JSValue* value)
{
    XMLHttpRequest* xmlHttpRequest = impl()->associatedXMLHttpRequest();
    if (!xmlHttpRequest)
        return;
    Document* document = xmlHttpRequest->document();
    if (!document)
        return;
    Frame* frame = document->frame();
    if (!frame)
        return;
    impl()->setOnAbortListener(toJSDOMWindow(frame)->findOrCreateJSUnprotectedEventListener(exec, value, true));
}
// 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 the opener frame for the lookupFrame in case the active frame is different from
    // the opener frame, and the name references a frame relative to the opener frame.
    Frame* newFrame = createWindow(lexicalFrame, openerFrame, 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();

        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;
}
JSValue* JSGeolocation::getCurrentPosition(ExecState* exec, const ArgList& args)
{
    // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
    RefPtr<PositionCallback> positionCallback;
    JSObject* object = args.at(exec, 0)->getObject();
    if (exec->hadException())
        return jsUndefined();
    if (!object) {
        setDOMException(exec, TYPE_MISMATCH_ERR);
        return jsUndefined();
    }

    if (Frame* frame = toJSDOMWindow(exec->lexicalGlobalObject())->impl()->frame())
        positionCallback = JSCustomPositionCallback::create(object, frame);

    RefPtr<PositionErrorCallback> positionErrorCallback;
    if (!args.at(exec, 1)->isUndefinedOrNull()) {
        JSObject* object = args.at(exec, 1)->getObject();
        if (!object) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }

        if (Frame* frame = toJSDOMWindow(exec->lexicalGlobalObject())->impl()->frame())
            positionErrorCallback = JSCustomPositionErrorCallback::create(object, frame);
    }

    RefPtr<PositionOptions> positionOptions;
    if (!args.at(exec, 2)->isUndefinedOrNull()) {
        positionOptions = createPositionOptions(exec, args.at(exec, 2));
        if (exec->hadException())
            return jsUndefined();
    }

    m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.get());

    return jsUndefined();
}
JSValue* JSXMLHttpRequest::removeEventListener(ExecState* exec, const ArgList& args)
{
    Document* document = impl()->document();
    if (!document)
        return jsUndefined();
    Frame* frame = document->frame();
    if (!frame)
        return jsUndefined();
    JSUnprotectedEventListener* listener = toJSDOMWindow(frame)->findJSUnprotectedEventListener(exec, args.at(exec, 1), true);
    if (!listener)
        return jsUndefined();
    impl()->removeEventListener(args.at(exec, 0)->toString(exec), listener, args.at(exec, 2)->toBoolean(exec));
    return jsUndefined();
}
Esempio n. 7
0
void InjectedBundle::reportException(JSContextRef context, JSValueRef exception)
{
    if (!context || !exception)
        return;

    JSLock lock(JSC::SilenceAssertionsOnly);
    JSC::ExecState* execState = toJS(context);

    // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a Page.
    if (!toJSDOMWindow(execState->lexicalGlobalObject()))
        return;

    WebCore::reportException(execState, toJS(execState, exception));
}
Esempio n. 8
0
void ScheduledAction::execute(Document* document)
{
    JSDOMWindow* window = toJSDOMWindow(document->frame(), m_isolatedWorld.get());
    if (!window)
        return;

    RefPtr<Frame> frame = window->impl()->frame();
    if (!frame || !frame->script()->canExecuteScripts(AboutToExecuteScript))
        return;

    if (m_function)
        executeFunctionInContext(window, window->shell(), document);
    else
        frame->script()->executeScriptInWorld(m_isolatedWorld.get(), m_code);
}
Esempio n. 9
0
JSValue* jsEventTargetRemoveEventListener(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
{
    Node* eventNode = 0;
    EventTarget* eventTarget = 0;
    if (!retrieveEventTargetAndCorrespondingNode(exec, thisValue, eventNode, eventTarget))
        return throwError(exec, TypeError);

    Frame* frame = eventNode->document()->frame();
    if (!frame)
        return jsUndefined();

    if (JSEventListener* listener = toJSDOMWindow(frame)->findJSEventListener(args.at(exec, 1)))
        eventTarget->removeEventListener(args.at(exec, 0)->toString(exec), listener, args.at(exec, 2)->toBoolean(exec));

    return jsUndefined();
}
Esempio n. 10
0
JSValue JSLocation::reload(ExecState* exec, const ArgList&)
{
    Frame* frame = impl()->frame();
    if (!frame)
        return jsUndefined();

    JSDOMWindow* window = toJSDOMWindow(frame);
    if (!window->allowsAccessFrom(exec))
        return jsUndefined();

    if (!frame->loader()->url().protocolIs("javascript") || (window && window->allowsAccessFrom(exec))) {
        bool userGesture = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame()->script()->processingUserGesture();
        frame->loader()->scheduleRefresh(userGesture);
    }
    return jsUndefined();
}
Esempio n. 11
0
void InspectorProfilerAgent::stopUserInitiatedProfiling()
{
    m_recordingUserInitiatedProfile = false;
    String title = getCurrentUserInitiatedProfileName();
#if USE(JSC)
    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorController->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
#else
    // Use null script state to avoid filtering by context security token.
    // All functions from all iframes should be visible from Inspector UI.
    ScriptState* scriptState = 0;
#endif
    RefPtr<ScriptProfile> profile = ScriptProfiler::stop(scriptState, title);
    if (profile)
        addProfile(profile, 0, String());
    toggleRecordButton(false);
}
Esempio n. 12
0
JSValue* jsEventTargetAddEventListener(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
{
    Node* eventNode = 0;
    EventTarget* eventTarget = 0;
    if (!retrieveEventTargetAndCorrespondingNode(exec, thisValue, eventNode, eventTarget))
        return throwError(exec, TypeError);

    Frame* frame = eventNode->document()->frame();
    if (!frame)
        return jsUndefined();

    if (RefPtr<JSEventListener> listener = toJSDOMWindow(frame)->findOrCreateJSEventListener(exec, args[1]))
        eventTarget->addEventListener(args[0]->toString(exec), listener.release(), args[2]->toBoolean(exec));

    return jsUndefined();
}
Esempio n. 13
0
static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& url,
    const String& frameName, const WindowFeatures& windowFeatures, JSValuePtr dialogArgs)
{
    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    ASSERT(activeFrame);

    ResourceRequest request;

    request.setHTTPReferrer(activeFrame->loader()->outgoingReferrer());
    FrameLoader::addHTTPOriginIfNeeded(request, activeFrame->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 = activeFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created);
    if (!newFrame)
        return 0;

    newFrame->loader()->setOpener(openerFrame);
    newFrame->loader()->setOpenedByDOM();

    JSDOMWindow* newWindow = toJSDOMWindow(newFrame);

    if (dialogArgs)
        newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);

    if (!protocolIs(url, "javascript") || newWindow->allowsAccessFrom(exec)) {
        KURL completedURL = url.isEmpty() ? KURL("") : activeFrame->document()->completeURL(url);
        bool userGesture = activeFrame->script()->processingUserGesture();

        if (created)
            newFrame->loader()->changeLocation(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
        else if (!url.isEmpty())
            newFrame->loader()->scheduleLocationChange(completedURL.string(), activeFrame->loader()->outgoingReferrer(), false, userGesture);
    }

    return newFrame;
}
Esempio n. 14
0
void InspectorProfilerAgent::startUserInitiatedProfiling()
{
    if (!enabled()) {
        enable(false);
        ScriptDebugServer::shared().recompileAllJSFunctions();
    }
    m_recordingUserInitiatedProfile = true;
    String title = getCurrentUserInitiatedProfileName(true);
#if USE(JSC)
    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectorController->inspectedPage()->mainFrame(), debuggerWorld())->globalExec();
#else
    ScriptState* scriptState = 0;
#endif
    ScriptProfiler::start(scriptState, title);
    addStartProfilingMessageToConsole(title, 0, String());
    toggleRecordButton(true);
}
JSValue* JSXMLHttpRequestUpload::addEventListener(ExecState* exec, const ArgList& args)
{
    XMLHttpRequest* xmlHttpRequest = impl()->associatedXMLHttpRequest();
    if (!xmlHttpRequest)
        return jsUndefined();
    Document* document = xmlHttpRequest->document();
    if (!document)
        return jsUndefined();
    Frame* frame = document->frame();
    if (!frame)
        return jsUndefined();
    RefPtr<JSUnprotectedEventListener> listener = toJSDOMWindow(frame)->findOrCreateJSUnprotectedEventListener(exec, args.at(exec, 1), true);
    if (!listener)
        return jsUndefined();
    impl()->addEventListener(args.at(exec, 0)->toString(exec), listener.release(), args.at(exec, 2)->toBoolean(exec));
    return jsUndefined();
}
Esempio n. 16
0
void ScheduledAction::execute(Document* document)
{
    JSDOMWindow* window = toJSDOMWindow(document->frame());
    if (!window)
        return;

    RefPtr<Frame> frame = window->impl()->frame();
    if (!frame || !frame->script()->isEnabled())
        return;

    frame->script()->setProcessingTimerCallback(true);

    if (m_function) {
        executeFunctionInContext(window, window->shell());
        Document::updateStyleForAllDocuments();
    } else
        frame->loader()->executeScript(m_code);

    frame->script()->setProcessingTimerCallback(false);
}
Esempio n. 17
0
void PagePopupBlackBerry::installDOMFunction(Frame* frame)
{
    JSDOMWindow* window = toJSDOMWindow(frame, mainThreadNormalWorld());
    ASSERT(window);

    JSC::ExecState* exec = window->globalExec();
    ASSERT(exec);
    JSC::JSLockHolder lock(exec);

    JSContextRef context = ::toRef(exec);
    JSObjectRef globalObject = JSContextGetGlobalObject(context);
    JSStringRef functionName = JSStringCreateWithUTF8CString(
            "setValueAndClosePopup");
    JSObjectRef function = JSObjectMakeFunctionWithCallback(context,
            functionName, setValueAndClosePopupCallback);
    JSObjectSetProperty(context, globalObject, functionName, function,
            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);

    // Register client into DOM
    JSClassDefinition definition = kJSClassDefinitionEmpty;
    definition.staticValues = popUpExtensionStaticValues;
    definition.staticFunctions = popUpExtensionStaticFunctions;
    definition.initialize = popUpExtensionInitialize;
    definition.finalize = popUpExtensionFinalize;
    JSClassRef clientClass = JSClassCreate(&definition);

    JSObjectRef clientClassObject = JSObjectMake(context, clientClass, 0);

    // Add a reference. See popUpExtensionFinalize.
    m_sharedClientPointer->ref();
    JSObjectSetPrivate(clientClassObject, m_sharedClientPointer.get());

    String name("popUp");

    JSC::PutPropertySlot slot;
    window->put(window, exec, JSC::Identifier(exec, name),
            toJS(clientClassObject), slot);

    JSClassRelease(clientClass);
}
Esempio n. 18
0
void JavaScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused)
{
    ASSERT_ARG(frame, frame);

    if (!frame->script()->isEnabled())
        return;

    frame->script()->setPaused(paused);

    if (JSDOMWindow* window = toJSDOMWindow(frame)) {
        if (paused) {
            OwnPtr<PausedTimeouts> timeouts;
            window->pauseTimeouts(timeouts);
            m_pausedTimeouts.set(frame, timeouts.release());
        } else {
            OwnPtr<PausedTimeouts> timeouts(m_pausedTimeouts.take(frame));
            window->resumeTimeouts(timeouts);
        }
    }

    setJavaScriptPaused(frame->view(), paused);
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
{
    if (!document)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), document);
    if (wrapper)
        return wrapper;

    if (DOMWindow* domWindow = document->domWindow()) {
        globalObject = toJSDOMWindow(toJS(exec, domWindow));
        // Creating a wrapper for domWindow might have created a wrapper for document as well.
        wrapper = getCachedWrapper(currentWorld(exec), document);
        if (wrapper)
            return wrapper;
    }

    if (document->isHTMLDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLDocument, document);
#if ENABLE(SVG)
    else if (document->isSVGDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGDocument, document);
#endif
    else
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Document, document);

    // Make sure the document is kept around by the window object, and works right with the
    // back/forward cache.
    if (!document->frame()) {
        size_t nodeCount = 0;
        for (Node* n = document; n; n = NodeTraversal::next(n))
            nodeCount++;
        
        exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
    }

    return wrapper;
}
Esempio n. 20
0
void InspectorProfilerAgent::stopUserInitiatedProfiling(bool ignoreProfile)
{
    if (!m_recordingUserInitiatedProfile)
        return;
    m_recordingUserInitiatedProfile = false;
    String title = getCurrentUserInitiatedProfileName();
#if USE(JSC)
    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
#else
    // Use null script state to avoid filtering by context security token.
    // All functions from all iframes should be visible from Inspector UI.
    ScriptState* scriptState = 0;
#endif
    RefPtr<ScriptProfile> profile = ScriptProfiler::stop(scriptState, title);
    if (profile) {
        if (!ignoreProfile)
            addProfile(profile, 0, String());
        else
            addProfileFinishedMessageToConsole(profile, 0, String());
    }
    toggleRecordButton(false);
    m_inspectorState->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
}
Esempio n. 21
0
static inline PassRefPtr<JSC::Profile> stopProfiling(Frame* frame, const String& title)
{
    return stopProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
}
Esempio n. 22
0
static inline void startProfiling(Frame* frame, const String& title, RefPtr<Stopwatch>&& stopwatch)
{
    startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title, WTF::move(stopwatch));
}
Esempio n. 23
0
JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld& world)
{
    return toJSDOMWindow(document->frame(), world);
}
Esempio n. 24
0
JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, JSC::ExecState* exec)
{
    return toJSDOMWindow(document->frame(), currentWorld(exec));
}
Esempio n. 25
0
static inline void startProfiling(Frame* frame, const String& title)
{
    JSC::LegacyProfiler::profiler()->startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
}
Esempio n. 26
0
static JSValuePtr showModalDialog(ExecState* exec, Frame* frame, const String& url, JSValuePtr dialogArgs, const String& featureArgs)
{
    if (!canShowModalDialogNow(frame) || !allowPopUp(exec))
        return jsUndefined();

    const HashMap<String, String> features = parseModalDialogFeatures(featureArgs);

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

    if (!frame)
        return jsUndefined();

    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, frame, url, "", wargs, dialogArgs);
    if (!dialogFrame)
        return jsUndefined();

    JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame);

    // Get the return value either just before clearing the dialog window's
    // properties (in JSDOMWindowBase::clear), or when on return from runModal.
    JSValuePtr returnValue = noValue();
    dialogWindow->setReturnValueSlot(&returnValue);
    dialogFrame->page()->chrome()->runModal();
    dialogWindow->setReturnValueSlot(0);

    // If we don't have a return value, get it now.
    // Either JSDOMWindowBase::clear was not called yet, or there was no return value,
    // and in that case, there's no harm in trying again (no benefit either).
    if (!returnValue)
        returnValue = dialogWindow->getDirect(Identifier(exec, "returnValue"));

    return returnValue ? returnValue : jsUndefined();
}
Esempio n. 27
0
void ScriptProfiler::startForPage(Page* inspectedPage, const String& title)
{
    JSC::ExecState* scriptState = toJSDOMWindow(inspectedPage->mainFrame(), debuggerWorld())->globalExec();
    start(scriptState, title);
}
Esempio n. 28
0
PassRefPtr<ScriptProfile> ScriptProfiler::stopForPage(Page* inspectedPage, const String& title)
{
    JSC::ExecState* scriptState = toJSDOMWindow(inspectedPage->mainFrame(), debuggerWorld())->globalExec();
    return stop(scriptState, title);
}
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) && (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();

            // 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))
        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();
}