summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/content.c11
-rw-r--r--content/content.h16
-rw-r--r--content/content_protected.h2
-rw-r--r--desktop/browser.c9
-rw-r--r--desktop/browser.h3
-rw-r--r--gtk/scaffolding.c61
-rw-r--r--gtk/viewdata.c2
-rw-r--r--render/html.c40
-rw-r--r--riscos/gui.c2
-rw-r--r--utils/errors.h4
-rw-r--r--utils/libdom.c193
-rw-r--r--utils/libdom.h10
12 files changed, 292 insertions, 61 deletions
diff --git a/content/content.c b/content/content.c
index 87dcfa226..4641571bd 100644
--- a/content/content.c
+++ b/content/content.c
@@ -860,14 +860,17 @@ void content_search_clear(struct hlcache_handle *h)
}
}
-
-void content_debug_dump(struct hlcache_handle *h, FILE *f)
+/* exported interface documented in content/content.h */
+nserror content_debug_dump(struct hlcache_handle *h, FILE *f, enum content_debug op)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
- if (c->handler->debug_dump != NULL)
- c->handler->debug_dump(c, f);
+ if (c->handler->debug_dump == NULL) {
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+
+ return c->handler->debug_dump(c, f, op);
}
diff --git a/content/content.h b/content/content.h
index a2d07926c..752370034 100644
--- a/content/content.h
+++ b/content/content.h
@@ -87,6 +87,12 @@ typedef enum {
CONTENT_MSG_GADGETCLICK/**< A gadget has been clicked on (mainly for file) */
} content_msg;
+/** Debugging dump operations */
+enum content_debug {
+ CONTENT_DEBUG_RENDER, /** Debug the contents rendering. */
+ CONTENT_DEBUG_DOM /** Debug teh contents Document Object. */
+};
+
/** RFC5988 metadata link */
struct content_rfc5988_link {
struct content_rfc5988_link *next; /**< next rfc5988_link in list */
@@ -271,7 +277,15 @@ void content_search(struct hlcache_handle *h, void *context,
search_flags_t flags, const char *string);
void content_search_clear(struct hlcache_handle *h);
-void content_debug_dump(struct hlcache_handle *h, FILE *f);
+/**
+ * Dump debug information to file.
+ *
+ * \param h content handle to debug.
+ * \param f File to write output to.
+ * \param op Debug operation type.
+ */
+nserror content_debug_dump(struct hlcache_handle *h, FILE *f, enum content_debug op);
+
struct content_rfc5988_link *content_find_rfc5988_link(struct hlcache_handle *c,
lwc_string *rel);
diff --git a/content/content_protected.h b/content/content_protected.h
index f5448c803..7d51e1b8c 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -76,7 +76,7 @@ struct content_handler {
void (*search)(struct content *c, void *context, search_flags_t flags,
const char *string);
void (*search_clear)(struct content *c);
- void (*debug_dump)(struct content *c, FILE *f);
+ nserror (*debug_dump)(struct content *c, FILE *f, enum content_debug op);
nserror (*clone)(const struct content *old, struct content **newc);
bool (*matches_quirks)(const struct content *c, bool quirks);
content_type (*type)(void);
diff --git a/desktop/browser.c b/desktop/browser.c
index b71d3ffd4..1fa9de648 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -664,10 +664,13 @@ void browser_window_set_gadget_filename(struct browser_window *bw,
}
/* exported interface, documented in browser.h */
-void browser_window_debug_dump(struct browser_window *bw, FILE *f)
+nserror browser_window_debug_dump(struct browser_window *bw, FILE *f, enum content_debug op)
{
- if (bw->current_content != NULL)
- content_debug_dump(bw->current_content, f);
+ if (bw->current_content == NULL) {
+ return NSERROR_OK;
+ }
+
+ return content_debug_dump(bw->current_content, f, op);
}
/** slow script handler
diff --git a/desktop/browser.h b/desktop/browser.h
index a9985200e..c7d8b7e79 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -42,6 +42,7 @@ struct selection;
struct fetch_multipart_data;
struct form_control;
struct nsurl;
+enum content_debug;
typedef enum {
DRAGGING_NONE,
@@ -452,7 +453,7 @@ char * browser_window_get_selection(struct browser_window *bw);
* \param bw The browser window
* \param f The file to dump to
*/
-void browser_window_debug_dump(struct browser_window *bw, FILE *f);
+nserror browser_window_debug_dump(struct browser_window *bw, FILE *f, enum content_debug op);
/* In platform specific theme_install.c. */
#ifdef WITH_THEME_INSTALL
diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c
index aed323e45..03a14e5dc 100644
--- a/gtk/scaffolding.c
+++ b/gtk/scaffolding.c
@@ -1318,7 +1318,7 @@ MULTIHANDLER(debugboxtree)
bw = nsgtk_get_browser_window(g->top_level);
- browser_window_debug_dump(bw, f);
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_RENDER);
fclose(f);
@@ -1331,50 +1331,35 @@ MULTIHANDLER(debugboxtree)
MULTIHANDLER(debugdomtree)
{
- GtkWidget *save_dialog;
-
- save_dialog = gtk_file_chooser_dialog_new("Save File", g->window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
+ gchar *fname;
+ gint handle;
+ FILE *f;
+ struct browser_window *bw;
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog),
- getenv("HOME") ? getenv("HOME") : "/");
+ handle = g_file_open_tmp("nsgtkdomtreeXXXXXX", &fname, NULL);
+ if ((handle == -1) || (fname == NULL)) {
+ return TRUE;
+ }
+ close(handle); /* in case it was binary mode */
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog),
- "domtree.txt");
+ /* save data to temporary file */
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ warn_user("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ unlink(fname);
+ return TRUE;
+ }
- if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) {
- gchar *filename = gtk_file_chooser_get_filename(
- GTK_FILE_CHOOSER(save_dialog));
- FILE *fh;
- LOG(("Saving dom tree to %s...\n", filename));
+ bw = nsgtk_get_browser_window(g->top_level);
- fh = fopen((const char *) filename, "w");
- if (fh == NULL) {
- warn_user("Error saving box tree dump.",
- "Unable to open file for writing.");
- } else {
- struct browser_window *bw;
- bw = nsgtk_get_browser_window(g->top_level);
-
- if (bw->current_content &&
- content_get_type(bw->current_content) ==
- CONTENT_HTML) {
-#ifdef FIXME
- xmlDebugDumpDocument(fh,
- html_get_document(bw->current_content));
-#endif
- }
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_DOM);
- fclose(fh);
- }
+ fclose(f);
- g_free(filename);
- }
+ nsgtk_viewfile("DOM Tree Debug", "domtree", fname);
- gtk_widget_destroy(save_dialog);
+ g_free(fname);
return TRUE;
}
diff --git a/gtk/viewdata.c b/gtk/viewdata.c
index 1eb78ccf1..6989b9a16 100644
--- a/gtk/viewdata.c
+++ b/gtk/viewdata.c
@@ -483,8 +483,6 @@ window_init_fname(const char *title,
ret = window_init(title, leafname, ndata, ndata_len);
- free(ndata);
-
return ret;
}
diff --git a/render/html.c b/render/html.c
index 9e576486f..12c173f0d 100644
--- a/render/html.c
+++ b/render/html.c
@@ -1971,17 +1971,43 @@ static bool html_drop_file_at_point(struct content *c, int x, int y, char *file)
/**
* Dump debug info concerning the html_content
*
- * \param bw The browser window
- * \param bw The file to dump to
+ * \param bw The browser window
+ * \param f The file to dump to
*/
-static void html_debug_dump(struct content *c, FILE *f)
+static nserror
+html_debug_dump(struct content *c, FILE *f, enum content_debug op)
{
- html_content *html = (html_content *) c;
+ html_content *htmlc = (html_content *)c;
+ dom_node *html;
+ dom_exception exc; /* returned by libdom functions */
+ nserror ret;
+
+ assert(htmlc != NULL);
- assert(html != NULL);
- assert(html->layout != NULL);
+ if (op == CONTENT_DEBUG_RENDER) {
+ assert(htmlc->layout != NULL);
+ box_dump(f, htmlc->layout, 0, true);
+ ret = NSERROR_OK;
+ } else {
+ if (htmlc->document == NULL) {
+ LOG(("No document to dump"));
+ return NSERROR_DOM;
+ }
+
+ exc = dom_document_get_document_element(htmlc->document, (void *) &html);
+ if ((exc != DOM_NO_ERR) || (html == NULL)) {
+ LOG(("Unable to obtain root node"));
+ return NSERROR_DOM;
+ }
+
+ ret = libdom_dump_structure(html, f, 0);
+
+ LOG(("DOM structure dump returning %d", ret));
+
+ dom_node_unref(html);
+ }
- box_dump(f, html->layout, 0, true);
+ return ret;
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 3253f796f..2e337e5a2 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -2370,7 +2370,7 @@ void ro_gui_dump_browser_window(struct browser_window *bw)
return;
}
- browser_window_debug_dump(bw, stream);
+ browser_window_debug_dump(bw, stream, CONTENT_DEBUG_RENDER);
fclose(stream);
diff --git a/utils/errors.h b/utils/errors.h
index aa0179a37..b9e157c66 100644
--- a/utils/errors.h
+++ b/utils/errors.h
@@ -77,7 +77,9 @@ typedef enum {
NSERROR_NOSPACE, /**< Insufficient space */
- NSERROR_BAD_SIZE /**< Bad size */
+ NSERROR_BAD_SIZE, /**< Bad size */
+
+ NSERROR_NOT_IMPLEMENTED, /**< Functionality is not implemented */
} nserror;
#endif
diff --git a/utils/libdom.c b/utils/libdom.c
index 245c9b229..d6b26b46b 100644
--- a/utils/libdom.c
+++ b/utils/libdom.c
@@ -21,11 +21,11 @@
*/
#include <assert.h>
+#include <string.h>
#include <dom/dom.h>
#include "utils/config.h"
#include "utils/log.h"
-
#include "utils/libdom.h"
/* exported interface documented in libdom.h */
@@ -196,7 +196,7 @@ dom_node *libdom_find_first_element(dom_node *parent, lwc_string *element_name)
/* exported interface documented in libdom.h */
/* TODO: return appropriate errors */
-nserror libdom_iterate_child_elements(dom_node *parent,
+nserror libdom_iterate_child_elements(dom_node *parent,
libdom_iterate_cb cb, void *ctx)
{
dom_nodelist *children;
@@ -309,6 +309,195 @@ static void ignore_dom_msg(uint32_t severity, void *ctx, const char *msg, ...)
{
}
+
+
+/**
+ * Dump attribute/value for an element node
+ *
+ * \param node The element node to dump attribute details for
+ * \param attribute The attribute to dump
+ * \return true on success, or false on error
+ */
+static bool dump_dom_element_attribute(dom_node *node, FILE *f, const char *attribute)
+{
+ dom_exception exc;
+ dom_string *attr = NULL;
+ dom_string *attr_value = NULL;
+ dom_node_type type;
+ const char *string;
+ size_t length;
+
+ /* Should only have element nodes here */
+ exc = dom_node_get_node_type(node, &type);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, " Exception raised for node_get_node_type\n");
+ return false;
+ }
+ assert(type == DOM_ELEMENT_NODE);
+
+ /* Create a dom_string containing required attribute name. */
+ exc = dom_string_create_interned((uint8_t *)attribute,
+ strlen(attribute), &attr);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, " Exception raised for dom_string_create\n");
+ return false;
+ }
+
+ /* Get class attribute's value */
+ exc = dom_element_get_attribute(node, attr, &attr_value);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, " Exception raised for element_get_attribute\n");
+ dom_string_unref(attr);
+ return false;
+ } else if (attr_value == NULL) {
+ /* Element lacks required attribute */
+ dom_string_unref(attr);
+ return true;
+ }
+
+ /* Finished with the attr dom_string */
+ dom_string_unref(attr);
+
+ /* Get attribute value's string data */
+ string = dom_string_data(attr_value);
+ length = dom_string_byte_length(attr_value);
+
+ /* Print attribute info */
+ fprintf(f, " %s=\"%.*s\"", attribute, (int)length, string);
+
+ /* Finished with the attr_value dom_string */
+ dom_string_unref(attr_value);
+
+ return true;
+}
+
+
+/**
+ * Print a line in a DOM structure dump for an element
+ *
+ * \param node The node to dump
+ * \param depth The node's depth
+ * \return true on success, or false on error
+ */
+static bool dump_dom_element(dom_node *node, FILE *f, int depth)
+{
+ dom_exception exc;
+ dom_string *node_name = NULL;
+ dom_node_type type;
+ int i;
+ const char *string;
+ size_t length;
+
+ /* Only interested in element nodes */
+ exc = dom_node_get_node_type(node, &type);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, "Exception raised for node_get_node_type\n");
+ return false;
+ } else if (type != DOM_ELEMENT_NODE) {
+ /* Nothing to print */
+ return true;
+ }
+
+ /* Get element name */
+ exc = dom_node_get_node_name(node, &node_name);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, "Exception raised for get_node_name\n");
+ return false;
+ } else if (node_name == NULL) {
+ fprintf(f, "Broken: root_name == NULL\n");
+ return false;
+ }
+
+ /* Print ASCII tree structure for current node */
+ if (depth > 0) {
+ for (i = 0; i < depth; i++) {
+ fprintf(f, "| ");
+ }
+ fprintf(f, "+-");
+ }
+
+ /* Get string data and print element name */
+ string = dom_string_data(node_name);
+ length = dom_string_byte_length(node_name);
+ fprintf(f, "[%.*s]", (int)length, string);
+
+ if (length == 5 && strncmp(string, "title", 5) == 0) {
+ /* Title tag, gather the title */
+ dom_string *str;
+ exc = dom_node_get_text_content(node, &str);
+ if (exc == DOM_NO_ERR && str != NULL) {
+ fprintf(f, " $%.*s$", (int)dom_string_byte_length(str),
+ dom_string_data(str));
+ dom_string_unref(str);
+ }
+ }
+
+ /* Finished with the node_name dom_string */
+ dom_string_unref(node_name);
+
+ /* Print the element's id & class, if it has them */
+ if (dump_dom_element_attribute(node, f, "id") == false ||
+ dump_dom_element_attribute(node, f, "class") == false) {
+ /* Error occured */
+ fprintf(f, "\n");
+ return false;
+ }
+
+ fprintf(f, "\n");
+ return true;
+}
+
+
+/* exported interface documented in libdom.h */
+nserror libdom_dump_structure(dom_node *node, FILE *f, int depth)
+{
+ dom_exception exc;
+ dom_node *child;
+ nserror ret;
+ dom_node *next_child;
+
+ /* Print this node's entry */
+ if (dump_dom_element(node, f, depth) == false) {
+ /* There was an error; return */
+ return NSERROR_DOM;
+ }
+
+ /* Get the node's first child */
+ exc = dom_node_get_first_child(node, &child);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, "Exception raised for node_get_first_child\n");
+ return NSERROR_DOM;
+ } else if (child != NULL) {
+ /* node has children; decend to children's depth */
+ depth++;
+
+ /* Loop though all node's children */
+ do {
+ /* Visit node's descendents */
+ ret = libdom_dump_structure(child, f, depth);
+ if (ret !=NSERROR_OK) {
+ /* There was an error; return */
+ dom_node_unref(child);
+ return NSERROR_DOM;
+ }
+
+ /* Go to next sibling */
+ exc = dom_node_get_next_sibling(child, &next_child);
+ if (exc != DOM_NO_ERR) {
+ fprintf(f, "Exception raised for node_get_next_sibling\n");
+ dom_node_unref(child);
+ return NSERROR_DOM;
+ }
+
+ dom_node_unref(child);
+ child = next_child;
+ } while (child != NULL); /* No more children */
+ }
+
+ return NSERROR_OK;
+}
+
+
/* exported interface documented in libdom.h */
nserror libdom_parse_file(const char *filename, const char *encoding, dom_document **doc)
{
diff --git a/utils/libdom.h b/utils/libdom.h
index dc8eacd12..4f78cd2e9 100644
--- a/utils/libdom.h
+++ b/utils/libdom.h
@@ -25,6 +25,7 @@
#define NETSURF_UTILS_LIBDOM_H_
#include <stdbool.h>
+#include <stdio.h>
#include <dom/dom.h>
@@ -77,4 +78,13 @@ nserror libdom_parse_file(const char *filename, const char *encoding,
*/
nserror libdom_hubbub_error_to_nserror(dom_hubbub_error error);
+/**
+ * Walk though a DOM (sub)tree, in depth first order, printing DOM structure.
+ *
+ * \param node The root node to start from.
+ * \param f The file to write output into.
+ * \param depth The depth of 'node' in the (sub)tree.
+ */
+nserror libdom_dump_structure(dom_node *node, FILE *f, int depth);
+
#endif