All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cobraparser.html.domimpl.HTMLScriptElementImpl Maven / Gradle / Ivy

There is a newer version: 1.0.2
Show newest version
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Contact info: [email protected]
 */
/*
 * Created on Oct 8, 2005
 */
package org.cobraparser.html.domimpl;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.logging.Level;

import org.cobraparser.html.js.Executor;
import org.cobraparser.html.js.Window;
import org.cobraparser.html.js.Window.JSRunnableTask;
import org.cobraparser.ua.NetworkRequest;
import org.cobraparser.ua.UserAgentContext;
import org.cobraparser.ua.UserAgentContext.Request;
import org.cobraparser.ua.UserAgentContext.RequestKind;
import org.cobraparser.util.SecurityUtil;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.w3c.dom.Document;
import org.w3c.dom.html.HTMLScriptElement;

public class HTMLScriptElementImpl extends HTMLElementImpl implements HTMLScriptElement {
  public HTMLScriptElementImpl() {
    super("SCRIPT", true);
  }

  public HTMLScriptElementImpl(final String name) {
    super(name, true);
  }

  private String text;

  public String getText() {
    final String t = this.text;
    if (t == null) {
      return this.getRawInnerText(true);
    } else {
      return t;
    }
  }

  public void setText(final String text) {
    this.text = text;
  }

  public String getHtmlFor() {
    return this.getAttribute("htmlFor");
  }

  public void setHtmlFor(final String htmlFor) {
    this.setAttribute("htmlFor", htmlFor);
  }

  public String getEvent() {
    return this.getAttribute("event");
  }

  public void setEvent(final String event) {
    this.setAttribute("event", event);
  }

  private boolean defer;

  public boolean getDefer() {
    return this.defer;
  }

  public void setDefer(final boolean defer) {
    this.defer = defer;
  }

  public String getSrc() {
    return this.getAttribute("src");
  }

  public void setSrc(final String src) {
    this.setAttribute("src", src);
  }

  public String getType() {
    return this.getAttribute("type");
  }

  public void setType(final String type) {
    this.setAttribute("type", type);
  }

  private static final String[] jsTypes = {
      "application/ecmascript",
      "application/javascript",
      "application/x-ecmascript",
      "application/x-javascript",
      "text/ecmascript",
      "text/javascript",
      "text/javascript1.0",
      "text/javascript1.1",
      "text/javascript1.2",
      "text/javascript1.3",
      "text/javascript1.4",
      "text/javascript1.5",
      "text/jscript",
      "text/livescript",
      "text/x-ecmascript",
      "text/x-javascript"
  };

  protected final void processScript() {
    final String scriptType = getType();
    if (scriptType != null) {
      if (Arrays.stream(jsTypes).noneMatch(e -> e.equals(scriptType))) {
        ((HTMLDocumentImpl) HTMLScriptElementImpl.this.document).markJobsFinished(1, false);
        return;
      }
    }
    final UserAgentContext bcontext = this.getUserAgentContext();
    if (bcontext == null) {
      throw new IllegalStateException("No user agent context.");
    }
    final Document docObj = this.document;
    if (!(docObj instanceof HTMLDocumentImpl)) {
      throw new IllegalStateException("no valid document");
    }
    final HTMLDocumentImpl doc = (HTMLDocumentImpl) docObj;
    if (bcontext.isScriptingEnabled()) {
      String text;
      final String scriptURI;
      int baseLineNumber;
      final String src = this.getSrc();
      if (src == null) {
        final Request request = new Request(doc.getDocumentURL(), RequestKind.JavaScript);
        if (bcontext.isRequestPermitted(request)) {
          text = this.getText();
          scriptURI = doc.getBaseURI();
          baseLineNumber = 1; // TODO: Line number of inner text??
        } else {
          text = null;
          scriptURI = null;
          baseLineNumber = -1;
        }
      } else {
        this.informExternalScriptLoading();
        try {
          final URL scriptURL = doc.getFullURL(src);
          scriptURI = scriptURL.toExternalForm();
          // Perform a synchronous request
          final NetworkRequest request = bcontext.createHttpRequest();
          SecurityUtil.doPrivileged(() -> {
            // Code might have restrictions on accessing
            // items from elsewhere.
            try {
              request.open("GET", scriptURI, false);
              request.send(null, new Request(scriptURL, RequestKind.JavaScript));
            } catch (final java.io.IOException thrown) {
              logger.log(Level.WARNING, "processScript()", thrown);
            }
            return null;
          });
          final int status = request.getStatus();
          if ((status != 200) && (status != 0)) {
            this.warn("Script at [" + scriptURI + "] failed to load; HTTP status: " + status + ".");
            return;
          }
          text = request.getResponseText();
          baseLineNumber = 1;
        } catch (final MalformedURLException mfe) {
          throw new IllegalArgumentException(mfe);
        }
      }

      final Window window = doc.getWindow();
      if (text != null) {
        final String textSub = text.substring(0, Math.min(50, text.length())).replaceAll("\n", "");
        window.addJSTaskUnchecked(new JSRunnableTask(0, "script: " + textSub, new Runnable() {
          public void run() {
            // final Context ctx = Executor.createContext(HTMLScriptElementImpl.this.getDocumentURL(), bcontext);
            final Context ctx = Executor.createContext(HTMLScriptElementImpl.this.getDocumentURL(), bcontext, window.getContextFactory());
            try {
              final Scriptable scope = window.getWindowScope();
              if (scope == null) {
                throw new IllegalStateException("Scriptable (scope) instance was null");
              }
              try {
                ctx.evaluateString(scope, text, scriptURI, baseLineNumber, null);
                // Why catch this?
                // } catch (final EcmaError ecmaError) {
                // logger.log(Level.WARNING,
                // "Javascript error at " + ecmaError.sourceName() + ":" + ecmaError.lineNumber() + ": " + ecmaError.getMessage(),
                // ecmaError);
              } catch (final Exception err) {
                Executor.logJSException(err);
              }
            } finally {
              Context.exit();
              doc.markJobsFinished(1, false);
            }
          }
        }));
      } else {
        doc.markJobsFinished(1, false);
      }
    } else {
      doc.markJobsFinished(1, false);
    }
  }

  @Override
  protected void appendInnerTextImpl(final StringBuffer buffer) {
    // nop
  }

  @Override
  protected void handleDocumentAttachmentChanged() {
    if (isAttachedToDocument()) {
      ((HTMLDocumentImpl) document).addJob(() -> processScript(), false);
    } else {
      // TODO What does script element do when detached?
    }
    super.handleDocumentAttachmentChanged();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy