Search in sources :

Example 16 with Window

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

the class HtmlPage method executeEventHandlersIfNeeded.

/**
 * Looks for and executes any appropriate event handlers. Looks for body and frame tags.
 * @param eventType either {@link Event#TYPE_LOAD}, {@link Event#TYPE_UNLOAD}, or {@link Event#TYPE_BEFORE_UNLOAD}
 * @return {@code true} if user accepted <tt>onbeforeunload</tt> (not relevant to other events)
 */
private boolean executeEventHandlersIfNeeded(final String eventType) {
    // If JavaScript isn't enabled, there's nothing for us to do.
    if (!getWebClient().isJavaScriptEnabled()) {
        return true;
    }
    // Execute the specified event on the document element.
    final WebWindow window = getEnclosingWindow();
    if (window.getScriptableObject() instanceof Window) {
        final Event event;
        if (eventType.equals(Event.TYPE_BEFORE_UNLOAD)) {
            event = new BeforeUnloadEvent(this, eventType);
        } else {
            event = new Event(this, eventType);
        }
        // here so it could be used with HtmlPage.
        if (LOG.isDebugEnabled()) {
            LOG.debug("Firing " + event);
        }
        final EventTarget jsNode;
        if (Event.TYPE_DOM_DOCUMENT_LOADED.equals(eventType)) {
            jsNode = this.getScriptableObject();
        } else {
            // The load/beforeunload/unload events target Document but paths Window only (tested in Chrome/FF)
            jsNode = window.getScriptableObject();
        }
        final HtmlUnitContextFactory cf = ((JavaScriptEngine) getWebClient().getJavaScriptEngine()).getContextFactory();
        cf.callSecured(cx -> jsNode.fireEvent(event), this);
        if (!isOnbeforeunloadAccepted(this, event)) {
            return false;
        }
    }
    // If this page was loaded in a frame, execute the version of the event specified on the frame tag.
    if (window instanceof FrameWindow) {
        final FrameWindow fw = (FrameWindow) window;
        final BaseFrameElement frame = fw.getFrameElement();
        // if part of a document fragment, then the load event is not triggered
        if (Event.TYPE_LOAD.equals(eventType) && frame.getParentNode() instanceof DomDocumentFragment) {
            return true;
        }
        if (frame.hasEventHandlers("on" + eventType)) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Executing on" + eventType + " handler for " + frame);
            }
            if (window.getScriptableObject() instanceof Window) {
                final Event event;
                if (Event.TYPE_BEFORE_UNLOAD.equals(eventType)) {
                    event = new BeforeUnloadEvent(frame, eventType);
                } else {
                    // ff does not trigger the onload event in this case
                    if (PageDenied.BY_CONTENT_SECURIRY_POLICY == fw.getPageDenied() && hasFeature(JS_EVENT_LOAD_SUPPRESSED_BY_CONTENT_SECURIRY_POLICY)) {
                        return true;
                    }
                    event = new Event(frame, eventType);
                }
                // This fires the "load" event for the <frame> element which, like all non-window
                // load events, propagates up to Document but not Window.  The "load" event for
                // <frameset> on the other hand, like that of <body>, is handled above where it is
                // fired against Document and directed to Window.
                frame.fireEvent(event);
                if (!isOnbeforeunloadAccepted((HtmlPage) frame.getPage(), event)) {
                    return false;
                }
            }
        }
    }
    return true;
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) TopLevelWindow(com.gargoylesoftware.htmlunit.TopLevelWindow) HtmlUnitContextFactory(com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory) Event(com.gargoylesoftware.htmlunit.javascript.host.event.Event) BeforeUnloadEvent(com.gargoylesoftware.htmlunit.javascript.host.event.BeforeUnloadEvent) BeforeUnloadEvent(com.gargoylesoftware.htmlunit.javascript.host.event.BeforeUnloadEvent) EventTarget(com.gargoylesoftware.htmlunit.javascript.host.event.EventTarget) WebWindow(com.gargoylesoftware.htmlunit.WebWindow) AbstractJavaScriptEngine(com.gargoylesoftware.htmlunit.javascript.AbstractJavaScriptEngine) JavaScriptEngine(com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine)

