bool ScriptController::anyPageIsProcessingUserGesture() const
{
    Page* page = m_frame->page();
    if (!page)
        return false;

    const HashSet<Page*>& pages = page->group().pages();
    HashSet<Page*>::const_iterator end = pages.end();
    for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
        for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
            if (frame->script()->processingUserGesture())
                return true;
        }
    }

    return false;
}
Example #2
0
void ScheduledAction::execute(ScriptExecutionContext* context)
{
    if (context->isDocument()) {
        Frame* frame = static_cast<Document*>(context)->frame();
        ScriptController* scriptController = frame->script();
        if (!scriptController->canExecuteScripts(NotAboutToExecuteScript))
            return;
        V8Proxy* proxy = V8Proxy::retrieve(frame);
        execute(proxy);
    }
#if ENABLE(WORKERS)
    else {
        ASSERT(context->isWorkerContext());
        execute(static_cast<WorkerContext*>(context));
    }
#endif
}
Example #3
0
void CachedFrameBase::restore()
{
    ASSERT(m_document->view() == m_view);

    if (m_isMainFrame)
        m_view->setParentVisible(true);

    Frame* frame = m_view->frame();
    m_cachedFrameScriptData->restore(frame);

#if ENABLE(SVG)
    if (m_document->svgExtensions())
        m_document->accessSVGExtensions()->unpauseAnimations();
#endif

    frame->animation()->resumeAnimationsForDocument(m_document.get());
    frame->eventHandler()->setMousePressNode(m_mousePressNode.get());
    m_document->resumeActiveDOMObjects();
    m_document->resumeScriptedAnimationControllerCallbacks();

    // It is necessary to update any platform script objects after restoring the
    // cached page.
    frame->script()->updatePlatformScriptObjects();

    frame->loader()->client()->didRestoreFromPageCache();

    // Reconstruct the FrameTree
    for (unsigned i = 0; i < m_childFrames.size(); ++i)
        frame->tree()->appendChild(m_childFrames[i]->view()->frame());

    // Open the child CachedFrames in their respective FrameLoaders.
    for (unsigned i = 0; i < m_childFrames.size(); ++i)
        m_childFrames[i]->open();

    m_document->enqueuePageshowEvent(PageshowEventPersisted);
    
    HistoryItem* historyItem = frame->loader()->history()->currentItem();
    m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue());
    
#if ENABLE(TOUCH_EVENTS)
    if (m_document->hasListenerType(Document::TOUCH_LISTENER))
        m_document->page()->chrome()->client()->needTouchEvents(true);
#endif

    m_document->documentDidBecomeActive();
}
Example #4
0
void JSDocument::setLocation(ExecState* exec, JSValuePtr value)
{
    Frame* frame = static_cast<Document*>(impl())->frame();
    if (!frame)
        return;

    String str = value->toString(exec);

    // IE and Mozilla both resolve the URL relative to the source frame,
    // not the target frame.
    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    if (activeFrame)
        str = activeFrame->document()->completeURL(str).string();

    bool userGesture = activeFrame->script()->processingUserGesture();
    frame->loader()->scheduleLocationChange(str, activeFrame->loader()->outgoingReferrer(), false, userGesture);
}
PassScriptInstance HTMLPlugInElement::getInstance() const
{
    Frame* frame = document()->frame();
    if (!frame)
        return 0;

    // If the host dynamically turns off JavaScript (or Java) we will still return
    // the cached allocated Bindings::Instance.  Not supporting this edge-case is OK.
    if (m_instance)
        return m_instance;

    RenderWidget* renderWidget = renderWidgetForJSBindings();
    if (renderWidget && renderWidget->widget())
        m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget());

    return m_instance;
}
bool ScriptController::processingUserGesture() const
{
    Frame* activeFrame = V8Proxy::retrieveFrameForEnteredContext();
    // No script is running, so it must be run by users.
    if (!activeFrame)
        return true;

    V8Proxy* activeProxy = activeFrame->script()->proxy();

    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = V8Proxy::GetContext(activeFrame);
    // FIXME: find all cases context can be empty:
    //  1) JS is disabled;
    //  2) page is NULL;
    if (context.IsEmpty())
        return true;

    v8::Context::Scope scope(context);

    v8::Handle<v8::Object> global = context->Global();
    v8::Handle<v8::Value> jsEvent = global->Get(v8::String::NewSymbol("event"));
    Event* event = V8Proxy::ToNativeEvent(jsEvent);

    // Based on code from kjs_bindings.cpp.
    // Note: This is more liberal than Firefox's implementation.
    if (event) {
        const AtomicString& type = event->type();
        bool eventOk =
            // mouse events
            type == eventNames().clickEvent || type == eventNames().mousedownEvent || type == eventNames().mouseupEvent || type == eventNames().dblclickEvent
            // keyboard events
            || type == eventNames().keydownEvent || type == eventNames().keypressEvent || type == eventNames().keyupEvent
            // other accepted events
            || type == eventNames().selectEvent || type == eventNames().changeEvent || type == eventNames().focusEvent || type == eventNames().blurEvent || type == eventNames().submitEvent;

        if (eventOk)
            return true;
    } else if (activeProxy->inlineCode() && !activeProxy->timerCallback()) {
        // This is the <a href="javascript:window.open('...')> case -> we let it through.
        return true;
    }

    // This is the <script>window.open(...)</script> case or a timer callback -> block it.
    return false;
}
Example #7
0
HTMLParserOptions::HTMLParserOptions(Document* document)
{
    Frame* frame = document ? document->frame() : 0;
    scriptEnabled = frame && frame->script().canExecuteScripts(NotAboutToExecuteScript);
    pluginsEnabled = frame && frame->loader().subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin);

    Settings* settings = document ? document->settings() : 0;
    usePreHTML5ParserQuirks = settings && settings->usePreHTML5ParserQuirks();
