Search in sources :

Example 26 with Window

use of com.gargoylesoftware.htmlunit.javascript.host.Window in project htmlunit by HtmlUnit.

the class ScriptElementSupport method executeScriptIfNeeded.

/**
 * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
 *
 * Executes this script node if necessary and/or possible.
 * @param element the element
 * @param ignoreAttachedToPage don't do the isAttachedToPage check
 * @param ignorePageIsAncestor don't do the element.getPage().isAncestorOf(element) check
 */
public static void executeScriptIfNeeded(final DomElement element, final boolean ignoreAttachedToPage, final boolean ignorePageIsAncestor) {
    if (!isExecutionNeeded(element, ignoreAttachedToPage, ignorePageIsAncestor)) {
        return;
    }
    final ScriptElement scriptElement = (ScriptElement) element;
    final String src = scriptElement.getSrcAttribute();
    if (src.equals(SLASH_SLASH_COLON)) {
        executeEvent(element, Event.TYPE_ERROR);
        return;
    }
    final HtmlPage page = (HtmlPage) element.getPage();
    if (src != ATTRIBUTE_NOT_DEFINED) {
        if (!src.startsWith(JavaScriptURLConnection.JAVASCRIPT_PREFIX)) {
            // <script src="[url]"></script>
            if (LOG.isDebugEnabled()) {
                LOG.debug("Loading external JavaScript: " + src);
            }
            try {
                scriptElement.setExecuted(true);
                Charset charset = EncodingSniffer.toCharset(scriptElement.getCharsetAttribute());
                if (charset == null) {
                    charset = page.getCharset();
                }
                final JavaScriptLoadResult result;
                final Window win = page.getEnclosingWindow().getScriptableObject();
                final Document doc = win.getDocument();
                try {
                    doc.setCurrentScript(element.getScriptableObject());
                    result = page.loadExternalJavaScriptFile(src, charset);
                } finally {
                    doc.setCurrentScript(null);
                }
                if (result == JavaScriptLoadResult.SUCCESS) {
                    executeEvent(element, Event.TYPE_LOAD);
                } else if (result == JavaScriptLoadResult.DOWNLOAD_ERROR) {
                    executeEvent(element, Event.TYPE_ERROR);
                } else if (result == JavaScriptLoadResult.NO_CONTENT) {
                    final BrowserVersion browserVersion = page.getWebClient().getBrowserVersion();
                    if (browserVersion.hasFeature(JS_SCRIPT_HANDLE_204_AS_ERROR)) {
                        executeEvent(element, Event.TYPE_ERROR);
                    } else {
                        executeEvent(element, Event.TYPE_LOAD);
                    }
                }
            } catch (final FailingHttpStatusCodeException e) {
                executeEvent(element, Event.TYPE_ERROR);
                throw e;
            }
        }
    } else if (element.getFirstChild() != null) {
        // <script>[code]</script>
        final Window win = page.getEnclosingWindow().getScriptableObject();
        final Document doc = win.getDocument();
        try {
            doc.setCurrentScript(element.getScriptableObject());
            executeInlineScriptIfNeeded(element);
        } finally {
            doc.setCurrentScript(null);
        }
        if (element.hasFeature(EVENT_ONLOAD_INTERNAL_JAVASCRIPT)) {
            executeEvent(element, Event.TYPE_LOAD);
        }
    }
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) FailingHttpStatusCodeException(com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException) Charset(java.nio.charset.Charset) HTMLDocument(com.gargoylesoftware.htmlunit.javascript.host.html.HTMLDocument) Document(com.gargoylesoftware.htmlunit.javascript.host.dom.Document) BrowserVersion(com.gargoylesoftware.htmlunit.BrowserVersion) JavaScriptLoadResult(com.gargoylesoftware.htmlunit.html.HtmlPage.JavaScriptLoadResult)

Example 27 with Window

use of com.gargoylesoftware.htmlunit.javascript.host.Window in project htmlunit by HtmlUnit.

the class ScriptElementSupport method executeInlineScriptIfNeeded.

/**
 * Executes this script node as inline script if necessary and/or possible.
 */
private static void executeInlineScriptIfNeeded(final DomElement element) {
    if (!isExecutionNeeded(element, false, false)) {
        return;
    }
    final ScriptElement scriptElement = (ScriptElement) element;
    final String src = scriptElement.getSrcAttribute();
    if (src != ATTRIBUTE_NOT_DEFINED) {
        return;
    }
    final String forr = element.getAttributeDirect("for");
    String event = element.getAttributeDirect("event");
    // The event name can be like "onload" or "onload()".
    if (event.endsWith("()")) {
        event = event.substring(0, event.length() - 2);
    }
    final String scriptCode = getScriptCode(element);
    if (event != ATTRIBUTE_NOT_DEFINED && forr != ATTRIBUTE_NOT_DEFINED && element.hasFeature(JS_SCRIPT_SUPPORTS_FOR_AND_EVENT_WINDOW) && "window".equals(forr)) {
        final Window window = element.getPage().getEnclosingWindow().getScriptableObject();
        final BaseFunction function = new EventHandler(element, event, scriptCode);
        window.getEventListenersContainer().addEventListener(StringUtils.substring(event, 2), function, false);
        return;
    }
    if (forr == ATTRIBUTE_NOT_DEFINED || "onload".equals(event)) {
        final String url = element.getPage().getUrl().toExternalForm();
        final int line1 = element.getStartLineNumber();
        final int line2 = element.getEndLineNumber();
        final int col1 = element.getStartColumnNumber();
        final int col2 = element.getEndColumnNumber();
        final String desc = "script in " + url + " from (" + line1 + ", " + col1 + ") to (" + line2 + ", " + col2 + ")";
        scriptElement.setExecuted(true);
        ((HtmlPage) element.getPage()).executeJavaScript(scriptCode, desc, line1);
    }
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) EventHandler(com.gargoylesoftware.htmlunit.javascript.host.event.EventHandler)

Example 28 with Window

use of com.gargoylesoftware.htmlunit.javascript.host.Window in project htmlunit by HtmlUnit.

the class ScriptElementSupport method onAllChildrenAddedToPage.

/**
 * Lifecycle method invoked after a node and all its children have been added to a page, during
 * parsing of the HTML. Intended to be overridden by nodes which need to perform custom logic
 * after they and all their child nodes have been processed by the HTML parser. This method is
 * not recursive, and the default implementation is empty, so there is no need to call
 * <tt>super.onAllChildrenAddedToPage()</tt> if you implement this method.
 * @param element the element
 * @param postponed whether to use {@link com.gargoylesoftware.htmlunit.javascript.PostponedAction} or no
 */