Example 17 with Window

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

the class HTMLDocument method setActiveElement.

/**
 * Sets the specified element as the document's active element.
 * @see HTMLElement#setActive()
 * @param element the new active element for this document
 */
public void setActiveElement(final HTMLElement element) {
    // TODO update page focus element also
    activeElement_ = element;
    if (element != null) {
        // if this is part of an iFrame, make the iFrame tag the
        // active element of his doc
        final WebWindow window = element.getDomNodeOrDie().getPage().getEnclosingWindow();
        if (window instanceof FrameWindow) {
            final BaseFrameElement frame = ((FrameWindow) window).getFrameElement();
            if (frame instanceof HtmlInlineFrame) {
                final Window winWithFrame = frame.getPage().getEnclosingWindow().getScriptableObject();
                ((HTMLDocument) winWithFrame.getDocument()).setActiveElement(frame.getScriptableObject());
            }
        }
    }
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) FrameWindow(com.gargoylesoftware.htmlunit.html.FrameWindow) BaseFrameElement(com.gargoylesoftware.htmlunit.html.BaseFrameElement) FrameWindow(com.gargoylesoftware.htmlunit.html.FrameWindow) HtmlInlineFrame(com.gargoylesoftware.htmlunit.html.HtmlInlineFrame) WebWindow(com.gargoylesoftware.htmlunit.WebWindow)

Example 18 with Window

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

the class History method goToUrlAtCurrentIndex.

/**
 * Loads the URL at the current index into the window to which this navigation history belongs.
 * @throws IOException if an IO error occurs
 */
private void goToUrlAtCurrentIndex() throws IOException {
    final Boolean old = ignoreNewPages_.get();
    ignoreNewPages_.set(Boolean.TRUE);
    try {
        final HistoryEntry entry = entries_.get(index_);
        final Page page = entry.getPage();
        if (page == null) {
            window_.getWebClient().getPage(window_, entry.getWebRequest(), false);
        } else {
            window_.setEnclosedPage(page);
            page.getWebResponse().getWebRequest().setUrl(entry.getUrl());
        }
        final Window jsWindow = window_.getScriptableObject();
        if (jsWindow != null && jsWindow.hasEventHandlers("onpopstate")) {
            final Event event = new PopStateEvent(jsWindow, Event.TYPE_POPSTATE, entry.getState());
            jsWindow.executeEventLocally(event);
        }
    } finally {
        ignoreNewPages_.set(old);
    }
}
Also used : Window(com.gargoylesoftware.htmlunit.javascript.host.Window) PopStateEvent(com.gargoylesoftware.htmlunit.javascript.host.event.PopStateEvent) Event(com.gargoylesoftware.htmlunit.javascript.host.event.Event) PopStateEvent(com.gargoylesoftware.htmlunit.javascript.host.event.PopStateEvent)

Example 19 with Window

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

the class JavaScriptEngine method handleJavaScriptException.

/**
 * Handles an exception that occurred during execution of JavaScript code.
 * @param scriptException the exception
 * @param triggerOnError if true, this triggers the onerror handler
 */