#if ENABLE(THREADED_HTML_PARSER)
    // We force the main-thread parser for about:blank, javascript: and data: urls for compatibility
    // with historical synchronous loading/parsing behavior of those schemes.
    useThreading = settings && settings->threadedHTMLParser() && !document->url().isBlankURL()
        && (settings->useThreadedHTMLParserForDataURLs() || !document->url().protocolIsData());
#else
    useThreading = false;
#endif
    maximumDOMTreeDepth = settings ? settings->maximumHTMLParserDOMTreeDepth() : Settings::defaultMaximumHTMLParserDOMTreeDepth;
}
Example #8
0
void JSDocument::setLocation(ExecState* exec, JSValue value)
{
    Frame* frame = static_cast<Document*>(impl())->frame();
    if (!frame)
        return;

    String str = ustringToString(value.toString(exec));

    Frame* lexicalFrame = asJSDOMWindow(exec->lexicalGlobalObject())->impl()->frame();

    // IE and Mozilla both resolve the URL relative to the source frame,
    // not the target frame.
    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    str = activeFrame->document()->completeURL(str).string();

    frame->navigationScheduler()->scheduleLocationChange(lexicalFrame->document()->securityOrigin(),
        str, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
}
Example #9
0
v8::Local<v8::Value> V8EventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event)
{

    v8::Local<v8::Function> handlerFunction = getListenerFunction(context);
    v8::Local<v8::Object> receiver = getReceiverObject(event);
    if (handlerFunction.IsEmpty() || receiver.IsEmpty())
        return v8::Local<v8::Value>();

    v8::Handle<v8::Value> parameters[1] = { jsEvent };

    if (V8Proxy* proxy = V8Proxy::retrieve(context)) {
        Frame* frame = static_cast<Document*>(context)->frame();
        if (frame->script()->canExecuteScripts(AboutToExecuteScript))
            return proxy->callFunction(handlerFunction, receiver, 1, parameters);
    }

    return v8::Local<v8::Value>();
}
Example #10
0
void ScriptCachedPageData::restore(Page* page)
{
    Frame* mainFrame = page->mainFrame();

    JSLock lock(false);

    ScriptController* scriptController = mainFrame->script();
    if (scriptController->haveWindowShell()) {
        JSDOMWindowShell* windowShell = scriptController->windowShell();
        if (m_window) {
            windowShell->setWindow(m_window.get());
        } else {
            windowShell->setWindow(mainFrame->domWindow());
            scriptController->attachDebugger(page->debugger());
            windowShell->window()->setProfileGroup(page->group().identifier());
        }
    }
}
void V8Window::eventAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
{
    v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::GetTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate())));
    if (holder.IsEmpty())
        return;

    Frame* frame = V8Window::toNative(holder)->frame();
    if (!BindingSecurity::shouldAllowAccessToFrame(frame))
        return;

    ASSERT(frame);
    v8::Local<v8::Context> context = frame->script()->currentWorldContext();
    if (context.IsEmpty())
        return;

    v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
    context->Global()->SetHiddenValue(eventSymbol, value);
}
bool InspectorClient::doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message)
{
    if (!frontendPage)
        return false;

    Frame* frame = frontendPage->mainFrame();
    if (!frame)
        return false;

    ScriptController* scriptController = frame->script();
    if (!scriptController)
        return false;

    String dispatchToFrontend = "InspectorFrontendAPI.dispatchMessageAsync(" + message + ");";

    // FIXME: This should execute the script in the appropriate world.
    scriptController->evaluate(ScriptSourceCode(dispatchToFrontend));
    return true;
}
Example #13
0
bool InspectorClient::sendMessageToFrontend(const String& message)
{
    if (!m_frontendPage)
        return false;

    Frame* frame = m_frontendPage->mainFrame();
    if (!frame)
        return false;

    ScriptController* scriptController = frame->script();
    if (!scriptController)
        return false;

    String dispatchToFrontend("WebInspector.dispatchMessageFromBackend(");
    dispatchToFrontend += message;
    dispatchToFrontend += ");";
    scriptController->executeScript(dispatchToFrontend);
    return true;
}
Example #14
0
bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    VOID_TO_NPVARIANT(*result);
    if (!npObject)
        return false;

    if (npObject->_class != npScriptObjectClass) {
        // Check if the object passed in is wrapped. If yes, then we need to invoke on the underlying object.
        NPObject* actualObject = NPObjectWrapper::getUnderlyingNPObject(npObject);
        if (!actualObject)
            return false;
        npObject = actualObject;
    }

    v8::HandleScope handleScope;
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    // FIXME: Is this branch still needed after switching to using UserGestureIndicator?
    String filename;
    if (!popupsAllowed)
        filename = "npscript";

    V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject);
    Frame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);

    UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture);
    v8::Local<v8::Value> v8result = frame->script()->compileAndRunScript(ScriptSourceCode(script, KURL(ParsedURLString, filename)));

    if (v8result.IsEmpty())
        return false;

    if (_NPN_IsAlive(npObject))
        convertV8ObjectToNPVariant(v8result, npObject, result);
    return true;
}
WebString WebPluginContainerImpl::executeScriptURL(const WebURL& url, bool popupsAllowed)
{
    Frame* frame = m_element->document()->frame();
    if (!frame)
        return WebString();

    const KURL& kurl = url;
    ASSERT(kurl.protocolIs("javascript"));

    String script = decodeURLEscapeSequences(
                        kurl.string().substring(strlen("javascript:")));

    ScriptValue result = frame->script()->executeScript(script, popupsAllowed);

    // Failure is reported as a null string.
    String resultStr;
    result.getString(resultStr);
    return resultStr;
}
void WebMediaPlayerProxy::invokeMethod(const String& methodName)
{
    Frame* frame = element()->document()->frame();
    RootObject *root = frame->script()->bindingRootObject();
    if (!root)
        return;
    ExecState *exec = root->globalObject()->globalExec();
    Instance* instance = pluginInstance().get();
    if (!instance)
        return;

    instance->begin();
    Class *aClass = instance->getClass();
    Identifier iden(exec, methodName);
    MethodList methodList = aClass->methodsNamed(iden, instance);
    ArgList args;
    instance->invokeMethod(exec, methodList , args);
    instance->end();
}
Example #17
0
bool handleOutOfMemory()
{
    v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();

    if (!context->HasOutOfMemoryException())
        return false;

    // Warning, error, disable JS for this frame?
    Frame* frame = toFrameIfNotDetached(context);
    if (!frame)
        return true;

    frame->script().clearForOutOfMemory();
    frame->loader().client()->didExhaustMemoryAvailableForScript();

    if (Settings* settings = frame->settings())
        settings->setScriptEnabled(false);

    return true;
}
Example #18
0
bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const String& urlString, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList)
{
    // Support for <frame src="javascript:string">
    URL scriptURL;
    URL url;
    if (protocolIsJavaScript(urlString)) {
        scriptURL = completeURL(urlString); // completeURL() encodes the URL.
        url = blankURL();
    } else
        url = completeURL(urlString);

    Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList);
    if (!frame)
        return false;

    if (!scriptURL.isEmpty())
        frame->script().executeIfJavaScriptURL(scriptURL);

    return true;
}
Example #19
0
void CachedFrame::restore()
{
    ASSERT(m_document->view() == m_view);
    
    Frame* frame = m_view->frame();
    m_cachedFrameScriptData->restore(frame);

#if ENABLE(SVG)
    if (m_document->svgExtensions())
        m_document->accessSVGExtensions()->unpauseAnimations();
#endif

    frame->animation()->resumeAnimations(m_document.get());
    frame->eventHandler()->setMousePressNode(mousePressNode());
    m_document->resumeActiveDOMObjects();

    // It is necessary to update any platform script objects after restoring the
    // cached page.
    frame->script()->updatePlatformScriptObjects();
}
Example #20
0
bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    VOID_TO_NPVARIANT(*result);
    if (!npObject)
        return false;

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    // FIXME: Is this branch still needed after switching to using UserGestureIndicator?
    String filename;
    if (!popupsAllowed)
        filename = "npscript";

    Frame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);

    UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture);
    v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(context, ScriptSourceCode(script, KURL(ParsedURLString, filename)));

    if (v8result.IsEmpty())
        return false;

    if (_NPN_IsAlive(npObject))
        convertV8ObjectToNPVariant(v8result, npObject, result, isolate);
    return true;
}
Example #21
0
void CachedPage::restore(Page* page)
{
    ASSERT(m_document->view() == m_view);

    Frame* mainFrame = page->mainFrame();

    JSLock lock(false);

    ScriptController* proxy = mainFrame->script();
    if (proxy->haveWindowShell()) {
        JSDOMWindowShell* windowShell = proxy->windowShell();
        if (m_window) {
            windowShell->setWindow(m_window.get());
            windowShell->window()->resumeTimeouts(m_pausedTimeouts);
        } else {
            windowShell->setWindow(mainFrame->domWindow());
            proxy->attachDebugger(page->debugger());
            windowShell->window()->setProfileGroup(page->group().identifier());
        }
    }

#if ENABLE(SVG)
    if (m_document && m_document->svgExtensions())
        m_document->accessSVGExtensions()->unpauseAnimations();
#endif

    mainFrame->animation()->resumeAnimations(m_document.get());

    mainFrame->eventHandler()->setMousePressNode(mousePressNode());
        
    // Restore the focus appearance for the focused element.
    // FIXME: Right now we don't support pages w/ frames in the b/f cache.  This may need to be tweaked when we add support for that.
    Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
    if (Node* node = focusedDocument->focusedNode()) {
        if (node->isElementNode())
            static_cast<Element*>(node)->updateFocusAppearance(true);
    }
}
Example #22
0
void ReplayController::unloadSegment(bool suppressNotifications)
{
    ASSERT(m_sessionState != SessionState::Inactive);
    ASSERT(m_segmentState == SegmentState::Loaded || m_segmentState == SegmentState::Appending);

    setSegmentState(SegmentState::Unloaded);

    LOG(WebReplay, "%-20s Clearing input cursors for page: %p\n", "ReplayController", &m_page);

    m_activeCursor = nullptr;
    RefPtr<ReplaySessionSegment> unloadedSegment = m_loadedSegment.release();
    for (Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
        frame->script().globalObject(mainThreadNormalWorld())->setInputCursor(m_emptyCursor.copyRef());
        frame->document()->setInputCursor(m_emptyCursor.copyRef());
    }

    // When we stop capturing, don't send out segment unloaded events since we
    // didn't send out the corresponding segmentLoaded event at the start of capture.
    if (!suppressNotifications) {
        LOG(WebReplay, "%-20sUnloading segment: %p.\n", "ReplayController", unloadedSegment.get());
        InspectorInstrumentation::segmentUnloaded(m_page);
    }
}
Example #23
0
PassScriptInstance HTMLPlugInElement::getInstance() const
{
    Frame* frame = document()->frame();
    if (!frame)
        return 0;

    // If the host dynamically turns off JavaScript (or Java) we will still return
    // the cached allocated Bindings::Instance.  Not supporting this edge-case is OK.
    if (m_instance)
        return m_instance;

    if (m_inBeforeLoadEventHandler) {
        // The plug-in hasn't loaded yet, and it makes no sense to try to load if beforeload handler happened to touch the plug-in element.
        // That would recursively call beforeload for the same element.
        return 0;
    }

    RenderWidget* renderWidget = renderWidgetForJSBindings();
    if (renderWidget && renderWidget->widget())
        m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget());

    return m_instance;
}
Example #24
0
void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
{
    v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate())));
    if (holder.IsEmpty())
        return;

    Frame* frame = V8Window::toNative(holder)->frame();
    ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate());
    if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) {
        exceptionState.throwIfNeeded();
        return;
    }

    ASSERT(frame);
    v8::Local<v8::Context> context = frame->script().currentWorldContext();
    if (context.IsEmpty())
        return;

    v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate());
    v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol);
    if (jsEvent.IsEmpty())
        return;
    v8SetReturnValue(info, jsEvent);
}
Example #25
0
void V8Custom::WindowSetLocation(DOMWindow* window, const String& v)
{
    if (!window->frame())
        return;

    Frame* activeFrame = V8Proxy::retrieveFrameForEnteredContext();
    if (!activeFrame)
        return;

    if (!activeFrame->loader()->shouldAllowNavigation(window->frame()))
        return;

    if (!parseURL(v).startsWith("javascript:", false)
        || ScriptController::isSafeScript(window->frame())) {
        String completedUrl = activeFrame->loader()->completeURL(v).string();
  
        // FIXME: The JSC bindings pass !anyPageIsProcessingUserGesture() for
        // the lockHistory parameter.  We should probably do something similar.
  
        window->frame()->loader()->scheduleLocationChange(completedUrl,
            activeFrame->loader()->outgoingReferrer(), false, false,
            activeFrame->script()->processingUserGesture());
    }
}
Example #26
0
void JSAbstractEventListener::handleEvent(Event* event, bool isWindowEvent)
{
    JSObject* listener = listenerObj();
    if (!listener)
        return;

    JSDOMWindow* window = this->window();
    // Null check as clearWindow() can clear this and we still get called back by
    // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
    if (!window)
        return;
    Frame* frame = window->impl()->frame();
    if (!frame)
        return;
    ScriptController* script = frame->script();
    if (!script->isEnabled() || script->isPaused())
        return;

    JSLock lock(false);

    ExecState* exec = window->globalExec();

    JSValue* handleEventFunction = listener->get(exec, Identifier(exec, "handleEvent"));
    CallData callData;
    CallType callType = handleEventFunction->getCallData(callData);
    if (callType == CallTypeNone) {
        handleEventFunction = 0;
        callType = listener->getCallData(callData);
    }

    if (callType != CallTypeNone) {
        ref();

        ArgList args;
        args.append(toJS(exec, event));

        Event* savedEvent = window->currentEvent();
        window->setCurrentEvent(event);

        JSValue* retval;
        if (handleEventFunction) {
            window->startTimeoutCheck();
            retval = call(exec, handleEventFunction, callType, callData, listener, args);
        } else {
            JSValue* thisValue;
            if (isWindowEvent)
                thisValue = window->shell();
            else
                thisValue = toJS(exec, event->currentTarget());
            window->startTimeoutCheck();
            retval = call(exec, listener, callType, callData, thisValue, args);
        }
        window->stopTimeoutCheck();

        window->setCurrentEvent(savedEvent);

        if (exec->hadException())
            frame->domWindow()->console()->reportCurrentException(exec);
        else {
            if (!retval->isUndefinedOrNull() && event->storesResultAsString())
                event->storeResult(retval->toString(exec));
            if (m_isHTML) {
                bool retvalbool;
                if (retval->getBoolean(retvalbool) && !retvalbool)
                    event->preventDefault();
            }
        }

        Document::updateDocumentsRendering();
        deref();
    }
}
Example #27
0
bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    if (!npObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject) {
        if (npObject->_class->invoke)
            return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result);

        VOID_TO_NPVARIANT(*result);
        return true;
    }

    PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName);
    if (!identifier->isString)
        return false;

    if (!strcmp(identifier->value.string, "eval")) {
        if (argumentCount != 1)
            return false;
        if (arguments[0].type != NPVariantType_String)
            return false;
        return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result);
    }

    v8::HandleScope handleScope(isolate);
    // FIXME: should use the plugin's owner frame as the security context.
    v8::Handle<v8::Context> context = toV8Context(npp, npObject);
    if (context.IsEmpty())
        return false;

    v8::Context::Scope scope(context);
    ExceptionCatcher exceptionCatcher;

    v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object);
    v8::Handle<v8::Value> functionObject = v8Object->Get(v8::String::NewSymbol(identifier->value.string));
    if (functionObject.IsEmpty() || functionObject->IsNull()) {
        NULL_TO_NPVARIANT(*result);
        return false;
    }
    if (functionObject->IsUndefined()) {
        VOID_TO_NPVARIANT(*result);
        return false;
    }

    Frame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    // Call the function object.
    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject);
    OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
    v8::Local<v8::Value> resultObject = frame->script().callFunction(function, v8Object, argumentCount, argv.get());

    // If we had an error, return false.  The spec is a little unclear here, but says "Returns true if the method was
    // successfully invoked".  If we get an error return value, was that successfully invoked?
    if (resultObject.IsEmpty())
        return false;

    convertV8ObjectToNPVariant(resultObject, npObject, result, isolate);
    return true;
}
Example #28
0
void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context)
{
    if (hasExistingListenerObject())
        return;

    if (context->isDocument() && !static_cast<Document*>(context)->contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_position.m_line))
        return;

    v8::HandleScope handleScope;

    ASSERT(context->isDocument());
    Frame* frame = static_cast<Document*>(context)->frame();
    ASSERT(frame);
    if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
        return;
    // Use the outer scope to hold context.
    v8::Local<v8::Context> v8Context = toV8Context(context, worldContext());
    // Bail out if we cannot get the context.
    if (v8Context.IsEmpty())
        return;

    v8::Context::Scope scope(v8Context);

    // Nodes other than the document object, when executing inline event
    // handlers push document, form, and the target node on the scope chain.
    // We do this by using 'with' statement.
    // See chrome/fast/forms/form-action.html
    //     chrome/fast/forms/selected-index-value.html
    //     base/fast/overflow/onscroll-layer-self-destruct.html
    //
    // Don't use new lines so that lines in the modified handler
    // have the same numbers as in the original code.
    // FIXME: V8 does not allow us to programmatically create object environments so
    //        we have to do this hack! What if m_code escapes to run arbitrary script?
    //
    // Call with 4 arguments instead of 3, pass additional null as the last parameter.
    // By calling the function with 4 arguments, we create a setter on arguments object
    // which would shadow property "3" on the prototype.
    String code = "(function() {"
        "with (this[2]) {"
        "with (this[1]) {"
        "with (this[0]) {"
            "return function(" + m_eventParameterName + ") {" +
                m_code + "\n" // Insert '\n' otherwise //-style comments could break the handler.
            "};"
        "}}}})";

    v8::Handle<v8::String> codeExternalString = v8ExternalString(code);

    v8::Handle<v8::Script> script = ScriptSourceCode::compileScript(codeExternalString, m_sourceURL, m_position);
    if (script.IsEmpty())
        return;

    // FIXME: Remove this code when we stop doing the 'with' hack above.
    v8::Local<v8::Value> value;
    {
        V8RecursionScope::MicrotaskSuppression scope;
        value = script->Run();
    }
    if (value.IsEmpty())
        return;

    // Call the outer function to get the inner function.
    ASSERT(value->IsFunction());
    v8::Local<v8::Function> intermediateFunction = value.As<v8::Function>();

    HTMLFormElement* formElement = 0;
    if (m_node && m_node->isHTMLElement())
        formElement = static_cast<HTMLElement*>(m_node)->form();

    v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node);
    v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement);
    v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0);

    v8::Local<v8::Object> thisObject = v8::Object::New();
    if (thisObject.IsEmpty())
        return;
    if (!thisObject->ForceSet(v8UnsignedInteger(0), nodeWrapper))
        return;
    if (!thisObject->ForceSet(v8UnsignedInteger(1), formWrapper))
        return;
    if (!thisObject->ForceSet(v8UnsignedInteger(2), documentWrapper))
        return;

    // FIXME: Remove this code when we stop doing the 'with' hack above.
    v8::Local<v8::Value> innerValue;
    {
        V8RecursionScope::MicrotaskSuppression scope;
        innerValue = intermediateFunction->Call(thisObject, 0, 0);
    }
    if (innerValue.IsEmpty() || !innerValue->IsFunction())
        return;

    v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>();

    // Change the toString function on the wrapper function to avoid it
    // returning the source for the actual wrapper function. Instead it
    // returns source for a clean wrapper function with the event
    // argument wrapping the event source code. The reason for this is
    // that some web sites use toString on event functions and eval the
    // source returned (sometimes a RegExp is applied as well) for some
    // other use. That fails miserably if the actual wrapper source is
    // returned.
    v8::Persistent<v8::FunctionTemplate>& toStringTemplate =
        V8PerIsolateData::current()->lazyEventListenerToStringTemplate();
    if (toStringTemplate.IsEmpty())
        toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString));
    v8::Local<v8::Function> toStringFunction;
    if (!toStringTemplate.IsEmpty())
        toStringFunction = toStringTemplate->GetFunction();
    if (!toStringFunction.IsEmpty()) {
        String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n  " + m_code + "\n}";
        wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringString));
        wrappedFunction->Set(v8::String::NewSymbol("toString"), toStringFunction);
    }

    wrappedFunction->SetName(v8String(m_functionName));

    // FIXME: Remove the following comment-outs.
    // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details.
    //
    // For the time being, we comment out the following code since the
    // second parsing can happen.
    // // Since we only parse once, there's no need to keep data used for parsing around anymore.
    // m_functionName = String();
    // m_code = String();
    // m_eventParameterName = String();
    // m_sourceURL = String();

    setListenerObject(wrappedFunction);
}
Example #29
0
JSValuePtr windowProtoFuncOpen(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
{
    JSDOMWindow* window = toJSDOMWindow(thisValue);
    if (!window)
        return throwError(exec, TypeError);
    if (!window->allowsAccessFrom(exec))
        return jsUndefined();

    Frame* frame = window->impl()->frame();
    if (!frame)
        return jsUndefined();
    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    if (!activeFrame)
        return  jsUndefined();

    Page* page = frame->page();

    String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
    AtomicString frameName = args.at(exec, 1)->isUndefinedOrNull() ? "_blank" : AtomicString(args.at(exec, 1)->toString(exec));

    // 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 (!allowPopUp(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) {
        if (!activeFrame->loader()->shouldAllowNavigation(frame))
            return jsUndefined();

        String completedURL;
        if (!urlString.isEmpty())
            completedURL = activeFrame->document()->completeURL(urlString).string();

        const JSDOMWindow* targetedWindow = toJSDOMWindow(frame);
        if (!completedURL.isEmpty() && (!protocolIs(completedURL, "javascript") || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
            bool userGesture = activeFrame->script()->processingUserGesture();
            frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);
        }
        return toJS(exec, frame->domWindow());
    }

    // In the case of a named frame or a new window, we'll use the createWindow() helper
    WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 2)));
    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, frame, urlString, frameName, windowFeatures, noValue());

    if (!frame)
        return jsUndefined();

    return toJS(exec, frame->domWindow()); // global object
}
Example #30
0
JSValue JSLocation::assign(ExecState* exec, const ArgList& args)
{
    Frame* frame = impl()->frame();
    if (!frame)
        return jsUndefined();

    Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
    if (!activeFrame)
        return jsUndefined();
    if (!activeFrame->loader()->shouldAllowNavigation(frame))
        return jsUndefined();

    // We want a new history item if this JS was called via a user gesture
    navigateIfAllowed(exec, frame, activeFrame->loader()->completeURL(args.at(0).toString(exec)), !frame->script()->anyPageIsProcessingUserGesture(), false);
    return jsUndefined();
}