2015-08-09 14:26:41 +03:00
|
|
|
/* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Document {
|
|
|
|
prologue %{
|
|
|
|
#include "utils/corestrings.h"
|
|
|
|
#include "utils/libdom.h"
|
2015-10-01 14:38:39 +03:00
|
|
|
#include "utils/utils.h"
|
2015-10-09 14:54:40 +03:00
|
|
|
|
|
|
|
#include "render/html_internal.h"
|
|
|
|
#include "content/urldb.h"
|
2015-08-09 14:26:41 +03:00
|
|
|
%};
|
2015-09-28 10:56:23 +03:00
|
|
|
};
|
2015-08-09 14:26:41 +03:00
|
|
|
|
2015-09-28 10:56:23 +03:00
|
|
|
init Document(struct dom_document *document::node);
|
2015-08-09 14:26:41 +03:00
|
|
|
|
|
|
|
method Document::write()
|
|
|
|
%{
|
|
|
|
struct html_content *htmlc;
|
|
|
|
duk_size_t text_len;
|
2015-10-09 14:54:40 +03:00
|
|
|
dom_exception err;
|
|
|
|
const char *text;
|
|
|
|
|
|
|
|
for (int i = 0; i < duk_get_top(ctx); ++i) {
|
2015-08-11 20:39:31 +03:00
|
|
|
duk_safe_to_string(ctx, i);
|
2015-10-09 14:54:40 +03:00
|
|
|
}
|
2015-08-11 20:39:31 +03:00
|
|
|
duk_concat(ctx, duk_get_top(ctx));
|
2015-10-09 14:54:40 +03:00
|
|
|
text = duk_safe_to_lstring(ctx, 0, &text_len);
|
2015-08-09 14:26:41 +03:00
|
|
|
LOG("Writing %*s", (int)text_len, text);
|
2015-10-09 14:54:40 +03:00
|
|
|
|
2015-08-09 14:26:41 +03:00
|
|
|
err = dom_node_get_user_data(priv->parent.node,
|
|
|
|
corestring_dom___ns_key_html_content_data,
|
|
|
|
&htmlc);
|
2015-10-12 21:51:13 +03:00
|
|
|
if ((err != DOM_NO_ERR) || (htmlc == NULL)) {
|
2015-10-05 23:53:43 +03:00
|
|
|
LOG("error getting htmlc. parent node:%p htmlc:%p",
|
2015-10-12 21:51:13 +03:00
|
|
|
priv->parent.node, htmlc);
|
|
|
|
return 0;
|
|
|
|
} else if (htmlc->parser == NULL) {
|
|
|
|
LOG("error; no parser for htmlc: %p", htmlc);
|
|
|
|
return 0;
|
2015-08-09 14:26:41 +03:00
|
|
|
}
|
2015-10-12 21:51:13 +03:00
|
|
|
|
|
|
|
dom_hubbub_parser_insert_chunk(htmlc->parser,
|
|
|
|
(uint8_t *)text, text_len);
|
|
|
|
|
2015-08-09 14:26:41 +03:00
|
|
|
return 0;
|
|
|
|
%}
|
|
|
|
|
2015-10-01 14:38:39 +03:00
|
|
|
method Document::writeln()
|
|
|
|
%{
|
|
|
|
const char nl[] = "\n";
|
|
|
|
struct html_content *htmlc;
|
|
|
|
duk_size_t text_len;
|
2015-10-10 13:14:54 +03:00
|
|
|
const char *text;
|
|
|
|
dom_exception err;
|
|
|
|
|
|
|
|
for (int i = 0; i < duk_get_top(ctx); ++i) {
|
2015-10-01 14:38:39 +03:00
|
|
|
duk_safe_to_string(ctx, i);
|
2015-10-10 13:14:54 +03:00
|
|
|
}
|
2015-10-01 14:38:39 +03:00
|
|
|
duk_concat(ctx, duk_get_top(ctx));
|
2015-10-10 13:14:54 +03:00
|
|
|
text = duk_safe_to_lstring(ctx, 0, &text_len);
|
|
|
|
|
2015-10-01 14:38:39 +03:00
|
|
|
LOG("Writeln %*s", (int)text_len, text);
|
|
|
|
err = dom_node_get_user_data(priv->parent.node,
|
|
|
|
corestring_dom___ns_key_html_content_data,
|
|
|
|
&htmlc);
|
2015-10-12 21:51:13 +03:00
|
|
|
if ((err != DOM_NO_ERR) || (htmlc == NULL)) {
|
2015-10-10 13:14:54 +03:00
|
|
|
LOG("error getting htmlc. parent node:%p htmlc:%p",
|
2015-10-12 21:51:13 +03:00
|
|
|
priv->parent.node, htmlc);
|
|
|
|
return 0;
|
|
|
|
} else if (htmlc->parser == NULL) {
|
|
|
|
LOG("error; no parser for htmlc: %p", htmlc);
|
|
|
|
return 0;
|
2015-10-01 14:38:39 +03:00
|
|
|
}
|
2015-10-12 21:51:13 +03:00
|
|
|
|
|
|
|
dom_hubbub_parser_insert_chunk(htmlc->parser, (uint8_t *)text, text_len);
|
|
|
|
dom_hubbub_parser_insert_chunk(htmlc->parser, (uint8_t *)nl, SLEN(nl));
|
|
|
|
|
2015-10-01 14:38:39 +03:00
|
|
|
return 0;
|
|
|
|
%}
|
|
|
|
|
2015-08-09 14:26:41 +03:00
|
|
|
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;
|
|
|
|
%}
|
|
|
|
|
|
|
|
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 */
|
|
|
|
%}
|
|
|
|
|
2015-09-10 10:51:56 +03:00
|
|
|
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;
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
2015-08-09 14:26:41 +03:00
|
|
|
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);
|
2015-08-12 13:27:18 +03:00
|
|
|
dom_node_unref(element);
|
2015-08-09 14:26:41 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
%}
|
|
|
|
|
2015-10-18 13:06:41 +03:00
|
|
|
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;
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
2015-08-09 14:26:41 +03:00
|
|
|
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 */
|
|
|
|
|
|
|
|
duk_push_pointer(ctx, nodes);
|
|
|
|
dukky_create_object(ctx, PROTO_NAME(NODELIST), 1);
|
|
|
|
dom_nodelist_unref(nodes);
|
|
|
|
return 1;
|
|
|
|
%}
|
2015-10-09 14:54:40 +03:00
|
|
|
|
|
|
|
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);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LOG("error getting htmlc. parent node:%p htmlc:%p",
|
|
|
|
priv->parent.node, htmlc);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
%}
|