You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
netsurf/content/handlers/javascript/duktape/Document.bnd

583 lines
14 KiB

/* document binding for browser using duktape and libdom
*
* Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* Released under the terms of the MIT License,
* http://www.opensource.org/licenses/mit-license
*/
prologue Document()
%{
#include "utils/corestrings.h"
#include "utils/libdom.h"
#include "utils/utils.h"
#include "content/hlcache.h"
#include "html/private.h"
#include "content/urldb.h"
#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
%}
init Document(struct dom_document *document::node);
method Document::write()
%{
struct html_content *htmlc;
duk_size_t text_len;
dom_exception err;
const char *text;
for (int i = 0; i < duk_get_top(ctx); ++i) {
duk_safe_to_string(ctx, i);
}
duk_concat(ctx, duk_get_top(ctx));
text = duk_safe_to_lstring(ctx, 0, &text_len);
NSLOG(netsurf, DEBUG, "Writing %*s", (int)text_len, text);
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
&htmlc);
if ((err != DOM_NO_ERR) || (htmlc == NULL)) {
NSLOG(netsurf, INFO,
"error getting htmlc. parent node:%p htmlc:%p",
priv->parent.node, htmlc);
return 0;
} else if (htmlc->parser == NULL) {
NSLOG(netsurf, INFO, "error; no parser for htmlc: %p", htmlc);
return 0;
}
dom_hubbub_parser_insert_chunk(htmlc->parser,
(uint8_t *)text, text_len);
return 0;
%}
method Document::writeln()
%{
const char nl[] = "\n";
struct html_content *htmlc;
duk_size_t text_len;
const char *text;
dom_exception err;
for (int i = 0; i < duk_get_top(ctx); ++i) {
duk_safe_to_string(ctx, i);
}
duk_concat(ctx, duk_get_top(ctx));
text = duk_safe_to_lstring(ctx, 0, &text_len);
NSLOG(netsurf, DEBUG, "Writeln %*s", (int)text_len, text);
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
&htmlc);
if ((err != DOM_NO_ERR) || (htmlc == NULL)) {
NSLOG(netsurf, INFO,
"error getting htmlc. parent node:%p htmlc:%p",
priv->parent.node, htmlc);
return 0;
} else if (htmlc->parser == NULL) {
NSLOG(netsurf, INFO, "error; no parser for htmlc: %p", htmlc);
return 0;
}
dom_hubbub_parser_insert_chunk(htmlc->parser, (uint8_t *)text, text_len);
dom_hubbub_parser_insert_chunk(htmlc->parser, (uint8_t *)nl, SLEN(nl));
return 0;
%}
method Document::createTextNode()
%{
dom_node *newnode;
dom_exception err;
duk_size_t text_len;
const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
dom_string *text_str;
err = dom_string_create((const uint8_t*)text, text_len, &text_str);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
err = dom_document_create_text_node(priv->parent.node,
text_str,
&newnode);
if (err != DOM_NO_ERR) {
dom_string_unref(text_str);
return 0; /* coerced to undefined */
}
dom_string_unref(text_str);
dukky_push_node(ctx, newnode);
dom_node_unref(newnode);
return 1;
%}
method Document::createElement()
%{
dom_node *newnode;
dom_exception err;
duk_size_t text_len;
const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
dom_string *text_str;
err = dom_string_create((const uint8_t*)text, text_len, &text_str);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
err = dom_document_create_element_ns(priv->parent.node,
corestring_dom_html_namespace,
text_str,
&newnode);
if (err != DOM_NO_ERR) {
dom_string_unref(text_str);
return 0; /* coerced to undefined */
}
dom_string_unref(text_str);
dukky_push_node(ctx, newnode);
dom_node_unref(newnode);
return 1;
%}
method Document::createElementNS()
%{
dom_node *newnode;
dom_exception err;
duk_size_t text_len;
duk_size_t ns_len;
const char *ns = duk_safe_to_lstring(ctx, 0, &ns_len);
const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
dom_string *text_str;
dom_string *ns_str;
err = dom_string_create((const uint8_t*)ns, ns_len, &ns_str);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
err = dom_string_create((const uint8_t*)text, text_len, &text_str);
if (err != DOM_NO_ERR) {
dom_string_unref(ns_str);
return 0; /* coerced to undefined */
}
err = dom_document_create_element_ns(priv->parent.node,
ns_str,
text_str,
&newnode);
if (err != DOM_NO_ERR) {
dom_string_unref(ns_str);
dom_string_unref(text_str);
return 0; /* coerced to undefined */
}
dom_string_unref(text_str);
dom_string_unref(ns_str);
dukky_push_node(ctx, newnode);
dom_node_unref(newnode);
return 1;
%}
method Document::createDocumentFragment()
%{
struct dom_document_fragment *frag = NULL;
dom_exception err;
err = dom_document_create_document_fragment(priv->parent.node, &frag);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
dukky_push_node(ctx, (dom_node *)frag);
dom_node_unref(frag); /* The pushed node holds the reference now */
return 1;
%}
getter Document::head()
%{
struct dom_nodelist *nodes;
struct dom_node *retnode;
dom_exception err;
err = dom_document_get_elements_by_tag_name(priv->parent.node,
corestring_dom_HEAD,
&nodes);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
err = dom_nodelist_item(nodes, 0, &retnode);
if (err != DOM_NO_ERR) {
dom_nodelist_unref(nodes);
return 0; /* coerced to undefined */
}
dom_nodelist_unref(nodes);
if (retnode == NULL) return 0; /* coerced to undefined */
dukky_push_node(ctx, retnode);
dom_node_unref(retnode);
return 1;
%}
getter Document::body()
%{
struct dom_nodelist *nodes;
struct dom_node *retnode;
dom_exception err;
err = dom_document_get_elements_by_tag_name(priv->parent.node,
corestring_dom_BODY,
&nodes);
if (err != DOM_NO_ERR) {
return 0; /* coerced to undefined */
}
err = dom_nodelist_item(nodes, 0, &retnode);
if (err != DOM_NO_ERR) {
dom_nodelist_unref(nodes);
return 0; /* coerced to undefined */
}
dom_nodelist_unref(nodes);
if (retnode != NULL) {
dukky_push_node(ctx, retnode);
dom_node_unref(retnode);
return 1;
}
return 0; /* coerced to undefined */
%}
getter Document::location()
%{
/* retrieve the location object from the root object (window) */
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, "location");
if (duk_is_undefined(ctx, -1)) {
duk_pop(ctx);
return 0;
}
return 1;
%}
method Document::getElementById()
%{
dom_string *elementId_dom;
dom_element *element;
dom_exception exc;
duk_size_t text_len;
const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
exc = dom_string_create((uint8_t*)text, text_len, &elementId_dom);
if (exc != DOM_NO_ERR) {
return 0;
}
exc = dom_document_get_element_by_id(((node_private_t *)priv)->node,
elementId_dom, &element);
dom_string_unref(elementId_dom);
if (exc != DOM_NO_ERR) {
return 0;
}
if (element != NULL) {
dukky_push_node(ctx, (dom_node *)element);
dom_node_unref(element);
return 1;
}
return 0;
%}
getter Document::documentElement()
%{
dom_exception exc;
dom_element *element;
exc = dom_document_get_document_element(((node_private_t *)priv)->node,
&element);
if (exc != DOM_NO_ERR) {
return 0;
}
if (element == NULL) {
return 0;
}
dukky_push_node(ctx, (dom_node *)element);
dom_node_unref(element);
return 1;
%}
method Document::getElementsByTagName()
%{
dom_nodelist *nodes;
dom_exception err;
duk_size_t text_len;
const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
dom_string *tag;
err = dom_string_create((uint8_t*)text, text_len, &tag);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
err = dom_document_get_elements_by_tag_name(((node_private_t *)priv)->node,
tag, &nodes);
dom_string_unref(tag);
if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
if (nodes == NULL) return 0; /* coerced to undefined */
dukky_push_generics(ctx, "makeListProxy");
duk_push_pointer(ctx, nodes);
dukky_create_object(ctx, PROTO_NAME(NODELIST), 1);
dom_nodelist_unref(nodes);
if (dukky_pcall(ctx, 1, false) != 0) {
NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
return 0; /* coerced to undefined */
}
return 1; /* The Proxy(NodeList) wrapper */
%}
getter Document::cookie()
%{
char *cookie_str;
struct html_content *htmlc;
dom_exception err;
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
&htmlc);
if ((err == DOM_NO_ERR) && (htmlc != NULL)) {
cookie_str = urldb_get_cookie(llcache_handle_get_url(htmlc->base.llcache), false);
if (cookie_str != NULL) {
duk_push_string(ctx, cookie_str);
free(cookie_str);
} else {
duk_push_string(ctx, "");
}
return 1;
} else {
NSLOG(netsurf, INFO,
"error getting htmlc. parent node:%p htmlc:%p",
priv->parent.node, htmlc);
}
return 0;
%}
setter Document::cookie()
%{
struct html_content *htmlc;
dom_exception err;
const char * cookie_str = duk_safe_to_string(ctx, 0);
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
&htmlc);
if ((err == DOM_NO_ERR) && (htmlc != NULL)) {
/* At this point we need to get the given cookie string parsed
* and inserted into the urldb
*/
bool ok = urldb_set_cookie(cookie_str, /* The cookie string to set */
/* The location to set the cookie for */
llcache_handle_get_url(htmlc->base.llcache),
NULL); /* The referer, which we trust */
if (!ok) {
NSLOG(netsurf, DEEPDEBUG, "unable to set cookie: %s", cookie_str);
/* However there's no useful way to signal that to JS */
}
} else {
NSLOG(netsurf, INFO,
"error getting htmlc. parent node:%p htmlc:%p",
priv->parent.node, htmlc);
}
return 0;
%}
method Document::createEvent ()
%{
/* Create a new event, mark it untrusted since it's new from JS */
dom_event *evt = NULL;
dom_exception exc;
exc = dom_event_create(&evt);
if (exc != DOM_NO_ERR) return 0;
exc = dom_event_set_is_trusted(evt, false);
if (exc != DOM_NO_ERR) { dom_event_unref(evt); return 0; }
dukky_push_event(ctx, evt);
dom_event_unref(evt);
return 1;
%}
getter Document::implementation ()
%{
/* Create a new DOMImplementation instance */
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, MAGIC(DOMImplementation));
if (duk_is_undefined(ctx, -1)) {
duk_pop(ctx);
if (dukky_create_object(ctx,
PROTO_NAME(DOMIMPLEMENTATION),
0) != DUK_EXEC_SUCCESS) {
return duk_error(ctx,
DUK_ERR_ERROR,
"Unable to create dom implementation object");
}
duk_dup(ctx, -1);
duk_put_prop_string(ctx, -3, MAGIC(DOMImplementation));
}
return 1;
%}
getter Document::onabort();
setter Document::onabort();
getter Document::onautocompleteerror();
setter Document::onautocompleteerror();
getter Document::onautocomplete();
setter Document::onautocomplete();
getter Document::onblur();
setter Document::onblur();
getter Document::oncancel();
setter Document::oncancel();
getter Document::oncanplaythrough();
setter Document::oncanplaythrough();
getter Document::oncanplay();
setter Document::oncanplay();
getter Document::onchange();
setter Document::onchange();
getter Document::onclick();
setter Document::onclick();
getter Document::onclose();
setter Document::onclose();
getter Document::oncontextmenu();
setter Document::oncontextmenu();
getter Document::oncuechange();
setter Document::oncuechange();
getter Document::ondblclick();
setter Document::ondblclick();
getter Document::ondragend();
setter Document::ondragend();
getter Document::ondragenter();
setter Document::ondragenter();
getter Document::ondragexit();
setter Document::ondragexit();
getter Document::ondragleave();
setter Document::ondragleave();
getter Document::ondragover();
setter Document::ondragover();
getter Document::ondragstart();
setter Document::ondragstart();
getter Document::ondrag();
setter Document::ondrag();
getter Document::ondrop();
setter Document::ondrop();
getter Document::ondurationchange();
setter Document::ondurationchange();
getter Document::onemptied();
setter Document::onemptied();
getter Document::onended();
setter Document::onended();
getter Document::onfocus();
setter Document::onfocus();
getter Document::oninput();
setter Document::oninput();
getter Document::oninvalid();
setter Document::oninvalid();
getter Document::onkeydown();
setter Document::onkeydown();
getter Document::onkeypress();
setter Document::onkeypress();
getter Document::onkeyup();
setter Document::onkeyup();
getter Document::onloadeddata();
setter Document::onloadeddata();
getter Document::onloadedmetadata();
setter Document::onloadedmetadata();
getter Document::onloadstart();
setter Document::onloadstart();
getter Document::onload();
setter Document::onload();
getter Document::onmousedown();
setter Document::onmousedown();
getter Document::onmouseenter();
setter Document::onmouseenter();
getter Document::onmouseleave();
setter Document::onmouseleave();
getter Document::onmousemove();
setter Document::onmousemove();
getter Document::onmouseout();
setter Document::onmouseout();
getter Document::onmouseover();
setter Document::onmouseover();
getter Document::onmouseup();
setter Document::onmouseup();
getter Document::onpause();
setter Document::onpause();
getter Document::onplaying();
setter Document::onplaying();
getter Document::onplay();
setter Document::onplay();
getter Document::onprogress();
setter Document::onprogress();
getter Document::onratechange();
setter Document::onratechange();
getter Document::onreadystatechange();
setter Document::onreadystatechange();
getter Document::onreset();
setter Document::onreset();
getter Document::onresize();
setter Document::onresize();
getter Document::onscroll();
setter Document::onscroll();
getter Document::onseeked();
setter Document::onseeked();
getter Document::onseeking();
setter Document::onseeking();
getter Document::onselect();
setter Document::onselect();
getter Document::onshow();
setter Document::onshow();
getter Document::onsort();
setter Document::onsort();
getter Document::onstalled();
setter Document::onstalled();
getter Document::onsubmit();
setter Document::onsubmit();
getter Document::onsuspend();
setter Document::onsuspend();
getter Document::ontimeupdate();
setter Document::ontimeupdate();
getter Document::ontoggle();
setter Document::ontoggle();
getter Document::onvolumechange();
setter Document::onvolumechange();
getter Document::onwaiting();
setter Document::onwaiting();
getter Document::onwheel();
setter Document::onwheel();