summaryrefslogtreecommitdiff
path: root/components/mozilla
diff options
context:
space:
mode:
authorMike Fleming <mfleming@eazel.com>2001-02-27 09:38:53 +0000
committerMichael Fleming <mfleming@src.gnome.org>2001-02-27 09:38:53 +0000
commit82b59b1a1468530596450736a0e1345e24b0912d (patch)
tree7b19b2e845402ecea2aa7f180ba55e8aa1b1caed /components/mozilla
parent92e74ae91451d3529982c6bad5cd7f4124e3ce37 (diff)
downloadnautilus-82b59b1a1468530596450736a0e1345e24b0912d.tar.gz
reviewed by: Eskil Olsen <eskil@eazel.com>
2001-02-27 Mike Fleming <mfleming@eazel.com> reviewed by: Eskil Olsen <eskil@eazel.com> Bug 7008: Navigation to anchors inside a document opened through gnome-vfs does not work. Fixed by manually navigating to anchors inside those documents. Note that this means anchor links only work inside the same document; external anchor links to gnome-vfs pages still do not work. * components/mozilla/mozilla-events.cpp: * components/mozilla/mozilla-events.h: * components/mozilla/nautilus-mozilla-content-view.c: (mozilla_dom_mouse_click_callback) 2001-02-26 Mike Fleming <mfleming@eazel.com> reviewed by: Ramiro Estrugo <ramiro@eazel.com> Bug 6958: Calling gtk_moz_embed_open_stream before control has realized will eventually cause crash, so all opens are postponed until after the stream has realized. Also changed "reload" code to eliminate case where the component and mozilla could get out of sync * components/mozilla/nautilus-mozilla-content-view.c: (nautilus_mozilla_content_view_initialize), (mozilla_realize_callback), (mozilla_dom_mouse_click_callback), (vfs_open_callback), (navigate_mozilla_to_nautilus_uri):
Diffstat (limited to 'components/mozilla')
-rw-r--r--components/mozilla/mozilla-events.cpp317
-rw-r--r--components/mozilla/mozilla-events.h2
-rw-r--r--components/mozilla/nautilus-mozilla-content-view.c110
3 files changed, 304 insertions, 125 deletions
diff --git a/components/mozilla/mozilla-events.cpp b/components/mozilla/mozilla-events.cpp
index 371c9473d..2215104b9 100644
--- a/components/mozilla/mozilla-events.cpp
+++ b/components/mozilla/mozilla-events.cpp
@@ -61,8 +61,10 @@
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIDOMHTMLElement.h"
+#include "nsIDOMHTMLAnchorElement.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIPresShell.h"
+#include "nsIMarkupDocumentViewer.h"
static char *
@@ -259,74 +261,172 @@ mozilla_events_get_href_for_event (gpointer dom_event)
return ret;
}
+static nsIDocShell*
+get_primary_docshell (GtkMozEmbed *b)
+{
+ nsresult result;
+ nsIWebBrowser *wb;
+ gtk_moz_embed_get_nsIWebBrowser (b, &wb);
-#if 0
+ nsCOMPtr<nsIDocShell> ds;
-/*
- * returns TRUE if the given event occurs in a SUBMIT button to a form with method=POST
- */
-extern "C" gboolean
-mozilla_events_is_in_form_POST_submit (gpointer dom_event)
+ nsCOMPtr<nsIDocShellTreeItem> browserAsItem = do_QueryInterface(wb);
+ if (!browserAsItem) return NULL;
+
+ // get the tree owner for that item
+ nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+ result = browserAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
+ if (!NS_SUCCEEDED (result) || ! treeOwner) return NULL;
+
+ // get the primary content shell as an item
+ nsCOMPtr<nsIDocShellTreeItem> contentItem;
+ result = treeOwner->GetPrimaryContentShell(getter_AddRefs(contentItem));
+ if (!NS_SUCCEEDED (result) || ! contentItem) return NULL;
+
+ // QI that back to a docshell
+ ds = do_QueryInterface(contentItem);
+
+ return ds;
+}
+
+nsIDOMElement *
+get_toplevel_doc_element (GtkMozEmbed *embed)
{
- g_return_val_if_fail (dom_event != NULL, FALSE);
- nsCOMPtr<nsIDOMEvent> aDOMEvent (do_QueryInterface ((nsIDOMEvent*) dom_event));
+ nsCOMPtr<nsIDocShell> ds;
+ nsresult rv, result;
- if (!aDOMEvent) {
- return FALSE;
+ ds = get_primary_docshell (embed);
+
+ if ( ! ds ) {
+ return NULL;
}
-
- nsCOMPtr<nsIDOMEventTarget> targetNode;
-
- aDOMEvent->GetTarget (getter_AddRefs (targetNode));
-
- if (!targetNode) {
- return FALSE;
+
+ /* get nsIPresShell */
+
+ nsCOMPtr<nsIPresShell> presShell;
+ result = ds->GetPresShell(getter_AddRefs(presShell));
+ if (!NS_SUCCEEDED(result) || (!presShell)) return NULL;
+
+ /* get nsIDocument */
+
+ nsCOMPtr<nsIDocument> document;
+ result = presShell->GetDocument(getter_AddRefs(document));
+ if (!NS_SUCCEEDED(result) || (!document)) return NULL;
+
+ /* get nsIDOMDocument */
+
+ nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
+ if (!domDoc) return NULL;
+
+ nsCOMPtr<nsIDOMElement> documentElement;
+
+ domDoc->GetDocumentElement (getter_AddRefs (documentElement));
+
+ return documentElement;
+}
+
+static void
+navigate_to_node (GtkMozEmbed *mozilla_embed, nsIDOMNode *node)
+{
+ nsresult rv;
+ nsCOMPtr<nsIDocShell> docShell;
+
+ docShell = get_primary_docshell (mozilla_embed);
+
+ if (!docShell) {
+ return;
}
-
- nsCOMPtr<nsIDOMHTMLInputElement> node = do_QueryInterface (targetNode);
- if (!node) {
- return FALSE;
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ rv = docShell->GetContentViewer (getter_AddRefs (contentViewer));
+ if (!NS_SUCCEEDED (rv) || !contentViewer) {
+ return;
}
- nsAutoString input_type_name;
+ nsCOMPtr<nsIMarkupDocumentViewer> markupDocumentViewer = do_QueryInterface (contentViewer, &rv);
+ if (!NS_SUCCEEDED (rv) || !markupDocumentViewer) {
+ return;
+ }
+ markupDocumentViewer->ScrollToNode (node);
+}
- node->GetType (input_type_name);
+/* Why can't I use GetElementsByTagName? I couldn't get it to work for me */
+static nsIDOMNode *
+get_anchor_named (nsIDOMNode *top_node, const nsAReadableString& aName)
+{
+ nsresult rv;
+ nsAutoString src_string;
+ nsCOMPtr<nsIDOMNodeList> nodes_list;
+ PRUint32 i;
+ nsCOMPtr<nsIDOMNode> child_node;
-#ifdef DEBUG_mfleming
- char *cstr = input_type_name.ToNewCString();
- g_print ("input node of type '%s'\n", cstr);
- nsMemory::Free (cstr);
-#endif
+ top_node->GetChildNodes (getter_AddRefs(nodes_list));
- if ( ! ( input_type_name.EqualsWithConversion ("SUBMIT", PR_TRUE)
- || input_type_name.EqualsWithConversion ("IMAGE", PR_TRUE) )
+ for ( i = 0
+ ; nodes_list && NS_SUCCEEDED (nodes_list->Item (i, getter_AddRefs (child_node)))
+ && child_node
+ ; i++
) {
- return FALSE;
+ nsAutoString currentNodeName;
+// nsAutoString currentNodeType;
+ nsCOMPtr<nsIDOMHTMLAnchorElement> child_html_node = do_QueryInterface (child_node);
+
+ PRBool has_children;
+
+ if (child_html_node
+ && NS_SUCCEEDED (child_html_node->GetName (currentNodeName))
+ && currentNodeName.Equals (aName)) {
+ return child_node;
+ }
+
+ rv = child_node->HasChildNodes (&has_children);
+
+ if ( NS_SUCCEEDED (rv) && has_children) {
+ nsCOMPtr<nsIDOMNode> ret;
+
+ ret = get_anchor_named (child_node, aName);
+
+ if (ret != nsnull) {
+ return ret;
+ }
+ }
}
- nsCOMPtr<nsIDOMHTMLFormElement> form_node;
+ return nsnull;
+}
- node->GetForm (getter_AddRefs (form_node));
+extern "C" void
+mozilla_navigate_to_anchor (GtkMozEmbed *mozilla_embed, const char *anchor)
+{
+ nsCOMPtr<nsIDOMNode> anchor_node;
- if (!form_node) {
- return FALSE;
+ DEBUG_MSG (("+%s", __FUNCTION__));
+
+ nsCOMPtr<nsIDOMNode> top_node;
+ nsCOMPtr<nsIDOMElement> top_element;
+
+ top_node = get_toplevel_doc_element (mozilla_embed);
+
+ if (!top_node) {
+ return;
}
- nsAutoString form_method;
+ top_element = do_QueryInterface (top_node);
- form_node->GetMethod (form_method);
+ nsAutoString anchor_string;
+ anchor_string.AssignWithConversion (anchor);
- if (form_method.EqualsWithConversion ("POST", PR_TRUE)) {
- return TRUE;
+ anchor_node = get_anchor_named (top_node, anchor_string);
+
+ if (anchor_node) {
+ DEBUG_MSG (("=%s found anchor node", __FUNCTION__));
+ navigate_to_node (mozilla_embed, anchor_node);
}
- return FALSE;
+ DEBUG_MSG (("-%s", __FUNCTION__));
}
-#endif /* 0 */
-
#if 0
static void
debug_dom_dump (nsIDOMElement *element, int depth)
@@ -396,9 +496,71 @@ debug_dom_dump (nsIDOMElement *element, int depth)
debug_dom_dump (child_element, depth + 1);
}
}
-#endif /* 0 */
-#if 0
+/*
+ * returns TRUE if the given event occurs in a SUBMIT button to a form with method=POST
+ */
+extern "C" gboolean
+mozilla_events_is_in_form_POST_submit (gpointer dom_event)
+{
+ g_return_val_if_fail (dom_event != NULL, FALSE);
+
+ nsCOMPtr<nsIDOMEvent> aDOMEvent (do_QueryInterface ((nsIDOMEvent*) dom_event));
+
+ if (!aDOMEvent) {
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIDOMEventTarget> targetNode;
+
+ aDOMEvent->GetTarget (getter_AddRefs (targetNode));
+
+ if (!targetNode) {
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIDOMHTMLInputElement> node = do_QueryInterface (targetNode);
+
+ if (!node) {
+ return FALSE;
+ }
+
+ nsAutoString input_type_name;
+
+ node->GetType (input_type_name);
+
+#ifdef DEBUG_mfleming
+ char *cstr = input_type_name.ToNewCString();
+ g_print ("input node of type '%s'\n", cstr);
+ nsMemory::Free (cstr);
+#endif
+
+ if ( ! ( input_type_name.EqualsWithConversion ("SUBMIT", PR_TRUE)
+ || input_type_name.EqualsWithConversion ("IMAGE", PR_TRUE) )
+ ) {
+ return FALSE;
+ }
+
+ nsCOMPtr<nsIDOMHTMLFormElement> form_node;
+
+ node->GetForm (getter_AddRefs (form_node));
+
+ if (!form_node) {
+ return FALSE;
+ }
+
+ nsAutoString form_method;
+
+ form_node->GetMethod (form_method);
+
+ if (form_method.EqualsWithConversion ("POST", PR_TRUE)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
/* Why can't I use GetElementsByTagName? I couldn't get it to work for me */
static gboolean
find_node_named_with_src (nsIDOMNode *top_node, const nsAReadableString& aName, const nsAReadableString& uri)
@@ -461,73 +623,6 @@ find_node_named_with_src (nsIDOMNode *top_node, const nsAReadableString& aName,
return FALSE;
}
-
-static nsIDocShell*
-get_primary_docshell (GtkMozEmbed *b)
-{
- nsresult result;
- nsIWebBrowser *wb;
- gtk_moz_embed_get_nsIWebBrowser (b, &wb);
-
- nsCOMPtr<nsIDocShell> ds;
-
- nsCOMPtr<nsIDocShellTreeItem> browserAsItem = do_QueryInterface(wb);
- if (!browserAsItem) return NULL;
-
- // get the tree owner for that item
- nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
- result = browserAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
- if (!NS_SUCCEEDED (result) || ! treeOwner) return NULL;
-
- // get the primary content shell as an item
- nsCOMPtr<nsIDocShellTreeItem> contentItem;
- result = treeOwner->GetPrimaryContentShell(getter_AddRefs(contentItem));
- if (!NS_SUCCEEDED (result) || ! contentItem) return NULL;
-
- // QI that back to a docshell
- ds = do_QueryInterface(contentItem);
-
- return ds;
-}
-
-nsIDOMElement *
-get_toplevel_doc_element (GtkMozEmbed *embed)
-{
-
- nsCOMPtr<nsIDocShell> ds;
- nsresult rv, result;
-
- ds = get_primary_docshell (embed);
-
- if ( ! ds ) {
- return NULL;
- }
-
- /* get nsIPresShell */
-
- nsCOMPtr<nsIPresShell> presShell;
- result = ds->GetPresShell(getter_AddRefs(presShell));
- if (!NS_SUCCEEDED(result) || (!presShell)) return NULL;
-
- /* get nsIDocument */
-
- nsCOMPtr<nsIDocument> document;
- result = presShell->GetDocument(getter_AddRefs(document));
- if (!NS_SUCCEEDED(result) || (!document)) return NULL;
-
- /* get nsIDOMDocument */
-
- nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
- if (!domDoc) return NULL;
-
- nsCOMPtr<nsIDOMElement> documentElement;
-
- domDoc->GetDocumentElement (getter_AddRefs (documentElement));
-
- return documentElement;
-}
-
-
gboolean
mozilla_events_is_url_in_iframe (GtkMozEmbed *embed, const char *uri)
{
diff --git a/components/mozilla/mozilla-events.h b/components/mozilla/mozilla-events.h
index 6a38ec2d8..b1d3b04a2 100644
--- a/components/mozilla/mozilla-events.h
+++ b/components/mozilla/mozilla-events.h
@@ -39,6 +39,8 @@ gboolean mozilla_events_is_key_return (gpointer dom_event);
char *mozilla_events_get_href_for_event (gpointer dom_event);
+void mozilla_navigate_to_anchor (GtkMozEmbed *mozilla_embed, const char *anchor);
+
#if 0
gboolean mozilla_events_is_in_form_POST_submit (gpointer dom_event);
diff --git a/components/mozilla/nautilus-mozilla-content-view.c b/components/mozilla/nautilus-mozilla-content-view.c
index 5c6b846e6..dd5a0d5d8 100644
--- a/components/mozilla/nautilus-mozilla-content-view.c
+++ b/components/mozilla/nautilus-mozilla-content-view.c
@@ -101,8 +101,8 @@ struct NautilusMozillaContentViewDetails {
* are not recorded in history
*/
gboolean user_initiated_navigation;
- BonoboUIComponent *ui;
+ BonoboUIComponent *ui;
/* For async NautilusView messages */
char *pending_title; /*for set_title*/
@@ -147,6 +147,9 @@ static void view_load_location_callback (NautilusView *nautilus_view,
/* GtkEmbedMoz callback functions */
+static void mozilla_realize_callback (GtkWidget *mozilla,
+ gpointer user_data);
+
static void mozilla_title_changed_callback (GtkMozEmbed *mozilla,
gpointer user_data);
@@ -327,6 +330,11 @@ nautilus_mozilla_content_view_initialize (NautilusMozillaContentView *view)
/* Add callbacks to the beast */
gtk_signal_connect (GTK_OBJECT (view->details->mozilla),
+ "realize",
+ GTK_SIGNAL_FUNC (mozilla_realize_callback),
+ view);
+
+ gtk_signal_connect (GTK_OBJECT (view->details->mozilla),
"title",
GTK_SIGNAL_FUNC (mozilla_title_changed_callback),
view);
@@ -769,6 +777,25 @@ bonobo_control_activate_callback (BonoboObject *control, gboolean state, gpointe
/***********************************************************************************/
static void
+mozilla_realize_callback (GtkWidget *mozilla, gpointer user_data)
+{
+ NautilusMozillaContentView *view;
+
+ DEBUG_MSG (("+%s\n", __FUNCTION__));
+
+ view = NAUTILUS_MOZILLA_CONTENT_VIEW (user_data);
+
+ g_assert (GTK_MOZ_EMBED (mozilla) == view->details->mozilla);
+
+ if (view->details->uri != NULL) {
+ DEBUG_MSG (("=%s navigating to uri after realize '%s'\n", __FUNCTION__, view->details->uri));
+ navigate_mozilla_to_nautilus_uri (view, view->details->uri);
+ }
+
+ DEBUG_MSG (("-%s\n", __FUNCTION__));
+}
+
+static void
mozilla_title_changed_callback (GtkMozEmbed *mozilla, gpointer user_data)
{
NautilusMozillaContentView *view;
@@ -1179,11 +1206,32 @@ mozilla_dom_mouse_click_callback (GtkMozEmbed *mozilla,
async_report_load_failed (view);
ret = NS_DOM_EVENT_CONSUMED;
} else if (href[0] == '#') {
- /* a navigation to an anchor within the same page, let it pass */
+ /* a navigation to an anchor within the same page */
view->details->user_initiated_navigation = TRUE;
- ret = NS_DOM_EVENT_IGNORED;
+
+ /* Anchor navigation is busted for documents that have
+ * been streamed into embedded mozilla.
+ * So, for stuff we've loaded over gnome-vfs,
+ * we do it by hand
+ */
+ if (should_mozilla_load_uri_directly (href_full)) {
+ DEBUG_MSG (("=%s : anchor navigation in normal uri, allowing navigate to continue\n", __FUNCTION__));
+ ret = NS_DOM_EVENT_IGNORED;
+ } else {
+ char *unescaped_anchor;
+
+ /* href+1 to skip the fragment identifier */
+ unescaped_anchor = gnome_vfs_unescape_string (href+1, NULL);
+
+ DEBUG_MSG (("=%s : anchor navigation in gnome-vfs uri, navigate by hand to anchor '%s'\n", __FUNCTION__, unescaped_anchor));
+
+ mozilla_navigate_to_anchor (view->details->mozilla, unescaped_anchor);
+ g_free (unescaped_anchor);
+ ret = NS_DOM_EVENT_CONSUMED;
+ }
} else if (0 == strncmp (href, "javascript:", strlen ("javascript:"))) {
/* This is a bullshit javascript uri, let it pass */
+ DEBUG_MSG (("=%s : javascript uri, allowing navigate to continue\n", __FUNCTION__));
ret = NS_DOM_EVENT_IGNORED;
} else if (should_uri_navigate_bypass_nautilus (href_full)) {
view->details->user_initiated_navigation = TRUE;
@@ -1257,7 +1305,7 @@ vfs_open_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer
if (view->details->vfs_read_buffer == NULL) {
view->details->vfs_read_buffer = g_malloc (VFS_READ_BUFFER_SIZE);
}
- gtk_moz_embed_open_stream (view->details->mozilla, "file://", "text/html");
+ gtk_moz_embed_open_stream (view->details->mozilla, "file:///", "text/html");
gnome_vfs_async_read (handle, view->details->vfs_read_buffer, VFS_READ_BUFFER_SIZE, vfs_read_callback, view);
}
DEBUG_MSG (("-%s\n", __FUNCTION__));
@@ -1402,6 +1450,8 @@ navigate_mozilla_to_nautilus_uri (NautilusMozillaContentView *view,
const char *nautilus_uri)
{
char *mozilla_uri;
+ char *old_mozilla_uri;
+ char *old_nautilus_uri;
mozilla_uri = translate_uri_nautilus_to_mozilla (view, nautilus_uri);
@@ -1410,19 +1460,51 @@ navigate_mozilla_to_nautilus_uri (NautilusMozillaContentView *view,
if (mozilla_uri == NULL) {
async_report_load_failed (view);
goto error;
- } else if (should_mozilla_load_uri_directly (nautilus_uri)) {
- if (view->details->uri != NULL && uris_identical (nautilus_uri, view->details->uri)) {
- DEBUG_MSG (("=%s uri's identical, telling mozilla to reload\n", __FUNCTION__));
- gtk_moz_embed_reload (view->details->mozilla,
- GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE);
+ }
+
+ if (!GTK_WIDGET_REALIZED (view->details->mozilla)) {
+ /* Doing certain things to gtkmozembed before
+ * the widget has realized (specifically, opening
+ * content streams) can cause crashes. To avoid
+ * this, we postpone all navigations
+ * until the widget has realized (we believe
+ * premature realization may cause other issues)
+ */
+
+ DEBUG_MSG (("=%s: Postponing navigation request to widget realization\n", __FUNCTION__));
+ /* Note that view->details->uri is still set below */
+ } else {
+ if (should_mozilla_load_uri_directly (nautilus_uri)) {
+
+ /* See if the current URI is the same as what mozilla already
+ * has. If so, issue a reload rather than a load.
+ * We ask mozilla for it's uri rather than using view->details->uri because,
+ * from time to time, our understanding of mozilla's URI can become inaccurate
+ * (in particular, certain errors may cause embedded mozilla to not change
+ * locations)
+ */
+
+ old_mozilla_uri = gtk_moz_embed_get_location (view->details->mozilla);
+ old_nautilus_uri = translate_uri_mozilla_to_nautilus (view, old_mozilla_uri);
+
+ if (old_nautilus_uri != NULL && uris_identical (nautilus_uri, old_nautilus_uri)) {
+ DEBUG_MSG (("=%s uri's identical, telling mozilla to reload\n", __FUNCTION__));
+ gtk_moz_embed_reload (view->details->mozilla,
+ GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE);
+ } else {
+ gtk_moz_embed_load_url (view->details->mozilla,
+ mozilla_uri);
+ }
+
+ g_free (old_mozilla_uri);
+ old_mozilla_uri = NULL;
+ g_free (old_nautilus_uri);
+ old_nautilus_uri = NULL;
} else {
- gtk_moz_embed_load_url (view->details->mozilla,
- mozilla_uri);
+ DEBUG_MSG (("=%s loading URI via gnome-vfs\n", __FUNCTION__));
+ gnome_vfs_async_open (&(view->details->vfs_handle), nautilus_uri, GNOME_VFS_OPEN_READ, vfs_open_callback, view);
}
- } else {
- DEBUG_MSG (("=%s loading URI via gnome-vfs\n", __FUNCTION__));
- gnome_vfs_async_open (&(view->details->vfs_handle), nautilus_uri, GNOME_VFS_OPEN_READ, vfs_open_callback, view);
}
g_free (view->details->uri);