protected void handleJavaScriptException(final ScriptException scriptException, final boolean triggerOnError) {
    // shutdown was already called
    final WebClient webClient = getWebClient();
    if (webClient == null) {
        if (LOG.isInfoEnabled()) {
            LOG.info("handleJavaScriptException('" + scriptException.getMessage() + "') called after the shutdown of the Javascript engine - exception ignored.");
        }
        return;
    }
    // Trigger window.onerror, if it has been set.
    final HtmlPage page = scriptException.getPage();
    if (triggerOnError && page != null) {
        final WebWindow window = page.getEnclosingWindow();
        if (window != null) {
            final Window w = window.getScriptableObject();
            if (w != null) {
                try {
                    w.triggerOnError(scriptException);
                } catch (final Exception e) {
                    handleJavaScriptException(new ScriptException(page, e, null), false);
                }
            }
        }
    }
    webClient.getJavaScriptErrorListener().scriptException(page, scriptException);
    // Throw a Java exception if the user wants us to.
    if (webClient.getOptions().isThrowExceptionOnScriptError()) {
        throw scriptException;
    }
}
Also used : WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) ScriptException(com.gargoylesoftware.htmlunit.ScriptException) HtmlPage(com.gargoylesoftware.htmlunit.html.HtmlPage) WebClient(com.gargoylesoftware.htmlunit.WebClient) RhinoException(net.sourceforge.htmlunit.corejs.javascript.RhinoException) ScriptException(com.gargoylesoftware.htmlunit.ScriptException) IOException(java.io.IOException) WebWindow(com.gargoylesoftware.htmlunit.WebWindow)

Example 20 with Window

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

the class JavaScriptEngine method init.

/**
 * Initializes all the JS stuff for the window.
 * @param webWindow the web window
 * @param context the current context
 * @throws Exception if something goes wrong
 */
