use of com.gargoylesoftware.htmlunit.javascript.PostponedAction in project htmlunit by HtmlUnit.
the class HtmlImage method doOnLoad.
/**
* <p><span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span></p>
*
* <p>Executes this element's <tt>onload</tt> or <tt>onerror</tt> handler. This method downloads the image
* if either of these handlers are present (prior to invoking the resulting handler), because applications
* sometimes use images to send information to the server and use these handlers to get notified when the
* information has been received by the server.</p>
*
* <p>See <a href="http://www.nabble.com/How-should-we-handle-image.onload--tt9850876.html">here</a> and
* <a href="http://www.nabble.com/Image-Onload-Support-td18895781.html">here</a> for the discussion which
* lead up to this method.</p>
*
* <p>This method may be called multiple times, but will only attempt to execute the <tt>onload</tt> or
* <tt>onerror</tt> handler the first time it is invoked.</p>
*/
public void doOnLoad() {
if (onloadProcessed_) {
return;
}
final HtmlPage htmlPage = getHtmlPageOrNull();
if (htmlPage == null) {
// nothing to do if embedded in XML code
return;
}
final WebClient client = htmlPage.getWebClient();
final boolean hasEventHandler = hasEventHandlers("onload") || hasEventHandlers("onerror");
if (((hasEventHandler && client.isJavaScriptEnabled()) || client.getOptions().isDownloadImages()) && hasAttribute(SRC_ATTRIBUTE)) {
boolean loadSuccessful = false;
final boolean tryDownload;
if (hasFeature(HTMLIMAGE_BLANK_SRC_AS_EMPTY)) {
tryDownload = !StringUtils.isBlank(getSrcAttribute());
} else {
tryDownload = !getSrcAttribute().isEmpty();
}
if (tryDownload) {
// We need to download the image and then call the resulting handler.
try {
downloadImageIfNeeded();
// if the download was a success
if (imageWebResponse_.isSuccess()) {
// Trigger the onload handler
loadSuccessful = true;
}
} catch (final IOException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("IOException while downloading image for '" + this + "' : " + e.getMessage());
}
}
}
if (!client.isJavaScriptEnabled()) {
onloadProcessed_ = true;
return;
}
if (!hasEventHandler) {
return;
}
onloadProcessed_ = true;
final Event event = new Event(this, loadSuccessful ? Event.TYPE_LOAD : Event.TYPE_ERROR);
if (LOG.isDebugEnabled()) {
LOG.debug("Firing the " + event.getType() + " event for '" + this + "'.");
}
if (READY_STATE_LOADING.equals(htmlPage.getReadyState())) {
final PostponedAction action = new PostponedAction(getPage(), "HtmlImage.doOnLoad") {
@Override
public void execute() throws Exception {
HtmlImage.this.fireEvent(event);
}
};
htmlPage.addAfterLoadAction(action);
} else {
fireEvent(event);
}
}
}
use of com.gargoylesoftware.htmlunit.javascript.PostponedAction in project htmlunit by HtmlUnit.
the class HtmlLink method onAllChildrenAddedToPage.
/**
* {@inheritDoc}
*/
@Override
public void onAllChildrenAddedToPage(final boolean postponed) {
if (getOwnerDocument() instanceof XmlPage) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Link node added: " + asXml());
}
if (!isStyleSheetLink()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Link type '" + getRelAttribute() + "' not supported (" + asXml().replaceAll("[\\r\\n]", "") + ").");
}
return;
}
final WebClient webClient = getPage().getWebClient();
if (!webClient.getOptions().isCssEnabled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Stylesheet Link found but ignored because css support is disabled (" + asXml().replaceAll("[\\r\\n]", "") + ").");
}
return;
}
if (!webClient.isJavaScriptEngineEnabled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Stylesheet Link found but ignored because javascript engine is disabled (" + asXml().replaceAll("[\\r\\n]", "") + ").");
}
return;
}
final PostponedAction action = new PostponedAction(getPage(), "Loading of link " + this) {
@Override
public void execute() {
final HTMLLinkElement linkElem = HtmlLink.this.getScriptableObject();
// force loading, caching inside the link
linkElem.getSheet();
}
};
final AbstractJavaScriptEngine<?> engine = webClient.getJavaScriptEngine();
if (postponed) {
engine.addPostponedAction(action);
} else {
try {
action.execute();
} catch (final RuntimeException e) {
throw e;
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
use of com.gargoylesoftware.htmlunit.javascript.PostponedAction in project htmlunit by HtmlUnit.
the class HTMLDocument method scheduleImplicitClose.
private void scheduleImplicitClose() {
if (!closePostponedAction_) {
closePostponedAction_ = true;
final HtmlPage page = (HtmlPage) getDomNodeOrDie();
final WebWindow enclosingWindow = page.getEnclosingWindow();
page.getWebClient().getJavaScriptEngine().addPostponedAction(new PostponedAction(page, "HTMLDocument.scheduleImplicitClose") {
@Override
public void execute() throws Exception {
if (writeBuilder_.length() != 0) {
close();
}
closePostponedAction_ = false;
}
@Override
public boolean isStillAlive() {
return !enclosingWindow.isClosed();
}
});
}
}
use of com.gargoylesoftware.htmlunit.javascript.PostponedAction 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);
}
}
}
}
use of com.gargoylesoftware.htmlunit.javascript.PostponedAction in project htmlunit by HtmlUnit.
the class MutationObserver method characterDataChanged.
/**
* {@inheritDoc}
*/
@Override
public void characterDataChanged(final CharacterDataChangeEvent event) {
final ScriptableObject target = event.getCharacterData().getScriptableObject();
if (subtree_ || target == node_) {
final MutationRecord mutationRecord = new MutationRecord();
final Scriptable scope = getParentScope();
mutationRecord.setParentScope(scope);
mutationRecord.setPrototype(getPrototype(mutationRecord.getClass()));
mutationRecord.setType("characterData");
mutationRecord.setTarget(target);
if (characterDataOldValue_) {
mutationRecord.setOldValue(event.getOldValue());
}
final Window window = getWindow();
final HtmlPage owningPage = (HtmlPage) window.getDocument().getPage();
final JavaScriptEngine jsEngine = (JavaScriptEngine) window.getWebWindow().getWebClient().getJavaScriptEngine();
jsEngine.addPostponedAction(new PostponedAction(owningPage, "MutationObserver.characterDataChanged") {
@Override
public void execute() throws Exception {
final NativeArray array = new NativeArray(new Object[] { mutationRecord });
ScriptRuntime.setBuiltinProtoAndParent(array, scope, TopLevel.Builtins.Array);
jsEngine.callFunction(owningPage, function_, scope, MutationObserver.this, new Object[] { array });
}
});
}
}
Aggregations