Initial import of ephy (rev# 7126) from svn
[ephy-soc.git] / embed / mozilla / .svn / text-base / mozilla-embed.cpp.svn-base
blob15622c9738d65d8399a3e57c7c2c6ab7a1327947
1 /*
2  *  Copyright © 2000-2004 Marco Pesenti Gritti
3  *  Copyright © 2003, 2004 Christian Persch
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  *  $Id$
20  */
22 #include "mozilla-config.h"
23 #include "config.h"
25 #include <nsStringAPI.h>
27 #include <gtkmozembed.h>
28 #include <nsIDOMKeyEvent.h>
29 #include <nsIDOMMouseEvent.h>
30 #include <nsIRequest.h>
31 #include <nsIURI.h>
32 #include <nsIWebNavigation.h>
33 #include <nsIWebProgressListener.h>
34 #include <nsMemory.h>
36 #include "EphyBrowser.h"
37 #include "EphyUtils.h"
38 #include "EventContext.h"
40 #include "ephy-command-manager.h"
41 #include "ephy-debug.h"
42 #include "ephy-embed-shell.h"
43 #include "ephy-embed-single.h"
44 #include "ephy-string.h"
45 #include "mozilla-embed-event.h"
47 #include "mozilla-embed.h"
49 static void     mozilla_embed_class_init        (MozillaEmbedClass *klass);
50 static void     mozilla_embed_init              (MozillaEmbed *gs);
51 static void     mozilla_embed_destroy           (GtkObject *object);
52 static void     mozilla_embed_finalize          (GObject *object);
53 static void     ephy_embed_iface_init           (EphyEmbedIface *iface);
55 static void mozilla_embed_location_changed_cb   (GtkMozEmbed *embed,
56                                                  MozillaEmbed *membed);
57 static void mozilla_embed_net_state_all_cb      (GtkMozEmbed *embed,
58                                                  const char *aURI,
59                                                  gint state,
60                                                  guint status,
61                                                  MozillaEmbed *membed);
62 static gboolean mozilla_embed_dom_mouse_click_cb(GtkMozEmbed *embed,
63                                                  gpointer dom_event,
64                                                  MozillaEmbed *membed);
65 static gboolean mozilla_embed_dom_mouse_down_cb (GtkMozEmbed *embed,
66                                                  gpointer dom_event, 
67                                                  MozillaEmbed *membed);
68 static gboolean mozilla_embed_dom_key_press_cb  (GtkMozEmbed *embed,
69                                                  gpointer dom_event, 
70                                                  MozillaEmbed *membed);
71 static void mozilla_embed_new_window_cb         (GtkMozEmbed *embed, 
72                                                  GtkMozEmbed **newEmbed,
73                                                  guint chrome_mask,
74                                                  MozillaEmbed *membed);
75 static void mozilla_embed_security_change_cb    (GtkMozEmbed *embed, 
76                                                  gpointer request,
77                                                  PRUint32 state,
78                                                  MozillaEmbed *membed);
79 static EphyEmbedSecurityLevel mozilla_embed_security_level (PRUint32 state);
81 #define MOZILLA_EMBED_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED, MozillaEmbedPrivate))
83 typedef enum
85         MOZILLA_EMBED_LOAD_STARTED,
86         MOZILLA_EMBED_LOAD_REDIRECTING,
87         MOZILLA_EMBED_LOAD_LOADING,
88         MOZILLA_EMBED_LOAD_STOPPED
89 } MozillaEmbedLoadState;
91 struct MozillaEmbedPrivate
93         EphyBrowser *browser;
94         MozillaEmbedLoadState load_state;
97 #define WINDOWWATCHER_CONTRACTID "@mozilla.org/embedcomp/window-watcher;1"
99 static GObjectClass *parent_class = NULL;
101 static void
102 impl_manager_do_command (EphyCommandManager *manager,
103                          const char *command) 
105         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(manager)->priv;
107         mpriv->browser->DoCommand (command);
110 static gboolean
111 impl_manager_can_do_command (EphyCommandManager *manager,
112                              const char *command) 
114         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(manager)->priv;
115         nsresult rv;
116         PRBool enabled;
118         rv = mpriv->browser->GetCommandState (command, &enabled);
120         return NS_SUCCEEDED (rv) ? enabled : FALSE;
123 static void
124 ephy_command_manager_iface_init (EphyCommandManagerIface *iface)
126         iface->do_command = impl_manager_do_command;
127         iface->can_do_command = impl_manager_can_do_command;
129         
130 GType 
131 mozilla_embed_get_type (void)
133         static GType type = 0;
135         if (G_UNLIKELY (type == 0))
136         {
137                 const GTypeInfo our_info =
138                 {
139                         sizeof (MozillaEmbedClass),
140                         NULL, /* base_init */
141                         NULL, /* base_finalize */
142                         (GClassInitFunc) mozilla_embed_class_init,
143                         NULL,
144                         NULL, /* class_data */
145                         sizeof (MozillaEmbed),
146                         0, /* n_preallocs */
147                         (GInstanceInitFunc) mozilla_embed_init
148                 };
150                 const GInterfaceInfo embed_info =
151                 {
152                         (GInterfaceInitFunc) ephy_embed_iface_init,
153                         NULL,
154                         NULL
155                 };
157                 const GInterfaceInfo ephy_command_manager_info =
158                 {
159                         (GInterfaceInitFunc) ephy_command_manager_iface_init,
160                         NULL,
161                         NULL
162                  };
163         
164                 type = g_type_register_static (GTK_TYPE_MOZ_EMBED,
165                                                "MozillaEmbed",
166                                                &our_info, 
167                                                (GTypeFlags)0);
168                 g_type_add_interface_static (type,
169                                              EPHY_TYPE_EMBED,
170                                              &embed_info);
171                 g_type_add_interface_static (type,
172                                              EPHY_TYPE_COMMAND_MANAGER,
173                                              &ephy_command_manager_info);
174         }
176         return type;
179 static void
180 mozilla_embed_grab_focus (GtkWidget *widget)
182         GtkWidget *child;
184         child = gtk_bin_get_child (GTK_BIN (widget));
186         if (child != NULL)
187         {
188                 gtk_widget_grab_focus (child);
189         }
190         else
191         {
192                 g_warning ("Need to realize the embed before grabbing focus!\n");
193         }
196 static void
197 impl_close (EphyEmbed *embed) 
199         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
201         mpriv->browser->Close ();
204 static void
205 mozilla_embed_realize (GtkWidget *widget)
207         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (widget)->priv;
209         GTK_WIDGET_CLASS (parent_class)->realize (widget);
211         /* Initialise our helper class */
212         nsresult rv;
213         rv = mpriv->browser->Init (GTK_MOZ_EMBED (widget));
214         if (NS_FAILED (rv))
215         {
216                 g_warning ("EphyBrowser initialization failed for %p\n", widget);
217                 return;
218         }
221 static GObject *
222 mozilla_embed_constructor (GType type, guint n_construct_properties,
223                            GObjectConstructParam *construct_params)
225         g_object_ref (embed_shell);
227         /* we depend on single because of mozilla initialization */
228         ephy_embed_shell_get_embed_single (embed_shell);
230         return parent_class->constructor (type, n_construct_properties,
231                                           construct_params);
234 static void
235 mozilla_embed_class_init (MozillaEmbedClass *klass)
237         GObjectClass *object_class = G_OBJECT_CLASS (klass);
238         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); 
239         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 
241         parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
243         object_class->constructor = mozilla_embed_constructor;
244         object_class->finalize = mozilla_embed_finalize;
246         gtk_object_class->destroy = mozilla_embed_destroy;
248         widget_class->grab_focus = mozilla_embed_grab_focus;
249         widget_class->realize = mozilla_embed_realize;
251         g_type_class_add_private (object_class, sizeof(MozillaEmbedPrivate));
254 static void
255 mozilla_embed_init (MozillaEmbed *embed)
257         embed->priv = MOZILLA_EMBED_GET_PRIVATE (embed);
258         embed->priv->browser = new EphyBrowser ();
260         g_signal_connect_object (embed, "location",
261                                  G_CALLBACK (mozilla_embed_location_changed_cb),
262                                  embed, (GConnectFlags) 0);
263         g_signal_connect_object (embed, "net_state_all",
264                                  G_CALLBACK (mozilla_embed_net_state_all_cb),
265                                  embed, (GConnectFlags) 0);
266         g_signal_connect_object (embed, "dom_mouse_click",
267                                  G_CALLBACK (mozilla_embed_dom_mouse_click_cb),
268                                  embed, (GConnectFlags) 0);
269         g_signal_connect_object (embed, "dom_mouse_down",
270                                  G_CALLBACK (mozilla_embed_dom_mouse_down_cb),
271                                  embed, (GConnectFlags) 0);
272         g_signal_connect_object (embed, "dom-key-press",
273                                  G_CALLBACK (mozilla_embed_dom_key_press_cb),
274                                  embed, (GConnectFlags) 0);
275         g_signal_connect_object (embed, "new_window",
276                                  G_CALLBACK (mozilla_embed_new_window_cb),
277                                  embed, (GConnectFlags) 0);
278         g_signal_connect_object (embed, "security_change",
279                                  G_CALLBACK (mozilla_embed_security_change_cb),
280                                  embed, (GConnectFlags) 0);
283 gpointer
284 _mozilla_embed_get_ephy_browser (MozillaEmbed *embed)
286         g_return_val_if_fail (embed->priv->browser != NULL, NULL);
287         
288         return embed->priv->browser;
291 static void
292 mozilla_embed_destroy (GtkObject *object)
294         MozillaEmbed *embed = MOZILLA_EMBED (object);
296         if (embed->priv->browser)
297         {
298                 embed->priv->browser->Destroy();
299         }
300         
301         GTK_OBJECT_CLASS (parent_class)->destroy (object);
304 static void
305 mozilla_embed_finalize (GObject *object)
307         MozillaEmbed *embed = MOZILLA_EMBED (object);
309         if (embed->priv->browser)
310         {
311                 delete embed->priv->browser;
312                 embed->priv->browser = nsnull;
313         }
315         G_OBJECT_CLASS (parent_class)->finalize (object);
317         g_object_unref (embed_shell);
320 static void
321 impl_load_url (EphyEmbed *embed, 
322                const char *url)
324         gtk_moz_embed_load_url (GTK_MOZ_EMBED(embed), url);
327 static char * impl_get_location (EphyEmbed *embed, gboolean toplevel);
329 static void
330 impl_load (EphyEmbed *embed, 
331            const char *url,
332            EphyEmbedLoadFlags flags,
333            EphyEmbed *preview_embed)
335         EphyBrowser *browser;
337         browser = MOZILLA_EMBED(embed)->priv->browser;
338         g_return_if_fail (browser != NULL);
340         nsCOMPtr<nsIURI> uri;
341         if (preview_embed != NULL)
342         {
343                 EphyBrowser *pbrowser;
345                 pbrowser = MOZILLA_EMBED(preview_embed)->priv->browser;
346                 if (pbrowser != NULL)
347                 {
348                         pbrowser->GetDocumentURI (getter_AddRefs (uri));
349                 }
350         }
352 #ifdef HAVE_GECKO_1_8_1
353         if (flags & EPHY_EMBED_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
354         {
355                 browser->LoadURI (url, nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, uri);      
356         }
357         else
358 #endif /* HAVE_GECKO_1_8_1 */
359         {
360                 browser->LoadURI (url, nsIWebNavigation::LOAD_FLAGS_NONE, uri); 
361         }
364 static void
365 impl_stop_load (EphyEmbed *embed)
367         gtk_moz_embed_stop_load (GTK_MOZ_EMBED(embed)); 
370 static gboolean
371 impl_can_go_back (EphyEmbed *embed)
373         return gtk_moz_embed_can_go_back (GTK_MOZ_EMBED(embed));
376 static gboolean
377 impl_can_go_forward (EphyEmbed *embed)
379         return gtk_moz_embed_can_go_forward (GTK_MOZ_EMBED(embed));
382 static gboolean
383 mozilla_embed_get_uri_parent (MozillaEmbed *membed,
384                               const char *aUri,
385                               nsCString &aParent)
387         nsresult rv;
388         nsCString encoding;
389         rv = membed->priv->browser->GetEncoding (encoding);
390         if (NS_FAILED (rv)) return FALSE;
392         nsCOMPtr<nsIURI> uri;
393         rv = EphyUtils::NewURI (getter_AddRefs(uri), nsCString(aUri), encoding.get());
394         if (NS_FAILED(rv) || !uri) return FALSE;
396         /* Don't support going 'up' with chrome url's, mozilla handily
397          * fixes them up for us, so it doesn't work properly, see
398          * rdf/chrome/src/nsChromeProtocolHandler.cpp::NewURI()
399          * (the Canonify() call)
400          */
401         nsCString scheme;
402         rv = uri->GetScheme (scheme);
403         if (NS_FAILED(rv) || !scheme.Length()) return FALSE;
404         if (strcmp (scheme.get(), "chrome") == 0) return FALSE;
406         nsCString path;
407         rv = uri->GetPath(path);
408         if (NS_FAILED(rv) || !path.Length()) return FALSE;
409         if (strcmp (path.get (), "/") == 0) return FALSE;
411         const char *slash = strrchr (path.BeginReading(), '/');
412         if (!slash) return FALSE;
414         if (slash[1] == '\0')
415         {
416                 /* ends with a slash - a directory, go to parent */
417                 rv = uri->Resolve (nsCString(".."), aParent);
418         }
419         else
420         {
421                 /* it's a file, go to the directory */
422                 rv = uri->Resolve (nsCString("."), aParent);
423         }
425         return NS_SUCCEEDED (rv);
428 static gboolean
429 impl_can_go_up (EphyEmbed *embed)
431         MozillaEmbed *membed = MOZILLA_EMBED (embed);
432         char *address;
433         gboolean result;
435         address = ephy_embed_get_location (embed, TRUE);
436         if (address == NULL) return FALSE;
438         nsCString parent;
439         result = mozilla_embed_get_uri_parent (membed, address, parent);
440         g_free (address);
442         return result;
445 static GSList *
446 impl_get_go_up_list (EphyEmbed *embed)
448         MozillaEmbed *membed = MOZILLA_EMBED (embed);
449         GSList *l = NULL;
450         char *address, *s;
452         address = ephy_embed_get_location (embed, TRUE);
453         if (address == NULL) return NULL;
455         s = address;
456         nsCString parent;
457         while (mozilla_embed_get_uri_parent (membed, s, parent))
458         {
459                 s = g_strdup (parent.get());
460                 l = g_slist_prepend (l, s);
461         }
463         g_free (address);
465         return g_slist_reverse (l);
468 static void
469 impl_go_back (EphyEmbed *embed)
471         gtk_moz_embed_go_back (GTK_MOZ_EMBED(embed));
473                 
474 static void
475 impl_go_forward (EphyEmbed *embed)
477         gtk_moz_embed_go_forward (GTK_MOZ_EMBED(embed));
480 static void
481 impl_go_up (EphyEmbed *embed)
483         MozillaEmbed *membed = MOZILLA_EMBED (embed);
484         char *uri;
486         uri = ephy_embed_get_location (embed, TRUE);
487         if (uri == NULL) return;
489         gboolean rv;
490         nsCString parent_uri;
491         rv = mozilla_embed_get_uri_parent (membed, uri, parent_uri);
492         g_free (uri);
494         g_return_if_fail (rv != FALSE);
496         ephy_embed_load_url (embed, parent_uri.get ());
499 static char *
500 impl_get_title (EphyEmbed *embed)
502         return gtk_moz_embed_get_title (GTK_MOZ_EMBED (embed));
505 static char *
506 impl_get_link_message (EphyEmbed *embed)
508         return gtk_moz_embed_get_link_message (GTK_MOZ_EMBED (embed));
511 static char *
512 impl_get_js_status (EphyEmbed *embed)
514         return gtk_moz_embed_get_js_status (GTK_MOZ_EMBED (embed));
517 static char *
518 impl_get_location (EphyEmbed *embed, 
519                    gboolean toplevel)
521         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
522         nsresult rv;
524         nsCOMPtr<nsIURI> uri;
525         if (toplevel)
526         {
527                 rv = mpriv->browser->GetDocumentURI (getter_AddRefs (uri));
528         }
529         else
530         {
531                 rv = mpriv->browser->GetTargetDocumentURI (getter_AddRefs (uri));
532         }
534         if (NS_FAILED (rv)) return NULL;
536         nsCOMPtr<nsIURI> furi;
537         rv = uri->Clone (getter_AddRefs (furi));
538         /* Some nsIURI impls return NS_OK even though they didn't put anything in the outparam!! */
539         if (NS_FAILED (rv) || !furi) furi.swap(uri);
541         /* Hide password part */
542         nsCString user;
543         furi->GetUsername (user);
544         furi->SetUserPass (user);
546         nsCString url;
547         furi->GetSpec (url);
549         return url.Length() ? g_strdup (url.get()) : NULL;
552 static void
553 impl_reload (EphyEmbed *embed, 
554              gboolean force)
556         guint32 mflags = GTK_MOZ_EMBED_FLAG_RELOADNORMAL;
558         if (force)
559         {
560                 mflags = GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE;
561         }
563         gtk_moz_embed_reload (GTK_MOZ_EMBED(embed), mflags);
566 static void
567 impl_set_zoom (EphyEmbed *embed, 
568                float zoom) 
570         EphyBrowser *browser;
571         nsresult rv;
573         g_return_if_fail (zoom > 0.0);
575         browser = MOZILLA_EMBED(embed)->priv->browser;
576         g_return_if_fail (browser != NULL);
578         rv = browser->SetZoom (zoom);
580         if (NS_SUCCEEDED (rv))
581         {
582                 g_signal_emit_by_name (embed, "ge_zoom_change", zoom);
583         }
586 static float
587 impl_get_zoom (EphyEmbed *embed)
589         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
590         float f;
592         nsresult rv;    
593         rv = mpriv->browser->GetZoom (&f);
594         
595         if (NS_SUCCEEDED (rv))
596         {
597                 return f;
598         }
600         return 1.0;
603 static void
604 impl_scroll_lines (EphyEmbed *embed,
605                    int num_lines)
607         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
609         mpriv->browser->ScrollLines (num_lines);
612 static void
613 impl_scroll_pages (EphyEmbed *embed,
614                    int num_pages)
616         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
618         mpriv->browser->ScrollPages (num_pages);
621 static void
622 impl_scroll_pixels (EphyEmbed *embed,
623                     int dx,
624                     int dy)
626         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
628         mpriv->browser->ScrollPixels (dx, dy);
631 static int
632 impl_shistory_n_items (EphyEmbed *embed)
634         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
635         nsresult rv;
636         int count, index;
638         rv = mpriv->browser->GetSHInfo (&count, &index);
640         return NS_SUCCEEDED(rv) ? count : 0;
643 static void
644 impl_shistory_get_nth (EphyEmbed *embed, 
645                        int nth,
646                        gboolean is_relative,
647                        char **aUrl,
648                        char **aTitle)
650         nsresult rv;
651         nsCString url;
652         PRUnichar *title;
653         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
655         if (is_relative)
656         {
657                 nth += ephy_embed_shistory_get_pos (embed);
658         }
659         
660         rv = mpriv->browser->GetSHUrlAtIndex(nth, url);
662         *aUrl = (NS_SUCCEEDED (rv) && url.Length()) ? g_strdup(url.get()) : NULL;
664         rv = mpriv->browser->GetSHTitleAtIndex(nth, &title);
666         if (title)
667         {
668                 nsCString cTitle;
669                 NS_UTF16ToCString (nsString(title),
670                                    NS_CSTRING_ENCODING_UTF8, cTitle);
671                 *aTitle = g_strdup (cTitle.get());
672                 nsMemory::Free (title);
673         }
674         else
675         {
676                 *aTitle = NULL;
677         }
680 static int
681 impl_shistory_get_pos (EphyEmbed *embed)
683         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
684         nsresult rv;
685         int count, index;
687         rv = mpriv->browser->GetSHInfo (&count, &index);
689         return NS_SUCCEEDED(rv) ? index : 0;
692 static void
693 impl_shistory_go_nth (EphyEmbed *embed, 
694                       int nth)
696         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
698         mpriv->browser->GoToHistoryIndex (nth);
701 static void
702 impl_shistory_copy (EphyEmbed *source,
703                     EphyEmbed *dest,
704                     gboolean copy_back,
705                     gboolean copy_forward,
706                     gboolean copy_current)
708         MozillaEmbedPrivate *spriv = MOZILLA_EMBED(source)->priv;
709         MozillaEmbedPrivate *dpriv = MOZILLA_EMBED(dest)->priv;
711         spriv->browser->CopySHistory(dpriv->browser, copy_back,
712                                      copy_forward, copy_current);
715 static void
716 impl_get_security_level (EphyEmbed *embed,
717                          EphyEmbedSecurityLevel *level,
718                          char **description)
720         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
722         if (level) *level = EPHY_EMBED_STATE_IS_UNKNOWN;
723         if (description) *description = NULL;
725         nsresult rv;
726         PRUint32 state;
727         nsCString desc;
728         rv = mpriv->browser->GetSecurityInfo (&state, desc);
729         if (NS_FAILED (rv)) return;
731         if (level) *level = mozilla_embed_security_level (state);
732         if (description) *description = g_strdup (desc.get());
735 static void
736 impl_show_page_certificate (EphyEmbed *embed)
738         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED (embed)->priv;
740         mpriv->browser->ShowCertificate ();
742         
743 static void
744 impl_print (EphyEmbed *embed)
746         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
748         mpriv->browser->Print ();
751 static void
752 impl_set_print_preview_mode (EphyEmbed *embed, gboolean preview_mode)
754         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
756         mpriv->browser->SetPrintPreviewMode (preview_mode);
759 static int
760 impl_print_preview_n_pages (EphyEmbed *embed)
762         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
763         nsresult rv;
764         int num;
766         rv = mpriv->browser->PrintPreviewNumPages(&num);
768         return NS_SUCCEEDED (rv) ? num : 0;
771 static void
772 impl_print_preview_navigate (EphyEmbed *embed,
773                              EphyEmbedPrintPreviewNavType type,
774                              int page)
776         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
778         mpriv->browser->PrintPreviewNavigate(type, page);
781 static void
782 impl_set_encoding (EphyEmbed *embed,
783                    const char *encoding)
785         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
786         nsresult rv;
787         nsCString currEnc;
789         g_return_if_fail (encoding != NULL);
791         rv = mpriv->browser->GetEncoding (currEnc);
792         if (NS_FAILED (rv)) return;
794         if (strcmp (currEnc.get(), encoding) != 0 ||
795             encoding[0] == '\0' && !ephy_embed_has_automatic_encoding (embed))
796         {
797                 rv = mpriv->browser->ForceEncoding (encoding);
798                 if (NS_FAILED (rv)) return;
799         }
801         gtk_moz_embed_reload (GTK_MOZ_EMBED (embed),
802                               GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE);
805 static char *
806 impl_get_encoding (EphyEmbed *embed)
808         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
809         nsresult rv;
810         nsCString encoding;
812         rv = mpriv->browser->GetEncoding (encoding);
814         if (NS_FAILED (rv) || !encoding.Length())
815         {
816                 return NULL;
817         }
819         return g_strdup (encoding.get());
822 static gboolean
823 impl_has_automatic_encoding (EphyEmbed *embed)
825         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
826         nsresult rv;
827         nsCString encoding;
829         rv = mpriv->browser->GetForcedEncoding (encoding);
831         if (NS_FAILED (rv) || !encoding.Length())
832         {
833                 return TRUE;
834         }
836         return FALSE;
839 static gboolean
840 impl_has_modified_forms (EphyEmbed *embed)
842         MozillaEmbedPrivate *mpriv = MOZILLA_EMBED(embed)->priv;
843         nsresult rv;
845         PRBool modified;
846         rv = mpriv->browser->GetHasModifiedForms (&modified);
848         return NS_SUCCEEDED (rv) ? modified : FALSE;
851 static void
852 mozilla_embed_location_changed_cb (GtkMozEmbed *embed, 
853                                    MozillaEmbed *membed)
855         char *location;
857         location = gtk_moz_embed_get_location (embed);
858         g_signal_emit_by_name (membed, "ge_location", location);
859         g_free (location);
862 static void
863 update_load_state (MozillaEmbed *membed, gint state)
865         MozillaEmbedPrivate *priv = membed->priv;
867         if (state & GTK_MOZ_EMBED_FLAG_IS_DOCUMENT &&
868             state & (GTK_MOZ_EMBED_FLAG_START | GTK_MOZ_EMBED_FLAG_STOP))
869         {
870                 g_signal_emit_by_name (membed, "ge-document-type",
871                                        priv->browser->GetDocumentType ());
872         }
874         if (state & GTK_MOZ_EMBED_FLAG_RESTORING &&
875             priv->load_state == MOZILLA_EMBED_LOAD_STARTED)
876         {
877                 priv->load_state = MOZILLA_EMBED_LOAD_LOADING;
879                 char *address;
880                 address = gtk_moz_embed_get_location (GTK_MOZ_EMBED (membed));
881                 g_signal_emit_by_name (membed, "ge-content-change", address);
882                 g_free (address);
883         }
885         if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK)
886         {
887                 if (state & GTK_MOZ_EMBED_FLAG_START)
888                 {
889                         priv->load_state = MOZILLA_EMBED_LOAD_STARTED;
890                 }
891                 else if (state & GTK_MOZ_EMBED_FLAG_STOP)
892                 {
893                         priv->load_state = MOZILLA_EMBED_LOAD_STOPPED;
894                 }
895         }
896         else if (state & GTK_MOZ_EMBED_FLAG_START &&
897                  state & GTK_MOZ_EMBED_FLAG_IS_REQUEST)
898         {
899                 if (priv->load_state == MOZILLA_EMBED_LOAD_REDIRECTING)
900                 {
901                         priv->load_state = MOZILLA_EMBED_LOAD_STARTED;
902                 }
903                 else if (priv->load_state != MOZILLA_EMBED_LOAD_LOADING)
904                 {
905                         priv->load_state = MOZILLA_EMBED_LOAD_LOADING;
907                         char *address;
908                         address = gtk_moz_embed_get_location (GTK_MOZ_EMBED (membed));
909                         g_signal_emit_by_name (membed, "ge_content_change", address);
910                         g_free (address);
911                 }
912         }
913         else if (state & GTK_MOZ_EMBED_FLAG_REDIRECTING &&
914                  priv->load_state == MOZILLA_EMBED_LOAD_STARTED)
915         {
916                 priv->load_state = MOZILLA_EMBED_LOAD_REDIRECTING;
917         }
920 static void
921 mozilla_embed_net_state_all_cb (GtkMozEmbed *embed, const char *aURI,
922                                 gint state, guint status, 
923                                 MozillaEmbed *membed)
925         EphyEmbedNetState estate = EPHY_EMBED_STATE_UNKNOWN;
926         int i;
928         struct
929         {
930                 guint state;
931                 EphyEmbedNetState embed_state;
932         }
933         conversion_map [] =
934         {
935                 { GTK_MOZ_EMBED_FLAG_START, EPHY_EMBED_STATE_START },
936                 { GTK_MOZ_EMBED_FLAG_STOP, EPHY_EMBED_STATE_STOP },
937                 { GTK_MOZ_EMBED_FLAG_REDIRECTING, EPHY_EMBED_STATE_REDIRECTING },
938                 { GTK_MOZ_EMBED_FLAG_TRANSFERRING, EPHY_EMBED_STATE_TRANSFERRING },
939                 { GTK_MOZ_EMBED_FLAG_NEGOTIATING, EPHY_EMBED_STATE_NEGOTIATING },
940                 { GTK_MOZ_EMBED_FLAG_IS_REQUEST, EPHY_EMBED_STATE_IS_REQUEST },
941                 { GTK_MOZ_EMBED_FLAG_IS_DOCUMENT, EPHY_EMBED_STATE_IS_DOCUMENT },
942                 { GTK_MOZ_EMBED_FLAG_IS_NETWORK, EPHY_EMBED_STATE_IS_NETWORK },
943                 { GTK_MOZ_EMBED_FLAG_RESTORING, EPHY_EMBED_STATE_RESTORING },
944                 { 0, EPHY_EMBED_STATE_UNKNOWN }
945         };
947         for (i = 0; conversion_map[i].state != 0; i++)
948         {
949                 if (state & conversion_map[i].state)
950                 {
951                         estate = (EphyEmbedNetState) (estate | conversion_map[i].embed_state);  
952                 }
953         }
955         update_load_state (membed, state);
956         
957         g_signal_emit_by_name (membed, "ge_net_state", aURI, /* FIXME: (gulong) */ estate);
960 static gboolean
961 mozilla_embed_emit_mouse_signal (MozillaEmbed *embed,
962                                  gpointer dom_event, 
963                                  const char *signal_name)
965         MozillaEmbedPrivate *mpriv = embed->priv;
966         MozillaEmbedEvent *info;
967         EventContext event_context;
968         gint return_value = FALSE;
969         nsresult rv;
971         if (dom_event == NULL) return FALSE;
973         nsCOMPtr<nsIDOMMouseEvent> ev = static_cast<nsIDOMMouseEvent*>(dom_event);
974         NS_ENSURE_TRUE (ev, FALSE);
975         nsCOMPtr<nsIDOMEvent> dev = do_QueryInterface (ev);
976         NS_ENSURE_TRUE (dev, FALSE);
978         info = mozilla_embed_event_new (NS_STATIC_CAST (gpointer, dev));
980         event_context.Init (mpriv->browser);
981         rv = event_context.GetMouseEventInfo (ev, MOZILLA_EMBED_EVENT (info));
982         if (NS_FAILED (rv))
983         {
984                 g_object_unref (info);
985                 return FALSE;
986         }
988         nsCOMPtr<nsIDOMDocument> domDoc;
989         rv = event_context.GetTargetDocument (getter_AddRefs(domDoc));
990         if (NS_SUCCEEDED (rv))
991         {
992                 mpriv->browser->PushTargetDocument (domDoc);
994                 g_signal_emit_by_name (embed, signal_name, 
995                                        info, &return_value); 
996                 mpriv->browser->PopTargetDocument ();
997         }
999         g_object_unref (info);
1001         return return_value;
1004 static gboolean
1005 mozilla_embed_dom_mouse_click_cb (GtkMozEmbed *embed,
1006                                   gpointer dom_event, 
1007                                   MozillaEmbed *membed)
1009         return mozilla_embed_emit_mouse_signal (membed, dom_event,
1010                                                 "ge_dom_mouse_click");
1013 static gboolean
1014 mozilla_embed_dom_mouse_down_cb (GtkMozEmbed *embed, gpointer dom_event, 
1015                                  MozillaEmbed *membed)
1017         return mozilla_embed_emit_mouse_signal (membed, dom_event,
1018                                                 "ge_dom_mouse_down");
1021 static gint
1022 mozilla_embed_dom_key_press_cb (GtkMozEmbed *embed,
1023                                 gpointer dom_event, 
1024                                 MozillaEmbed *membed)
1026         gint retval = FALSE;
1028         if (dom_event == NULL) return FALSE;
1030         nsCOMPtr<nsIDOMKeyEvent> ev = static_cast<nsIDOMKeyEvent*>(dom_event);
1031         NS_ENSURE_TRUE (ev, FALSE);
1033         if (!EventContext::CheckKeyPress (ev)) return FALSE;
1035         GdkEvent *event = gtk_get_current_event ();
1036         if (event == NULL) return FALSE; /* shouldn't happen! */
1038         g_return_val_if_fail (GDK_KEY_PRESS == event->type, FALSE);
1040         g_signal_emit_by_name (embed, "ge-search-key-press", event, &retval);
1042         gdk_event_free (event);
1044         return retval;
1047 EphyEmbedChrome
1048 _mozilla_embed_translate_chrome (GtkMozEmbedChromeFlags flags)
1050         static const struct
1051         {
1052                 guint mozilla_flag;
1053                 guint ephy_flag;
1054         }
1055         conversion_map [] =
1056         {
1057                 { GTK_MOZ_EMBED_FLAG_MENUBARON, EPHY_EMBED_CHROME_MENUBAR },
1058                 { GTK_MOZ_EMBED_FLAG_TOOLBARON, EPHY_EMBED_CHROME_TOOLBAR },
1059                 { GTK_MOZ_EMBED_FLAG_STATUSBARON, EPHY_EMBED_CHROME_STATUSBAR },
1060                 { GTK_MOZ_EMBED_FLAG_PERSONALTOOLBARON, EPHY_EMBED_CHROME_BOOKMARKSBAR },
1061         };
1063         guint mask = 0, i;
1065         for (i = 0; i < G_N_ELEMENTS (conversion_map); i++)
1066         {
1067                 if (flags & conversion_map[i].mozilla_flag)
1068                 {
1069                         mask |= conversion_map[i].ephy_flag;
1070                 }
1071         }
1073         return (EphyEmbedChrome) mask;
1076 static void
1077 mozilla_embed_new_window_cb (GtkMozEmbed *embed, 
1078                              GtkMozEmbed **newEmbed,
1079                              guint chrome_mask, 
1080                              MozillaEmbed *membed)
1082         GtkMozEmbedChromeFlags chrome = (GtkMozEmbedChromeFlags) chrome_mask;
1083         EphyEmbed *new_embed = NULL;
1084         GObject *single;
1085         EphyEmbedChrome mask;
1087         if (chrome & GTK_MOZ_EMBED_FLAG_OPENASCHROME)
1088         {
1089                 *newEmbed = _mozilla_embed_new_xul_dialog ();
1090                 return;
1091         }
1093         mask = _mozilla_embed_translate_chrome (chrome);
1095         single = ephy_embed_shell_get_embed_single (embed_shell);
1096         g_signal_emit_by_name (single, "new-window", embed, mask,
1097                                &new_embed);
1099         g_assert (new_embed != NULL);
1101         gtk_moz_embed_set_chrome_mask (GTK_MOZ_EMBED (new_embed), chrome);
1103         g_signal_emit_by_name (membed, "ge-new-window", new_embed);
1105         *newEmbed = GTK_MOZ_EMBED (new_embed);
1108 static void
1109 mozilla_embed_security_change_cb (GtkMozEmbed *embed, 
1110                                   gpointer requestptr,
1111                                   PRUint32 state,
1112                                   MozillaEmbed *membed)
1114         g_signal_emit_by_name (membed, "ge_security_change",
1115                                mozilla_embed_security_level (state));
1118 static EphyEmbedSecurityLevel
1119 mozilla_embed_security_level (PRUint32 state)
1121         EphyEmbedSecurityLevel level;
1123         switch (state)
1124         {
1125         case nsIWebProgressListener::STATE_IS_INSECURE:
1126                 level = EPHY_EMBED_STATE_IS_INSECURE;
1127                 break;
1128         case nsIWebProgressListener::STATE_IS_BROKEN:
1129                 level = EPHY_EMBED_STATE_IS_BROKEN;
1130                 break;
1131         case nsIWebProgressListener::STATE_IS_SECURE|
1132              nsIWebProgressListener::STATE_SECURE_HIGH:
1133                 level = EPHY_EMBED_STATE_IS_SECURE_HIGH;
1134                 break;
1135         case nsIWebProgressListener::STATE_IS_SECURE|
1136              nsIWebProgressListener::STATE_SECURE_MED:
1137                 level = EPHY_EMBED_STATE_IS_SECURE_MED;
1138                 break;
1139         case nsIWebProgressListener::STATE_IS_SECURE|
1140              nsIWebProgressListener::STATE_SECURE_LOW:
1141                 level = EPHY_EMBED_STATE_IS_SECURE_LOW;
1142                 break;
1143         default:
1144                 level = EPHY_EMBED_STATE_IS_UNKNOWN;
1145                 break;
1146         }
1147         return level;
1150 static void
1151 ephy_embed_iface_init (EphyEmbedIface *iface)
1153         iface->load_url = impl_load_url; 
1154         iface->load = impl_load; 
1155         iface->stop_load = impl_stop_load;
1156         iface->can_go_back = impl_can_go_back;
1157         iface->can_go_forward =impl_can_go_forward;
1158         iface->can_go_up = impl_can_go_up;
1159         iface->get_go_up_list = impl_get_go_up_list;
1160         iface->go_back = impl_go_back;
1161         iface->go_forward = impl_go_forward;
1162         iface->go_up = impl_go_up;
1163         iface->get_title = impl_get_title;
1164         iface->get_location = impl_get_location;
1165         iface->get_link_message = impl_get_link_message;
1166         iface->get_js_status = impl_get_js_status;
1167         iface->reload = impl_reload;
1168         iface->set_zoom = impl_set_zoom;
1169         iface->get_zoom = impl_get_zoom;
1170         iface->scroll_lines = impl_scroll_lines;
1171         iface->scroll_pages = impl_scroll_pages;
1172         iface->scroll_pixels = impl_scroll_pixels;
1173         iface->shistory_n_items = impl_shistory_n_items;
1174         iface->shistory_get_nth = impl_shistory_get_nth;
1175         iface->shistory_get_pos = impl_shistory_get_pos;
1176         iface->shistory_go_nth = impl_shistory_go_nth;
1177         iface->shistory_copy = impl_shistory_copy;
1178         iface->get_security_level = impl_get_security_level;
1179         iface->show_page_certificate = impl_show_page_certificate;
1180         iface->close = impl_close;
1181         iface->set_encoding = impl_set_encoding;
1182         iface->get_encoding = impl_get_encoding;
1183         iface->has_automatic_encoding = impl_has_automatic_encoding;
1184         iface->print = impl_print;
1185         iface->set_print_preview_mode = impl_set_print_preview_mode;
1186         iface->print_preview_n_pages = impl_print_preview_n_pages;
1187         iface->print_preview_navigate = impl_print_preview_navigate;
1188         iface->has_modified_forms = impl_has_modified_forms;
1191 static void
1192 xul_visibility_cb (GtkWidget *embed, gboolean visibility, GtkWidget *window)
1194         if (visibility)
1195         {
1196                 gtk_widget_show (window);
1197         }
1198         else
1199         {
1200                 gtk_widget_hide (window);
1201         }
1204 static void
1205 xul_size_to_cb (GtkWidget *embed, gint width, gint height, gpointer dummy)
1207         gtk_widget_set_size_request (embed, width, height);
1210 static void
1211 xul_new_window_cb (GtkMozEmbed *embed,
1212                    GtkMozEmbed **retval, 
1213                    guint chrome_mask,
1214                    gpointer dummy)
1216         g_assert (chrome_mask & GTK_MOZ_EMBED_FLAG_OPENASCHROME);
1218         *retval = _mozilla_embed_new_xul_dialog ();
1221 static void
1222 xul_title_cb (GtkMozEmbed *embed,
1223               GtkWindow *window)
1225         char *title;
1227         title = gtk_moz_embed_get_title (embed);
1228         gtk_window_set_title (window, title);
1229         g_free (title);
1232 GtkMozEmbed *
1233 _mozilla_embed_new_xul_dialog (void)
1235         GtkWidget *window, *embed;
1237         g_object_ref (embed_shell);
1239         window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1240         g_object_set_data_full (G_OBJECT (window), "EmbedShellRef",
1241                                 embed_shell,
1242                                 (GDestroyNotify) g_object_unref);
1243         g_signal_connect_object (embed_shell, "prepare_close",
1244                                  G_CALLBACK (gtk_widget_destroy), window,
1245                                  (GConnectFlags) G_CONNECT_SWAPPED);
1247         embed = gtk_moz_embed_new ();
1248         gtk_widget_show (embed);
1249         gtk_container_add (GTK_CONTAINER (window), embed);
1251         g_signal_connect_object (embed, "destroy_browser",
1252                                  G_CALLBACK (gtk_widget_destroy),
1253                                  window, G_CONNECT_SWAPPED);
1254         g_signal_connect_object (embed, "visibility",
1255                                  G_CALLBACK (xul_visibility_cb),
1256                                  window, (GConnectFlags) 0);
1257         g_signal_connect_object (embed, "size_to",
1258                                  G_CALLBACK (xul_size_to_cb),
1259                                  NULL, (GConnectFlags) 0);
1260         g_signal_connect_object (embed, "new_window",
1261                                  G_CALLBACK (xul_new_window_cb),
1262                                  NULL, (GConnectFlags) 0);
1263         g_signal_connect_object (embed, "title",
1264                                  G_CALLBACK (xul_title_cb),
1265                                  window, (GConnectFlags) 0);
1267         return GTK_MOZ_EMBED (embed);