private void init(final WebWindow webWindow, final Page page, final Context context) throws Exception {
    final WebClient webClient = webWindow.getWebClient();
    final BrowserVersion browserVersion = webClient.getBrowserVersion();
    final Window window = new Window();
    window.setClassName("Window");
    context.initSafeStandardObjects(window);
    final ClassConfiguration windowConfig = jsConfig_.getClassConfiguration("Window");
    if (windowConfig.getJsConstructor() != null) {
        final FunctionObject functionObject = new RecursiveFunctionObject("Window", windowConfig.getJsConstructor(), window);
        ScriptableObject.defineProperty(window, "constructor", functionObject, ScriptableObject.DONTENUM | ScriptableObject.PERMANENT | ScriptableObject.READONLY);
    } else {
        defineConstructor(window, window, new Window());
    }
    // remove some objects, that Rhino defines in top scope but that we don't want
    deleteProperties(window, "Continuation", "Iterator", "StopIteration", "BigInt");
    if (!browserVersion.hasFeature(JS_PROMISE)) {
        deleteProperties(window, "Promise");
    }
    if (!browserVersion.hasFeature(JS_SYMBOL)) {
        deleteProperties(window, "Symbol");
    }
    final ScriptableObject errorObject = (ScriptableObject) ScriptableObject.getProperty(window, "Error");
    if (browserVersion.hasFeature(JS_ERROR_STACK_TRACE_LIMIT)) {
        errorObject.defineProperty("stackTraceLimit", 10, ScriptableObject.EMPTY);
    } else {
        ScriptableObject.deleteProperty(errorObject, "stackTraceLimit");
    }
    if (!browserVersion.hasFeature(JS_ERROR_CAPTURE_STACK_TRACE)) {
        ScriptableObject.deleteProperty(errorObject, "captureStackTrace");
    }
    if (browserVersion.hasFeature(JS_URL_SEARCH_PARMS_ITERATOR_SIMPLE_NAME)) {
        URLSearchParams.NativeParamsIterator.init(window, "Iterator");
    } else {
        URLSearchParams.NativeParamsIterator.init(window, "URLSearchParams Iterator");
    }
    if (browserVersion.hasFeature(JS_FORM_DATA_ITERATOR_SIMPLE_NAME)) {
        FormData.FormDataIterator.init(window, "Iterator");
    } else {
        FormData.FormDataIterator.init(window, "FormData Iterator");
    }
    final Intl intl = new Intl();
    intl.setParentScope(window);
    window.defineProperty(intl.getClassName(), intl, ScriptableObject.DONTENUM);
    if (browserVersion.hasFeature(JS_INTL_NAMED_OBJECT)) {
        intl.setClassName("Object");
    }
    intl.defineProperties(browserVersion);
    if (browserVersion.hasFeature(JS_REFLECT)) {
        final Reflect reflect = new Reflect();
        reflect.setParentScope(window);
        window.defineProperty(reflect.getClassName(), reflect, ScriptableObject.DONTENUM);
    }
    final Map<Class<? extends Scriptable>, Scriptable> prototypes = new HashMap<>();
    final Map<String, Scriptable> prototypesPerJSName = new HashMap<>();
    final String windowClassName = Window.class.getName();
    for (final ClassConfiguration config : jsConfig_.getAll()) {
        final boolean isWindow = windowClassName.equals(config.getHostClass().getName());
        if (isWindow) {
            configureConstantsPropertiesAndFunctions(config, window);
            final HtmlUnitScriptable prototype = configureClass(config, window, browserVersion);
            prototypesPerJSName.put(config.getClassName(), prototype);
        } else {
            final HtmlUnitScriptable prototype = configureClass(config, window, browserVersion);
            if (config.isJsObject()) {
                // Place object with prototype property in Window scope
                final HtmlUnitScriptable obj = config.getHostClass().newInstance();
                prototype.defineProperty("__proto__", prototype, ScriptableObject.DONTENUM);
                // but not setPrototype!
                obj.defineProperty("prototype", prototype, ScriptableObject.DONTENUM);
                obj.setParentScope(window);
                obj.setClassName(config.getClassName());
                ScriptableObject.defineProperty(window, obj.getClassName(), obj, ScriptableObject.DONTENUM);
                // this obj won't have prototype, constants need to be configured on it again
                configureConstants(config, obj);
            }
            prototypes.put(config.getHostClass(), prototype);
            prototypesPerJSName.put(config.getClassName(), prototype);
        }
    }
    for (final ClassConfiguration config : jsConfig_.getAll()) {
        final Executable jsConstructor = config.getJsConstructor();
        final String jsClassName = config.getClassName();
        Scriptable prototype = prototypesPerJSName.get(jsClassName);
        final String hostClassSimpleName = config.getHostClassSimpleName();
        if ("Image".equals(hostClassSimpleName)) {
            prototype = prototypesPerJSName.get("HTMLImageElement");
        }
        if ("Option".equals(hostClassSimpleName)) {
            prototype = prototypesPerJSName.get("HTMLOptionElement");
        }
        switch(hostClassSimpleName) {
            case "WebKitMutationObserver":
                prototype = prototypesPerJSName.get("MutationObserver");
                break;
            case "webkitURL":
                prototype = prototypesPerJSName.get("URL");
                break;
            default:
        }
        if (prototype != null && config.isJsObject()) {
            if (jsConstructor == null) {
                final ScriptableObject constructor;
                if ("Window".equals(jsClassName)) {
                    constructor = (ScriptableObject) ScriptableObject.getProperty(window, "constructor");
                } else {
                    constructor = config.getHostClass().newInstance();
                    ((HtmlUnitScriptable) constructor).setClassName(config.getClassName());
                }
                defineConstructor(window, prototype, constructor);
                configureConstantsStaticPropertiesAndStaticFunctions(config, constructor);
            } else {
                final BaseFunction function;
                if ("Window".equals(jsClassName)) {
                    function = (BaseFunction) ScriptableObject.getProperty(window, "constructor");
                } else {
                    function = new RecursiveFunctionObject(jsClassName, jsConstructor, window);
                }
                if ("WebKitMutationObserver".equals(hostClassSimpleName) || "webkitURL".equals(hostClassSimpleName) || "Image".equals(hostClassSimpleName) || "Option".equals(hostClassSimpleName)) {
                    final Object prototypeProperty = ScriptableObject.getProperty(window, prototype.getClassName());
                    if (function instanceof FunctionObject) {
                        try {
                            ((FunctionObject) function).addAsConstructor(window, prototype);
                        } catch (final Exception e) {
                            // TODO see issue #1897
                            if (LOG.isWarnEnabled()) {
                                final String newline = System.lineSeparator();
                                LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                            }
                        }
                    }
                    ScriptableObject.defineProperty(window, hostClassSimpleName, function, ScriptableObject.DONTENUM);
                    // so we restore its value
                    if (!hostClassSimpleName.equals(prototype.getClassName())) {
                        if (prototypeProperty == UniqueTag.NOT_FOUND) {
                            ScriptableObject.deleteProperty(window, prototype.getClassName());
                        } else {
                            ScriptableObject.defineProperty(window, prototype.getClassName(), prototypeProperty, ScriptableObject.DONTENUM);
                        }
                    }
                } else {
                    if (function instanceof FunctionObject) {
                        try {
                            ((FunctionObject) function).addAsConstructor(window, prototype);
                        } catch (final Exception e) {
                            // TODO see issue #1897
                            if (LOG.isWarnEnabled()) {
                                final String newline = System.lineSeparator();
                                LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                            }
                        }
                    }
                }
                configureConstantsStaticPropertiesAndStaticFunctions(config, function);
            }
        }
    }
    window.setPrototype(prototypesPerJSName.get(Window.class.getSimpleName()));
    // once all prototypes have been build, it's possible to configure the chains
    final Scriptable objectPrototype = ScriptableObject.getObjectPrototype(window);
    for (final Map.Entry<String, Scriptable> entry : prototypesPerJSName.entrySet()) {
        final String name = entry.getKey();
        final ClassConfiguration config = jsConfig_.getClassConfiguration(name);
        final Scriptable prototype = entry.getValue();
        if (!StringUtils.isEmpty(config.getExtendedClassName())) {
            final Scriptable parentPrototype = prototypesPerJSName.get(config.getExtendedClassName());
            prototype.setPrototype(parentPrototype);
        } else {
            prototype.setPrototype(objectPrototype);
        }
    }
    // if we need more in the future, we have to enhance our JSX annotations
    if (browserVersion.hasFeature(JS_WINDOW_ACTIVEXOBJECT_HIDDEN)) {
        final Scriptable prototype = prototypesPerJSName.get("ActiveXObject");
        if (null != prototype) {
            final Method jsConstructor = ActiveXObject.class.getDeclaredMethod("jsConstructor", Context.class, Object[].class, Function.class, boolean.class);
            final FunctionObject functionObject = new HiddenFunctionObject("ActiveXObject", jsConstructor, window);
            try {
                functionObject.addAsConstructor(window, prototype);
            } catch (final Exception e) {
                // TODO see issue #1897
                if (LOG.isWarnEnabled()) {
                    final String newline = System.lineSeparator();
                    LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                }
            }
        }
    }
    configureRhino(webClient, browserVersion, window);
    window.setPrototypes(prototypes, prototypesPerJSName);
    window.initialize(webWindow, page);
    applyPolyfills(webClient, browserVersion, context, window);
}
Also used : HashMap(java.util.HashMap) IdFunctionObject(net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject) FunctionObject(net.sourceforge.htmlunit.corejs.javascript.FunctionObject) Executable(java.lang.reflect.Executable) ClassConfiguration(com.gargoylesoftware.htmlunit.javascript.configuration.ClassConfiguration) Intl(com.gargoylesoftware.htmlunit.javascript.host.intl.Intl) WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) Method(java.lang.reflect.Method) Scriptable(net.sourceforge.htmlunit.corejs.javascript.Scriptable) WebClient(com.gargoylesoftware.htmlunit.WebClient) RhinoException(net.sourceforge.htmlunit.corejs.javascript.RhinoException) ScriptException(com.gargoylesoftware.htmlunit.ScriptException) IOException(java.io.IOException) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) Reflect(com.gargoylesoftware.htmlunit.javascript.host.Reflect) IdFunctionObject(net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) FunctionObject(net.sourceforge.htmlunit.corejs.javascript.FunctionObject) ActiveXObject(com.gargoylesoftware.htmlunit.javascript.host.ActiveXObject) BrowserVersion(com.gargoylesoftware.htmlunit.BrowserVersion) Map(java.util.Map) HashMap(java.util.HashMap)

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