public static void onAllChildrenAddedToPage(final DomElement element, final boolean postponed) {
    if (element.getOwnerDocument() instanceof XmlPage) {
        return;
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("Script node added: " + element.asXml());
    }
    if (!element.getPage().getWebClient().isJavaScriptEngineEnabled()) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Script found but not executed because javascript engine is disabled");
        }
        return;
    }
    final ScriptElement script = (ScriptElement) element;
    final String srcAttrib = script.getSrcAttribute();
    if (ATTRIBUTE_NOT_DEFINED != srcAttrib && script.isDeferred()) {
        return;
    }
    final WebWindow webWindow = element.getPage().getEnclosingWindow();
    if (webWindow != null) {
        final StringBuilder description = new StringBuilder().append("Execution of ").append(srcAttrib == ATTRIBUTE_NOT_DEFINED ? "inline " : "external ").append(element.getClass().getSimpleName());
        if (srcAttrib != ATTRIBUTE_NOT_DEFINED) {
            description.append(" (").append(srcAttrib).append(')');
        }
        final PostponedAction action = new PostponedAction(element.getPage(), description.toString()) {

            @Override
            public void execute() {
                // see HTMLDocument.setExecutingDynamicExternalPosponed(boolean)
                HTMLDocument jsDoc = null;
                final Window window = webWindow.getScriptableObject();
                if (window != null) {
                    jsDoc = (HTMLDocument) window.getDocument();
                    jsDoc.setExecutingDynamicExternalPosponed(element.getStartLineNumber() == -1 && ATTRIBUTE_NOT_DEFINED != srcAttrib);
                }
                try {
                    executeScriptIfNeeded(element, false, false);
                } finally {
                    if (jsDoc != null) {
                        jsDoc.setExecutingDynamicExternalPosponed(false);
                    }
                }
            }
        };
        final AbstractJavaScriptEngine<?> engine = element.getPage().getWebClient().getJavaScriptEngine();
        if (engine != null && element.hasAttribute("async") && !engine.isScriptRunning()) {
            final HtmlPage owningPage = element.getHtmlPageOrNull();
            owningPage.addAfterLoadAction(action);
        } else if (engine != null && (element.hasAttribute("async") || postponed && StringUtils.isBlank(element.getTextContent()))) {
            engine.addPostponedAction(action);
        } else {
            try {
                action.execute();
            } catch (final RuntimeException e) {
                throw e;
            } catch (final Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) HTMLDocument(com.gargoylesoftware.htmlunit.javascript.host.html.HTMLDocument) XmlPage(com.gargoylesoftware.htmlunit.xml.XmlPage) PostponedAction(com.gargoylesoftware.htmlunit.javascript.PostponedAction) FailingHttpStatusCodeException(com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException) WebWindow(com.gargoylesoftware.htmlunit.WebWindow)

Example 29 with Window

use of com.gargoylesoftware.htmlunit.javascript.host.Window in project htmlunit by HtmlUnit.

the class EventTarget method fireEvent.

/**
 * Fires the event on the node with capturing and bubbling phase.
 * @param event the event
 * @return the result
 */
public ScriptResult fireEvent(final Event event) {
    final Window window = getWindow();
    event.startFire();
    final Event previousEvent = window.getCurrentEvent();
    window.setCurrentEvent(event);
    try {
        // These can be null if we aren't tied to a DOM node
        final DomNode ourNode = getDomNodeOrNull();
        final DomNode ourParentNode = (ourNode != null) ? ourNode.getParentNode() : null;
        // Determine the propagation path which is fixed here and not affected by
        // DOM tree modification from intermediate listeners (tested in Chrome)
        final List<EventTarget> propagationPath = new ArrayList<>();
        // We're added to the propagation path first
        propagationPath.add(this);
        // and MessagePort, etc. will not have any parents)
        for (DomNode parent = ourParentNode; parent != null; parent = parent.getParentNode()) {
            propagationPath.add(parent.getScriptableObject());
        }
        // (see Note in https://www.w3.org/TR/DOM-Level-3-Events/#event-type-load)
        if (!Event.TYPE_LOAD.equals(event.getType())) {
            // Add Window if the the propagation path reached Document
            if (propagationPath.get(propagationPath.size() - 1) instanceof Document) {
                propagationPath.add(window);
            }
        }
        // capturing phase
        event.setEventPhase(Event.CAPTURING_PHASE);
        for (int i = propagationPath.size() - 1; i >= 1; i--) {
            final EventTarget jsNode = propagationPath.get(i);
            final EventListenersContainer elc = jsNode.eventListenersContainer_;
            if (elc != null) {
                elc.executeCapturingListeners(event, new Object[] { event });
                if (event.isPropagationStopped()) {
                    return new ScriptResult(null);
                }
            }
        }
        // at target phase
        event.setEventPhase(Event.AT_TARGET);
        if (!propagationPath.isEmpty()) {
            // Note: This element is not always the same as event.getTarget():
            // e.g. the 'load' event targets Document but "at target" is on Window.
            final EventTarget jsNode = propagationPath.get(0);
            final EventListenersContainer elc = jsNode.eventListenersContainer_;
            if (elc != null) {
                elc.executeAtTargetListeners(event, new Object[] { event });
                if (event.isPropagationStopped()) {
                    return new ScriptResult(null);
                }
            }
        }
        // bubbling phase
        if (event.isBubbles()) {
            // This belongs here inside the block because events that don't bubble never set
            // eventPhase = 3 (tested in Chrome)
            event.setEventPhase(Event.BUBBLING_PHASE);
            for (int i = 1, size = propagationPath.size(); i < size; i++) {
                final EventTarget jsNode = propagationPath.get(i);
                final EventListenersContainer elc = jsNode.eventListenersContainer_;
                if (elc != null) {
                    elc.executeBubblingListeners(event, new Object[] { event });
                    if (event.isPropagationStopped()) {
                        return new ScriptResult(null);
                    }
                }
            }
        }
        HtmlLabel label = null;
        if (event.processLabelAfterBubbling()) {
            for (DomNode parent = ourParentNode; parent != null; parent = parent.getParentNode()) {
                if (parent instanceof HtmlLabel) {
                    label = (HtmlLabel) parent;
                    break;
                }
            }
        }
        if (label != null) {
            final HtmlElement element = label.getLabeledElement();
            if (element != null && element != getDomNodeOrNull()) {
                try {
                    element.click(event.isShiftKey(), event.isCtrlKey(), event.isAltKey(), false, true, true, true);
                } catch (final IOException e) {
                // ignore for now
                }
            }
        }
    } finally {
        event.endFire();
        // reset event
        window.setCurrentEvent(previousEvent);
    }
    return new ScriptResult(null);
}
Also used : Window(com.gargoylesoftware.htmlunit.javascript.host.Window) HtmlElement(com.gargoylesoftware.htmlunit.html.HtmlElement) ArrayList(java.util.ArrayList) IOException(java.io.IOException) Document(com.gargoylesoftware.htmlunit.javascript.host.dom.Document) ScriptResult(com.gargoylesoftware.htmlunit.ScriptResult) DomNode(com.gargoylesoftware.htmlunit.html.DomNode) HtmlLabel(com.gargoylesoftware.htmlunit.html.HtmlLabel)

Example 30 with Window

use of com.gargoylesoftware.htmlunit.javascript.host.Window in project htmlunit by HtmlUnit.

the class EventTarget method executeEventLocally.

/**
 * Executes the event on this object only (needed for instance for onload on (i)frame tags).
 * @param event the event
 * @see #fireEvent(Event)
 */
public void executeEventLocally(final Event event) {
    final EventListenersContainer eventListenersContainer = getEventListenersContainer();
    final Window window = getWindow();
    final Object[] args = { event };
    final Event previousEvent = window.getCurrentEvent();
    window.setCurrentEvent(event);
    try {
        event.setEventPhase(Event.AT_TARGET);
        eventListenersContainer.executeAtTargetListeners(event, args);
    } finally {
        // reset event
        window.setCurrentEvent(previousEvent);
    }
}
Also used : Window(com.gargoylesoftware.htmlunit.javascript.host.Window)

Aggregations

Window (com.gargoylesoftware.htmlunit.javascript.host.Window)33 HtmlPage (com.gargoylesoftware.htmlunit.html.HtmlPage)13 WebWindow (com.gargoylesoftware.htmlunit.WebWindow)10 ScriptableObject (net.sourceforge.htmlunit.corejs.javascript.ScriptableObject)9 Scriptable (net.sourceforge.htmlunit.corejs.javascript.Scriptable)7 JavaScriptEngine (com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine)6 JsxFunction (com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction)6 WebClient (com.gargoylesoftware.htmlunit.WebClient)5 FrameWindow (com.gargoylesoftware.htmlunit.html.FrameWindow)5 JsxGetter (com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter)5 HTMLDocument (com.gargoylesoftware.htmlunit.javascript.host.html.HTMLDocument)5 IOException (java.io.IOException)5 PostponedAction (com.gargoylesoftware.htmlunit.javascript.PostponedAction)4 DomNode (com.gargoylesoftware.htmlunit.html.DomNode)3 HtmlElement (com.gargoylesoftware.htmlunit.html.HtmlElement)3 XHtmlPage (com.gargoylesoftware.htmlunit.html.XHtmlPage)3 JsxConstructor (com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor)3 XmlPage (com.gargoylesoftware.htmlunit.xml.XmlPage)3 AjaxController (com.gargoylesoftware.htmlunit.AjaxController)2 BrowserVersion (com.gargoylesoftware.htmlunit.BrowserVersion)2